Ver Fonte

refactor: pass around the ConstraintFactory instead of creating repeatedly

Sam Jaffe há 1 ano atrás
pai
commit
ea06076453

+ 1 - 0
include/jvalidate/forward.h

@@ -121,6 +121,7 @@ concept RegexEngine = std::constructible_from<std::string> && requires(R const r
 }
 
 namespace jvalidate {
+template <Adapter A> class ConstraintFactory;
 template <Adapter A, RegexEngine RE> class ValidationVisitor;
 
 class Validator;

+ 4 - 3
include/jvalidate/parser_context.h

@@ -15,15 +15,16 @@ template <Adapter A> struct ParserContext {
 
   schema::Version version;
   detail::Reference where = {};
+  ConstraintFactory<A> const & factory;
 
   ParserContext child(A const & child, std::string const & key) const {
-    return {root, child, schema.as_object(), version, where / key};
+    return {root, child, schema.as_object(), version, where / key, factory};
   }
   ParserContext child(A const & child, size_t index) const {
-    return {root, child, std::nullopt, version, where / index};
+    return {root, child, std::nullopt, version, where / index, factory};
   }
   ParserContext neighbor(std::string const & key) const {
-    return {root, (*parent)[key], parent, version, where.parent() / key};
+    return {root, (*parent)[key], parent, version, where.parent() / key, factory};
   }
 
   schema::Node const * resolve(std::string_view uri) const;

+ 8 - 7
include/jvalidate/schema.h

@@ -101,11 +101,14 @@ private:
   std::map<detail::Reference, schema::Node const *> alias_cache_;
 
 public:
-  explicit Schema(Adapter auto const & json) : Schema(json, schema_version(json)) {}
+  template <Adapter A>
+  explicit Schema(A const & json, ConstraintFactory<A> const & factory = {})
+      : Schema(json, schema_version(json), factory) {}
 
   template <Adapter A>
-  Schema(A const & json, schema::Version version)
-      : schema::Node(ParserContext<A>{.root = *this, .schema = json, .version = version}) {}
+  Schema(A const & json, schema::Version version, ConstraintFactory<A> const & factory = {})
+      : schema::Node(ParserContext<A>{
+            .root = *this, .schema = json, .version = version, .factory = factory}) {}
 
   template <typename JSON, typename... Args>
   explicit Schema(JSON const & json, Args &&... args)
@@ -220,12 +223,10 @@ template <Adapter A> Node::Node(ParserContext<A> context) {
     description_ = schema["description"].as_string();
   }
 
-  // TODO(samjaffe): Pass this around instead
-  ConstraintFactory<A> factory;
   for (auto [key, subschema] : schema) {
     // Using a constraint store allows overriding certain rules, or the creation
     // of user-defined extention vocabularies.
-    if (auto make_constraint = factory(key, context.version)) {
+    if (auto make_constraint = context.factory(key, context.version)) {
       EXPECT_M(not has_reference || context.version >= Version::Draft2019_09,
                "Cannot directly extend $ref schemas before Draft2019-09");
       // A constraint may return null if it is not applicable - but otherwise
@@ -234,7 +235,7 @@ template <Adapter A> Node::Node(ParserContext<A> context) {
       // Therefore, we parse it alongside parsing "maximum", and could return
       // nullptr when requesting a constraint pointer for "exclusiveMaximum".
       if (auto constraint = make_constraint(context.child(subschema, key))) {
-        auto & into = factory.is_post_constraint(key) ? post_constraints_ : constraints_;
+        auto & into = context.factory.is_post_constraint(key) ? post_constraints_ : constraints_;
         into.emplace(key, std::move(constraint));
       }
     }