Files
rippled/include/xrpl/protocol/Serializer.h
2025-10-23 11:04:30 -04:00

459 lines
8.8 KiB
C++

#ifndef XRPL_PROTOCOL_SERIALIZER_H_INCLUDED
#define XRPL_PROTOCOL_SERIALIZER_H_INCLUDED
#include <xrpl/basics/Blob.h>
#include <xrpl/basics/Buffer.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/SField.h>
#include <cstdint>
#include <cstring>
#include <type_traits>
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 <typename T>
requires(std::is_same_v<
std::make_unsigned_t<std::remove_cv_t<T>>,
std::uint32_t>)
int
add32(T i)
{
int ret = mData.size();
mData.push_back(static_cast<unsigned char>((i >> 24) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 16) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 8) & 0xff));
mData.push_back(static_cast<unsigned char>(i & 0xff));
return ret;
}
int
add32(HashPrefix p);
template <typename T>
requires(std::is_same_v<
std::make_unsigned_t<std::remove_cv_t<T>>,
std::uint64_t>)
int
add64(T i)
{
int ret = mData.size();
mData.push_back(static_cast<unsigned char>((i >> 56) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 48) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 40) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 32) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 24) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 16) & 0xff));
mData.push_back(static_cast<unsigned char>((i >> 8) & 0xff));
mData.push_back(static_cast<unsigned char>(i & 0xff));
return ret;
}
template <typename Integer>
int addInteger(Integer);
template <std::size_t Bits, class Tag>
int
addBitString(base_uint<Bits, Tag> 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 <class Iter>
int
addVL(Iter begin, Iter end, int len);
int
addVL(void const* ptr, int len);
// disassemble functions
bool
get8(int&, int offset) const;
template <typename Integer>
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 <std::size_t Bits, typename Tag = void>
bool
getBitString(base_uint<Bits, Tag>& 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<int>(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<char const*>(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 <class Iter>
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 <int N>
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<int>(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 <std::size_t Bits, class Tag = void>
base_uint<Bits, Tag>
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 <class T>
T
getRawHelper(int size);
};
template <std::size_t Bits, class Tag>
base_uint<Bits, Tag>
SerialIter::getBitString()
{
auto const n = Bits / 8;
if (remain_ < n)
Throw<std::runtime_error>("invalid SerialIter getBitString");
auto const x = p_;
p_ += n;
used_ += n;
remain_ -= n;
return base_uint<Bits, Tag>::fromVoid(x);
}
} // namespace ripple
#endif