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