Skip to content

Commit af4fde9

Browse files
refactor: Clio Config (#1593)
Add constraint + parse json into Config Second part of refactoring Clio Config; First PR found [here](#1544) Steps that are left to implement: - Replacing all the places where we fetch config values (by using config.valueOr/MaybeValue) to instead get it from Config Definition - Generate markdown file using Clio Config Description
1 parent 0282504 commit af4fde9

26 files changed

+2056
-333
lines changed

src/util/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ target_sources(
2525
TimeUtils.cpp
2626
TxUtils.cpp
2727
LedgerUtils.cpp
28+
newconfig/Array.cpp
29+
newconfig/ArrayView.cpp
30+
newconfig/ConfigConstraints.cpp
2831
newconfig/ConfigDefinition.cpp
32+
newconfig/ConfigFileJson.cpp
2933
newconfig/ObjectView.cpp
30-
newconfig/ArrayView.cpp
3134
newconfig/ValueView.cpp
3235
)
3336

src/util/newconfig/Array.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//------------------------------------------------------------------------------
2+
/*
3+
This file is part of clio: https://github.com/XRPLF/clio
4+
Copyright (c) 2024, 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+
#include "util/newconfig/Array.hpp"
21+
22+
#include "util/Assert.hpp"
23+
#include "util/newconfig/ConfigValue.hpp"
24+
#include "util/newconfig/Error.hpp"
25+
#include "util/newconfig/Types.hpp"
26+
27+
#include <cstddef>
28+
#include <optional>
29+
#include <string_view>
30+
#include <utility>
31+
#include <vector>
32+
33+
namespace util::config {
34+
35+
Array::Array(ConfigValue arg) : itemPattern_{std::move(arg)}
36+
{
37+
}
38+
39+
std::optional<Error>
40+
Array::addValue(Value value, std::optional<std::string_view> key)
41+
{
42+
auto const& configValPattern = itemPattern_;
43+
auto const constraint = configValPattern.getConstraint();
44+
45+
auto newElem = constraint.has_value() ? ConfigValue{configValPattern.type()}.withConstraint(constraint->get())
46+
: ConfigValue{configValPattern.type()};
47+
if (auto const maybeError = newElem.setValue(value, key); maybeError.has_value())
48+
return maybeError;
49+
elements_.emplace_back(std::move(newElem));
50+
return std::nullopt;
51+
}
52+
53+
size_t
54+
Array::size() const
55+
{
56+
return elements_.size();
57+
}
58+
59+
ConfigValue const&
60+
Array::at(std::size_t idx) const
61+
{
62+
ASSERT(idx < elements_.size(), "Index is out of scope");
63+
return elements_[idx];
64+
}
65+
66+
ConfigValue const&
67+
Array::getArrayPattern() const
68+
{
69+
return itemPattern_;
70+
}
71+
72+
std::vector<ConfigValue>::const_iterator
73+
Array::begin() const
74+
{
75+
return elements_.begin();
76+
}
77+
78+
std::vector<ConfigValue>::const_iterator
79+
Array::end() const
80+
{
81+
return elements_.end();
82+
}
83+
84+
} // namespace util::config

src/util/newconfig/Array.hpp

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,58 +19,50 @@
1919

2020
#pragma once
2121

22-
#include "util/Assert.hpp"
2322
#include "util/newconfig/ConfigValue.hpp"
24-
#include "util/newconfig/ObjectView.hpp"
25-
#include "util/newconfig/ValueView.hpp"
23+
#include "util/newconfig/Error.hpp"
24+
#include "util/newconfig/Types.hpp"
2625

2726
#include <cstddef>
28-
#include <iterator>
29-
#include <type_traits>
30-
#include <utility>
27+
#include <optional>
28+
#include <string_view>
3129
#include <vector>
3230

3331
namespace util::config {
3432

3533
/**
36-
* @brief Array definition for Json/Yaml config
34+
* @brief Array definition to store multiple values provided by the user from Json/Yaml
3735
*
3836
* Used in ClioConfigDefinition to represent multiple potential values (like whitelist)
37+
* Is constructed with only 1 element which states which type/constraint must every element
38+
* In the array satisfy
3939
*/
4040
class Array {
4141
public:
4242
/**
43-
* @brief Constructs an Array with the provided arguments
43+
* @brief Constructs an Array with provided Arg
4444
*
45-
* @tparam Args Types of the arguments
46-
* @param args Arguments to initialize the elements of the Array
45+
* @param arg Argument to set the type and constraint of ConfigValues in Array
4746
*/
48-
template <typename... Args>
49-
constexpr Array(Args&&... args) : elements_{std::forward<Args>(args)...}
50-
{
51-
}
47+
Array(ConfigValue arg);
5248

5349
/**
5450
* @brief Add ConfigValues to Array class
5551
*
5652
* @param value The ConfigValue to add
53+
* @param key optional string key to include that will show in error message
54+
* @return optional error if adding config value to array fails. nullopt otherwise
5755
*/
58-
void
59-
emplaceBack(ConfigValue value)
60-
{
61-
elements_.push_back(std::move(value));
62-
}
56+
std::optional<Error>
57+
addValue(Value value, std::optional<std::string_view> key = std::nullopt);
6358

6459
/**
6560
* @brief Returns the number of values stored in the Array
6661
*
6762
* @return Number of values stored in the Array
6863
*/
6964
[[nodiscard]] size_t
70-
size() const
71-
{
72-
return elements_.size();
73-
}
65+
size() const;
7466

7567
/**
7668
* @brief Returns the ConfigValue at the specified index
@@ -79,13 +71,35 @@ class Array {
7971
* @return ConfigValue at the specified index
8072
*/
8173
[[nodiscard]] ConfigValue const&
82-
at(std::size_t idx) const
83-
{
84-
ASSERT(idx < elements_.size(), "index is out of scope");
85-
return elements_[idx];
86-
}
74+
at(std::size_t idx) const;
75+
76+
/**
77+
* @brief Returns the ConfigValue that defines the type/constraint every
78+
* ConfigValue must follow in Array
79+
*
80+
* @return The item_pattern
81+
*/
82+
[[nodiscard]] ConfigValue const&
83+
getArrayPattern() const;
84+
85+
/**
86+
* @brief Returns an iterator to the beginning of the ConfigValue vector.
87+
*
88+
* @return A constant iterator to the beginning of the vector.
89+
*/
90+
[[nodiscard]] std::vector<ConfigValue>::const_iterator
91+
begin() const;
92+
93+
/**
94+
* @brief Returns an iterator to the end of the ConfigValue vector.
95+
*
96+
* @return A constant iterator to the end of the vector.
97+
*/
98+
[[nodiscard]] std::vector<ConfigValue>::const_iterator
99+
end() const;
87100

88101
private:
102+
ConfigValue itemPattern_;
89103
std::vector<ConfigValue> elements_;
90104
};
91105

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//------------------------------------------------------------------------------
2+
/*
3+
This file is part of clio: https://github.com/XRPLF/clio
4+
Copyright (c) 2024, 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+
#include "util/newconfig/ConfigConstraints.hpp"
21+
22+
#include "util/newconfig/Error.hpp"
23+
#include "util/newconfig/Types.hpp"
24+
25+
#include <fmt/core.h>
26+
27+
#include <cstdint>
28+
#include <optional>
29+
#include <regex>
30+
#include <stdexcept>
31+
#include <string>
32+
#include <variant>
33+
34+
namespace util::config {
35+
36+
std::optional<Error>
37+
PortConstraint::checkTypeImpl(Value const& port) const
38+
{
39+
if (!(std::holds_alternative<int64_t>(port) || std::holds_alternative<std::string>(port)))
40+
return Error{"Port must be a string or integer"};
41+
return std::nullopt;
42+
}
43+
44+
std::optional<Error>
45+
PortConstraint::checkValueImpl(Value const& port) const
46+
{
47+
uint32_t p = 0;
48+
if (std::holds_alternative<std::string>(port)) {
49+
try {
50+
p = static_cast<uint32_t>(std::stoi(std::get<std::string>(port)));
51+
} catch (std::invalid_argument const& e) {
52+
return Error{"Port string must be an integer."};
53+
}
54+
} else {
55+
p = static_cast<uint32_t>(std::get<int64_t>(port));
56+
}
57+
if (p >= portMin && p <= portMax)
58+
return std::nullopt;
59+
return Error{"Port does not satisfy the constraint bounds"};
60+
}
61+
62+
std::optional<Error>
63+
ValidIPConstraint::checkTypeImpl(Value const& ip) const
64+
{
65+
if (!std::holds_alternative<std::string>(ip))
66+
return Error{"Ip value must be a string"};
67+
return std::nullopt;
68+
}
69+
70+
std::optional<Error>
71+
ValidIPConstraint::checkValueImpl(Value const& ip) const
72+
{
73+
if (std::get<std::string>(ip) == "localhost")
74+
return std::nullopt;
75+
76+
static std::regex const ipv4(
77+
R"(^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$)"
78+
);
79+
80+
static std::regex const ip_url(
81+
R"(^((http|https):\/\/)?((([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,6})|(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])))(:\d{1,5})?(\/[^\s]*)?$)"
82+
);
83+
if (std::regex_match(std::get<std::string>(ip), ipv4) || std::regex_match(std::get<std::string>(ip), ip_url))
84+
return std::nullopt;
85+
86+
return Error{"Ip is not a valid ip address"};
87+
}
88+
89+
std::optional<Error>
90+
PositiveDouble::checkTypeImpl(Value const& num) const
91+
{
92+
if (!(std::holds_alternative<double>(num) || std::holds_alternative<int64_t>(num)))
93+
return Error{"Double number must be of type int or double"};
94+
return std::nullopt;
95+
}
96+
97+
std::optional<Error>
98+
PositiveDouble::checkValueImpl(Value const& num) const
99+
{
100+
if (std::get<double>(num) >= 0)
101+
return std::nullopt;
102+
return Error{"Double number must be greater than 0"};
103+
}
104+
105+
} // namespace util::config

0 commit comments

Comments
 (0)