6#include <toml++/toml.hpp>
59 if constexpr (std::is_same_v<T, int> || std::is_same_v<T, int64_t>) {
61 }
else if constexpr (std::is_same_v<T, size_t>) {
62 return "nonnegative integer";
63 }
else if constexpr (std::is_same_v<T, double> || std::is_same_v<T, float>) {
65 }
else if constexpr (std::is_same_v<T, std::string>) {
67 }
else if constexpr (std::is_same_v<T, bool>) {
70 return "unknown type";
80 : std::runtime_error(
"Validation error for field '" +
field +
"': " + message) {}
109 const toml::table& config;
111 std::optional<T> greater_than;
112 std::optional<T> greater_than_equal;
113 std::optional<T> less_than;
116 Validator(
const toml::table& config_,
const std::string& key_) : config(config_), key(key_) {}
125 greater_than = greater_than_;
136 greater_than_equal = greater_than_equal_;
147 less_than = less_than_;
162 std::optional<T> extractValue() {
164 if (!config.contains(key)) {
169 auto val = config[key].template value<T>();
172 throw ValidationError(key,
"wrong type (expected " + getTypeName<T>() +
")");
178 T validateValue(T result) {
179 if (greater_than && result <= *greater_than) {
180 std::ostringstream oss;
181 oss <<
"must be > " << *greater_than <<
", got " << result;
182 throw ValidationError(key, oss.str());
185 if (greater_than_equal && result < *greater_than_equal) {
186 std::ostringstream oss;
187 oss <<
"must be >= " << *greater_than_equal <<
", got " << result;
188 throw ValidationError(key, oss.str());
191 if (less_than && result >= *less_than) {
192 std::ostringstream oss;
193 oss <<
"must be < " << *less_than <<
", got " << result;
194 throw ValidationError(key, oss.str());
211 auto val = extractValue();
217 return validateValue(*val);
231 auto val = extractValue();
232 if (!val)
return default_value_;
234 return validateValue(*val);
266 const toml::table& config;
268 std::optional<size_t> min_length;
269 std::optional<size_t> exact_length;
270 bool is_positive =
false;
273 VectorValidator(
const toml::table& config_,
const std::string& key_) : config(config_), key(key_) {}
282 min_length = min_len_;
303 exact_length = exact_len_;
308 std::optional<std::vector<T>> extractVector() {
310 if (!config.contains(key)) {
315 auto* arr = config[key].as_array();
318 throw ValidationError(key,
"wrong type (expected array)");
322 std::vector<T> result;
323 for (
size_t i = 0; i < arr->size(); ++i) {
324 auto val = arr->at(i).template value<T>();
326 std::ostringstream oss;
327 oss <<
"element [" << i <<
"] wrong type (expected " << getTypeName<T>() <<
")";
328 throw ValidationError(key, oss.str());
330 result.push_back(*val);
336 std::vector<T> validateVector(std::vector<T> result) {
337 if (exact_length && result.size() != *exact_length) {
338 std::ostringstream oss;
339 oss <<
"must have exactly " << *exact_length <<
" elements, got " << result.size();
340 throw ValidationError(key, oss.str());
343 if (min_length && result.size() < *min_length) {
344 std::ostringstream oss;
345 oss <<
"must have at least " << *min_length <<
" elements, got " << result.size();
346 throw ValidationError(key, oss.str());
349 for (
size_t i = 0; i < result.size(); ++i) {
350 T& element = result[i];
352 if (is_positive && element <= T{0}) {
353 std::ostringstream oss;
354 oss <<
"element [" << i <<
"] must be positive, got " << element;
355 throw ValidationError(key, oss.str());
370 auto val = extractVector();
376 return validateVector(*val);
386 std::vector<T>
valueOr(
const std::vector<T>& default_value_) {
387 auto val = extractVector();
388 if (!val)
return default_value_;
390 return validateVector(*val);
436template <
typename T,
typename NodeType>
437std::optional<T>
getOptional(
const toml::node_view<NodeType>& node) {
438 return node.template value<T>();
453template <
typename T,
typename NodeType>
455 auto* arr = node.as_array();
456 if (!arr)
return std::nullopt;
458 std::vector<T> result;
459 for (
size_t i = 0; i < arr->size(); ++i) {
460 auto val = arr->at(i).template value<T>();
461 if (!val)
return std::nullopt;
462 result.push_back(*val);
478inline const toml::table&
getRequiredTable(
const toml::table& config,
const std::string& key) {
479 if (!config.contains(key)) {
483 auto* table = config[key].as_table();
506std::vector<T>
scalarOrVector(
const toml::table& config,
const std::string& key,
size_t expected_size) {
507 if (!config.contains(key)) {
511 if (
auto* arr = config[key].as_array()) {
513 if (arr->size() != expected_size) {
514 std::ostringstream oss;
515 oss <<
"array must have exactly " << expected_size <<
" elements, got " << arr->size();
518 std::vector<T> result;
519 for (
size_t i = 0; i < arr->size(); ++i) {
520 auto val = arr->at(i).template value<T>();
522 std::ostringstream oss;
523 oss <<
"element [" << i <<
"] wrong type (expected " << getTypeName<T>() <<
")";
526 result.push_back(*val);
531 if (
auto val = config[key].
template value<T>()) {
533 return std::vector<T>(expected_size, *val);
536 throw ValidationError(key,
"must be either a scalar value or an array of " + getTypeName<T>());
553std::vector<T>
scalarOrVectorOr(
const toml::table& config,
const std::string& key,
size_t expected_size,
const std::vector<T>& default_value) {
554 if (!config.contains(key)) {
555 return default_value;
557 return scalarOrVector<T>(config, key, expected_size);
Exception thrown when configuration validation fails.
Definition config_validators.hpp:77
ValidationError(const std::string &field, const std::string &message)
Definition config_validators.hpp:79
Chainable validator for scalar TOML fields.
Definition config_validators.hpp:107
Validator & greaterThan(T greater_than_)
Requires value to be strictly greater than threshold.
Definition config_validators.hpp:124
Validator & lessThan(T less_than_)
Requires value to be strictly less than threshold.
Definition config_validators.hpp:146
Validator & positive()
Requires value to be strictly positive (> 0).
Definition config_validators.hpp:156
T value()
Extracts and validates the field value.
Definition config_validators.hpp:210
Validator(const toml::table &config_, const std::string &key_)
Definition config_validators.hpp:116
Validator & greaterThanEqual(T greater_than_equal_)
Requires value to be greater than or equal to threshold.
Definition config_validators.hpp:135
T valueOr(T default_value_)
Extracts field value or returns default if missing.
Definition config_validators.hpp:230
Chainable validator for vector TOML fields.
Definition config_validators.hpp:264
VectorValidator & positive()
Requires all vector elements to be strictly positive (> 0).
Definition config_validators.hpp:291
std::vector< T > value()
Extracts and validates the vector field.
Definition config_validators.hpp:369
VectorValidator & hasLength(size_t exact_len_)
Requires vector to have exactly the specified length.
Definition config_validators.hpp:302
VectorValidator & minLength(size_t min_len_)
Requires minimum vector length.
Definition config_validators.hpp:281
std::vector< T > valueOr(const std::vector< T > &default_value_)
Extracts vector or returns default if missing.
Definition config_validators.hpp:386
VectorValidator(const toml::table &config_, const std::string &key_)
Definition config_validators.hpp:273
Validation utilities for TOML configuration parsing.
Definition config_validators.hpp:52
std::string getTypeName()
Helper to get readable type names for error messages.
Definition config_validators.hpp:58
VectorValidator< T > vectorField(const toml::table &config_, const std::string &key_)
Creates a vector field validator.
Definition config_validators.hpp:420
std::vector< T > scalarOrVectorOr(const toml::table &config, const std::string &key, size_t expected_size, const std::vector< T > &default_value)
Parses an optional field that can be either a scalar or an exact-size array.
Definition config_validators.hpp:553
const toml::table & getRequiredTable(const toml::table &config, const std::string &key)
Extracts a required table from a TOML configuration.
Definition config_validators.hpp:478
std::vector< T > scalarOrVector(const toml::table &config, const std::string &key, size_t expected_size)
Parses a field that can be either a scalar (applied to all) or an exact-size array.
Definition config_validators.hpp:506
std::optional< std::vector< T > > getOptionalVector(const toml::node_view< NodeType > &node)
Extracts an optional vector from a TOML node.
Definition config_validators.hpp:454
Validator< T > field(const toml::table &config_, const std::string &key_)
Creates a scalar field validator.
Definition config_validators.hpp:405
std::optional< T > getOptional(const toml::node_view< NodeType > &node)
Extracts an optional scalar value from a TOML node.
Definition config_validators.hpp:437