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] = util::toLower(boost::json::value_to<std::string>(value.as_object().at(key)));
103 return {};
104 }
105};
106
112struct ToNumber final {
120 [[nodiscard]] static MaybeError
121 modify(boost::json::value& value, std::string_view key)
122 {
123 if (not value.is_object() or not value.as_object().contains(key))
124 return {}; // ignore. field does not exist, let 'required' fail instead
125
126 if (not value.as_object().at(key).is_string())
127 return {}; // ignore for non-string types
128
129 auto const strInt = boost::json::value_to<std::string>(value.as_object().at(key));
130 if (strInt.find('.') != std::string::npos)
131 return Error{Status{RippledError::rpcINVALID_PARAMS}}; // maybe a float
132
133 try {
134 value.as_object()[key] = std::stoi(strInt);
135 } catch (std::exception& e) {
136 return Error{Status{RippledError::rpcINVALID_PARAMS}};
137 }
138 return {};
139 }
140};
141
145class CustomModifier final {
146 std::function<MaybeError(boost::json::value&, std::string_view)> modifier_;
147
148public:
155 template <typename Fn>
156 requires std::invocable<Fn, boost::json::value&, std::string_view>
157 explicit CustomModifier(Fn&& fn) : modifier_{std::forward<Fn>(fn)}
158 {
159 }
160
168 [[nodiscard]] MaybeError
169 modify(boost::json::value& value, std::string_view key) const
170 {
171 if (not value.is_object() or not value.as_object().contains(key))
172 return {}; // ignore. field does not exist, let 'required' fail instead
173
174 return modifier_(value.as_object().at(key), key);
175 };
176};
177
178} // namespace rpc::modifiers
Clamp value between min and max.
Definition Modifiers.hpp:42
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
Customised modifier allowing user define how to modify input in provided callable.
Definition Modifiers.hpp:145
CustomModifier(Fn &&fn)
Constructs a custom modifier from any supported callable.
Definition Modifiers.hpp:157
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:169
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:41
A status returned from any RPC handler.
Definition Errors.hpp:82
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:112
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:121