Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Modifiers.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/Types.hpp"
24#include "util/JsonUtils.hpp"
25
26#include <boost/json/value.hpp>
27#include <boost/json/value_to.hpp>
28#include <xrpl/protocol/ErrorCodes.h>
29
30#include <concepts>
31#include <exception>
32#include <functional>
33#include <string>
34#include <string_view>
35
36namespace rpc::modifiers {
37
41template <typename Type>
42class Clamp final {
43 Type min_;
44 Type max_;
45
46public:
53 explicit Clamp(Type min, Type max) : min_{min}, max_{max}
54 {
55 }
56
64 [[nodiscard]] MaybeError
65 modify(boost::json::value& value, std::string_view key) const
66 {
67 using boost::json::value_to;
68
69 if (not value.is_object() or not value.as_object().contains(key))
70 return {}; // ignore. field does not exist, let 'required' fail instead
71
72 // clamp to min_ and max_
73 auto const oldValue = value_to<Type>(value.as_object().at(key));
74 value.as_object()[key] = std::clamp<Type>(oldValue, min_, max_);
75
76 return {};
77 }
78};
79
85struct ToLower final {
93 [[nodiscard]] static MaybeError
94 modify(boost::json::value& value, std::string_view key)
95 {
96 if (not value.is_object() or not value.as_object().contains(key))
97 return {}; // ignore. field does not exist, let 'required' fail instead
98
99 if (not value.as_object().at(key).is_string())
100 return {}; // ignore for non-string types
101
102 value.as_object()[key] =
103 util::toLower(boost::json::value_to<std::string>(value.as_object().at(key)));
104 return {};
105 }
106};
107
113struct ToNumber final {
121 [[nodiscard]] static MaybeError
122 modify(boost::json::value& value, std::string_view key)
123 {
124 if (not value.is_object() or not value.as_object().contains(key))
125 return {}; // ignore. field does not exist, let 'required' fail instead
126
127 if (not value.as_object().at(key).is_string())
128 return {}; // ignore for non-string types
129
130 auto const strInt = boost::json::value_to<std::string>(value.as_object().at(key));
131 if (strInt.find('.') != std::string::npos)
132 return Error{Status{RippledError::rpcINVALID_PARAMS}}; // maybe a float
133
134 try {
135 value.as_object()[key] = std::stoi(strInt);
136 } catch (std::exception& e) {
137 return Error{Status{RippledError::rpcINVALID_PARAMS}};
138 }
139 return {};
140 }
141};
142
146class CustomModifier final {
147 std::function<MaybeError(boost::json::value&, std::string_view)> modifier_;
148
149public:
156 template <typename Fn>
157 requires std::invocable<Fn, boost::json::value&, std::string_view>
158 explicit CustomModifier(Fn&& fn) : modifier_{std::forward<Fn>(fn)}
159 {
160 }
161
170 [[nodiscard]] MaybeError
171 modify(boost::json::value& value, std::string_view key) const
172 {
173 if (not value.is_object() or not value.as_object().contains(key))
174 return {}; // ignore. field does not exist, let 'required' fail instead
175
176 return modifier_(value.as_object().at(key), key);
177 };
178};
179
180} // namespace rpc::modifiers
MaybeError modify(boost::json::value &value, std::string_view key) const
Clamp the value to stored min and max values.
Definition Modifiers.hpp:65
Clamp(Type min, Type max)
Construct the modifier storing min and max values.
Definition Modifiers.hpp:53
CustomModifier(Fn &&fn)
Constructs a custom modifier from any supported callable.
Definition Modifiers.hpp:158
MaybeError modify(boost::json::value &value, std::string_view key) const
Modify the JSON value according to the custom modifier function stored.
Definition Modifiers.hpp:171
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
std::string toLower(std::string str)
Convert a string to lowercase.
Definition JsonUtils.hpp:48
A status returned from any RPC handler.
Definition Errors.hpp:84
Convert input string to lower case.
Definition Modifiers.hpp:85
static MaybeError modify(boost::json::value &value, std::string_view key)
Update the input string to lower case.
Definition Modifiers.hpp:94
Convert input string to integer.
Definition Modifiers.hpp:113
static MaybeError modify(boost::json::value &value, std::string_view key)
Update the input string to integer if it can be converted to integer by stoi.
Definition Modifiers.hpp:122