Porytiles
Loading...
Searching...
No Matches
config_validators.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <functional>
5#include <string>
6#include <vector>
7
8#include "fmt/format.h"
9
12
13namespace porytiles2 {
14
15/*
16 * Regular (single-value) validators
17 */
18
30[[nodiscard]] inline ChainableResult<ConfigValue<std::size_t>>
32{
33 if (val == 0) {
34 std::vector<std::string> err_text{};
35 std::vector<std::vector<FormatParam>> params{};
36
37 err_text.emplace_back("'{}' must be greater than '{}'");
38 params.emplace_back(std::vector{FormatParam{val.name(), Style::bold}, FormatParam{"0", Style::bold}});
39 err_text.emplace_back("");
40 params.emplace_back();
41
42 auto [format_text, format_params] = val.format_data();
43 std::ranges::copy(format_text, std::back_inserter(err_text));
44 std::ranges::copy(format_params, std::back_inserter(params));
45 return FormattableError{err_text, params};
46 }
47 return val;
48}
49
50/*
51 * Cross-field validators
52 * These validators can access other config values for validation
53 */
54
55namespace details {
56
79template <typename T, typename ConfigInterface, typename FetchFunc, typename Comparator>
81 const ConfigValue<T> &val,
82 const ConfigInterface &config,
83 const std::string &scope_param,
84 const std::string &other_field_name,
85 FetchFunc fetch_other,
86 Comparator comp,
87 std::string_view error_message)
88{
89 auto other_result = fetch_other(config, scope_param);
90
91 // If fetching the other value failed, propagate that error
92 if (!other_result.has_value()) {
93 return other_result.error();
94 }
95
96 const auto &other_val = other_result.value();
97
98 // Perform the comparison
99 if (!comp(val.value(), other_val.value())) {
100 std::vector<std::string> err_text{};
101 std::vector<std::vector<FormatParam>> params{};
102
103 err_text.emplace_back("'{}' {} '{}'");
104 params.emplace_back(
105 std::vector{
107 FormatParam{std::string{error_message}, Style::none},
108 FormatParam{other_field_name, Style::bold}});
109 err_text.emplace_back("");
110 params.emplace_back();
111
112 auto [format_text, format_params] = val.format_data();
113 std::ranges::copy(format_text, std::back_inserter(err_text));
114 std::ranges::copy(format_params, std::back_inserter(params));
115
116 err_text.emplace_back("");
117 params.emplace_back();
118 err_text.emplace_back("{}");
119 params.emplace_back(std::vector{FormatParam{"Comparison value:", Style::italic}});
120 err_text.emplace_back("");
121 params.emplace_back();
122
123 auto [other_format_text, other_format_params] = other_val.format_data();
124 std::ranges::copy(other_format_text, std::back_inserter(err_text));
125 std::ranges::copy(other_format_params, std::back_inserter(params));
126
127 return FormattableError{err_text, params};
128 }
129
130 return val;
131}
132
133} // namespace details
134
153template <typename T, typename ConfigInterface, typename FetchFunc>
155 const ConfigValue<T> &val,
156 const ConfigInterface &config,
157 const std::string &scope_param,
158 const std::string &other_field_name,
159 FetchFunc fetch_other)
160{
162 val, config, scope_param, other_field_name, fetch_other, std::greater<>{}, "must be greater than");
163}
164
178template <typename T, typename ConfigInterface, typename FetchFunc>
180 const ConfigValue<T> &val,
181 const ConfigInterface &config,
182 const std::string &scope_param,
183 const std::string &other_field_name,
184 FetchFunc fetch_other)
185{
187 val, config, scope_param, other_field_name, fetch_other, std::less<>{}, "must be less than");
188}
189
203template <typename T, typename ConfigInterface, typename FetchFunc>
205 const ConfigValue<T> &val,
206 const ConfigInterface &config,
207 const std::string &scope_param,
208 const std::string &other_field_name,
209 FetchFunc fetch_other)
210{
212 val,
213 config,
214 scope_param,
215 other_field_name,
216 fetch_other,
217 std::greater_equal<>{},
218 "must be greater than or equal to");
219}
220
234template <typename T, typename ConfigInterface, typename FetchFunc>
236 const ConfigValue<T> &val,
237 const ConfigInterface &config,
238 const std::string &scope_param,
239 const std::string &other_field_name,
240 FetchFunc fetch_other)
241{
243 val, config, scope_param, other_field_name, fetch_other, std::less_equal<>{}, "must be less than or equal to");
244}
245
259template <typename T, typename ConfigInterface, typename FetchFunc>
261 const ConfigValue<T> &val,
262 const ConfigInterface &config,
263 const std::string &scope_param,
264 const std::string &other_field_name,
265 FetchFunc fetch_other)
266{
268 val, config, scope_param, other_field_name, fetch_other, std::equal_to<>{}, "must be equal to");
269}
270
284template <typename T, typename ConfigInterface, typename FetchFunc>
286 const ConfigValue<T> &val,
287 const ConfigInterface &config,
288 const std::string &scope_param,
289 const std::string &other_field_name,
290 FetchFunc fetch_other)
291{
293 val, config, scope_param, other_field_name, fetch_other, std::not_equal_to<>{}, "must not be equal to");
294}
295
296} // namespace porytiles2
A result type that maintains a chainable sequence of errors for debugging and error reporting.
A container that wraps a configuration value with its name and source information.
const T & value() const &
Gets a const reference to the underlying value.
std::pair< std::vector< std::string >, std::vector< std::vector< FormatParam > > > format_data() const
Generates formatted text data for displaying this configuration value.
const std::string & name() const
Gets the name of this configuration value.
A text parameter with associated styling for formatted output.
General-purpose error implementation with formatted message support.
Definition error.hpp:117
ChainableResult< ConfigValue< T > > compare_values(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other, Comparator comp, std::string_view error_message)
Generic comparison validator that compares the current value against another config value.
ChainableResult< ConfigValue< T > > compare_equal(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other)
Validates that the current value is equal to another config value.
ChainableResult< ConfigValue< T > > compare_greater_than(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other)
Validates that the current value is greater than another config value.
@ italic
Italic text formatting.
@ none
No styling applied.
@ bold
Bold text formatting.
ChainableResult< ConfigValue< T > > compare_less_equal(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other)
Validates that the current value is less than or equal to another config value.
ChainableResult< ConfigValue< T > > compare_greater_equal(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other)
Validates that the current value is greater than or equal to another config value.
ChainableResult< ConfigValue< std::size_t > > size_t_val_greater_than_zero(const ConfigValue< std::size_t > &val)
Validates that a size_t config value is greater than zero.
ChainableResult< ConfigValue< T > > compare_less_than(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other)
Validates that the current value is less than another config value.
ChainableResult< ConfigValue< T > > compare_not_equal(const ConfigValue< T > &val, const ConfigInterface &config, const std::string &scope_param, const std::string &other_field_name, FetchFunc fetch_other)
Validates that the current value is not equal to another config value.