diff --git a/DEPENDENCIES b/DEPENDENCIES index 55c1b004..7291b73c 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,4 +1,4 @@ vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a4140267959ae334d3ecf4 noa https://github.com/sourcemeta/noa 5ff4024902642afc9cc2f9a9e02ae9dff9d15d4f -jsontoolkit https://github.com/sourcemeta/jsontoolkit 2775ccc05af7be64dd2532694bb17274185aeec1 +jsontoolkit https://github.com/sourcemeta/jsontoolkit 466493636bdc27725ad5b171141410ec072919bc hydra https://github.com/sourcemeta/hydra d5e0c314dae88b0bf2ac4eeff2c7395910e2c7e9 diff --git a/vendor/jsontoolkit/src/jsonschema/compile_describe.cc b/vendor/jsontoolkit/src/jsonschema/compile_describe.cc index d777ba9c..8b10c8fa 100644 --- a/vendor/jsontoolkit/src/jsonschema/compile_describe.cc +++ b/vendor/jsontoolkit/src/jsonschema/compile_describe.cc @@ -20,6 +20,19 @@ struct DescribeVisitor { auto operator()(const SchemaCompilerLogicalNot &) const -> std::string { return "The given schema is expected to not validate successfully"; } + auto + operator()(const SchemaCompilerInternalContainer &) const -> std::string { + return "Internal"; + } + auto + operator()(const SchemaCompilerInternalNoAnnotation &) const -> std::string { + return "The target was not annotated with the given value"; + } + auto + operator()(const SchemaCompilerInternalDefinesAll &) const -> std::string { + return "The target object is expected to define all of the given " + "properties"; + } auto operator()(const SchemaCompilerControlLabel &) const -> std::string { return "Mark the current position of the evaluation process for future " "jumps"; @@ -46,6 +59,11 @@ struct DescribeVisitor { auto operator()(const SchemaCompilerAssertionDefines &) const -> std::string { return "The target object is expected to define the given property"; } + auto + operator()(const SchemaCompilerAssertionDefinesAll &) const -> std::string { + return "The target object is expected to define all of the given " + "properties"; + } auto operator()(const SchemaCompilerAssertionType &) const -> std::string { return "The target document is expected to be of the given type"; } @@ -57,10 +75,6 @@ struct DescribeVisitor { "expression"; } auto - operator()(const SchemaCompilerAssertionNotContains &) const -> std::string { - return "The target array is expected to not contain the given value"; - } - auto operator()(const SchemaCompilerAssertionSizeGreater &) const -> std::string { return "The target size is expected to be greater than the given number"; } @@ -98,6 +112,10 @@ struct DescribeVisitor { operator()(const SchemaCompilerAssertionStringType &) const -> std::string { return "The target string is expected to match the given logical type"; } + auto + operator()(const SchemaCompilerAssertionEqualsAny &) const -> std::string { + return "The target document is expected to be one of the given values"; + } }; } // namespace diff --git a/vendor/jsontoolkit/src/jsonschema/compile_evaluate.cc b/vendor/jsontoolkit/src/jsonschema/compile_evaluate.cc index af0b0046..73be4604 100644 --- a/vendor/jsontoolkit/src/jsonschema/compile_evaluate.cc +++ b/vendor/jsontoolkit/src/jsonschema/compile_evaluate.cc @@ -200,6 +200,21 @@ auto evaluate_step( const auto &target{ context.resolve_target(assertion.target, instance)}; result = target.is_object() && target.defines(value); + } else if (std::holds_alternative(step)) { + const auto &assertion{std::get(step)}; + context.push(assertion); + EVALUATE_CONDITION_GUARD(assertion.condition, instance); + const auto &value{context.resolve_value(assertion.value, instance)}; + const auto &target{ + context.resolve_target(assertion.target, instance)}; + assert(target.is_object()); + result = true; + for (const auto &property : value) { + if (!target.defines(property)) { + result = false; + break; + } + } } else if (std::holds_alternative(step)) { const auto &assertion{std::get(step)}; context.push(assertion); @@ -225,14 +240,6 @@ auto evaluate_step( context.resolve_target(assertion.target, instance)}; assert(target.is_string()); result = std::regex_search(target.to_string(), value.first); - } else if (std::holds_alternative(step)) { - const auto &assertion{std::get(step)}; - context.push(assertion); - EVALUATE_CONDITION_GUARD(assertion.condition, instance); - const auto &value{context.resolve_value(assertion.value, instance)}; - const auto &target{ - context.resolve_target>(assertion.target, instance)}; - result = !target.contains(value); } else if (std::holds_alternative(step)) { const auto &assertion{std::get(step)}; context.push(assertion); @@ -259,6 +266,14 @@ auto evaluate_step( const auto &target{ context.resolve_target(assertion.target, instance)}; result = (target == value); + } else if (std::holds_alternative(step)) { + const auto &assertion{std::get(step)}; + context.push(assertion); + EVALUATE_CONDITION_GUARD(assertion.condition, instance); + const auto &value{context.resolve_value(assertion.value, instance)}; + const auto &target{ + context.resolve_target(assertion.target, instance)}; + result = value.contains(target); } else if (std::holds_alternative( step)) { const auto &assertion{std::get(step)}; @@ -412,6 +427,55 @@ auto evaluate_step( } } } + } else if (std::holds_alternative(step)) { + const auto &assertion{std::get(step)}; + context.push(assertion); + EVALUATE_CONDITION_GUARD(assertion.condition, instance); + const auto &value{context.resolve_value(assertion.value, instance)}; + const auto &target{ + context.resolve_target>(assertion.target, instance)}; + result = !target.contains(value); + + // We treat this step as transparent to the consumer + context.pop(); + return result; + } else if (std::holds_alternative(step)) { + const auto &container{std::get(step)}; + assert(std::holds_alternative(container.value)); + context.push(container); + EVALUATE_CONDITION_GUARD(container.condition, instance); + result = true; + for (const auto &child : container.children) { + if (!evaluate_step(child, instance, mode, callback, context)) { + result = false; + if (mode == SchemaCompilerEvaluationMode::Fast) { + break; + } + } + } + + // We treat this step as transparent to the consumer + context.pop(); + return result; + } else if (std::holds_alternative(step)) { + const auto &assertion{std::get(step)}; + context.push(assertion); + EVALUATE_CONDITION_GUARD(assertion.condition, instance); + const auto &value{context.resolve_value(assertion.value, instance)}; + const auto &target{ + context.resolve_target(assertion.target, instance)}; + assert(target.is_object()); + result = true; + for (const auto &property : value) { + if (!target.defines(property)) { + result = false; + break; + } + } + + // We treat this step as transparent to the consumer + context.pop(); + return result; } else if (std::holds_alternative(step)) { const auto &control{std::get(step)}; context.mark(control.id, control.children); @@ -488,21 +552,21 @@ auto evaluate_step( return result; } else if (std::holds_alternative(step)) { const auto &loop{std::get(step)}; - assert(std::holds_alternative(loop.value)); context.push(loop); EVALUATE_CONDITION_GUARD(loop.condition, instance); + const auto value{context.resolve_value(loop.value, instance)}; const auto &target{context.resolve_target(loop.target, instance)}; assert(target.is_object()); result = true; - for (const auto &[key, value] : target.as_object()) { - context.push(empty_pointer, {key}); + for (const auto &entry : target.as_object()) { + context.push(empty_pointer, {entry.first}); for (const auto &child : loop.children) { if (!evaluate_step(child, instance, mode, callback, context)) { result = false; if (mode == SchemaCompilerEvaluationMode::Fast) { context.pop(); // For efficiently breaking from the outer loop too - goto evaluate_step_end; + goto evaluate_loop_properties_end; } else { break; } @@ -511,6 +575,13 @@ auto evaluate_step( context.pop(); } + + evaluate_loop_properties_end: + // Setting the value to false means "don't report it" + if (!value) { + context.pop(); + return result; + } } else if (std::holds_alternative(step)) { const auto &loop{std::get(step)}; context.push(loop); diff --git a/vendor/jsontoolkit/src/jsonschema/compile_json.cc b/vendor/jsontoolkit/src/jsonschema/compile_json.cc index 6e59fc0c..d32397c4 100644 --- a/vendor/jsontoolkit/src/jsonschema/compile_json.cc +++ b/vendor/jsontoolkit/src/jsonschema/compile_json.cc @@ -49,6 +49,10 @@ auto value_to_json(const sourcemeta::jsontoolkit::SchemaCompilerStepValue result.assign("type", JSON{"json"}); result.assign("value", JSON{std::get(value)}); return result; + } else if constexpr (std::is_same_v) { + result.assign("type", JSON{"boolean"}); + result.assign("value", JSON{std::get(value)}); + return result; } else if constexpr (std::is_same_v) { result.assign("type", JSON{"regex"}); result.assign("value", JSON{std::get(value).second}); @@ -74,6 +78,24 @@ auto value_to_json(const sourcemeta::jsontoolkit::SchemaCompilerStepValue result.assign("type", JSON{"string"}); result.assign("value", JSON{std::get(value)}); return result; + } else if constexpr (std::is_same_v) { + result.assign("type", JSON{"strings"}); + JSON items{JSON::make_array()}; + for (const auto &item : std::get(value)) { + items.push_back(JSON{item}); + } + + result.assign("value", std::move(items)); + return result; + } else if constexpr (std::is_same_v) { + result.assign("type", JSON{"array"}); + JSON items{JSON::make_array()}; + for (const auto &item : std::get(value)) { + items.push_back(item); + } + + result.assign("value", std::move(items)); + return result; } else if constexpr (std::is_same_v) { result.assign("type", JSON{"unsigned-integer"}); result.assign("value", JSON{std::get(value)}); @@ -155,10 +177,10 @@ struct StepVisitor { HANDLE_STEP("assertion", "fail", SchemaCompilerAssertionFail) HANDLE_STEP("assertion", "defines", SchemaCompilerAssertionDefines) + HANDLE_STEP("assertion", "defines-all", SchemaCompilerAssertionDefinesAll) HANDLE_STEP("assertion", "type", SchemaCompilerAssertionType) HANDLE_STEP("assertion", "type-any", SchemaCompilerAssertionTypeAny) HANDLE_STEP("assertion", "regex", SchemaCompilerAssertionRegex) - HANDLE_STEP("assertion", "not-contains", SchemaCompilerAssertionNotContains) HANDLE_STEP("assertion", "size-greater", SchemaCompilerAssertionSizeGreater) HANDLE_STEP("assertion", "size-less", SchemaCompilerAssertionSizeLess) HANDLE_STEP("assertion", "equal", SchemaCompilerAssertionEqual) @@ -169,12 +191,16 @@ struct StepVisitor { HANDLE_STEP("assertion", "unique", SchemaCompilerAssertionUnique) HANDLE_STEP("assertion", "divisible", SchemaCompilerAssertionDivisible) HANDLE_STEP("assertion", "string-type", SchemaCompilerAssertionStringType) + HANDLE_STEP("assertion", "equals-any", SchemaCompilerAssertionEqualsAny) HANDLE_STEP("annotation", "public", SchemaCompilerAnnotationPublic) HANDLE_STEP("annotation", "private", SchemaCompilerAnnotationPrivate) HANDLE_STEP("logical", "or", SchemaCompilerLogicalOr) HANDLE_STEP("logical", "and", SchemaCompilerLogicalAnd) HANDLE_STEP("logical", "xor", SchemaCompilerLogicalXor) HANDLE_STEP("logical", "not", SchemaCompilerLogicalNot) + HANDLE_STEP("internal", "no-annotation", SchemaCompilerInternalNoAnnotation) + HANDLE_STEP("internal", "container", SchemaCompilerInternalContainer) + HANDLE_STEP("internal", "defines-all", SchemaCompilerInternalDefinesAll) HANDLE_STEP("loop", "properties", SchemaCompilerLoopProperties) HANDLE_STEP("loop", "items", SchemaCompilerLoopItems) HANDLE_STEP("control", "label", SchemaCompilerControlLabel) diff --git a/vendor/jsontoolkit/src/jsonschema/default_compiler_draft4.h b/vendor/jsontoolkit/src/jsonschema/default_compiler_draft4.h index c34d638a..43bfd4c6 100644 --- a/vendor/jsontoolkit/src/jsonschema/default_compiler_draft4.h +++ b/vendor/jsontoolkit/src/jsonschema/default_compiler_draft4.h @@ -30,11 +30,6 @@ auto compiler_draft4_core_ref(const SchemaCompilerContext &context) return {make(context, label, {})}; } - // TODO: Only create a wrapper "label" step if there is indeed recursion - // going on, which we can probably confirm through the framing results. - // Otherwise, if no recursion would actually happen, then fully unrolling - // the references would be more efficient. - // The idea to handle recursion is to expand the reference once, and when // doing so, create a "checkpoint" that we can jump back to in a subsequent // recursive reference. While unrolling the reference once may initially @@ -145,18 +140,16 @@ auto compiler_draft4_validation_required(const SchemaCompilerContext &context) assert(!context.value.empty()); if (context.value.size() > 1) { - SchemaCompilerTemplate children; - const auto subcontext{applicate(context)}; + std::set properties; for (const auto &property : context.value.as_array()) { assert(property.is_string()); - children.push_back(make( - subcontext, property.to_string(), {}, - SchemaCompilerTargetType::Instance)); + properties.emplace(property.to_string()); } - return {make( - context, SchemaCompilerValueNone{}, std::move(children), - type_condition(context, JSON::Type::Object))}; + return {make( + context, std::move(properties), + type_condition(context, JSON::Type::Object), + SchemaCompilerTargetType::Instance)}; } else { assert(context.value.front().is_string()); return {make( @@ -171,15 +164,17 @@ auto compiler_draft4_applicator_allof(const SchemaCompilerContext &context) assert(context.value.is_array()); assert(!context.value.empty()); - SchemaCompilerTemplate result; + SchemaCompilerTemplate children; for (std::uint64_t index = 0; index < context.value.size(); index++) { - for (auto &&step : - compile(context, {static_cast(index)})) { - result.push_back(std::move(step)); + for (auto &&step : compile(applicate(context), + {static_cast(index)})) { + children.push_back(std::move(step)); } } - return result; + return {make(context, SchemaCompilerValueNone{}, + std::move(children), + SchemaCompilerTemplate{})}; } auto compiler_draft4_applicator_anyof(const SchemaCompilerContext &context) @@ -190,7 +185,7 @@ auto compiler_draft4_applicator_anyof(const SchemaCompilerContext &context) const auto subcontext{applicate(context)}; SchemaCompilerTemplate disjunctors; for (std::uint64_t index = 0; index < context.value.size(); index++) { - disjunctors.push_back(make( + disjunctors.push_back(make( subcontext, SchemaCompilerValueNone{}, compile(subcontext, {static_cast(index)}), SchemaCompilerTemplate{})); @@ -209,7 +204,7 @@ auto compiler_draft4_applicator_oneof(const SchemaCompilerContext &context) const auto subcontext{applicate(context)}; SchemaCompilerTemplate disjunctors; for (std::uint64_t index = 0; index < context.value.size(); index++) { - disjunctors.push_back(make( + disjunctors.push_back(make( subcontext, SchemaCompilerValueNone{}, compile(subcontext, {static_cast(index)}), SchemaCompilerTemplate{})); @@ -236,7 +231,7 @@ auto compiler_draft4_applicator_properties(const SchemaCompilerContext &context) // as such don't exist in Draft 4, so emit a private annotation instead substeps.push_back(make( subcontext, JSON{key}, {}, SchemaCompilerTargetType::Instance)); - children.push_back(make( + children.push_back(make( subcontext, SchemaCompilerValueNone{}, std::move(substeps), // TODO: As an optimization, avoid this condition if the subschema // declares `required` and includes the given key @@ -284,10 +279,12 @@ auto compiler_draft4_applicator_patternproperties( // Loop over the instance properties children.push_back(make( - subcontext, SchemaCompilerValueNone{}, - {make(subcontext, SchemaCompilerValueNone{}, - std::move(substeps), - std::move(loop_condition))}, + subcontext, + // Treat this as an internal step + false, + {make( + subcontext, SchemaCompilerValueNone{}, std::move(substeps), + std::move(loop_condition))}, SchemaCompilerTemplate{})); } @@ -312,7 +309,7 @@ auto compiler_draft4_applicator_additionalproperties( // TODO: As an optimization, avoid this condition if the subschema does // not declare `properties` - make( + make( subcontext, SchemaCompilerTarget{SchemaCompilerTargetType::InstanceBasename, empty_pointer}, @@ -321,7 +318,7 @@ auto compiler_draft4_applicator_additionalproperties( // TODO: As an optimization, avoid this condition if the subschema does // not declare `patternProperties` - make( + make( subcontext, SchemaCompilerTarget{SchemaCompilerTargetType::InstanceBasename, empty_pointer}, @@ -329,7 +326,7 @@ auto compiler_draft4_applicator_additionalproperties( Pointer{"patternProperties"}), }; - SchemaCompilerTemplate wrapper{make( + SchemaCompilerTemplate wrapper{make( subcontext, SchemaCompilerValueNone{}, compile(subcontext, empty_pointer, empty_pointer), {make(subcontext, SchemaCompilerValueNone{}, @@ -337,7 +334,7 @@ auto compiler_draft4_applicator_additionalproperties( SchemaCompilerTemplate{})})}; return {make( - context, SchemaCompilerValueNone{}, {std::move(wrapper)}, + context, true, {std::move(wrapper)}, // TODO: As an optimization, avoid this condition if the subschema // declares `type` to `object` already @@ -427,7 +424,7 @@ auto compiler_draft4_applicator_items(const SchemaCompilerContext &context) for (auto iterator{array.cbegin()}; iterator != array.cend(); ++iterator) { const auto index{ static_cast(std::distance(array.cbegin(), iterator))}; - children.push_back(make( + children.push_back(make( subcontext, SchemaCompilerValueNone{}, compile(subcontext, {index}, {index}), @@ -479,7 +476,7 @@ auto compiler_draft4_applicator_dependencies( for (const auto &entry : context.value.as_object()) { if (entry.second.is_object()) { - children.push_back(make( + children.push_back(make( subcontext, SchemaCompilerValueNone{}, compile(subcontext, {entry.first}, empty_pointer), @@ -489,22 +486,19 @@ auto compiler_draft4_applicator_dependencies( subcontext, entry.first, {}, SchemaCompilerTargetType::Instance)})); } else if (entry.second.is_array()) { - SchemaCompilerTemplate substeps; - for (const auto &key : entry.second.as_array()) { - assert(key.is_string()); - substeps.push_back(make( - subcontext, key.to_string(), {}, - SchemaCompilerTargetType::Instance)); + std::set properties; + for (const auto &property : entry.second.as_array()) { + assert(property.is_string()); + properties.emplace(property.to_string()); } - children.push_back(make( - subcontext, SchemaCompilerValueNone{}, std::move(substeps), - + children.push_back(make( + subcontext, std::move(properties), // TODO: As an optimization, avoid this condition if the subschema // declares `required` and includes the given key {make( - subcontext, entry.first, {}, - SchemaCompilerTargetType::Instance)})); + subcontext, entry.first, {}, SchemaCompilerTargetType::Instance)}, + SchemaCompilerTargetType::Instance)); } } @@ -523,17 +517,14 @@ auto compiler_draft4_validation_enum(const SchemaCompilerContext &context) SchemaCompilerTargetType::Instance)}; } - // TODO: Create a higher level "contains" step - SchemaCompilerTemplate children; - const auto subcontext{applicate(context)}; - for (const auto &choice : context.value.as_array()) { - children.push_back(make( - subcontext, choice, {}, SchemaCompilerTargetType::Instance)); + std::set options; + for (const auto &option : context.value.as_array()) { + options.insert(option); } - return {make(context, SchemaCompilerValueNone{}, - std::move(children), - SchemaCompilerTemplate{})}; + return {make( + context, std::move(options), SchemaCompilerTemplate{}, + SchemaCompilerTargetType::Instance)}; } auto compiler_draft4_validation_uniqueitems( diff --git a/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h b/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h index 5d874332..bbf4a14f 100644 --- a/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h +++ b/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h @@ -56,10 +56,18 @@ struct SchemaCompilerValueNone {}; /// Represents a compiler step JSON value using SchemaCompilerValueJSON = JSON; +/// @ingroup jsonschema +/// Represents a set of JSON values +using SchemaCompilerValueArray = std::set; + /// @ingroup jsonschema /// Represents a compiler step string value using SchemaCompilerValueString = JSON::String; +/// @ingroup jsonschema +/// Represents a compiler step string values +using SchemaCompilerValueStrings = std::set; + /// @ingroup jsonschema /// Represents a compiler step JSON type value using SchemaCompilerValueType = JSON::Type; @@ -79,6 +87,10 @@ using SchemaCompilerValueRegex = std::pair; /// Represents a compiler step JSON unsigned integer value using SchemaCompilerValueUnsignedInteger = std::size_t; +/// @ingroup jsonschema +/// Represents a compiler step boolean value +using SchemaCompilerValueBoolean = bool; + /// @ingroup jsonschema /// Represents a compiler step a string logical type enum class SchemaCompilerValueStringType { URI }; @@ -97,6 +109,11 @@ struct SchemaCompilerAssertionFail; /// given property struct SchemaCompilerAssertionDefines; +/// @ingroup jsonschema +/// Represents a compiler assertion step that checks if an object defines a +/// set of properties +struct SchemaCompilerAssertionDefinesAll; + /// @ingroup jsonschema /// Represents a compiler assertion step that checks if a document is of the /// given type @@ -112,11 +129,6 @@ struct SchemaCompilerAssertionTypeAny; /// regular expression struct SchemaCompilerAssertionRegex; -/// @ingroup jsonschema -/// Represents a compiler assertion step that checks a given set does not -/// contain a JSON value -struct SchemaCompilerAssertionNotContains; - /// @ingroup jsonschema /// Represents a compiler assertion step that checks a given array, object, or /// string has at least a certain number of items, properties, or characters, @@ -134,6 +146,11 @@ struct SchemaCompilerAssertionSizeLess; /// JSON document struct SchemaCompilerAssertionEqual; +/// @ingroup jsonschema +/// Represents a compiler assertion step that checks that a JSON document is +/// equal to at least one of the given elements +struct SchemaCompilerAssertionEqualsAny; + /// @ingroup jsonschema /// Represents a compiler assertion step that checks a JSON document is greater /// than or equal to another JSON document @@ -193,6 +210,20 @@ struct SchemaCompilerLogicalXor; /// Represents a compiler logical step that represents a negation struct SchemaCompilerLogicalNot; +/// @ingroup jsonschema +/// Represents a hidden compiler assertion step that checks a certain +/// annotation was not produced +struct SchemaCompilerInternalNoAnnotation; + +/// @ingroup jsonschema +/// Represents a hidden conjunction compiler step +struct SchemaCompilerInternalContainer; + +/// @ingroup jsonschema +/// Represents a hidden compiler assertion step that checks if an object defines +/// a set of properties +struct SchemaCompilerInternalDefinesAll; + /// @ingroup jsonschema /// Represents a compiler step that loops over object properties struct SchemaCompilerLoopProperties; @@ -215,18 +246,20 @@ struct SchemaCompilerControlJump; /// Represents a schema compilation step that can be evaluated using SchemaCompilerTemplate = std::vector>; + SchemaCompilerAssertionEqual, SchemaCompilerAssertionEqualsAny, + SchemaCompilerAssertionGreaterEqual, SchemaCompilerAssertionLessEqual, + SchemaCompilerAssertionGreater, SchemaCompilerAssertionLess, + SchemaCompilerAssertionUnique, SchemaCompilerAssertionDivisible, + SchemaCompilerAssertionStringType, SchemaCompilerAnnotationPublic, + SchemaCompilerAnnotationPrivate, SchemaCompilerLogicalOr, + SchemaCompilerLogicalAnd, SchemaCompilerLogicalXor, + SchemaCompilerLogicalNot, SchemaCompilerInternalNoAnnotation, + SchemaCompilerInternalContainer, SchemaCompilerInternalDefinesAll, + SchemaCompilerLoopProperties, SchemaCompilerLoopItems, + SchemaCompilerControlLabel, SchemaCompilerControlJump>>; #if !defined(DOXYGEN) #define DEFINE_STEP_WITH_VALUE(category, name, type) \ @@ -261,14 +294,15 @@ using SchemaCompilerTemplate = std::vector