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/format.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
64 [[nodiscard]] MaybeError
65 verify(boost::json::value& value, std::string_view key) const;
66};
67
72class ValidateArrayAt final {
73 std::size_t idx_;
74 std::vector<FieldSpec> specs_;
75
76public:
83 ValidateArrayAt(std::size_t idx, std::initializer_list<FieldSpec> specs)
84 : idx_{idx}, specs_{specs}
85 {
86 }
87
95 [[nodiscard]] MaybeError
96 verify(boost::json::value& value, std::string_view key) const;
97};
98
103template <typename Type>
104class IfType final {
105public:
110 template <SomeRequirement... Requirements>
111 explicit IfType(Requirements&&... requirements)
112 : processor_(
113 [... r = std::forward<Requirements>(
114 requirements
115 )](boost::json::value& j, std::string_view key) -> MaybeError {
116 std::optional<Status> firstFailure = std::nullopt;
117
118 // the check logic is the same as fieldspec
119 (
120 [&j, &key, &firstFailure, req = &r]() {
121 if (firstFailure)
122 return;
123
124 if (auto const res = req->verify(j, key); not res)
125 firstFailure = res.error();
126 }(),
127 ...
128 );
129
130 if (firstFailure)
131 return Error{firstFailure.value()};
132
133 return {};
134 }
135 )
136 {
137 }
138
139 IfType(IfType const&) = default;
140 IfType(IfType&&) = default;
141
150 [[nodiscard]] MaybeError
151 verify(boost::json::value& value, std::string_view key) const
152 {
153 if (not value.is_object() or not value.as_object().contains(key))
154 return {}; // ignore. field does not exist, let 'required' fail instead
155
156 if (not rpc::validation::checkType<Type>(value.as_object().at(key)))
157 return {}; // ignore if type does not match
158
159 return processor_(value, key);
160 }
161
162private:
163 std::function<MaybeError(boost::json::value&, std::string_view)> processor_;
164};
165
170template <typename RequirementOrModifierType>
172class WithCustomError final {
173 RequirementOrModifierType reqOrModifier_;
174 Status error_;
175
176public:
184 WithCustomError(RequirementOrModifierType reqOrModifier, Status err)
185 : reqOrModifier_{std::move(reqOrModifier)}, error_{std::move(err)}
186 {
187 }
188
196 [[nodiscard]] MaybeError
197 verify(boost::json::value const& value, std::string_view key) const
199 {
200 if (auto const res = reqOrModifier_.verify(value, key); not res)
201 return Error{error_};
202
203 return {};
204 }
205
215 [[nodiscard]] MaybeError
216 verify(boost::json::value& value, std::string_view key) const
218 {
219 if (auto const res = reqOrModifier_.verify(value, key); not res)
220 return Error{error_};
221
222 return {};
223 }
224
234 modify(boost::json::value& value, std::string_view key) const
236
237 {
238 if (auto const res = reqOrModifier_.modify(value, key); not res)
239 return Error{error_};
240 return {};
241 }
242};
243
244} // namespace rpc::meta
A meta-processor that specifies a list of requirements to run against when the type matches the templ...
Definition MetaProcessors.hpp:104
IfType(Requirements &&... requirements)
Constructs a validator that validates the specs if the type matches.
Definition MetaProcessors.hpp:111
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:151
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
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:83
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:197
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:216
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:184
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:234
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:84