mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
refactor: Simplify STParsedJSON with some helper functions (#5591)
- Add code coverage for STParsedJSON edge cases Co-authored-by: Denis Angell <dangell@transia.co>
This commit is contained in:
@@ -202,6 +202,175 @@ non_object_in_array(std::string const& item, Json::UInt index)
|
||||
" is not an object. Arrays may only contain objects.");
|
||||
}
|
||||
|
||||
template <class STResult, class Integer>
|
||||
static std::optional<detail::STVar>
|
||||
parseUnsigned(
|
||||
SField const& field,
|
||||
std::string const& json_name,
|
||||
std::string const& fieldName,
|
||||
SField const* name,
|
||||
Json::Value const& value,
|
||||
Json::Value& error)
|
||||
{
|
||||
std::optional<detail::STVar> ret;
|
||||
|
||||
try
|
||||
{
|
||||
if (value.isString())
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
safe_cast<typename STResult::value_type>(
|
||||
beast::lexicalCastThrow<Integer>(value.asString())));
|
||||
}
|
||||
else if (value.isInt())
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
to_unsigned<typename STResult::value_type>(value.asInt()));
|
||||
}
|
||||
else if (value.isUInt())
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
to_unsigned<typename STResult::value_type>(value.asUInt()));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = bad_type(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class STResult, class Integer = std::uint16_t>
|
||||
static std::optional<detail::STVar>
|
||||
parseUint16(
|
||||
SField const& field,
|
||||
std::string const& json_name,
|
||||
std::string const& fieldName,
|
||||
SField const* name,
|
||||
Json::Value const& value,
|
||||
Json::Value& error)
|
||||
{
|
||||
std::optional<detail::STVar> ret;
|
||||
|
||||
try
|
||||
{
|
||||
if (value.isString())
|
||||
{
|
||||
std::string const strValue = value.asString();
|
||||
|
||||
if (!strValue.empty() &&
|
||||
((strValue[0] < '0') || (strValue[0] > '9')))
|
||||
{
|
||||
if (field == sfTransactionType)
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
safe_cast<typename STResult::value_type>(
|
||||
static_cast<Integer>(
|
||||
TxFormats::getInstance().findTypeByName(
|
||||
strValue))));
|
||||
|
||||
if (*name == sfGeneric)
|
||||
name = &sfTransaction;
|
||||
}
|
||||
else if (field == sfLedgerEntryType)
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
safe_cast<typename STResult::value_type>(
|
||||
static_cast<Integer>(
|
||||
LedgerFormats::getInstance().findTypeByName(
|
||||
strValue))));
|
||||
|
||||
if (*name == sfGeneric)
|
||||
name = &sfLedgerEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
return parseUnsigned<STResult, Integer>(
|
||||
field, json_name, fieldName, name, value, error);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class STResult, class Integer = std::uint32_t>
|
||||
static std::optional<detail::STVar>
|
||||
parseUint32(
|
||||
SField const& field,
|
||||
std::string const& json_name,
|
||||
std::string const& fieldName,
|
||||
SField const* name,
|
||||
Json::Value const& value,
|
||||
Json::Value& error)
|
||||
{
|
||||
std::optional<detail::STVar> ret;
|
||||
|
||||
try
|
||||
{
|
||||
if (value.isString())
|
||||
{
|
||||
if (field == sfPermissionValue)
|
||||
{
|
||||
std::string const strValue = value.asString();
|
||||
auto const granularPermission =
|
||||
Permission::getInstance().getGranularValue(strValue);
|
||||
if (granularPermission)
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field, *granularPermission);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& txType =
|
||||
TxFormats::getInstance().findTypeByName(strValue);
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
Permission::getInstance().txToPermissionType(txType));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = detail::make_stvar<STResult>(
|
||||
field,
|
||||
safe_cast<typename STResult::value_type>(
|
||||
beast::lexicalCastThrow<Integer>(value.asString())));
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
return parseUnsigned<STResult, Integer>(
|
||||
field, json_name, fieldName, name, value, error);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This function is used by parseObject to parse any JSON type that doesn't
|
||||
// recurse. Everything represented here is a leaf-type.
|
||||
static std::optional<detail::STVar>
|
||||
@@ -302,130 +471,18 @@ parseLeaf(
|
||||
break;
|
||||
|
||||
case STI_UINT16:
|
||||
try
|
||||
{
|
||||
if (value.isString())
|
||||
{
|
||||
std::string const strValue = value.asString();
|
||||
|
||||
if (!strValue.empty() &&
|
||||
((strValue[0] < '0') || (strValue[0] > '9')))
|
||||
{
|
||||
if (field == sfTransactionType)
|
||||
{
|
||||
ret = detail::make_stvar<STUInt16>(
|
||||
field,
|
||||
static_cast<std::uint16_t>(
|
||||
TxFormats::getInstance().findTypeByName(
|
||||
strValue)));
|
||||
|
||||
if (*name == sfGeneric)
|
||||
name = &sfTransaction;
|
||||
}
|
||||
else if (field == sfLedgerEntryType)
|
||||
{
|
||||
ret = detail::make_stvar<STUInt16>(
|
||||
field,
|
||||
static_cast<std::uint16_t>(
|
||||
LedgerFormats::getInstance().findTypeByName(
|
||||
strValue)));
|
||||
|
||||
if (*name == sfGeneric)
|
||||
name = &sfLedgerEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = detail::make_stvar<STUInt16>(
|
||||
field,
|
||||
beast::lexicalCastThrow<std::uint16_t>(strValue));
|
||||
}
|
||||
}
|
||||
else if (value.isInt())
|
||||
{
|
||||
ret = detail::make_stvar<STUInt16>(
|
||||
field, to_unsigned<std::uint16_t>(value.asInt()));
|
||||
}
|
||||
else if (value.isUInt())
|
||||
{
|
||||
ret = detail::make_stvar<STUInt16>(
|
||||
field, to_unsigned<std::uint16_t>(value.asUInt()));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = bad_type(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
ret = parseUint16<STUInt16>(
|
||||
field, json_name, fieldName, name, value, error);
|
||||
if (!ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STI_UINT32:
|
||||
try
|
||||
{
|
||||
if (value.isString())
|
||||
{
|
||||
if (field == sfPermissionValue)
|
||||
{
|
||||
std::string const strValue = value.asString();
|
||||
auto const granularPermission =
|
||||
Permission::getInstance().getGranularValue(
|
||||
strValue);
|
||||
if (granularPermission)
|
||||
{
|
||||
ret = detail::make_stvar<STUInt32>(
|
||||
field, *granularPermission);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& txType =
|
||||
TxFormats::getInstance().findTypeByName(
|
||||
strValue);
|
||||
ret = detail::make_stvar<STUInt32>(
|
||||
field,
|
||||
Permission::getInstance().txToPermissionType(
|
||||
txType));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = detail::make_stvar<STUInt32>(
|
||||
field,
|
||||
beast::lexicalCastThrow<std::uint32_t>(
|
||||
value.asString()));
|
||||
}
|
||||
}
|
||||
else if (value.isInt())
|
||||
{
|
||||
ret = detail::make_stvar<STUInt32>(
|
||||
field, to_unsigned<std::uint32_t>(value.asInt()));
|
||||
}
|
||||
else if (value.isUInt())
|
||||
{
|
||||
ret = detail::make_stvar<STUInt32>(
|
||||
field, safe_cast<std::uint32_t>(value.asUInt()));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = bad_type(json_name, fieldName);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
error = invalid_data(json_name, fieldName);
|
||||
ret = parseUint32<STUInt32>(
|
||||
field, json_name, fieldName, name, value, error);
|
||||
if (!ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user