Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Factories.hpp
1#pragma once
2
3#include "rpc/Errors.hpp"
4#include "rpc/common/Checkers.hpp"
5#include "rpc/common/Concepts.hpp"
6#include "rpc/common/Types.hpp"
7#include "util/UnsupportedType.hpp"
8
9#include <boost/json/array.hpp>
10#include <boost/json/value.hpp>
11
12#include <expected>
13#include <functional>
14#include <optional>
15#include <string>
16#include <utility>
17#include <vector>
18
19namespace rpc::impl {
20
21using FieldSpecProcessor = std::function<MaybeError(boost::json::value&)>;
22
23static FieldSpecProcessor const kEMPTY_FIELD_PROCESSOR = [](boost::json::value&) -> MaybeError {
24 return {};
25};
26
27template <SomeProcessor... Processors>
28[[nodiscard]] FieldSpecProcessor
29makeFieldProcessor(std::string const& key, Processors&&... procs)
30{
31 return [key, ... proc = std::forward<Processors>(procs)](boost::json::value& j) -> MaybeError {
32 std::optional<Status> firstFailure = std::nullopt;
33
34 // This expands in order of Requirements and stops evaluating after first failure which is
35 // stored in `firstFailure` and can be checked later on to see whether the verification
36 // failed as a whole or not.
37 (
38 [&j, &key, &firstFailure, req = &proc]() {
39 if (firstFailure)
40 return; // already failed earlier - skip
41
42 if constexpr (SomeRequirement<decltype(*req)>) {
43 if (auto const res = req->verify(j, key); not res)
44 firstFailure = res.error();
45 } else if constexpr (SomeModifier<decltype(*req)>) {
46 if (auto const res = req->modify(j, key); not res)
47 firstFailure = res.error();
48 } else {
49 static_assert(util::Unsupported<decltype(*req)>);
50 }
51 }(),
52 ...);
53
54 if (firstFailure)
55 return std::unexpected{std::move(firstFailure).value()};
56
57 return {};
58 };
59}
60
61using FieldChecker = std::function<check::Warnings(boost::json::value const&)>;
62
63static FieldChecker const kEMPTY_FIELD_CHECKER = [](boost::json::value const&) -> check::Warnings {
64 return {};
65};
66
67template <SomeCheck... Checks>
68[[nodiscard]] FieldChecker
69makeFieldChecker(std::string const& key, Checks&&... checks)
70{
71 return [key,
72 ... checks =
73 std::forward<Checks>(checks)](boost::json::value const& j) -> check::Warnings {
74 check::Warnings warnings;
75 // This expands in order of Checks and collects all warnings into a WarningsCollection
76 (
77 [&j, &key, &warnings, req = &checks]() {
78 if (auto res = req->check(j, key); res)
79 warnings.push_back(std::move(res).value());
80 }(),
81 ...);
82 return warnings;
83 };
84}
85
86} // namespace rpc::impl
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
static constexpr bool Unsupported
used for compile time checking of unsupported types
Definition UnsupportedType.hpp:7