#pragma once #include <deque> #include "for_each_field.hpp" #include "stream.hpp" #include <list> #include <map> #include <optional> #include <set> #include <variant> #include <vector> namespace eosio { template <typename S> bool to_bin(std::string_view sv, S& stream, std::string_view&); template <typename S> bool to_bin(const std::string& s, S& stream, std::string_view&); template <typename T, typename S> bool to_bin(const std::vector<T>& obj, S& stream, std::string_view&); template <typename T, typename S> bool to_bin(const std::optional<T>& obj, S& stream, std::string_view&); template <typename... Ts, typename S> bool to_bin(const std::variant<Ts...>& obj, S& stream, std::string_view&); template <typename... Ts, typename S> bool to_bin(const std::tuple<Ts...>& obj, S& stream, std::string_view&); template <typename T, typename S> bool to_bin(const T& obj, S& stream, std::string_view&); template <typename S> void varuint32_to_bin(uint64_t val, S& stream) { check( !(val >> 32), convert_stream_error( stream_error::varuint_too_big) ); do { uint8_t b = val & 0x7f; val >>= 7; b |= ((val > 0) << 7); stream.write(b); } while (val); } inline void push_varuint32(std::vector<char>& bin, uint32_t v) { vector_stream st{ bin }; varuint32_to_bin(v, st); } template <typename S> void to_bin(std::string_view sv, S& stream) { varuint32_to_bin(sv.size(), stream); stream.write(sv.data(), sv.size()); } template <typename S> void to_bin(const std::string& s, S& stream) { to_bin(std::string_view{ s }, stream); } template <typename T, typename S> void to_bin_range(const T& obj, S& stream) { varuint32_to_bin(obj.size(), stream); for (auto& x : obj) { to_bin(x, stream); } } template <typename T, std::size_t N, typename S> void to_bin(const T (&obj)[N], S& stream) { varuint32_to_bin(N, stream); if constexpr (has_bitwise_serialization<T>()) { stream.write(reinterpret_cast<const char*>(&obj), N * sizeof(T)); } else { for (auto& x : obj) { to_bin(x, stream); } } } template <typename T, typename S> void to_bin(const std::vector<T>& obj, S& stream) { varuint32_to_bin(obj.size(), stream); if constexpr (has_bitwise_serialization<T>()) { stream.write(reinterpret_cast<const char*>(obj.data()), obj.size() * sizeof(T)); } else { for (auto& x : obj) { to_bin(x, stream); } } } template <typename T, typename S> void to_bin(const std::list<T>& obj, S& stream) { to_bin_range(obj, stream); } template <typename T, typename S> void to_bin(const std::deque<T>& obj, S& stream) { to_bin_range(obj, stream); } template <typename T, typename S> void to_bin(const std::set<T>& obj, S& stream) { to_bin_range(obj, stream); } template <typename T, typename U, typename S> void to_bin(const std::map<T, U>& obj, S& stream) { to_bin_range(obj, stream); } template <typename S> void to_bin(const input_stream& obj, S& stream) { varuint32_to_bin(obj.end - obj.pos, stream); stream.write(obj.pos, obj.end - obj.pos); } template <typename First, typename Second, typename S> void to_bin(const std::pair<First, Second>& obj, S& stream) { to_bin(obj.first, stream); return to_bin(obj.second, stream); } template <typename T, typename S> void to_bin(const std::optional<T>& obj, S& stream) { to_bin(obj.has_value(), stream); if (obj) to_bin(*obj, stream); } template <typename... Ts, typename S> void to_bin(const std::variant<Ts...>& obj, S& stream) { varuint32_to_bin(obj.index(), stream); std::visit([&](auto& x) { return to_bin(x, stream); }, obj); } template <int i, typename T, typename S> void to_bin_tuple(const T& obj, S& stream) { if constexpr (i < std::tuple_size_v<T>) { to_bin(std::get<i>(obj), stream); to_bin_tuple<i + 1>(obj, stream); } } template <typename... Ts, typename S> void to_bin(const std::tuple<Ts...>& obj, S& stream) { to_bin_tuple<0>(obj, stream); } template <typename T, std::size_t N, typename S> void to_bin(const std::array<T, N>& obj, S& stream) { for (const T& elem : obj) { to_bin(elem, stream); } } template <typename T, typename S> void to_bin(const T& obj, S& stream) { if constexpr (has_bitwise_serialization<T>()) { stream.write(reinterpret_cast<const char*>(&obj), sizeof(obj)); } else { for_each_field(obj, [&](auto& member) { to_bin(member, stream); }); } } template <typename T> void convert_to_bin(const T& t, std::vector<char>& bin) { size_stream ss; to_bin(t, ss); auto orig_size = bin.size(); bin.resize(orig_size + ss.size); fixed_buf_stream fbs(bin.data() + orig_size, ss.size); to_bin(t, fbs); check( fbs.pos == fbs.end, convert_stream_error(stream_error::underrun) ); } template <typename T> std::vector<char> convert_to_bin(const T& t) { std::vector<char> result; convert_to_bin(t, result); return result; } } // namespace eosio