Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
MetaProcessors.hpp
1#pragma once
2
3#include "rpc/Errors.hpp"
4#include "rpc/common/Concepts.hpp"
5#include "rpc/common/Specs.hpp"
6#include "rpc/common/Types.hpp"
7
8#include <boost/json/value.hpp>
9#include <fmt/format.h>
10
11#include <cstddef>
12#include <functional>
13#include <initializer_list>
14#include <optional>
15#include <string_view>
16#include <utility>
17#include <vector>
18
19namespace rpc::meta {
20
24class Section final {
25 std::vector<FieldSpec> specs_;
26
27public:
33 explicit Section(std::initializer_list<FieldSpec> specs) : specs_{specs}
34 {
35 }
36
45 [[nodiscard]] MaybeError
46 verify(boost::json::value& value, std::string_view key) const;
47};
48
53class ValidateArrayAt final {
54 std::size_t idx_;
55 std::vector<FieldSpec> specs_;
56
57public:
64 ValidateArrayAt(std::size_t idx, std::initializer_list<FieldSpec> specs)
65 : idx_{idx}, specs_{specs}
66 {
67 }
68
76 [[nodiscard]] MaybeError
77 verify(boost::json::value& value, std::string_view key) const;
78};
79
84template <typename Type>
85class IfType final {
86public:
91 template <SomeRequirement... Requirements>
92 explicit IfType(Requirements&&... requirements)
93 : processor_(
94 [... r = std::forward<Requirements>(
95 requirements
96 )](boost::json::value& j, std::string_view key) -> MaybeError {
97 std::optional<Status> firstFailure = std::nullopt;
98
99 // the check logic is the same as fieldspec
100 (
101 [&j, &key, &firstFailure, req = &r]() {
102 if (firstFailure)
103 return;
104
105 if (auto const res = req->verify(j, key); not res)
106 firstFailure = res.error();
107 }(),
108 ...);
109
110 if (firstFailure)
111 return Error{firstFailure.value()};
112
113 return {};
114 }
115 )
116 {
117 }
118
119 IfType(IfType const&) = default;
120 IfType(IfType&&) = default;
121
130 [[nodiscard]] MaybeError
131 verify(boost::json::value& value, std::string_view key) const
132 {
133 if (not value.is_object() or not value.as_object().contains(key))
134 return {}; // ignore. field does not exist, let 'required' fail instead
135
136 if (not rpc::validation::checkType<Type>(value.as_object().at(key)))
137 return {}; // ignore if type does not match
138
139 return processor_(value, key);
140 }
141
142private:
143 std::function<MaybeError(boost::json::value&, std::string_view)> processor_;
144};
145
150template <typename RequirementOrModifierType>
152class WithCustomError final {
153 RequirementOrModifierType reqOrModifier_;
154 Status error_;
155
156public:
164 WithCustomError(RequirementOrModifierType reqOrModifier, Status err)
165 : reqOrModifier_{std::move(reqOrModifier)}, error_{std::move(err)}
166 {
167 }
168
176 [[nodiscard]] MaybeError
177 verify(boost::json::value const& value, std::string_view key) const
179 {
180 if (auto const res = reqOrModifier_.verify(value, key); not res)
181 return Error{error_};
182
183 return {};
184 }
185
195 [[nodiscard]] MaybeError
196 verify(boost::json::value& value, std::string_view key) const
198 {
199 if (auto const res = reqOrModifier_.verify(value, key); not res)
200 return Error{error_};
201
202 return {};
203 }
204
214 modify(boost::json::value& value, std::string_view key) const
216
217 {
218 if (auto const res = reqOrModifier_.modify(value, key); not res)
219 return Error{error_};
220 return {};
221 }
222};
223
224} // namespace rpc::meta
A meta-processor that specifies a list of requirements to run against when the type matches the templ...
Definition MetaProcessors.hpp:85
IfType(Requirements &&... requirements)
Constructs a validator that validates the specs if the type matches.
Definition MetaProcessors.hpp:92
MaybeError verify(boost::json::value &value, std::string_view key) const
Verify that the element is valid according to the stored requirements when type matches.
Definition MetaProcessors.hpp:131
Section(std::initializer_list< FieldSpec > specs)
Construct new section validator from a list of specs.
Definition MetaProcessors.hpp:33
MaybeError verify(boost::json::value &value, std::string_view key) const
Verify that the JSON value representing the section is valid according to the given specs.
Definition MetaProcessors.cpp:13
MaybeError verify(boost::json::value &value, std::string_view key) const
Verify that the JSON array element at given index is valid according the stored specs.
Definition MetaProcessors.cpp:33
ValidateArrayAt(std::size_t idx, std::initializer_list< FieldSpec > specs)
Constructs a processor that validates the specified element of a JSON array.
Definition MetaProcessors.hpp:64
MaybeError verify(boost::json::value const &value, std::string_view key) const
Runs the stored validator and produces a custom error if the wrapped validator fails.
Definition MetaProcessors.hpp:177
MaybeError verify(boost::json::value &value, std::string_view key) const
Runs the stored validator and produces a custom error if the wrapped validator fails....
Definition MetaProcessors.hpp:196
WithCustomError(RequirementOrModifierType reqOrModifier, Status err)
Constructs a validator that calls the given validator req and returns a custom error err in case req ...
Definition MetaProcessors.hpp:164
MaybeError modify(boost::json::value &value, std::string_view key) const
Runs the stored modifier and produces a custom error if the wrapped modifier fails.
Definition MetaProcessors.hpp:214
Specifies what a modifier used with rpc::FieldSpec must provide.
Definition Concepts.hpp:31
Specifies what a requirement used with rpc::FieldSpec must provide.
Definition Concepts.hpp:23
std::expected< void, Status > MaybeError
Return type used for Validators that can return error but don't have specific value to return.
Definition Types.hpp:36
std::unexpected< Status > Error
The type that represents just the error part of MaybeError.
Definition Types.hpp:56
A status returned from any RPC handler.
Definition Errors.hpp:65