rippled
Loading...
Searching...
No Matches
json_get_or_throw.h
1#ifndef PROTOCOL_GET_OR_THROW_H_
2#define PROTOCOL_GET_OR_THROW_H_
3
4#include <xrpl/basics/Buffer.h>
5#include <xrpl/basics/StringUtilities.h>
6#include <xrpl/basics/contract.h>
7#include <xrpl/json/json_value.h>
8#include <xrpl/protocol/SField.h>
9
10#include <charconv>
11#include <exception>
12#include <optional>
13
14namespace Json {
16{
17 char const* const key;
20 {
21 }
22 char const*
23 what() const noexcept override
24 {
25 if (msg.empty())
26 {
27 msg = std::string("Missing json key: ") + key;
28 }
29 return msg.c_str();
30 }
31};
32
34{
35 char const* const key;
39 : key{k.c_str()}, expectedType{std::move(et)}
40 {
41 }
42 char const*
43 what() const noexcept override
44 {
45 if (msg.empty())
46 {
47 msg = std::string("Type mismatch on json key: ") + key +
48 "; expected type: " + expectedType;
49 }
50 return msg.c_str();
51 }
52};
53
54template <class T>
55T
56getOrThrow(Json::Value const& v, ripple::SField const& field)
57{
58 static_assert(sizeof(T) == -1, "This function must be specialized");
59}
60
61template <>
62inline std::string
63getOrThrow(Json::Value const& v, ripple::SField const& field)
64{
65 using namespace ripple;
66 Json::StaticString const& key = field.getJsonName();
67 if (!v.isMember(key))
68 Throw<JsonMissingKeyError>(key);
69
70 Json::Value const& inner = v[key];
71 if (!inner.isString())
72 Throw<JsonTypeMismatchError>(key, "string");
73 return inner.asString();
74}
75
76// Note, this allows integer numeric fields to act as bools
77template <>
78inline bool
79getOrThrow(Json::Value const& v, ripple::SField const& field)
80{
81 using namespace ripple;
82 Json::StaticString const& key = field.getJsonName();
83 if (!v.isMember(key))
84 Throw<JsonMissingKeyError>(key);
85 Json::Value const& inner = v[key];
86 if (inner.isBool())
87 return inner.asBool();
88 if (!inner.isIntegral())
89 Throw<JsonTypeMismatchError>(key, "bool");
90
91 return inner.asInt() != 0;
92}
93
94template <>
95inline std::uint64_t
96getOrThrow(Json::Value const& v, ripple::SField const& field)
97{
98 using namespace ripple;
99 Json::StaticString const& key = field.getJsonName();
100 if (!v.isMember(key))
101 Throw<JsonMissingKeyError>(key);
102 Json::Value const& inner = v[key];
103 if (inner.isUInt())
104 return inner.asUInt();
105 if (inner.isInt())
106 {
107 auto const r = inner.asInt();
108 if (r < 0)
109 Throw<JsonTypeMismatchError>(key, "uint64");
110 return r;
111 }
112 if (inner.isString())
113 {
114 auto const s = inner.asString();
115 // parse as hex
116 std::uint64_t val;
117
118 auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), val, 16);
119
120 if (ec != std::errc() || (p != s.data() + s.size()))
121 Throw<JsonTypeMismatchError>(key, "uint64");
122 return val;
123 }
124 Throw<JsonTypeMismatchError>(key, "uint64");
125}
126
127template <>
128inline ripple::Buffer
129getOrThrow(Json::Value const& v, ripple::SField const& field)
130{
131 using namespace ripple;
132 std::string const hex = getOrThrow<std::string>(v, field);
133 if (auto const r = strUnHex(hex))
134 {
135 // TODO: mismatch between a buffer and a blob
136 return Buffer{r->data(), r->size()};
137 }
138 Throw<JsonTypeMismatchError>(field.getJsonName(), "Buffer");
139}
140
141// This function may be used by external projects (like the witness server).
142template <class T>
145{
146 try
147 {
148 return getOrThrow<T>(v, field);
149 }
150 catch (...)
151 {
152 }
153 return {};
154}
155
156} // namespace Json
157
158#endif // PROTOCOL_GET_OR_THROW_H_
T c_str(T... args)
Lightweight wrapper to tag static string.
Definition json_value.h:44
Represents a JSON value.
Definition json_value.h:130
Int asInt() const
bool isString() const
UInt asUInt() const
std::string asString() const
Returns the unquoted string value.
bool isBool() const
bool isIntegral() const
bool asBool() const
bool isUInt() const
bool isMember(char const *key) const
Return true if the object has a member named key.
bool isInt() const
Like std::vector<char> but better.
Definition Buffer.h:17
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Buffer.h:132
Identifies fields.
Definition SField.h:127
T empty(T... args)
T from_chars(T... args)
JSON (JavaScript Object Notation).
Definition json_errors.h:6
ripple::AccountID getOrThrow(Json::Value const &v, ripple::SField const &field)
Definition AccountID.h:112
std::optional< T > getOptional(Json::Value const &v, ripple::SField const &field)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
STL namespace.
char const * what() const noexcept override
JsonMissingKeyError(Json::StaticString const &k)
char const * what() const noexcept override
JsonTypeMismatchError(Json::StaticString const &k, std::string et)