#ifndef XRPL_PROTOCOL_SERIALIZER_H_INCLUDED #define XRPL_PROTOCOL_SERIALIZER_H_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ripple { class Serializer { private: // DEPRECATED Blob mData; public: explicit Serializer(int n = 256) { mData.reserve(n); } Serializer(void const* data, std::size_t size) { mData.resize(size); if (size) { XRPL_ASSERT( data, "ripple::Serializer::Serializer(void const*) : non-null input"); std::memcpy(mData.data(), data, size); } } Slice slice() const noexcept { return Slice(mData.data(), mData.size()); } std::size_t size() const noexcept { return mData.size(); } void const* data() const noexcept { return mData.data(); } // assemble functions int add8(unsigned char i); int add16(std::uint16_t i); template requires(std::is_same_v< std::make_unsigned_t>, std::uint32_t>) int add32(T i) { int ret = mData.size(); mData.push_back(static_cast((i >> 24) & 0xff)); mData.push_back(static_cast((i >> 16) & 0xff)); mData.push_back(static_cast((i >> 8) & 0xff)); mData.push_back(static_cast(i & 0xff)); return ret; } int add32(HashPrefix p); template requires(std::is_same_v< std::make_unsigned_t>, std::uint64_t>) int add64(T i) { int ret = mData.size(); mData.push_back(static_cast((i >> 56) & 0xff)); mData.push_back(static_cast((i >> 48) & 0xff)); mData.push_back(static_cast((i >> 40) & 0xff)); mData.push_back(static_cast((i >> 32) & 0xff)); mData.push_back(static_cast((i >> 24) & 0xff)); mData.push_back(static_cast((i >> 16) & 0xff)); mData.push_back(static_cast((i >> 8) & 0xff)); mData.push_back(static_cast(i & 0xff)); return ret; } template int addInteger(Integer); template int addBitString(base_uint const& v) { return addRaw(v.data(), v.size()); } int addRaw(Blob const& vector); int addRaw(Slice slice); int addRaw(void const* ptr, int len); int addRaw(Serializer const& s); int addVL(Blob const& vector); int addVL(Slice const& slice); template int addVL(Iter begin, Iter end, int len); int addVL(void const* ptr, int len); // disassemble functions bool get8(int&, int offset) const; template bool getInteger(Integer& number, int offset) { static auto const bytes = sizeof(Integer); if ((offset + bytes) > mData.size()) return false; number = 0; auto ptr = &mData[offset]; for (auto i = 0; i < bytes; ++i) { if (i) number <<= 8; number |= *ptr++; } return true; } template bool getBitString(base_uint& data, int offset) const { auto success = (offset + (Bits / 8)) <= mData.size(); if (success) memcpy(data.begin(), &(mData.front()) + offset, (Bits / 8)); return success; } int addFieldID(int type, int name); int addFieldID(SerializedTypeID type, int name) { return addFieldID(safe_cast(type), name); } // DEPRECATED uint256 getSHA512Half() const; // totality functions Blob const& peekData() const { return mData; } Blob getData() const { return mData; } Blob& modData() { return mData; } int getDataLength() const { return mData.size(); } void const* getDataPtr() const { return mData.data(); } void* getDataPtr() { return mData.data(); } int getLength() const { return mData.size(); } std::string getString() const { return std::string(static_cast(getDataPtr()), size()); } void erase() { mData.clear(); } bool chop(int num); // vector-like functions Blob ::iterator begin() { return mData.begin(); } Blob ::iterator end() { return mData.end(); } Blob ::const_iterator begin() const { return mData.begin(); } Blob ::const_iterator end() const { return mData.end(); } void reserve(size_t n) { mData.reserve(n); } void resize(size_t n) { mData.resize(n); } size_t capacity() const { return mData.capacity(); } bool operator==(Blob const& v) const { return v == mData; } bool operator!=(Blob const& v) const { return v != mData; } bool operator==(Serializer const& v) const { return v.mData == mData; } bool operator!=(Serializer const& v) const { return v.mData != mData; } static int decodeLengthLength(int b1); static int decodeVLLength(int b1); static int decodeVLLength(int b1, int b2); static int decodeVLLength(int b1, int b2, int b3); private: static int encodeLengthLength(int length); // length to encode length int addEncoded(int length); }; template int Serializer::addVL(Iter begin, Iter end, int len) { int ret = addEncoded(len); for (; begin != end; ++begin) { addRaw(begin->data(), begin->size()); #ifndef NDEBUG len -= begin->size(); #endif } XRPL_ASSERT( len == 0, "ripple::Serializer::addVL : length matches distance"); return ret; } //------------------------------------------------------------------------------ // DEPRECATED // Transitional adapter to new serialization interfaces class SerialIter { private: std::uint8_t const* p_; std::size_t remain_; std::size_t used_ = 0; public: SerialIter(void const* data, std::size_t size) noexcept; SerialIter(Slice const& slice) : SerialIter(slice.data(), slice.size()) { } // Infer the size of the data based on the size of the passed array. template explicit SerialIter(std::uint8_t const (&data)[N]) : SerialIter(&data[0], N) { static_assert(N > 0, ""); } std::size_t empty() const noexcept { return remain_ == 0; } void reset() noexcept; int getBytesLeft() const noexcept { return static_cast(remain_); } // get functions throw on error unsigned char get8(); std::uint16_t get16(); std::uint32_t get32(); std::int32_t geti32(); std::uint64_t get64(); std::int64_t geti64(); template base_uint getBitString(); uint128 get128() { return getBitString<128>(); } uint160 get160() { return getBitString<160>(); } uint192 get192() { return getBitString<192>(); } uint256 get256() { return getBitString<256>(); } void getFieldID(int& type, int& name); // Returns the size of the VL if the // next object is a VL. Advances the iterator // to the beginning of the VL. int getVLDataLength(); Slice getSlice(std::size_t bytes); // VFALCO DEPRECATED Returns a copy Blob getRaw(int size); // VFALCO DEPRECATED Returns a copy Blob getVL(); void skip(int num); Buffer getVLBuffer(); template T getRawHelper(int size); }; template base_uint SerialIter::getBitString() { auto const n = Bits / 8; if (remain_ < n) Throw("invalid SerialIter getBitString"); auto const x = p_; p_ += n; used_ += n; remain_ -= n; return base_uint::fromVoid(x); } } // namespace ripple #endif