Files
rippled/src/libxrpl/protocol/STVar.cpp
2026-03-03 20:23:22 +00:00

224 lines
5.8 KiB
C++

#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAccount.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STArray.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/STBitString.h>
#include <xrpl/protocol/STBlob.h>
#include <xrpl/protocol/STCurrency.h>
#include <xrpl/protocol/STInteger.h>
#include <xrpl/protocol/STIssue.h>
#include <xrpl/protocol/STNumber.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/STPathSet.h>
#include <xrpl/protocol/STVector256.h>
#include <xrpl/protocol/STXChainBridge.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/detail/STVar.h>
#include <stdexcept>
#include <tuple>
#include <type_traits>
namespace xrpl {
namespace detail {
defaultObject_t defaultObject;
nonPresentObject_t nonPresentObject;
//------------------------------------------------------------------------------
STVar::~STVar()
{
destroy();
}
STVar::STVar(STVar const& other)
{
if (other.p_ != nullptr)
p_ = other.p_->copy(max_size, &d_);
}
STVar::STVar(STVar&& other)
{
if (other.on_heap())
{
p_ = other.p_;
other.p_ = nullptr;
}
else
{
p_ = other.p_->move(max_size, &d_);
}
}
STVar&
STVar::operator=(STVar const& rhs)
{
if (&rhs != this)
{
destroy();
if (rhs.p_)
p_ = rhs.p_->copy(max_size, &d_);
else
p_ = nullptr;
}
return *this;
}
STVar&
STVar::operator=(STVar&& rhs)
{
if (&rhs != this)
{
destroy();
if (rhs.on_heap())
{
p_ = rhs.p_;
rhs.p_ = nullptr;
}
else
{
p_ = rhs.p_->move(max_size, &d_);
}
}
return *this;
}
STVar::STVar(defaultObject_t, SField const& name) : STVar(name.fieldType, name)
{
}
STVar::STVar(nonPresentObject_t, SField const& name) : STVar(STI_NOTPRESENT, name)
{
}
STVar::STVar(SerialIter& sit, SField const& name, int depth)
{
if (depth > 10)
Throw<std::runtime_error>("Maximum nesting depth of STVar exceeded");
constructST(name.fieldType, depth, sit, name);
}
STVar::STVar(SerializedTypeID id, SField const& name)
{
XRPL_ASSERT(
(id == STI_NOTPRESENT) || (id == name.fieldType),
"xrpl::detail::STVar::STVar(SerializedTypeID) : valid type input");
constructST(id, 0, name);
}
void
STVar::destroy()
{
if (on_heap())
delete p_;
else
p_->~STBase();
p_ = nullptr;
}
template <typename... Args>
requires ValidConstructSTArgs<Args...>
void
STVar::constructST(SerializedTypeID id, int depth, Args&&... args)
{
auto constructWithDepth = [&]<typename T>() {
if constexpr (std::is_same_v<std::tuple<std::remove_cvref_t<Args>...>, std::tuple<SField>>)
{
construct<T>(std::forward<Args>(args)...);
}
else if constexpr (
std::
is_same_v<std::tuple<std::remove_cvref_t<Args>...>, std::tuple<SerialIter, SField>>)
{
construct<T>(std::forward<Args>(args)..., depth);
}
else
{
constexpr bool alwaysFalse = !std::is_same_v<std::tuple<Args...>, std::tuple<Args...>>;
static_assert(alwaysFalse, "Invalid STVar constructor arguments");
}
};
switch (id)
{
case STI_NOTPRESENT: {
// Last argument is always SField
SField const& field = std::get<sizeof...(args) - 1>(std::forward_as_tuple(args...));
construct<STBase>(field);
return;
}
case STI_UINT8:
construct<STUInt8>(std::forward<Args>(args)...);
return;
case STI_UINT16:
construct<STUInt16>(std::forward<Args>(args)...);
return;
case STI_UINT32:
construct<STUInt32>(std::forward<Args>(args)...);
return;
case STI_UINT64:
construct<STUInt64>(std::forward<Args>(args)...);
return;
case STI_AMOUNT:
construct<STAmount>(std::forward<Args>(args)...);
return;
case STI_NUMBER:
construct<STNumber>(std::forward<Args>(args)...);
return;
case STI_UINT128:
construct<STUInt128>(std::forward<Args>(args)...);
return;
case STI_UINT160:
construct<STUInt160>(std::forward<Args>(args)...);
return;
case STI_UINT192:
construct<STUInt192>(std::forward<Args>(args)...);
return;
case STI_UINT256:
construct<STUInt256>(std::forward<Args>(args)...);
return;
case STI_INT32:
construct<STInt32>(std::forward<Args>(args)...);
return;
case STI_VECTOR256:
construct<STVector256>(std::forward<Args>(args)...);
return;
case STI_VL:
construct<STBlob>(std::forward<Args>(args)...);
return;
case STI_ACCOUNT:
construct<STAccount>(std::forward<Args>(args)...);
return;
case STI_PATHSET:
construct<STPathSet>(std::forward<Args>(args)...);
return;
case STI_OBJECT:
constructWithDepth.template operator()<STObject>();
return;
case STI_ARRAY:
constructWithDepth.template operator()<STArray>();
return;
case STI_ISSUE:
construct<STIssue>(std::forward<Args>(args)...);
return;
case STI_XCHAIN_BRIDGE:
construct<STXChainBridge>(std::forward<Args>(args)...);
return;
case STI_CURRENCY:
construct<STCurrency>(std::forward<Args>(args)...);
return;
default:
Throw<std::runtime_error>("Unknown object type");
}
}
} // namespace detail
} // namespace xrpl