20#include <xrpl/basics/StringUtilities.h>
21#include <xrpl/basics/base_uint.h>
22#include <xrpl/basics/contract.h>
23#include <xrpl/basics/safe_cast.h>
24#include <xrpl/beast/core/LexicalCast.h>
25#include <xrpl/json/json_forwards.h>
26#include <xrpl/json/json_value.h>
27#include <xrpl/protocol/AccountID.h>
28#include <xrpl/protocol/ErrorCodes.h>
29#include <xrpl/protocol/LedgerFormats.h>
30#include <xrpl/protocol/Permissions.h>
31#include <xrpl/protocol/SField.h>
32#include <xrpl/protocol/STAccount.h>
33#include <xrpl/protocol/STAmount.h>
34#include <xrpl/protocol/STArray.h>
35#include <xrpl/protocol/STBitString.h>
36#include <xrpl/protocol/STBlob.h>
37#include <xrpl/protocol/STCurrency.h>
38#include <xrpl/protocol/STInteger.h>
39#include <xrpl/protocol/STIssue.h>
40#include <xrpl/protocol/STParsedJSON.h>
41#include <xrpl/protocol/STPathSet.h>
42#include <xrpl/protocol/STVector256.h>
43#include <xrpl/protocol/STXChainBridge.h>
44#include <xrpl/protocol/TER.h>
45#include <xrpl/protocol/TxFormats.h>
46#include <xrpl/protocol/UintTypes.h>
47#include <xrpl/protocol/detail/STVar.h>
64namespace STParsedJSONDetail {
65template <
typename U,
typename S>
71 Throw<std::runtime_error>(
"Value out of range");
72 return static_cast<U
>(value);
75template <
typename U1,
typename U2>
81 Throw<std::runtime_error>(
"Value out of range");
82 return static_cast<U1
>(value);
91 return object +
"." + field;
99 "Field '" +
make_name(
object, field) +
"' is not a JSON object.");
120 "Field '" +
make_name(
object, field) +
"' is unknown.");
128 "Field '" +
make_name(
object, field) +
"' is out of range.");
136 "Field '" +
make_name(
object, field) +
"' has bad type.");
144 "Field '" +
make_name(
object, field) +
"' has invalid data.");
158 "Field '" +
make_name(
object, field) +
"' must be a JSON array.");
166 "Field '" +
make_name(
object, field) +
"' must be a string.");
174 "Field '" +
object +
"' exceeds nesting depth limit.");
183 "]' must be an object with a single key/object value.");
191 "Object '" + sField.
getName() +
192 "' contents did not meet requirements for that type.");
201 " is not an object. Arrays may only contain objects.");
224 switch (field.fieldType)
229 constexpr auto minValue =
231 constexpr auto maxValue =
237 if (!strValue.
empty() &&
238 ((strValue[0] <
'0') || (strValue[0] >
'9')))
240 if (field == sfTransactionResult)
244 if (!ter ||
TERtoInt(*ter) < minValue ||
251 ret = detail::make_stvar<STUInt8>(
257 error =
bad_type(json_name, fieldName);
263 ret = detail::make_stvar<STUInt8>(
265 beast::lexicalCastThrow<std::uint8_t>(strValue));
268 else if (value.
isInt())
270 if (value.
asInt() < minValue || value.
asInt() > maxValue)
276 ret = detail::make_stvar<STUInt8>(
281 if (value.
asUInt() > maxValue)
287 ret = detail::make_stvar<STUInt8>(
292 error =
bad_type(json_name, fieldName);
310 if (!strValue.
empty() &&
311 ((strValue[0] <
'0') || (strValue[0] >
'9')))
313 if (field == sfTransactionType)
315 ret = detail::make_stvar<STUInt16>(
322 name = &sfTransaction;
324 else if (field == sfLedgerEntryType)
326 ret = detail::make_stvar<STUInt16>(
333 name = &sfLedgerEntry;
343 ret = detail::make_stvar<STUInt16>(
345 beast::lexicalCastThrow<std::uint16_t>(strValue));
348 else if (value.
isInt())
350 ret = detail::make_stvar<STUInt16>(
351 field, to_unsigned<std::uint16_t>(value.
asInt()));
355 ret = detail::make_stvar<STUInt16>(
356 field, to_unsigned<std::uint16_t>(value.
asUInt()));
360 error =
bad_type(json_name, fieldName);
377 if (field == sfPermissionValue)
380 auto const granularPermission =
383 if (granularPermission)
385 ret = detail::make_stvar<STUInt32>(
386 field, *granularPermission);
393 ret = detail::make_stvar<STUInt32>(
401 ret = detail::make_stvar<STUInt32>(
403 beast::lexicalCastThrow<std::uint32_t>(
407 else if (value.
isInt())
409 ret = detail::make_stvar<STUInt32>(
410 field, to_unsigned<std::uint32_t>(value.
asInt()));
414 ret = detail::make_stvar<STUInt32>(
415 field, safe_cast<std::uint32_t>(value.
asUInt()));
419 error =
bad_type(json_name, fieldName);
440 bool const useBase10 =
446 str.data() + str.size(),
448 useBase10 ? 10 : 16);
450 if (ec !=
std::errc() || (p != str.data() + str.size()))
451 Throw<std::invalid_argument>(
"invalid data");
453 ret = detail::make_stvar<STUInt64>(field, val);
455 else if (value.
isInt())
457 ret = detail::make_stvar<STUInt64>(
458 field, to_unsigned<std::uint64_t>(value.
asInt()));
462 ret = detail::make_stvar<STUInt64>(
463 field, safe_cast<std::uint64_t>(value.
asUInt()));
467 error =
bad_type(json_name, fieldName);
482 error =
bad_type(json_name, fieldName);
499 ret = detail::make_stvar<STUInt128>(field, num);
506 error =
bad_type(json_name, fieldName);
523 ret = detail::make_stvar<STUInt192>(field, num);
530 error =
bad_type(json_name, fieldName);
547 ret = detail::make_stvar<STUInt160>(field, num);
554 error =
bad_type(json_name, fieldName);
571 ret = detail::make_stvar<STUInt256>(field, num);
578 error =
bad_type(json_name, fieldName);
586 ret = detail::make_stvar<STBlob>(
587 field, vBlob->data(), vBlob->size());
591 Throw<std::invalid_argument>(
"invalid data");
630 Throw<std::invalid_argument>(
"invalid data");
633 ret = detail::make_stvar<STVector256>(std::move(tail));
658 if (!value[i].isArrayOrNull())
661 ss << fieldName <<
"[" << i <<
"]";
669 ss << fieldName <<
"[" << i <<
"][" << j <<
"]";
671 json_name +
"." + ss.
str());
687 bool hasCurrency =
false;
694 if (!account.isString())
703 if (!uAccount.
parseHex(account.asString()))
706 parseBase58<AccountID>(account.asString());
753 parseBase58<AccountID>(issuer.
asString());
765 uAccount, uCurrency, uIssuer, hasCurrency);
770 ret = detail::make_stvar<STPathSet>(std::move(tail));
783 error =
bad_type(json_name, fieldName);
791 if (
AccountID account; account.parseHex(strValue))
792 return detail::make_stvar<STAccount>(field, account);
794 if (
auto result = parseBase58<AccountID>(strValue))
795 return detail::make_stvar<STAccount>(field, *result);
811 ret = detail::make_stvar<STIssue>(
issueFromJson(field, value));
820 case STI_XCHAIN_BRIDGE:
823 ret = detail::make_stvar<STXChainBridge>(
836 ret = detail::make_stvar<STCurrency>(
847 error =
bad_type(json_name, fieldName);
901 switch (field.fieldType)
905 case STI_TRANSACTION:
906 case STI_LEDGERENTRY:
917 json_name +
"." + fieldName,
924 data.emplace_back(std::move(*ret));
939 json_name +
"." + fieldName,
944 if (!array.has_value())
946 data.emplace_back(std::move(*array));
959 parseLeaf(json_name, fieldName, &inName, value, error);
964 data.emplace_back(std::move(*leaf));
972 data.applyTemplateFromSField(inName);
1005 return std::nullopt;
1014 bool const isObjectOrNull(json[i].isObjectOrNull());
1015 bool const singleKey(isObjectOrNull ? json[i].size() == 1 :
true);
1017 if (!isObjectOrNull || !singleKey)
1021 return std::nullopt;
1027 std::string const objectName(json[i].getMemberNames()[0]);
1034 return std::nullopt;
1037 Json::Value const objectFields(json[i][objectName]);
1040 ss << json_name <<
"." <<
"[" << i <<
"]." << objectName;
1043 ss.
str(), objectFields, nameField, depth + 1, error);
1046 std::string errMsg = error[
"error_message"].asString();
1047 error[
"error_message"] =
1048 "Error at '" + ss.
str() +
"'. " + errMsg;
1049 return std::nullopt;
1052 if (ret->getFName().fieldType != STI_OBJECT)
1054 ss <<
"Field type: " << ret->getFName().fieldType <<
" ";
1056 return std::nullopt;
1062 return detail::make_stvar<STArray>(std::move(tail));
1067 return std::nullopt;
1079 using namespace STParsedJSONDetail;
1089 using namespace STParsedJSONDetail;
1095 auto p =
dynamic_cast<STArray*
>(&arr->get());
1099 array = std::move(*p);
bool isObjectOrNull() const
Members getMemberNames() const
Return a list of the member names.
bool isValidIndex(UInt index) const
Return true if index < size().
std::string asString() const
Returns the unquoted string value.
bool isArrayOrNull() const
std::optional< std::uint32_t > getGranularValue(std::string const &name) const
static Permission const & getInstance()
std::string const & getName() const
static const SField & getField(int fieldCode)
void push_back(STObject const &object)
std::optional< STArray > array
The STArray if the parse was successful.
Json::Value error
On failure, an appropriate set of error values.
STParsedJSONArray()=delete
Json::Value error
On failure, an appropriate set of error values.
STParsedJSONObject()=delete
void push_back(STPath const &e)
void emplace_back(Args &&... args)
void push_back(uint256 const &v)
Integers of any length that is a multiple of 32-bits.
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
static std::optional< detail::STVar > parseLeaf(std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
static Json::Value not_an_object(std::string const &object, std::string const &field)
static Json::Value bad_type(std::string const &object, std::string const &field)
constexpr std::enable_if_t< std::is_unsigned< U >::value &&std::is_signed< S >::value, U > to_unsigned(S value)
static const int maxDepth
static std::optional< detail::STVar > parseArray(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
static Json::Value array_expected(std::string const &object, std::string const &field)
static Json::Value singleton_expected(std::string const &object, unsigned int index)
static Json::Value not_an_array(std::string const &object)
static Json::Value invalid_data(std::string const &object, std::string const &field)
static Json::Value non_object_in_array(std::string const &item, Json::UInt index)
static std::optional< STObject > parseObject(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
static Json::Value too_deep(std::string const &object)
static Json::Value unknown_field(std::string const &object, std::string const &field)
static Json::Value template_mismatch(SField const &sField)
static Json::Value out_of_range(std::string const &object, std::string const &field)
static Json::Value string_expected(std::string const &object, std::string const &field)
static std::string make_name(std::string const &object, std::string const &field)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
STCurrency currencyFromJson(SField const &name, Json::Value const &v)
STAmount amountFromJson(SField const &name, Json::Value const &v)
Issue issueFromJson(Json::Value const &v)
constexpr TERUnderlyingType TERtoInt(TELcodes v)
std::optional< TER > transCode(std::string const &token)
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.