Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
MetaProcessors.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2023, the clio developers.
5
6 Permission to use, copy, modify, and distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#pragma once
21
22#include "rpc/Errors.hpp"
23#include "rpc/common/Concepts.hpp"
24#include "rpc/common/Specs.hpp"
25#include "rpc/common/Types.hpp"
26
27#include <boost/json/value.hpp>
28#include <fmt/core.h>
29
30#include <cstddef>
31#include <functional>
32#include <initializer_list>
33#include <optional>
34#include <string_view>
35#include <utility>
36#include <vector>
37
38namespace rpc::meta {
39
43class Section final {
44 std::vector<FieldSpec> specs_;
45
46public:
52 explicit Section(std::initializer_list<FieldSpec> specs) : specs_{specs}
53 {
54 }
55
63 [[nodiscard]] MaybeError
64 verify(boost::json::value& value, std::string_view key) const;
65};
66
70class ValidateArrayAt final {
71 std::size_t idx_;
72 std::vector<FieldSpec> specs_;
73
74public:
81 ValidateArrayAt(std::size_t idx, std::initializer_list<FieldSpec> specs) : idx_{idx}, specs_{specs}
82 {
83 }
84
92 [[nodiscard]] MaybeError
93 verify(boost::json::value& value, std::string_view key) const;
94};
95
100template <typename Type>
101class IfType final {
102public:
107 template <SomeRequirement... Requirements>
108 explicit IfType(Requirements&&... requirements)
109 : processor_(
110 [... r = std::forward<Requirements>(requirements
111 )](boost::json::value& j, std::string_view key) -> MaybeError {
112 std::optional<Status> firstFailure = std::nullopt;
113
114 // the check logic is the same as fieldspec
115 (
116 [&j, &key, &firstFailure, req = &r]() {
117 if (firstFailure)
118 return;
119
120 if (auto const res = req->verify(j, key); not res)
121 firstFailure = res.error();
122 }(),
123 ...
124 );
125
126 if (firstFailure)
127 return Error{firstFailure.value()};
128
129 return {};
130 }
131 )
132 {
133 }
134
135 IfType(IfType const&) = default;
136 IfType(IfType&&) = default;
137
145 [[nodiscard]] MaybeError
146 verify(boost::json::value& value, std::string_view key) const
147 {
148 if (not value.is_object() or not value.as_object().contains(key))
149 return {}; // ignore. field does not exist, let 'required' fail instead
150
151 if (not rpc::validation::checkType<Type>(value.as_object().at(key)))
152 return {}; // ignore if type does not match
153
154 return processor_(value, key);
155 }
156
157private:
158 std::function<MaybeError(boost::json::value&, std::string_view)> processor_;
159};
160
164template <typename RequirementOrModifierType>
166class WithCustomError final {
167 RequirementOrModifierType reqOrModifier_;
168 Status error_;
169
170public:
178 WithCustomError(RequirementOrModifierType reqOrModifier, Status err)
179 : reqOrModifier_{std::move(reqOrModifier)}, error_{std::move(err)}
180 {
181 }
182
190 [[nodiscard]] MaybeError
191 verify(boost::json::value const& value, std::string_view key) const
193 {
194 if (auto const res = reqOrModifier_.verify(value, key); not res)
195 return Error{error_};
196
197 return {};
198 }
199
208 [[nodiscard]] MaybeError
209 verify(boost::json::value& value, std::string_view key) const
211 {
212 if (auto const res = reqOrModifier_.verify(value, key); not res)
213 return Error{error_};
214
215 return {};
216 }
217
226 modify(boost::json::value& value, std::string_view key) const
228
229 {
230 if (auto const res = reqOrModifier_.modify(value, key); not res)
231 return Error{error_};
232 return {};
233 }
234};
235
236} // namespace rpc::meta
A meta-processor that specifies a list of requirements to run against when the type matches the templ...
Definition MetaProcessors.hpp:101
IfType(Requirements &&... requirements)
Constructs a validator that validates the specs if the type matches.
Definition MetaProcessors.hpp:108
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:146
A meta-processor that acts as a spec for a sub-object/section.
Definition MetaProcessors.hpp:43
Section(std::initializer_list< FieldSpec > specs)
Construct new section validator from a list of specs.
Definition MetaProcessors.hpp:52
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:32
A meta-processor that specifies a list of specs to run against the object at the given index in the a...
Definition MetaProcessors.hpp:70
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:52
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:81
A meta-processor that wraps a validator and produces a custom error in case the wrapped validator fai...
Definition MetaProcessors.hpp:166
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:191
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:209
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:178
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:226
Specifies what a modifier used with rpc::FieldSpec must provide.
Definition Concepts.hpp:50
Specifies what a requirement used with rpc::FieldSpec must provide.
Definition Concepts.hpp:42
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:55
std::unexpected< Status > Error
The type that represents just the error part of MaybeError.
Definition Types.hpp:75
A status returned from any RPC handler.
Definition Errors.hpp:82