소스 검색

refactor: rename Result -> ValidationResult, record visited props/items

Sam Jaffe 1 년 전
부모
커밋
242281f822

+ 1 - 1
include/jvalidate/constraint/constraint.h

@@ -24,6 +24,6 @@ public:
   Status accept(ConstraintVisitor const & visitor) const final { return visitor.visit(*this); }
 
   virtual Status validate(adapter::Adapter const & json, detail::Pointer const & where,
-                          Result * result) const = 0;
+                          ValidationResult * result) const = 0;
 };
 }

+ 1 - 1
include/jvalidate/forward.h

@@ -4,7 +4,7 @@
 #include <string>
 
 namespace jvalidate {
-class Result;
+class ValidationResult;
 class Schema;
 class Status;
 }

+ 0 - 11
include/jvalidate/result.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#include <jvalidate/forward.h>
-
-namespace jvalidate {
-class Result {
-public:
-  std::unordered_set<std::string> visited_properties;
-  std::unordered_set<size_t> visited_items;
-};
-}

+ 17 - 0
include/jvalidate/validation_result.h

@@ -0,0 +1,17 @@
+#pragma once
+
+#include <unordered_set>
+
+#include <jvalidate/forward.h>
+
+namespace jvalidate {
+class ValidationResult {
+public:
+  std::unordered_set<std::string> visited_properties;
+  std::unordered_set<size_t> visited_items;
+
+public:
+  void record(size_t item) { visited_items.insert(item); }
+  void record(std::string const & property) { visited_properties.insert(property); }
+};
+}

+ 26 - 23
include/jvalidate/validation_visitor.h

@@ -10,9 +10,9 @@
 #include <jvalidate/constraint/visitor.h>
 #include <jvalidate/detail/expect.h>
 #include <jvalidate/forward.h>
-#include <jvalidate/result.h>
 #include <jvalidate/schema.h>
 #include <jvalidate/status.h>
+#include <jvalidate/validation_result.h>
 
 #define NOOP_UNLESS_TYPE(etype)                                                                    \
   RETURN_UNLESS(document_.type() == adapter::Type::etype, Status::Noop)
@@ -24,12 +24,13 @@ private:
   A document_;
   detail::Pointer where_;
   schema::Node const & schema_;
-  Result * result_;
+  ValidationResult * result_;
+  ValidationResult * local_result_;
   std::unordered_map<std::string, RE> & regex_cache_;
 
 public:
   ValidationVisitor(A const & json, schema::Node const & schema,
-                    std::unordered_map<std::string, RE> & regex_cache, Result * result)
+                    std::unordered_map<std::string, RE> & regex_cache, ValidationResult * result)
       : ValidationVisitor(json, schema, {}, regex_cache, result) {}
 
   Status visit(constraint::TypeConstraint const & cons) const {
@@ -42,7 +43,7 @@ public:
 
   Status visit(constraint::EnumConstraint const & cons) const {
     for (auto const & option : cons.enumeration) {
-      // TODO(samjaffe) Strictness
+      // TODO(samjaffe): Strictness
       if (option->apply([this](auto const & frozen) { return document_.equals(frozen); })) {
         return Status::Accept;
       }
@@ -358,15 +359,15 @@ public:
   }
 
   Status visit(constraint::UnevaluatedItemsConstraint const & cons) const {
+    EXPECT_M(local_result_, "Invalid State - no result object for post-constraint");
     NOOP_UNLESS_TYPE(Array);
 
     Status rval = Status::Accept;
     auto array = document_.as_array();
     for (size_t i = 0; i < array.size(); ++i) {
-      if (not result_->visited_items.contains(i)) {
+      if (not local_result_->visited_items.contains(i)) {
         rval &= validate_subschema_on(cons.subschema, array[i], i);
       }
-      // TODO(samjaffe): Special Rule
       if (!rval && result_ == nullptr) {
         break;
       }
@@ -374,14 +375,14 @@ public:
   }
 
   Status visit(constraint::UnevaluatedPropertiesConstraint const & cons) const {
+    EXPECT_M(local_result_, "Invalid State - no result object for post-constraint");
     NOOP_UNLESS_TYPE(Object);
 
     Status rval = Status::Accept;
     for (auto const & [key, elem] : document_.as_object()) {
-      if (not result_->visited_properties.contains(key)) {
+      if (not local_result_->visited_properties.contains(key)) {
         rval &= validate_subschema_on(cons.subschema, elem, key);
       }
-      // TODO(samjaffe): Special Rule
       if (!rval && result_ == nullptr) {
         break;
       }
@@ -393,12 +394,13 @@ public:
       return Status::Reject;
     }
 
-    Status rval = Status::Noop;
-    if (schema_.requires_result_context()) {
+    ValidationResult local_result;
+    if (schema_.requires_result_context() && not local_result_) {
       // Ensure that we store results even if there aren't any...
-      // TODO(samjaffe) Implement this
+      local_result_ = &local_result;
     }
 
+    Status rval = Status::Noop;
     if (auto ref = schema_.reference_schema()) {
       rval = validate_subschema(*ref);
     }
@@ -420,25 +422,26 @@ public:
 
 private:
   ValidationVisitor(A const & json, detail::Pointer const & where, schema::Node const & schema,
-                    std::unordered_map<std::string, RE> & regex_cache, Result * result)
-      : document_(json), where_(where), schema_(schema), regex_cache_(regex_cache),
-        result_(result) {}
-
-  template <typename K> Status validate(A const & document, K const & key) const {
-    return validate_subschema_on(&schema_, document_, key);
-  }
+                    std::unordered_map<std::string, RE> & regex_cache, ValidationResult * result,
+                    ValidationResult * local_result = nullptr)
+      : document_(json), where_(where), schema_(schema), regex_cache_(regex_cache), result_(result),
+        local_result_(local_result ?: result_) {}
 
   Status validate_subschema(schema::Node const * subschema) const {
-    // TODO(samjaffe): Propagation for Unevaluated*Constraint
-    return CRTP(document_, *subschema, where_, regex_cache_, result_).validate();
+    return CRTP(document_, *subschema, where_, regex_cache_, result_, local_result_).validate();
   }
 
   template <typename K>
   Status validate_subschema_on(schema::Node const * subschema, A const & document,
                                K const & key) const {
-    Result next;
-    Result * pnext = result_ ? &next : nullptr;
-    return CRTP(document, *subschema, where_ / key, regex_cache_, pnext).validate();
+    ValidationResult next;
+    ValidationResult * pnext = result_ ? &next : nullptr;
+
+    auto status = CRTP(document, *subschema, where_ / key, regex_cache_, pnext).validate();
+    if (status != Status::Noop and local_result_) {
+      local_result_->record(key);
+    }
+    return status;
   }
 };
 }

+ 2 - 1
include/jvalidate/validator.h

@@ -29,7 +29,8 @@ private:
 public:
   ExtendedValidator(schema::Node const & schema) : schema_(schema) {}
 
-  template <Adapter A> Status validate(A const & json, Result const * result = nullptr) const {
+  template <Adapter A>
+  Status validate(A const & json, ValidationResult const * result = nullptr) const {
     return ValidationVisitor<A, RE>(json, schema_, regex_cache_, result).validate();
   }
 };