src/scale/scale_encoder_stream.hpp¶
Namespaces¶
| Name |
|---|
| sgns |
| sgns::scale |
Classes¶
| Name | |
|---|---|
| class | sgns::scale::ScaleEncoderStream Scale-encodes data into a byte stream. |
Source code¶
#ifndef SUPERGENIUS_SRC_SCALE_SCALE_ENCODER_STREAM_HPP
#define SUPERGENIUS_SRC_SCALE_SCALE_ENCODER_STREAM_HPP
#include <deque>
#include <list>
#include <boost/variant/get.hpp>
#include <boost/variant/variant.hpp>
#include <boost/optional.hpp>
#include <gsl/span>
#include "scale/detail/fixed_witdh_integer.hpp"
#include "scale/types.hpp"
namespace sgns::scale {
class ScaleEncoderStream {
public:
// special tag to differentiate encoding streams from others
static constexpr auto is_encoder_stream = true;
std::vector<uint8_t> data() const;
template <class F, class S>
ScaleEncoderStream &operator<<(const std::pair<F, S> &p) {
return *this << p.first << p.second;
}
template <class... Ts>
ScaleEncoderStream &operator<<(const std::tuple<Ts...> &v) {
if constexpr (sizeof...(Ts) > 0) {
encodeElementOfTuple<0>(v);
}
return *this;
}
template <class... T>
ScaleEncoderStream &operator<<(const boost::variant<T...> &v) {
tryEncodeAsOneOfVariant<0>(v);
return *this;
}
template <class T>
ScaleEncoderStream &operator<<(const std::shared_ptr<T> &v) {
if (v == nullptr) {
base::raise(EncodeError::DEREF_NULLPOINTER);
}
return *this << *v;
}
template <class T>
ScaleEncoderStream &operator<<(const std::unique_ptr<T> &v) {
if (v == nullptr) {
base::raise(EncodeError::DEREF_NULLPOINTER);
}
return *this << *v;
}
template <class T>
ScaleEncoderStream &operator<<(const std::vector<T> &c) {
return encodeCollection(c.size(), c.begin(), c.end());
}
template <class T>
ScaleEncoderStream &operator<<(const std::list<T> &c) {
return encodeCollection(c.size(), c.begin(), c.end());
}
template <class T>
ScaleEncoderStream &operator<<(const boost::optional<T> &v) {
// optional bool is a special case of optional values
// it should be encoded using one byte instead of two
// as described in specification
if constexpr (std::is_same<T, bool>::value) {
return encodeOptionalBool(v);
}
if (!v.has_value()) {
return putByte(0u);
}
return putByte(1u) << *v;
}
template <class T>
ScaleEncoderStream &operator<<(const gsl::span<T> &v) {
return encodeCollection(v.size(), v.begin(), v.end());
}
template <typename T, size_t size>
ScaleEncoderStream &operator<<(const std::array<T, size> &a) {
// TODO(akvinikym) PRE-285: bad implementation: maybe move to another file
// and implement it
return encodeCollection(size, a.begin(), a.end());
}
ScaleEncoderStream &operator<<(const boost::multiprecision::uint256_t &i) {
// TODO(akvinikym) PRE-285: maybe move to another file and implement it
return *this;
}
template <class T>
ScaleEncoderStream &operator<<(const std::reference_wrapper<T> &v) {
return *this << static_cast<const T &>(v);
}
ScaleEncoderStream &operator<<(std::string_view sv) {
return encodeCollection(sv.size(), sv.begin(), sv.end());
}
template <typename T, typename I = std::decay_t<T>, typename = std::enable_if_t<std::is_integral_v<I>>>
ScaleEncoderStream &operator<<( T &&v )
{
// encode bool
if constexpr ( std::is_same<I, bool>::value )
{
uint8_t byte = ( v ? 1u : 0u );
return putByte( byte );
}
// put byte
if constexpr ( sizeof( T ) == 1u )
{
// to avoid infinite recursion
return putByte( static_cast<uint8_t>( v ) );
}
// encode any other integer
detail::encodeInteger<I>( v, *this );
return *this;
}
ScaleEncoderStream &operator<<(const CompactInteger &v);
protected:
template <size_t I, class... Ts>
void encodeElementOfTuple(const std::tuple<Ts...> &v) {
*this << std::get<I>(v);
if constexpr (sizeof...(Ts) > I + 1) {
encodeElementOfTuple<I + 1>(v);
}
}
template <uint8_t I, class... Ts>
void tryEncodeAsOneOfVariant(const boost::variant<Ts...> &v) {
using T = std::tuple_element_t<I, std::tuple<Ts...>>;
if (v.type() == typeid(T)) {
*this << I << boost::get<T>(v);
return;
}
if constexpr (sizeof...(Ts) > I + 1) {
tryEncodeAsOneOfVariant<I + 1>(v);
}
}
template <class It>
ScaleEncoderStream &encodeCollection(const CompactInteger &size,
It &&begin,
It &&end) {
*this << size;
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
for (auto &&it = begin; it != end; ++it) {
*this << *it;
}
return *this;
}
ScaleEncoderStream &putByte(uint8_t v);
private:
ScaleEncoderStream &encodeOptionalBool(const boost::optional<bool> &v);
std::deque<uint8_t> stream_;
};
} // namespace sgns::scale
#endif // SUPERGENIUS_SRC_SCALE_SCALE_ENCODER_STREAM_HPP
Updated on 2026-03-04 at 13:10:45 -0800