cppfig 0.1.0
Modern C++20 compile-time type-safe configuration library
Loading...
Searching...
No Matches
validator.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <functional>
5#include <string>
6#include <type_traits>
7#include <vector>
8
9namespace cppfig {
10
13 bool is_valid = true;
14 std::string error_message;
15
17 static auto Ok() -> ValidationResult { return { .is_valid = true, .error_message = "" }; }
18
20 static auto Error(std::string message) -> ValidationResult { return { .is_valid = false, .error_message = std::move(message) }; }
21
22 explicit operator bool() const { return is_valid; }
23};
24
26template <typename V, typename T>
27concept ValidatorFor = requires(const V& validator, const T& value) {
28 { validator(value) } -> std::same_as<ValidationResult>;
29};
30
32template <typename T>
33class Validator {
34public:
35 using validator_fn = std::function<ValidationResult(const T&)>;
36
39 : fn_([](const T&) { return ValidationResult::Ok(); })
40 {
41 }
42
45 : fn_(std::move(fn))
46 {
47 }
48
50 auto operator()(const T& value) const -> ValidationResult { return fn_(value); }
51
53 [[nodiscard]] auto And(Validator<T> other) const -> Validator<T>
54 {
55 auto this_fn = fn_;
56 auto other_fn = other.fn_;
57 return Validator<T>([this_fn, other_fn](const T& value) -> ValidationResult {
58 auto result = this_fn(value);
59 if (!result) {
60 return result;
61 }
62 return other_fn(value);
63 });
64 }
65
67 [[nodiscard]] auto Or(Validator<T> other) const -> Validator<T>
68 {
69 auto this_fn = fn_;
70 auto other_fn = other.fn_;
71 return Validator<T>([this_fn, other_fn](const T& value) -> ValidationResult {
72 auto result = this_fn(value);
73 if (result) {
74 return result;
75 }
76 return other_fn(value);
77 });
78 }
79
80private:
81 validator_fn fn_;
82};
83
85template <typename T>
86 requires std::is_arithmetic_v<T>
87auto Min(T min_value) -> Validator<T>
88{
89 return Validator<T>([min_value](const T& value) -> ValidationResult {
90 if (value < min_value) {
91 return ValidationResult::Error("Value " + std::to_string(value) + " is less than minimum " + std::to_string(min_value));
92 }
93 return ValidationResult::Ok();
94 });
95}
96
98template <typename T>
99 requires std::is_arithmetic_v<T>
100auto Max(T max_value) -> Validator<T>
101{
102 return Validator<T>([max_value](const T& value) -> ValidationResult {
103 if (value > max_value) {
104 return ValidationResult::Error("Value " + std::to_string(value) + " exceeds maximum " + std::to_string(max_value));
105 }
106 return ValidationResult::Ok();
107 });
108}
109
111template <typename T>
112 requires std::is_arithmetic_v<T>
113auto Range(T min_value, T max_value) -> Validator<T>
114{
115 return Min(min_value).And(Max(max_value));
116}
117
119template <typename T>
120 requires std::is_arithmetic_v<T>
122{
123 return Validator<T>([](const T& value) -> ValidationResult {
124 if (value <= T { 0 }) {
125 return ValidationResult::Error("Value must be positive");
126 }
127 return ValidationResult::Ok();
128 });
129}
130
132template <typename T>
133 requires std::is_arithmetic_v<T>
135{
136 return Validator<T>([](const T& value) -> ValidationResult {
137 if (value < T { 0 }) {
138 return ValidationResult::Error("Value must be non-negative");
139 }
140 return ValidationResult::Ok();
141 });
142}
143
146{
147 return Validator<std::string>([](const std::string& value) -> ValidationResult {
148 if (value.empty()) {
149 return ValidationResult::Error("Value must not be empty");
150 }
151 return ValidationResult::Ok();
152 });
153}
154
156inline auto MaxLength(std::size_t max_len) -> Validator<std::string>
157{
158 return Validator<std::string>([max_len](const std::string& value) -> ValidationResult {
159 if (value.size() > max_len) {
160 return ValidationResult::Error("String length " + std::to_string(value.size()) + " exceeds maximum " + std::to_string(max_len));
161 }
162 return ValidationResult::Ok();
163 });
164}
165
167inline auto MinLength(std::size_t min_len) -> Validator<std::string>
168{
169 return Validator<std::string>([min_len](const std::string& value) -> ValidationResult {
170 if (value.size() < min_len) {
171 return ValidationResult::Error("String length " + std::to_string(value.size()) + " is less than minimum " + std::to_string(min_len));
172 }
173 return ValidationResult::Ok();
174 });
175}
176
178template <typename T>
179auto OneOf(std::vector<T> allowed_values) -> Validator<T>
180{
181 return Validator<T>([allowed = std::move(allowed_values)](const T& value) -> ValidationResult {
182 for (const auto& allowed_value : allowed) {
183 if (value == allowed_value) {
184 return ValidationResult::Ok();
185 }
186 }
187 return ValidationResult::Error("Value is not in the list of allowed values");
188 });
189}
190
192template <typename T, typename Pred>
193 requires std::predicate<Pred, const T&>
194auto Predicate(Pred pred, std::string error_message) -> Validator<T>
195{
196 return Validator<T>([p = std::move(pred), msg = std::move(error_message)](const T& value) -> ValidationResult {
197 if (!p(value)) {
198 return ValidationResult::Error(msg);
199 }
200 return ValidationResult::Ok();
201 });
202}
203
205template <typename T>
207{
208 return Validator<T>();
209}
210
211} // namespace cppfig
Type-erased validator that can hold any validation function.
Definition validator.h:33
Validator()
Creates an always-valid validator.
Definition validator.h:38
auto And(Validator< T > other) const -> Validator< T >
Combines this validator with another (both must pass).
Definition validator.h:53
auto Or(Validator< T > other) const -> Validator< T >
Combines this validator with another (either must pass).
Definition validator.h:67
auto operator()(const T &value) const -> ValidationResult
Validates a value.
Definition validator.h:50
std::function< ValidationResult(const T &)> validator_fn
Definition validator.h:35
Validator(validator_fn fn)
Creates a validator from a function.
Definition validator.h:44
Concept for validator types.
Definition validator.h:27
C++20 compile-time type-safe configuration library.
Definition conf.h:13
auto Positive() -> Validator< T >
Creates a validator that checks if a numeric value is positive.
Definition validator.h:121
auto Predicate(Pred pred, std::string error_message) -> Validator< T >
Creates a validator from a predicate function.
Definition validator.h:194
auto Max(T max_value) -> Validator< T >
Creates a validator that checks if a numeric value is at most max.
Definition validator.h:100
auto MaxLength(std::size_t max_len) -> Validator< std::string >
Creates a validator that checks if a string length is at most max.
Definition validator.h:156
auto NonNegative() -> Validator< T >
Creates a validator that checks if a numeric value is non-negative.
Definition validator.h:134
auto MinLength(std::size_t min_len) -> Validator< std::string >
Creates a validator that checks if a string length is at least min.
Definition validator.h:167
auto Range(T min_value, T max_value) -> Validator< T >
Creates a validator that checks if a numeric value is within [min, max].
Definition validator.h:113
auto AlwaysValid() -> Validator< T >
Creates an always-valid validator.
Definition validator.h:206
auto Min(T min_value) -> Validator< T >
Creates a validator that checks if a numeric value is at least min.
Definition validator.h:87
auto OneOf(std::vector< T > allowed_values) -> Validator< T >
Creates a validator that checks if a value is one of the allowed values.
Definition validator.h:179
auto NotEmpty() -> Validator< std::string >
Creates a validator that checks if a string is not empty.
Definition validator.h:145
Result of a validation operation.
Definition validator.h:12
static auto Ok() -> ValidationResult
Creates a successful validation result.
Definition validator.h:17
static auto Error(std::string message) -> ValidationResult
Creates a failed validation result with an error message.
Definition validator.h:20
std::string error_message
Definition validator.h:14
bool is_valid
Definition validator.h:13