| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- #pragma once
- #include <map>
- #include <ostream>
- #include <unordered_set>
- #include <vector>
- #include <jvalidate/forward.h>
- namespace jvalidate {
- class ValidationResult {
- public:
- struct Errors {
- std::string constraint;
- std::string message;
- std::map<std::string, ValidationResult> properties;
- std::map<size_t, ValidationResult> items;
- };
- private:
- std::unordered_set<std::string> visited_properties_;
- std::unordered_set<size_t> visited_items_;
- std::string message_;
- std::vector<Errors> errors_;
- public:
- void constraint(std::string const & name) { errors_.push_back({name}); }
- void message(std::string const & message) {
- (errors_.empty() ? message_ : errors_.back().message) = message;
- }
- void error(size_t item, ValidationResult && result) {
- errors_.back().items.emplace(item, std::move(result));
- visited_items_.emplace(item);
- }
- void error(std::string const & property, ValidationResult && result) {
- errors_.back().properties.emplace(property, std::move(result));
- visited_properties_.emplace(property);
- }
- void visit(size_t item) { visited_items_.emplace(item); }
- bool has_visited(size_t item) const { return visited_items_.contains(item); }
- void visit(std::string const & property) { visited_properties_.emplace(property); }
- bool has_visited(std::string const & property) const {
- return visited_properties_.contains(property);
- }
- friend std::ostream & operator<<(std::ostream & os, ValidationResult const & result) {
- result.print(os, 0);
- return os;
- }
- private:
- static void indent(std::ostream & os, int depth) {
- for (int i = 0; i < depth; ++i) {
- os << ' ' << ' ';
- }
- }
- void print(std::ostream & os, int depth) const {
- if (not message_.empty()) {
- indent(os, depth);
- os << message_ << "\n";
- }
- for (auto const & error : errors_) {
- if (error.items.empty() and error.properties.empty()) {
- continue;
- }
- indent(os, depth);
- os << "for constraint '" << error.constraint << "'";
- if (not error.message.empty()) {
- os << ": " << error.message;
- }
- os << "\n";
- for (auto const & [i, r] : error.items) {
- indent(os, depth + 1);
- os << "at " << i << ":\n";
- r.print(os, depth + 2);
- }
- for (auto const & [i, r] : error.properties) {
- indent(os, depth + 1);
- os << "at '" << i << "':\n";
- r.print(os, depth + 2);
- }
- }
- }
- };
- }
|