From ff6e845bbd48a0ac91c28cb532e0894db43eb17c Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 2 Sep 2024 19:18:19 -0400 Subject: [PATCH] Remove the idea of explicit conditions in the compiler Signed-off-by: Juan Cruz Viotti --- src/jsonschema/compile.cc | 5 +- src/jsonschema/compile_describe.cc | 162 +++-- src/jsonschema/compile_evaluate.cc | 97 ++- src/jsonschema/compile_helpers.h | 36 +- src/jsonschema/compile_json.cc | 21 +- src/jsonschema/default_compiler_2019_09.h | 31 +- src/jsonschema/default_compiler_2020_12.h | 2 +- src/jsonschema/default_compiler_draft4.h | 221 +++--- src/jsonschema/default_compiler_draft6.h | 60 +- src/jsonschema/default_compiler_draft7.h | 9 +- .../jsontoolkit/jsonschema_compile.h | 67 +- .../jsonschema_compile_draft4_test.cc | 66 +- .../jsonschema_compile_draft6_test.cc | 20 +- .../jsonschema_compile_evaluate_test.cc | 653 +++--------------- .../jsonschema_compile_json_test.cc | 532 ++------------ .../jsonschema_template_format_test.cc | 4 +- 16 files changed, 527 insertions(+), 1459 deletions(-) diff --git a/src/jsonschema/compile.cc b/src/jsonschema/compile.cc index d032e519c..cfc8b2180 100644 --- a/src/jsonschema/compile.cc +++ b/src/jsonschema/compile.cc @@ -28,7 +28,7 @@ auto compile_subschema( } else { return {make(true, context, schema_context, dynamic_context, - SchemaCompilerValueNone{}, {})}; + SchemaCompilerValueNone{})}; } } @@ -154,8 +154,7 @@ auto compile(const JSON &schema, const SchemaWalker &walker, true, context, nested_schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{label}, compile(context, nested_schema_context, relative_dynamic_context, - empty_pointer, empty_pointer, entry.first.second), - {})); + empty_pointer, empty_pointer, entry.first.second))); } } diff --git a/src/jsonschema/compile_describe.cc b/src/jsonschema/compile_describe.cc index eecd9eb12..33438e975 100644 --- a/src/jsonschema/compile_describe.cc +++ b/src/jsonschema/compile_describe.cc @@ -839,11 +839,11 @@ struct DescribeVisitor { return message.str(); } - auto operator()(const SchemaCompilerAssertionSizeGreater &step) const + auto operator()(const SchemaCompilerAssertionStringSizeLess &step) const -> std::string { - if (this->keyword == "minLength") { + if (this->keyword == "maxLength") { std::ostringstream message; - const auto minimum{step_value(step) + 1}; + const auto maximum{step_value(step) - 1}; if (is_within_keyword(this->evaluate_path, "propertyNames")) { assert(this->instance_location.back().is_property()); @@ -854,8 +854,8 @@ struct DescribeVisitor { stringify(this->target, message); } - message << " was expected to consist of at least " << minimum - << (minimum == 1 ? " character" : " characters"); + message << " was expected to consist of at most " << maximum + << (maximum == 1 ? " character" : " characters"); if (this->valid) { message << " and"; @@ -878,45 +878,63 @@ struct DescribeVisitor { return message.str(); } - if (this->keyword == "minItems") { - assert(this->target.is_array()); + return unknown(); + } + + auto operator()(const SchemaCompilerAssertionStringSizeGreater &step) const + -> std::string { + if (this->keyword == "minLength") { std::ostringstream message; const auto minimum{step_value(step) + 1}; - message << "The array value was expected to contain at least " << minimum; - assert(minimum > 0); - if (minimum == 1) { - message << " item"; + + if (is_within_keyword(this->evaluate_path, "propertyNames")) { + assert(this->instance_location.back().is_property()); + message << "The object property name " + << escape_string(this->instance_location.back().to_property()); } else { - message << " items"; + message << "The string value "; + stringify(this->target, message); } + message << " was expected to consist of at least " << minimum + << (minimum == 1 ? " character" : " characters"); + if (this->valid) { message << " and"; } else { message << " but"; } - message << " it contained " << this->target.size(); - if (this->target.size() == 1) { - message << " item"; + message << " it consisted of "; + + if (is_within_keyword(this->evaluate_path, "propertyNames")) { + message << this->instance_location.back().to_property().size(); + message << (this->instance_location.back().to_property().size() == 1 + ? " character" + : " characters"); } else { - message << " items"; + message << this->target.size(); + message << (this->target.size() == 1 ? " character" : " characters"); } return message.str(); } - if (this->keyword == "minProperties") { - assert(this->target.is_object()); + return unknown(); + } + + auto operator()(const SchemaCompilerAssertionArraySizeLess &step) const + -> std::string { + if (this->keyword == "maxItems") { + assert(this->target.is_array()); std::ostringstream message; - const auto minimum{step_value(step) + 1}; - message << "The object value was expected to contain at least " - << minimum; - assert(minimum > 0); - if (minimum == 1) { - message << " property"; + const auto maximum{step_value(step) - 1}; + message << "The array value was expected to contain at most " << maximum; + assert(maximum > 0); + if (maximum == 1) { + message << " item"; } else { - message << " properties"; + message << " items"; } if (this->valid) { @@ -927,18 +945,9 @@ struct DescribeVisitor { message << " it contained " << this->target.size(); if (this->target.size() == 1) { - message << " property: "; - message << escape_string(this->target.as_object().cbegin()->first); + message << " item"; } else { - message << " properties: "; - for (auto iterator = this->target.as_object().cbegin(); - iterator != this->target.as_object().cend(); ++iterator) { - if (std::next(iterator) == this->target.as_object().cend()) { - message << "and " << escape_string(iterator->first); - } else { - message << escape_string(iterator->first) << ", "; - } - } + message << " items"; } return message.str(); @@ -947,55 +956,51 @@ struct DescribeVisitor { return unknown(); } - auto - operator()(const SchemaCompilerAssertionSizeLess &step) const -> std::string { - if (this->keyword == "maxLength") { + auto operator()(const SchemaCompilerAssertionArraySizeGreater &step) const + -> std::string { + if (this->keyword == "minItems") { + assert(this->target.is_array()); std::ostringstream message; - const auto maximum{step_value(step) - 1}; - - if (is_within_keyword(this->evaluate_path, "propertyNames")) { - assert(this->instance_location.back().is_property()); - message << "The object property name " - << escape_string(this->instance_location.back().to_property()); + const auto minimum{step_value(step) + 1}; + message << "The array value was expected to contain at least " << minimum; + assert(minimum > 0); + if (minimum == 1) { + message << " item"; } else { - message << "The string value "; - stringify(this->target, message); + message << " items"; } - message << " was expected to consist of at most " << maximum - << (maximum == 1 ? " character" : " characters"); - if (this->valid) { message << " and"; } else { message << " but"; } - message << " it consisted of "; - - if (is_within_keyword(this->evaluate_path, "propertyNames")) { - message << this->instance_location.back().to_property().size(); - message << (this->instance_location.back().to_property().size() == 1 - ? " character" - : " characters"); + message << " it contained " << this->target.size(); + if (this->target.size() == 1) { + message << " item"; } else { - message << this->target.size(); - message << (this->target.size() == 1 ? " character" : " characters"); + message << " items"; } return message.str(); } - if (this->keyword == "maxItems") { - assert(this->target.is_array()); + return unknown(); + } + + auto operator()(const SchemaCompilerAssertionObjectSizeLess &step) const + -> std::string { + if (this->keyword == "maxProperties") { + assert(this->target.is_object()); std::ostringstream message; const auto maximum{step_value(step) - 1}; - message << "The array value was expected to contain at most " << maximum; + message << "The object value was expected to contain at most " << maximum; assert(maximum > 0); if (maximum == 1) { - message << " item"; + message << " property"; } else { - message << " items"; + message << " properties"; } if (this->valid) { @@ -1006,21 +1011,36 @@ struct DescribeVisitor { message << " it contained " << this->target.size(); if (this->target.size() == 1) { - message << " item"; + message << " property: "; + message << escape_string(this->target.as_object().cbegin()->first); } else { - message << " items"; + message << " properties: "; + for (auto iterator = this->target.as_object().cbegin(); + iterator != this->target.as_object().cend(); ++iterator) { + if (std::next(iterator) == this->target.as_object().cend()) { + message << "and " << escape_string(iterator->first); + } else { + message << escape_string(iterator->first) << ", "; + } + } } return message.str(); } - if (this->keyword == "maxProperties") { + return unknown(); + } + + auto operator()(const SchemaCompilerAssertionObjectSizeGreater &step) const + -> std::string { + if (this->keyword == "minProperties") { assert(this->target.is_object()); std::ostringstream message; - const auto maximum{step_value(step) - 1}; - message << "The object value was expected to contain at most " << maximum; - assert(maximum > 0); - if (maximum == 1) { + const auto minimum{step_value(step) + 1}; + message << "The object value was expected to contain at least " + << minimum; + assert(minimum > 0); + if (minimum == 1) { message << " property"; } else { message << " properties"; diff --git a/src/jsonschema/compile_evaluate.cc b/src/jsonschema/compile_evaluate.cc index 68022a0ff..7333283c2 100644 --- a/src/jsonschema/compile_evaluate.cc +++ b/src/jsonschema/compile_evaluate.cc @@ -347,16 +347,6 @@ auto evaluate_step( return true; \ } -#define EVALUATE_CONDITION_GUARD(title, step, instance) \ - for (const auto &child : step.condition) { \ - if (!evaluate_step(child, instance, SchemaCompilerEvaluationMode::Fast, \ - std::nullopt, context)) { \ - context.pop(step); \ - SOURCEMETA_TRACE_END(trace_id, title); \ - return true; \ - } \ - } - if (std::holds_alternative(step)) { SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionFail"); const auto &assertion{std::get(step)}; @@ -483,30 +473,80 @@ auto evaluate_step( CALLBACK_PRE(assertion, context.instance_location()); result = std::regex_search(target.to_string(), assertion.value.first); CALLBACK_POST("SchemaCompilerAssertionRegex", assertion); - } else if (std::holds_alternative(step)) { - SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionSizeGreater"); - const auto &assertion{std::get(step)}; + } else if (std::holds_alternative( + step)) { + SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionStringSizeLess"); + const auto &assertion{ + std::get(step)}; + context.push(assertion); + const auto &target{context.resolve_target(instance)}; + EVALUATE_IMPLICIT_PRECONDITION("SchemaCompilerAssertionStringSizeLess", + assertion, target.is_string()); + CALLBACK_PRE(assertion, context.instance_location()); + result = (target.size() < assertion.value); + CALLBACK_POST("SchemaCompilerAssertionStringSizeLess", assertion); + } else if (std::holds_alternative( + step)) { + SOURCEMETA_TRACE_START(trace_id, + "SchemaCompilerAssertionStringSizeGreater"); + const auto &assertion{ + std::get(step)}; + context.push(assertion); + const auto &target{context.resolve_target(instance)}; + EVALUATE_IMPLICIT_PRECONDITION("SchemaCompilerAssertionStringSizeGreater", + assertion, target.is_string()); + CALLBACK_PRE(assertion, context.instance_location()); + result = (target.size() > assertion.value); + CALLBACK_POST("SchemaCompilerAssertionStringSizeGreater", assertion); + + } else if (std::holds_alternative( + step)) { + SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionArraySizeLess"); + const auto &assertion{std::get(step)}; context.push(assertion); - // TODO: Get rid of this - EVALUATE_CONDITION_GUARD("SchemaCompilerAssertionSizeGreater", assertion, - instance); + const auto &target{context.resolve_target(instance)}; + EVALUATE_IMPLICIT_PRECONDITION("SchemaCompilerAssertionArraySizeLess", + assertion, target.is_array()); CALLBACK_PRE(assertion, context.instance_location()); + result = (target.size() < assertion.value); + CALLBACK_POST("SchemaCompilerAssertionArraySizeLess", assertion); + } else if (std::holds_alternative( + step)) { + SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionArraySizeGreater"); + const auto &assertion{ + std::get(step)}; + context.push(assertion); const auto &target{context.resolve_target(instance)}; - result = (target.is_array() || target.is_object() || target.is_string()) && - (target.size() > assertion.value); - CALLBACK_POST("SchemaCompilerAssertionSizeGreater", assertion); - } else if (std::holds_alternative(step)) { - SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionSizeLess"); - const auto &assertion{std::get(step)}; + EVALUATE_IMPLICIT_PRECONDITION("SchemaCompilerAssertionArraySizeGreater", + assertion, target.is_array()); + CALLBACK_PRE(assertion, context.instance_location()); + result = (target.size() > assertion.value); + CALLBACK_POST("SchemaCompilerAssertionArraySizeGreater", assertion); + } else if (std::holds_alternative( + step)) { + SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionObjectSizeLess"); + const auto &assertion{ + std::get(step)}; context.push(assertion); - // TODO: Get rid of this - EVALUATE_CONDITION_GUARD("SchemaCompilerAssertionSizeLess", assertion, - instance); + const auto &target{context.resolve_target(instance)}; + EVALUATE_IMPLICIT_PRECONDITION("SchemaCompilerAssertionObjectSizeLess", + assertion, target.is_object()); CALLBACK_PRE(assertion, context.instance_location()); + result = (target.size() < assertion.value); + CALLBACK_POST("SchemaCompilerAssertionObjectSizeLess", assertion); + } else if (std::holds_alternative( + step)) { + SOURCEMETA_TRACE_START(trace_id, + "SchemaCompilerAssertionObjectSizeGreater"); + const auto &assertion{ + std::get(step)}; + context.push(assertion); const auto &target{context.resolve_target(instance)}; - result = (target.is_array() || target.is_object() || target.is_string()) && - (target.size() < assertion.value); - CALLBACK_POST("SchemaCompilerAssertionSizeLess", assertion); + EVALUATE_IMPLICIT_PRECONDITION("SchemaCompilerAssertionObjectSizeGreater", + assertion, target.is_object()); + CALLBACK_PRE(assertion, context.instance_location()); + result = (target.size() > assertion.value); + CALLBACK_POST("SchemaCompilerAssertionObjectSizeGreater", assertion); } else if (std::holds_alternative(step)) { SOURCEMETA_TRACE_START(trace_id, "SchemaCompilerAssertionEqual"); const auto &assertion{std::get(step)}; @@ -1358,7 +1398,6 @@ auto evaluate_step( #undef CALLBACK_POST #undef CALLBACK_ANNOTATION #undef EVALUATE_IMPLICIT_PRECONDITION -#undef EVALUATE_CONDITION_GUARD // We should never get here assert(false); return result; diff --git a/src/jsonschema/compile_helpers.h b/src/jsonschema/compile_helpers.h index ccc6bc516..23d73febc 100644 --- a/src/jsonschema/compile_helpers.h +++ b/src/jsonschema/compile_helpers.h @@ -16,8 +16,7 @@ auto make(const bool report, const SchemaCompilerContext &context, const SchemaCompilerSchemaContext &schema_context, const SchemaCompilerDynamicContext &dynamic_context, // Take the value type from the "type" property of the step struct - decltype(std::declval().value) &&value, - SchemaCompilerTemplate &&condition) -> Step { + decltype(std::declval().value) &&value) -> Step { return { dynamic_context.keyword.empty() ? dynamic_context.base_schema_location @@ -28,8 +27,7 @@ auto make(const bool report, const SchemaCompilerContext &context, schema_context.base.recompose(), context.uses_dynamic_scopes, report, - std::move(value), - std::move(condition)}; + std::move(value)}; } // Instantiate an applicator step @@ -39,8 +37,7 @@ auto make(const bool report, const SchemaCompilerContext &context, const SchemaCompilerDynamicContext &dynamic_context, // Take the value type from the "value" property of the step struct decltype(std::declval().value) &&value, - SchemaCompilerTemplate &&children, - SchemaCompilerTemplate &&condition) -> Step { + SchemaCompilerTemplate &&children) -> Step { return { dynamic_context.keyword.empty() ? dynamic_context.base_schema_location @@ -52,32 +49,7 @@ auto make(const bool report, const SchemaCompilerContext &context, context.uses_dynamic_scopes, report, std::move(value), - std::move(children), - std::move(condition)}; -} - -// TODO: Completely get rid of this. We should never have -// explicit type conditions -inline auto type_condition(const SchemaCompilerContext &context, - const SchemaCompilerSchemaContext &schema_context, - const JSON::Type type) -> SchemaCompilerTemplate { - // As an optimization - if (schema_context.schema.is_object() && - schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string()) { - const auto &type_string{schema_context.schema.at("type").to_string()}; - if (type == JSON::Type::String && type_string == "string") { - return {}; - } else if (type == JSON::Type::Array && type_string == "array") { - return {}; - } else if (type == JSON::Type::Object && type_string == "object") { - return {}; - } - } - - return {make( - true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueType{type}, {})}; + std::move(children)}; } } // namespace sourcemeta::jsontoolkit diff --git a/src/jsonschema/compile_json.cc b/src/jsonschema/compile_json.cc index 5e08b513a..0d3ac4122 100644 --- a/src/jsonschema/compile_json.cc +++ b/src/jsonschema/compile_json.cc @@ -173,10 +173,6 @@ auto encode_step(const std::string_view category, const std::string_view type, result.assign("dynamic", JSON{step.dynamic}); result.assign("report", JSON{step.report}); result.assign("value", value_to_json(step.value)); - result.assign("condition", JSON::make_array()); - for (const auto &substep : step.condition) { - result.at("condition").push_back(step_to_json(substep)); - } if constexpr (requires { step.children; }) { result.assign("children", JSON::make_array()); @@ -206,8 +202,18 @@ struct StepVisitor { HANDLE_STEP("assertion", "type-strict-any", SchemaCompilerAssertionTypeStrictAny) HANDLE_STEP("assertion", "regex", SchemaCompilerAssertionRegex) - HANDLE_STEP("assertion", "size-greater", SchemaCompilerAssertionSizeGreater) - HANDLE_STEP("assertion", "size-less", SchemaCompilerAssertionSizeLess) + HANDLE_STEP("assertion", "string-size-less", + SchemaCompilerAssertionStringSizeLess) + HANDLE_STEP("assertion", "string-size-greater", + SchemaCompilerAssertionStringSizeGreater) + HANDLE_STEP("assertion", "array-size-less", + SchemaCompilerAssertionArraySizeLess) + HANDLE_STEP("assertion", "array-size-greater", + SchemaCompilerAssertionArraySizeGreater) + HANDLE_STEP("assertion", "object-size-less", + SchemaCompilerAssertionObjectSizeLess) + HANDLE_STEP("assertion", "object-size-greater", + SchemaCompilerAssertionObjectSizeGreater) HANDLE_STEP("assertion", "equal", SchemaCompilerAssertionEqual) HANDLE_STEP("assertion", "greater-equal", SchemaCompilerAssertionGreaterEqual) HANDLE_STEP("assertion", "less-equal", SchemaCompilerAssertionLessEqual) @@ -289,8 +295,7 @@ auto compiler_template_format_compare(const JSON::String &left, {"location", 7}, {"report", 8}, {"dynamic", 9}, - {"condition", 10}, - {"children", 11}}; + {"children", 10}}; // We define and control all of these keywords, so if we are missing // some here, then we did something wrong? diff --git a/src/jsonschema/default_compiler_2019_09.h b/src/jsonschema/default_compiler_2019_09.h index c0f314255..2ac6f1c06 100644 --- a/src/jsonschema/default_compiler_2019_09.h +++ b/src/jsonschema/default_compiler_2019_09.h @@ -35,14 +35,13 @@ auto compiler_2019_09_applicator_dependentschemas( false, context, schema_context, relative_dynamic_context, SchemaCompilerValueString{entry.first}, compile(context, schema_context, relative_dynamic_context, - {entry.first}, empty_pointer), - SchemaCompilerTemplate{})); + {entry.first}, empty_pointer))); } } return {make( true, context, schema_context, dynamic_context, JSON::Type::Object, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_2019_09_validation_dependentrequired( @@ -83,8 +82,7 @@ auto compiler_2019_09_validation_dependentrequired( } return {make( - true, context, schema_context, dynamic_context, std::move(dependencies), - SchemaCompilerTemplate{})}; + true, context, schema_context, dynamic_context, std::move(dependencies))}; } auto compiler_2019_09_core_annotation( @@ -94,7 +92,7 @@ auto compiler_2019_09_core_annotation( -> SchemaCompilerTemplate { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, {})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } auto compiler_2019_09_applicator_contains_conditional_annotate( @@ -135,7 +133,7 @@ auto compiler_2019_09_applicator_contains_conditional_annotate( if (maximum.has_value() && minimum > maximum.value()) { return {make(true, context, schema_context, dynamic_context, - SchemaCompilerValueNone{}, {})}; + SchemaCompilerValueNone{})}; } if (minimum == 0 && !maximum.has_value()) { @@ -149,7 +147,7 @@ auto compiler_2019_09_applicator_contains_conditional_annotate( if (annotate) { children.push_back(make( true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueNone{}, {})); + SchemaCompilerValueNone{})); // TODO: If after emitting the above annotation, the number of annotations // for the current schema location + instance location is equal to the @@ -165,7 +163,7 @@ auto compiler_2019_09_applicator_contains_conditional_annotate( // in use on the schema. Can we pre-determine that and speed things up // if not? annotate}, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_2019_09_applicator_contains( @@ -219,7 +217,7 @@ auto compiler_2019_09_applicator_unevaluateditems( relative_dynamic_context, empty_pointer, empty_pointer)}; children.push_back(make( - true, context, schema_context, relative_dynamic_context, JSON{true}, {})); + true, context, schema_context, relative_dynamic_context, JSON{true})); if (schema_context.vocabularies.contains( "https://json-schema.org/draft/2019-09/vocab/applicator")) { @@ -227,7 +225,7 @@ auto compiler_2019_09_applicator_unevaluateditems( true, context, schema_context, dynamic_context, SchemaCompilerValueItemsAnnotationKeywords{ "items", {}, {"items", "additionalItems", "unevaluatedItems"}}, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } else if (schema_context.vocabularies.contains( "https://json-schema.org/draft/2020-12/vocab/applicator")) { return {make( @@ -236,12 +234,11 @@ auto compiler_2019_09_applicator_unevaluateditems( "prefixItems", {"contains"}, {"prefixItems", "items", "contains", "unevaluatedItems"}}, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } else { return {make( true, context, schema_context, dynamic_context, - SchemaCompilerValueStrings{"unevaluatedItems"}, std::move(children), - SchemaCompilerTemplate{})}; + SchemaCompilerValueStrings{"unevaluatedItems"}, std::move(children))}; } } @@ -277,11 +274,11 @@ auto compiler_2019_09_applicator_unevaluatedproperties( empty_pointer, empty_pointer)}; children.push_back(make( true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueNone{}, {})); + SchemaCompilerValueNone{})); return {make( true, context, schema_context, dynamic_context, std::move(dependencies), - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_2019_09_core_recursiveref( @@ -299,7 +296,7 @@ auto compiler_2019_09_core_recursiveref( } return {make( - true, context, schema_context, dynamic_context, "", {}, {})}; + true, context, schema_context, dynamic_context, "", {})}; } auto compiler_2019_09_applicator_anyof( diff --git a/src/jsonschema/default_compiler_2020_12.h b/src/jsonschema/default_compiler_2020_12.h index 84d009cf1..14050b89f 100644 --- a/src/jsonschema/default_compiler_2020_12.h +++ b/src/jsonschema/default_compiler_2020_12.h @@ -69,7 +69,7 @@ auto compiler_2020_12_core_dynamicref( // look for the oldest dynamic anchor in the schema resource chain. return {make( true, context, schema_context, dynamic_context, - std::string{reference.fragment().value()}, {}, {})}; + std::string{reference.fragment().value()}, {})}; } } // namespace internal diff --git a/src/jsonschema/default_compiler_draft4.h b/src/jsonschema/default_compiler_draft4.h index 8b5bc36d2..f62df80d1 100644 --- a/src/jsonschema/default_compiler_draft4.h +++ b/src/jsonschema/default_compiler_draft4.h @@ -38,7 +38,7 @@ auto compiler_draft4_core_ref(const SchemaCompilerContext &context, if (schema_context.labels.contains(label)) { return {make( true, context, schema_context, dynamic_context, - SchemaCompilerValueUnsignedInteger{label}, {}, {})}; + SchemaCompilerValueUnsignedInteger{label}, {})}; } // TODO: Avoid this copy @@ -60,8 +60,7 @@ auto compiler_draft4_core_ref(const SchemaCompilerContext &context, true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{label}, compile(context, std::move(new_schema_context), relative_dynamic_context, - empty_pointer, empty_pointer, reference.destination), - {})}; + empty_pointer, empty_pointer, reference.destination))}; } auto compiler_draft4_validation_type( @@ -74,32 +73,26 @@ auto compiler_draft4_validation_type( schema_context.schema.at(dynamic_context.keyword).to_string()}; if (type == "null") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Null, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Null)}; } else if (type == "boolean") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Boolean, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Boolean)}; } else if (type == "object") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Object, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Object)}; } else if (type == "array") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Array, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Array)}; } else if (type == "number") { return {make( true, context, schema_context, dynamic_context, - std::set{JSON::Type::Real, JSON::Type::Integer}, {})}; + std::set{JSON::Type::Real, JSON::Type::Integer})}; } else if (type == "integer") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Integer, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Integer)}; } else if (type == "string") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::String, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::String)}; } else { return {}; } @@ -112,32 +105,26 @@ auto compiler_draft4_validation_type( schema_context.schema.at(dynamic_context.keyword).front().to_string()}; if (type == "null") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Null, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Null)}; } else if (type == "boolean") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Boolean, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Boolean)}; } else if (type == "object") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Object, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Object)}; } else if (type == "array") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Array, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Array)}; } else if (type == "number") { return {make( true, context, schema_context, dynamic_context, - std::set{JSON::Type::Real, JSON::Type::Integer}, {})}; + std::set{JSON::Type::Real, JSON::Type::Integer})}; } else if (type == "integer") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Integer, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Integer)}; } else if (type == "string") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::String, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::String)}; } else { return {}; } @@ -168,7 +155,7 @@ auto compiler_draft4_validation_type( assert(types.size() >= schema_context.schema.at(dynamic_context.keyword).size()); return {make( - true, context, schema_context, dynamic_context, std::move(types), {})}; + true, context, schema_context, dynamic_context, std::move(types))}; } return {}; @@ -200,12 +187,11 @@ auto compiler_draft4_validation_required( if (properties.size() == 1) { return {make( true, context, schema_context, dynamic_context, - SchemaCompilerValueString{*(properties.cbegin())}, - SchemaCompilerTemplate{})}; + SchemaCompilerValueString{*(properties.cbegin())})}; } else { return {make( - true, context, schema_context, dynamic_context, std::move(properties), - SchemaCompilerTemplate{})}; + true, context, schema_context, dynamic_context, + std::move(properties))}; } } else { assert( @@ -215,8 +201,7 @@ auto compiler_draft4_validation_required( SchemaCompilerValueString{ schema_context.schema.at(dynamic_context.keyword) .front() - .to_string()}, - SchemaCompilerTemplate{})}; + .to_string()})}; } } @@ -241,7 +226,7 @@ auto compiler_draft4_applicator_allof( return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_draft4_applicator_anyof_conditional_exhaustive( @@ -260,14 +245,12 @@ auto compiler_draft4_applicator_anyof_conditional_exhaustive( false, context, schema_context, relative_dynamic_context, SchemaCompilerValueNone{}, compile(context, schema_context, relative_dynamic_context, - {static_cast(index)}), - SchemaCompilerTemplate{})); + {static_cast(index)}))); } return {make( true, context, schema_context, dynamic_context, - SchemaCompilerValueBoolean{exhaustive}, std::move(disjunctors), - SchemaCompilerTemplate{})}; + SchemaCompilerValueBoolean{exhaustive}, std::move(disjunctors))}; } auto compiler_draft4_applicator_anyof( @@ -295,13 +278,12 @@ auto compiler_draft4_applicator_oneof( false, context, schema_context, relative_dynamic_context, SchemaCompilerValueNone{}, compile(context, schema_context, relative_dynamic_context, - {static_cast(index)}), - SchemaCompilerTemplate{})); + {static_cast(index)}))); } return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, - std::move(disjunctors), SchemaCompilerTemplate{})}; + std::move(disjunctors))}; } auto compiler_draft4_applicator_properties( @@ -379,20 +361,19 @@ auto compiler_draft4_applicator_properties( loads_unevaluated_keywords || schema_context.schema.defines("additionalProperties")) { substeps.push_back(make( - true, context, schema_context, relative_dynamic_context, JSON{name}, - {})); + true, context, schema_context, relative_dynamic_context, + JSON{name})); } children.push_back(make( false, context, schema_context, relative_dynamic_context, - SchemaCompilerValueNone{}, std::move(substeps), - SchemaCompilerTemplate{})); + SchemaCompilerValueNone{}, std::move(substeps))); cursor += 1; } return {make( true, context, schema_context, dynamic_context, std::move(indexes), - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } SchemaCompilerTemplate children; @@ -407,8 +388,7 @@ auto compiler_draft4_applicator_properties( loads_unevaluated_keywords || schema_context.schema.defines("additionalProperties")) { substeps.push_back(make( - true, context, schema_context, relative_dynamic_context, JSON{key}, - {})); + true, context, schema_context, relative_dynamic_context, JSON{key})); } // We can avoid this "defines" condition if the property is a required one @@ -422,14 +402,13 @@ auto compiler_draft4_applicator_properties( } else { children.push_back(make( false, context, schema_context, relative_dynamic_context, - SchemaCompilerValueString{key}, std::move(substeps), - SchemaCompilerTemplate{})); + SchemaCompilerValueString{key}, std::move(substeps))); } } return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_draft4_applicator_patternproperties( @@ -472,7 +451,7 @@ auto compiler_draft4_applicator_patternproperties( // `patternProperties` substeps.push_back(make( true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueNone{}, {})); + SchemaCompilerValueNone{})); } // Loop over the instance properties @@ -481,13 +460,13 @@ auto compiler_draft4_applicator_patternproperties( false, context, schema_context, relative_dynamic_context, SchemaCompilerValueRegex{ std::regex{entry.first, std::regex::ECMAScript}, entry.first}, - std::move(substeps), SchemaCompilerTemplate{})); + std::move(substeps))); } // If the instance is an object... return {make( true, context, schema_context, dynamic_context, JSON::Type::Object, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_draft4_applicator_additionalproperties_conditional_annotation( @@ -508,7 +487,7 @@ auto compiler_draft4_applicator_additionalproperties_conditional_annotation( if (annotate) { children.push_back(make( true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueNone{}, {})); + SchemaCompilerValueNone{})); } SchemaCompilerValueStrings dependencies; @@ -523,12 +502,11 @@ auto compiler_draft4_applicator_additionalproperties_conditional_annotation( if (dependencies.empty()) { return {make( true, context, schema_context, dynamic_context, - SchemaCompilerValueNone{}, std::move(children), - SchemaCompilerTemplate{})}; + SchemaCompilerValueNone{}, std::move(children))}; } else { return {make( true, context, schema_context, dynamic_context, std::move(dependencies), - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } } @@ -559,8 +537,7 @@ auto compiler_draft4_validation_pattern( return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueRegex{std::regex{regex_string, std::regex::ECMAScript}, - regex_string}, - SchemaCompilerTemplate{})}; + regex_string})}; } auto compiler_draft4_validation_format( @@ -591,7 +568,7 @@ auto compiler_draft4_validation_format( if (format == "uri") { return {make( true, context, schema_context, dynamic_context, - SchemaCompilerValueStringType::URI, SchemaCompilerTemplate{})}; + SchemaCompilerValueStringType::URI)}; } #define COMPILE_FORMAT_REGEX(name, regular_expression) \ @@ -600,8 +577,7 @@ auto compiler_draft4_validation_format( true, context, schema_context, dynamic_context, \ SchemaCompilerValueRegex{ \ std::regex{(regular_expression), std::regex::ECMAScript}, \ - (regular_expression)}, \ - SchemaCompilerTemplate{})}; \ + (regular_expression)})}; \ } COMPILE_FORMAT_REGEX("ipv4", FORMAT_REGEX_IPV4) @@ -619,8 +595,7 @@ auto compiler_draft4_applicator_not( return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; } auto compiler_draft4_applicator_items_array( @@ -674,36 +649,33 @@ auto compiler_draft4_applicator_items_array( if (annotate) { subchildren.push_back(make( true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueIndexedJSON{cursor, JSON{true}}, - SchemaCompilerTemplate{})); + SchemaCompilerValueIndexedJSON{cursor, JSON{true}})); subchildren.push_back( make( true, context, schema_context, relative_dynamic_context, - SchemaCompilerValueIndexedJSON{cursor, JSON{cursor - 1}}, - SchemaCompilerTemplate{})); + SchemaCompilerValueIndexedJSON{cursor, JSON{cursor - 1}})); } children.push_back(make( false, context, schema_context, relative_dynamic_context, SchemaCompilerValueUnsignedInteger{cursor - 1}, - std::move(subchildren), SchemaCompilerTemplate{})); + std::move(subchildren))); } else { if (annotate) { subchildren.push_back(make( true, context, schema_context, relative_dynamic_context, - JSON{cursor - 1}, {})); + JSON{cursor - 1})); } children.push_back(make( false, context, schema_context, relative_dynamic_context, - SchemaCompilerValueUnsignedInteger{cursor}, std::move(subchildren), - SchemaCompilerTemplate{})); + SchemaCompilerValueUnsignedInteger{cursor}, std::move(subchildren))); } } return {make( true, context, schema_context, dynamic_context, JSON::Type::Array, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_draft4_applicator_items_conditional_annotation( @@ -724,23 +696,20 @@ auto compiler_draft4_applicator_items_conditional_annotation( true, context, schema_context, relative_dynamic_context, SchemaCompilerValueUnsignedInteger{0}, compile(context, schema_context, relative_dynamic_context, - empty_pointer, empty_pointer), - SchemaCompilerTemplate{})); + empty_pointer, empty_pointer))); children.push_back(make( - true, context, schema_context, relative_dynamic_context, JSON{true}, - {})); + true, context, schema_context, relative_dynamic_context, JSON{true})); return {make( false, context, schema_context, dynamic_context, JSON::Type::Array, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{0}, compile(context, schema_context, relative_dynamic_context, - empty_pointer, empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer, empty_pointer))}; } return compiler_draft4_applicator_items_array(context, schema_context, @@ -771,19 +740,16 @@ auto compiler_draft4_applicator_additionalitems_from_cursor( true, context, schema_context, relative_dynamic_context, SchemaCompilerValueUnsignedInteger{cursor}, compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; if (annotate) { children.push_back(make( - true, context, schema_context, relative_dynamic_context, JSON{true}, - {})); + true, context, schema_context, relative_dynamic_context, JSON{true})); } return {make( false, context, schema_context, dynamic_context, - SchemaCompilerValueUnsignedInteger{cursor}, std::move(children), - SchemaCompilerTemplate{})}; + SchemaCompilerValueUnsignedInteger{cursor}, std::move(children))}; } auto compiler_draft4_applicator_additionalitems_conditional_annotation( @@ -846,8 +812,7 @@ auto compiler_draft4_applicator_dependencies( false, context, schema_context, relative_dynamic_context, SchemaCompilerValueString{entry.first}, compile(context, schema_context, relative_dynamic_context, - {entry.first}, empty_pointer), - SchemaCompilerTemplate{})); + {entry.first}, empty_pointer))); } } else if (entry.second.is_array()) { std::set properties; @@ -865,12 +830,12 @@ auto compiler_draft4_applicator_dependencies( if (!dependencies.empty()) { children.push_back(make( false, context, schema_context, relative_dynamic_context, - std::move(dependencies), SchemaCompilerTemplate{})); + std::move(dependencies))); } return {make( true, context, schema_context, dynamic_context, JSON::Type::Object, - std::move(children), SchemaCompilerTemplate{})}; + std::move(children))}; } auto compiler_draft4_validation_enum( @@ -883,7 +848,7 @@ auto compiler_draft4_validation_enum( if (schema_context.schema.at(dynamic_context.keyword).size() == 1) { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword).front()}, {})}; + JSON{schema_context.schema.at(dynamic_context.keyword).front()})}; } std::set options; @@ -893,8 +858,7 @@ auto compiler_draft4_validation_enum( } return {make( - true, context, schema_context, dynamic_context, std::move(options), - SchemaCompilerTemplate{})}; + true, context, schema_context, dynamic_context, std::move(options))}; } auto compiler_draft4_validation_uniqueitems( @@ -913,9 +877,9 @@ auto compiler_draft4_validation_uniqueitems( return {}; } - return {make( - true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, - SchemaCompilerTemplate{})}; + return {make(true, context, schema_context, + dynamic_context, + SchemaCompilerValueNone{})}; } auto compiler_draft4_validation_maxlength( @@ -935,15 +899,12 @@ auto compiler_draft4_validation_maxlength( // TODO: As an optimization, if `minLength` is set to the same number, do // a single size equality assertion - return {make( + return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{ static_cast( schema_context.schema.at(dynamic_context.keyword).as_integer()) + - 1}, - // TODO: We could get rid of this condition if we had an - // AssertionStringSizeLess step instead - type_condition(context, schema_context, JSON::Type::String))}; + 1})}; } auto compiler_draft4_validation_minlength( @@ -963,15 +924,12 @@ auto compiler_draft4_validation_minlength( // TODO: As an optimization, if `maxLength` is set to the same number, do // a single size equality assertion - return {make( + return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{ static_cast( schema_context.schema.at(dynamic_context.keyword).as_integer()) - - 1}, - // TODO: We could get rid of this condition if we had an - // AssertionStringSizeGreater step instead - type_condition(context, schema_context, JSON::Type::String))}; + 1})}; } auto compiler_draft4_validation_maxitems( @@ -991,15 +949,12 @@ auto compiler_draft4_validation_maxitems( // TODO: As an optimization, if `minItems` is set to the same number, do // a single size equality assertion - return {make( + return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{ static_cast( schema_context.schema.at(dynamic_context.keyword).as_integer()) + - 1}, - // TODO: We could get rid of this condition if we had an - // AssertionArraySizeLess step instead - type_condition(context, schema_context, JSON::Type::Array))}; + 1})}; } auto compiler_draft4_validation_minitems( @@ -1019,15 +974,12 @@ auto compiler_draft4_validation_minitems( // TODO: As an optimization, if `maxItems` is set to the same number, do // a single size equality assertion - return {make( + return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{ static_cast( schema_context.schema.at(dynamic_context.keyword).as_integer()) - - 1}, - // TODO: We could get rid of this condition if we had an - // AssertionArraySizeGreater step instead - type_condition(context, schema_context, JSON::Type::Array))}; + 1})}; } auto compiler_draft4_validation_maxproperties( @@ -1047,15 +999,12 @@ auto compiler_draft4_validation_maxproperties( // TODO: As an optimization, if `minProperties` is set to the same number, do // a single size equality assertion - return {make( + return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{ static_cast( schema_context.schema.at(dynamic_context.keyword).as_integer()) + - 1}, - // TODO: We could get rid of this condition if we had an - // AssertionObjectSizeLess step instead - type_condition(context, schema_context, JSON::Type::Object))}; + 1})}; } auto compiler_draft4_validation_minproperties( @@ -1075,15 +1024,12 @@ auto compiler_draft4_validation_minproperties( // TODO: As an optimization, if `maxProperties` is set to the same number, do // a single size equality assertion - return {make( + return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueUnsignedInteger{ static_cast( schema_context.schema.at(dynamic_context.keyword).as_integer()) - - 1}, - // TODO: We could get rid of this condition if we had an - // AssertionObjectSizeGreater step instead - type_condition(context, schema_context, JSON::Type::Object))}; + 1})}; } auto compiler_draft4_validation_maximum( @@ -1109,13 +1055,11 @@ auto compiler_draft4_validation_maximum( schema_context.schema.at("exclusiveMaximum").to_boolean()) { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } else { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } } @@ -1142,13 +1086,11 @@ auto compiler_draft4_validation_minimum( schema_context.schema.at("exclusiveMinimum").to_boolean()) { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } else { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } } @@ -1169,8 +1111,7 @@ auto compiler_draft4_validation_multipleof( return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } } // namespace internal diff --git a/src/jsonschema/default_compiler_draft6.h b/src/jsonschema/default_compiler_draft6.h index 645379f00..6ac2b6987 100644 --- a/src/jsonschema/default_compiler_draft6.h +++ b/src/jsonschema/default_compiler_draft6.h @@ -19,32 +19,26 @@ auto compiler_draft6_validation_type( schema_context.schema.at(dynamic_context.keyword).to_string()}; if (type == "null") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Null, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Null)}; } else if (type == "boolean") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Boolean, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Boolean)}; } else if (type == "object") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Object, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Object)}; } else if (type == "array") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Array, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Array)}; } else if (type == "number") { return {make( true, context, schema_context, dynamic_context, - std::set{JSON::Type::Real, JSON::Type::Integer}, {})}; + std::set{JSON::Type::Real, JSON::Type::Integer})}; } else if (type == "integer") { - return {make(true, context, schema_context, - dynamic_context, - JSON::Type::Integer, {})}; + return {make( + true, context, schema_context, dynamic_context, JSON::Type::Integer)}; } else if (type == "string") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::String, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::String)}; } else { return {}; } @@ -57,32 +51,26 @@ auto compiler_draft6_validation_type( schema_context.schema.at(dynamic_context.keyword).front().to_string()}; if (type == "null") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Null, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Null)}; } else if (type == "boolean") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Boolean, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Boolean)}; } else if (type == "object") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Object, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Object)}; } else if (type == "array") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::Array, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::Array)}; } else if (type == "number") { return {make( true, context, schema_context, dynamic_context, - std::set{JSON::Type::Real, JSON::Type::Integer}, {})}; + std::set{JSON::Type::Real, JSON::Type::Integer})}; } else if (type == "integer") { - return {make(true, context, schema_context, - dynamic_context, - JSON::Type::Integer, {})}; + return {make( + true, context, schema_context, dynamic_context, JSON::Type::Integer)}; } else if (type == "string") { return {make( - true, context, schema_context, dynamic_context, JSON::Type::String, - {})}; + true, context, schema_context, dynamic_context, JSON::Type::String)}; } else { return {}; } @@ -113,7 +101,7 @@ auto compiler_draft6_validation_type( assert(types.size() >= schema_context.schema.at(dynamic_context.keyword).size()); return {make( - true, context, schema_context, dynamic_context, std::move(types), {})}; + true, context, schema_context, dynamic_context, std::move(types))}; } return {}; @@ -126,7 +114,7 @@ auto compiler_draft6_validation_const( -> SchemaCompilerTemplate { return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, {})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } auto compiler_draft6_validation_exclusivemaximum( @@ -145,8 +133,7 @@ auto compiler_draft6_validation_exclusivemaximum( return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } auto compiler_draft6_validation_exclusiveminimum( @@ -165,8 +152,7 @@ auto compiler_draft6_validation_exclusiveminimum( return {make( true, context, schema_context, dynamic_context, - JSON{schema_context.schema.at(dynamic_context.keyword)}, - SchemaCompilerTemplate{})}; + JSON{schema_context.schema.at(dynamic_context.keyword)})}; } auto compiler_draft6_applicator_contains( @@ -184,8 +170,7 @@ auto compiler_draft6_applicator_contains( true, context, schema_context, dynamic_context, SchemaCompilerValueRange{1, std::nullopt, false}, compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; } auto compiler_draft6_validation_propertynames( @@ -202,8 +187,7 @@ auto compiler_draft6_validation_propertynames( return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; } } // namespace internal diff --git a/src/jsonschema/default_compiler_draft7.h b/src/jsonschema/default_compiler_draft7.h index 5c2dd0e72..51f9ac18a 100644 --- a/src/jsonschema/default_compiler_draft7.h +++ b/src/jsonschema/default_compiler_draft7.h @@ -17,8 +17,7 @@ auto compiler_draft7_applicator_if( return {make( true, context, schema_context, dynamic_context, SchemaCompilerValueNone{}, compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; } auto compiler_draft7_applicator_then( @@ -36,8 +35,7 @@ auto compiler_draft7_applicator_then( return {make( true, context, schema_context, dynamic_context, "if", compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; } auto compiler_draft7_applicator_else( @@ -55,8 +53,7 @@ auto compiler_draft7_applicator_else( return {make( true, context, schema_context, dynamic_context, "if", compile(context, schema_context, relative_dynamic_context, empty_pointer, - empty_pointer), - SchemaCompilerTemplate{})}; + empty_pointer))}; } } // namespace internal diff --git a/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h b/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h index b7c1a7bba..f143a590e 100644 --- a/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h +++ b/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_compile.h @@ -146,16 +146,34 @@ struct SchemaCompilerAssertionTypeStrictAny; struct SchemaCompilerAssertionRegex; /// @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, -/// respectively -struct SchemaCompilerAssertionSizeGreater; +/// Represents a compiler assertion step that checks a given string has less +/// than a certain number of characters +struct SchemaCompilerAssertionStringSizeLess; /// @ingroup jsonschema -/// Represents a compiler assertion step that checks a given array, object, or -/// string has less than a certain number of items, properties, or characters, -/// respectively -struct SchemaCompilerAssertionSizeLess; +/// Represents a compiler assertion step that checks a given string has greater +/// than a certain number of characters +struct SchemaCompilerAssertionStringSizeGreater; + +/// @ingroup jsonschema +/// Represents a compiler assertion step that checks a given array has less +/// than a certain number of items +struct SchemaCompilerAssertionArraySizeLess; + +/// @ingroup jsonschema +/// Represents a compiler assertion step that checks a given array has greater +/// than a certain number of items +struct SchemaCompilerAssertionArraySizeGreater; + +/// @ingroup jsonschema +/// Represents a compiler assertion step that checks a given object has less +/// than a certain number of properties +struct SchemaCompilerAssertionObjectSizeLess; + +/// @ingroup jsonschema +/// Represents a compiler assertion step that checks a given object has greater +/// than a certain number of properties +struct SchemaCompilerAssertionObjectSizeGreater; /// @ingroup jsonschema /// Represents a compiler assertion step that checks the instance equals a given @@ -348,13 +366,17 @@ using SchemaCompilerTemplate = std::vector #include -TEST(JSONSchema_compile_evaluate, fast_step_defines_true_no_condition) { +TEST(JSONSchema_compile_evaluate, fast_step_defines_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionDefines{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueString{"foo"}, - {}}}; + SchemaCompilerAssertionDefines{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueString{"foo"}}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_TRUE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_defines_false_no_condition) { +TEST(JSONSchema_compile_evaluate, fast_step_defines_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionDefines{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueString{"bar"}, - {}}}; + SchemaCompilerAssertionDefines{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueString{"bar"}}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_FALSE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_defines_true_with_condition) { +TEST(JSONSchema_compile_evaluate, fast_step_fail) { using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate condition{ - SchemaCompilerAssertionDefines{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueString{"foo"}, - {}}}; - - const SchemaCompilerTemplate steps{SchemaCompilerAssertionDefines{ - Pointer{}, Pointer{}, "#", "", true, true, - SchemaCompilerValueString{"bar"}, condition}}; - - const JSON instance{parse("{ \"foo\": 1, \"bar\": 2 }")}; - const auto result{evaluate(steps, instance)}; - EXPECT_TRUE(result); -} - -TEST(JSONSchema_compile_evaluate, fast_step_fail_no_condition) { - using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionFail{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - {}}}; + const SchemaCompilerTemplate steps{SchemaCompilerAssertionFail{ + Pointer{}, Pointer{}, "#", "", true, true, SchemaCompilerValueNone{}}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_FALSE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_fail_with_condition_true) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate condition{ - SchemaCompilerAssertionDefines{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueString{"foo"}, - {}}}; - - const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionFail{Pointer{}, Pointer{}, "#", "", true, true, - SchemaCompilerValueNone{}, condition}}; - - const JSON instance{parse("{ \"foo\": 1, \"bar\": 2 }")}; - const auto result{evaluate(steps, instance)}; - EXPECT_FALSE(result); -} - -TEST(JSONSchema_compile_evaluate, fast_step_type_true_no_condition) { +TEST(JSONSchema_compile_evaluate, fast_step_type_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Object}}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_TRUE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_type_false_no_condition) { +TEST(JSONSchema_compile_evaluate, fast_step_type_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_FALSE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_or_empty_no_condition) { - using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, {}, {}}}; - - const JSON instance{parse("{ \"foo\": 1 }")}; - const auto result{evaluate(steps, instance)}; - EXPECT_TRUE(result); -} - -TEST(JSONSchema_compile_evaluate, fast_step_or_no_condition_true) { +TEST(JSONSchema_compile_evaluate, fast_step_or_empty) { using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate children{ - SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}, - SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; - const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, children, {}}}; + Pointer{}, Pointer{}, "#", "", true, true, false, {}}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_TRUE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_or_no_condition_false) { +TEST(JSONSchema_compile_evaluate, fast_step_or_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{ SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}, + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}, SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Array}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Array}}}; const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, children, {}}}; + Pointer{}, Pointer{}, "#", "", true, true, false, children}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; EXPECT_FALSE(result); } -TEST(JSONSchema_compile_evaluate, - fast_step_or_no_condition_true_with_callback) { - using namespace sourcemeta::jsontoolkit; - - const auto assertion_1{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; - const auto assertion_2{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; - - const SchemaCompilerTemplate children{assertion_1, assertion_2}; - - const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - false, - children, - {assertion_1}}}; - - std::vector< - std::tuple> - trace; - const JSON instance{"foo bar"}; - const auto result{evaluate( - steps, instance, SchemaCompilerEvaluationMode::Fast, - [&trace]( - const sourcemeta::jsontoolkit::SchemaCompilerEvaluationType type, - const bool subresult, const SchemaCompilerTemplate::value_type &step, - const Pointer &evaluate_path, const Pointer &, const JSON &value) { - if (type != - sourcemeta::jsontoolkit::SchemaCompilerEvaluationType::Post) { - return; - } - - trace.push_back({subresult, step, evaluate_path, value}); - })}; - - EXPECT_TRUE(result); - EXPECT_EQ(trace.size(), 2); - - EXPECT_TRUE(std::get<0>(trace.at(0))); - EXPECT_TRUE(std::holds_alternative( - std::get<1>(trace.at(0)))); - EXPECT_TRUE(std::get<2>(trace.at(0)).empty()); - EXPECT_TRUE(std::get<3>(trace.at(0)).is_null()); - - EXPECT_TRUE(std::get<0>(trace.at(1))); - EXPECT_TRUE(std::holds_alternative( - std::get<1>(trace.at(1)))); - EXPECT_TRUE(std::get<2>(trace.at(1)).empty()); - EXPECT_TRUE(std::get<3>(trace.at(1)).is_null()); -} - -TEST(JSONSchema_compile_evaluate, - exhaustive_step_or_no_condition_true_with_callback) { - using namespace sourcemeta::jsontoolkit; - - const auto assertion_1{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; - const auto assertion_2{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; - - const SchemaCompilerTemplate children{assertion_1, assertion_2}; - - const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - false, - children, - {assertion_1}}}; - - std::vector< - std::tuple> - trace; - const JSON instance{"foo bar"}; - const auto result{evaluate( - steps, instance, SchemaCompilerEvaluationMode::Exhaustive, - [&trace]( - const sourcemeta::jsontoolkit::SchemaCompilerEvaluationType type, - const bool subresult, const SchemaCompilerTemplate::value_type &step, - const Pointer &evaluate_path, const Pointer &, const JSON &value) { - if (type != - sourcemeta::jsontoolkit::SchemaCompilerEvaluationType::Post) { - return; - } - - trace.push_back({subresult, step, evaluate_path, value}); - })}; - - EXPECT_TRUE(result); - EXPECT_EQ(trace.size(), 3); - - EXPECT_TRUE(std::get<0>(trace.at(0))); - EXPECT_TRUE(std::holds_alternative( - std::get<1>(trace.at(0)))); - EXPECT_TRUE(std::get<2>(trace.at(0)).empty()); - EXPECT_TRUE(std::get<3>(trace.at(0)).is_null()); - - EXPECT_FALSE(std::get<0>(trace.at(1))); - EXPECT_TRUE(std::holds_alternative( - std::get<1>(trace.at(1)))); - EXPECT_TRUE(std::get<2>(trace.at(1)).empty()); - EXPECT_TRUE(std::get<3>(trace.at(1)).is_null()); - - EXPECT_TRUE(std::get<0>(trace.at(2))); - EXPECT_TRUE(std::holds_alternative( - std::get<1>(trace.at(2)))); - EXPECT_TRUE(std::get<2>(trace.at(2)).empty()); - EXPECT_TRUE(std::get<3>(trace.at(2)).is_null()); -} - -TEST(JSONSchema_compile_evaluate, fast_step_and_empty_no_condition) { - using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalAnd{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - {}, - {}}}; - - const JSON instance{parse("{ \"foo\": 1 }")}; - const auto result{evaluate(steps, instance)}; - EXPECT_TRUE(result); -} - -TEST(JSONSchema_compile_evaluate, fast_step_and_no_condition_true) { +TEST(JSONSchema_compile_evaluate, fast_step_and_empty) { using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; - const SchemaCompilerTemplate steps{ SchemaCompilerLogicalAnd{Pointer{}, Pointer{}, @@ -391,7 +100,6 @@ TEST(JSONSchema_compile_evaluate, fast_step_and_no_condition_true) { true, true, SchemaCompilerValueNone{}, - children, {}}}; const JSON instance{parse("{ \"foo\": 1 }")}; @@ -399,39 +107,20 @@ TEST(JSONSchema_compile_evaluate, fast_step_and_no_condition_true) { EXPECT_TRUE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_and_no_condition_false) { +TEST(JSONSchema_compile_evaluate, fast_step_and_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{ SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}, + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}, SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Array}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Array}}}; const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalAnd{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - children, - {}}}; + SchemaCompilerLogicalAnd{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueNone{}, children}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; @@ -442,14 +131,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_empty) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopProperties{{"loop"}, @@ -459,8 +142,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_empty) { true, true, SchemaCompilerValueNone{}, - children, - {}}}; + children}}; const JSON instance{parse("{}")}; const auto result{evaluate(steps, instance)}; @@ -471,14 +153,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_single_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{"loop", "type"}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Integer}, - {}}}; + Pointer{"loop", "type"}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::Integer}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopProperties{{"loop"}, @@ -488,8 +164,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_single_true) { true, true, SchemaCompilerValueNone{}, - children, - {}}}; + children}}; const JSON instance{parse("{ \"foo\": 1 }")}; const auto result{evaluate(steps, instance)}; @@ -500,14 +175,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_single_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{"loop", "type"}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Integer}, - {}}}; + Pointer{"loop", "type"}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::Integer}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopProperties{{"loop"}, @@ -517,8 +186,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_single_false) { true, true, SchemaCompilerValueNone{}, - children, - {}}}; + children}}; const JSON instance{parse("{ \"foo\": true }")}; const auto result{evaluate(steps, instance)}; @@ -529,14 +197,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_multi_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{"loop", "type"}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Integer}, - {}}}; + Pointer{"loop", "type"}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::Integer}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopProperties{{"loop"}, @@ -546,8 +208,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_multi_true) { true, true, SchemaCompilerValueNone{}, - children, - {}}}; + children}}; const JSON instance{parse("{ \"foo\": 1, \"bar\": 2 }")}; const auto result{evaluate(steps, instance)}; @@ -558,14 +219,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_multi_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{"loop", "type"}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Integer}, - {}}}; + Pointer{"loop", "type"}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::Integer}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopProperties{{"loop"}, @@ -575,8 +230,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_properties_multi_false) { true, true, SchemaCompilerValueNone{}, - children, - {}}}; + children}}; const JSON instance{parse("{ \"foo\": 1, \"bar\": true }")}; const auto result{evaluate(steps, instance)}; @@ -587,14 +241,9 @@ TEST(JSONSchema_compile_evaluate, fast_regex_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerAssertionRegex{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueRegex{std::regex{"^a", std::regex::ECMAScript}, "^a"}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueRegex{std::regex{"^a", std::regex::ECMAScript}, + "^a"}}}; const JSON instance{"abc"}; const auto result{evaluate(steps, instance)}; @@ -605,14 +254,9 @@ TEST(JSONSchema_compile_evaluate, fast_regex_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerAssertionRegex{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueRegex{std::regex{"^a", std::regex::ECMAScript}, "^a"}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueRegex{std::regex{"^a", std::regex::ECMAScript}, + "^a"}}}; const JSON instance{"foo"}; const auto result{evaluate(steps, instance)}; @@ -622,25 +266,12 @@ TEST(JSONSchema_compile_evaluate, fast_regex_false) { TEST(JSONSchema_compile_evaluate, fast_step_not_type_true) { using namespace sourcemeta::jsontoolkit; SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Integer}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Integer}}}; const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalNot{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - std::move(children), - {}}}; + SchemaCompilerLogicalNot{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueNone{}, std::move(children)}}; const JSON instance{"foo"}; const auto result{evaluate(steps, instance)}; @@ -650,25 +281,12 @@ TEST(JSONSchema_compile_evaluate, fast_step_not_type_true) { TEST(JSONSchema_compile_evaluate, fast_step_not_type_false) { using namespace sourcemeta::jsontoolkit; SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Integer}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Integer}}}; const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalNot{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - std::move(children), - {}}}; + SchemaCompilerLogicalNot{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueNone{}, std::move(children)}}; const JSON instance{5}; const auto result{evaluate(steps, instance)}; @@ -679,14 +297,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_empty) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -696,8 +308,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_empty) { true, true, SchemaCompilerValueUnsignedInteger{0}, - children, - {}}}; + children}}; const JSON instance{parse("[]")}; const auto result{evaluate(steps, instance)}; @@ -708,14 +319,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_single_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -725,8 +330,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_single_true) { true, true, SchemaCompilerValueUnsignedInteger{0}, - children, - {}}}; + children}}; const JSON instance{parse("[ \"foo\" ]")}; const auto result{evaluate(steps, instance)}; @@ -737,14 +341,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_single_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -754,8 +352,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_single_false) { true, true, SchemaCompilerValueUnsignedInteger{0}, - children, - {}}}; + children}}; const JSON instance{parse("[ 5 ]")}; const auto result{evaluate(steps, instance)}; @@ -766,14 +363,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_multi_true) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -783,8 +374,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_multi_true) { true, true, SchemaCompilerValueUnsignedInteger{0}, - children, - {}}}; + children}}; const JSON instance{parse("[ \"foo\", \"bar\", \"baz\" ]")}; const auto result{evaluate(steps, instance)}; @@ -795,14 +385,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_multi_false) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -812,60 +396,19 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_multi_false) { true, true, SchemaCompilerValueUnsignedInteger{0}, - children, - {}}}; + children}}; const JSON instance{parse("[ \"foo\", 4, \"baz\" ]")}; const auto result{evaluate(steps, instance)}; EXPECT_FALSE(result); } -TEST(JSONSchema_compile_evaluate, fast_step_size_greater_array_true) { - using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionSizeGreater{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueUnsignedInteger{2}, - {}}}; - - const JSON instance{parse("[ 1, 2, 3 ]")}; - const auto result{evaluate(steps, instance)}; - EXPECT_TRUE(result); -} - -TEST(JSONSchema_compile_evaluate, fast_step_size_greater_array_false) { - using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionSizeGreater{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueUnsignedInteger{3}, - {}}}; - - const JSON instance{parse("[ 1, 2, 3 ]")}; - const auto result{evaluate(steps, instance)}; - EXPECT_FALSE(result); -} - TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_empty) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -875,8 +418,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_empty) { true, true, SchemaCompilerValueUnsignedInteger{2}, - children, - {}}}; + children}}; const JSON instance{parse("[]")}; const auto result{evaluate(steps, instance)}; @@ -887,14 +429,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_less) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -904,8 +440,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_less) { true, true, SchemaCompilerValueUnsignedInteger{2}, - children, - {}}}; + children}}; const JSON instance{parse("[ 1, 2 ]")}; const auto result{evaluate(steps, instance)}; @@ -916,14 +451,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_match) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -933,8 +462,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_match) { true, true, SchemaCompilerValueUnsignedInteger{2}, - children, - {}}}; + children}}; const JSON instance{parse("[ 1, 2, \"foo\", \"bar\" ]")}; const auto result{evaluate(steps, instance)}; @@ -945,14 +473,8 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_no_match) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#/loop/type", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#/loop/type", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ SchemaCompilerLoopItems{{"loop"}, @@ -962,8 +484,7 @@ TEST(JSONSchema_compile_evaluate, fast_loop_items_with_index_no_match) { true, true, SchemaCompilerValueUnsignedInteger{2}, - children, - {}}}; + children}}; const JSON instance{parse("[ 1, 2, 3, \"foo\" ]")}; const auto result{evaluate(steps, instance)}; diff --git a/test/jsonschema/jsonschema_compile_json_test.cc b/test/jsonschema/jsonschema_compile_json_test.cc index 8c1245f60..6bdd1ba66 100644 --- a/test/jsonschema/jsonschema_compile_json_test.cc +++ b/test/jsonschema/jsonschema_compile_json_test.cc @@ -6,14 +6,8 @@ TEST(JSONSchema_compile_json, defines_basic_root) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionDefines{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueString{"foo"}, - {}}}; + SchemaCompilerAssertionDefines{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueString{"foo"}}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -30,8 +24,7 @@ TEST(JSONSchema_compile_json, defines_basic_root) { "category": "value", "type": "string", "value": "foo" - }, - "condition": [] + } } ])EOF")}; @@ -40,15 +33,9 @@ TEST(JSONSchema_compile_json, defines_basic_root) { TEST(JSONSchema_compile_json, defines_basic_nested) { using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionDefines{Pointer{"foo", "bar"}, - Pointer{}, - "#/foo/bar", - "", - true, - true, - SchemaCompilerValueString{"foo"}, - {}}}; + const SchemaCompilerTemplate steps{SchemaCompilerAssertionDefines{ + Pointer{"foo", "bar"}, Pointer{}, "#/foo/bar", "", true, true, + SchemaCompilerValueString{"foo"}}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -65,65 +52,7 @@ TEST(JSONSchema_compile_json, defines_basic_nested) { "category": "value", "type": "string", "value": "foo" - }, - "condition": [] - } - ])EOF")}; - - EXPECT_EQ(result, expected); -} - -TEST(JSONSchema_compile_json, defines_with_condition) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate condition{ - SchemaCompilerAssertionDefines{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueString{"xxx"}, - {}}}; - - const SchemaCompilerTemplate steps{SchemaCompilerAssertionDefines{ - Pointer{}, Pointer{}, "#", "", true, true, - SchemaCompilerValueString{"baz"}, condition}}; - - const JSON result{to_json(steps)}; - const JSON expected{parse(R"EOF([ - { - "category": "assertion", - "type": "defines", - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "value": { - "category": "value", - "type": "string", - "value": "baz" - }, - "condition": [ - { - "category": "assertion", - "condition": [], - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "type": "defines", - "value": { - "category": "value", - "type": "string", - "value": "xxx" - } - } - ] + } } ])EOF")}; @@ -132,15 +61,8 @@ TEST(JSONSchema_compile_json, defines_with_condition) { TEST(JSONSchema_compile_json, fail_basic_root) { using namespace sourcemeta::jsontoolkit; - const SchemaCompilerTemplate steps{ - SchemaCompilerAssertionFail{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - {}}}; + const SchemaCompilerTemplate steps{SchemaCompilerAssertionFail{ + Pointer{}, Pointer{}, "#", "", true, true, SchemaCompilerValueNone{}}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -153,8 +75,7 @@ TEST(JSONSchema_compile_json, fail_basic_root) { "dynamic": true, "report": true, "absoluteKeywordLocation": "#", - "value": null, - "condition": [] + "value": null } ])EOF")}; @@ -164,14 +85,8 @@ TEST(JSONSchema_compile_json, fail_basic_root) { TEST(JSONSchema_compile_json, type_basic_root) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -188,8 +103,7 @@ TEST(JSONSchema_compile_json, type_basic_root) { "category": "value", "type": "type", "value": "string" - }, - "condition": [] + } } ])EOF")}; @@ -199,7 +113,7 @@ TEST(JSONSchema_compile_json, type_basic_root) { TEST(JSONSchema_compile_json, or_empty) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, {}, {}}}; + Pointer{}, Pointer{}, "#", "", true, true, false, {}}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -217,8 +131,7 @@ TEST(JSONSchema_compile_json, or_empty) { "dynamic": true, "report": true, "absoluteKeywordLocation": "#", - "children": [], - "condition": [] + "children": [] } ])EOF")}; @@ -229,17 +142,11 @@ TEST(JSONSchema_compile_json, or_single_child) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, children, {}}}; + Pointer{}, Pointer{}, "#", "", true, true, false, children}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -271,11 +178,9 @@ TEST(JSONSchema_compile_json, or_single_child) { "category": "value", "type": "type", "value": "string" - }, - "condition": [] + } } - ], - "condition": [] + ] } ])EOF")}; @@ -287,26 +192,14 @@ TEST(JSONSchema_compile_json, or_multiple_children) { const SchemaCompilerTemplate children{ SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}, + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}, SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Array}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Array}}}; const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, children, {}}}; + Pointer{}, Pointer{}, "#", "", true, true, false, children}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -338,8 +231,7 @@ TEST(JSONSchema_compile_json, or_multiple_children) { "category": "value", "type": "type", "value": "string" - }, - "condition": [] + } }, { "category": "assertion", @@ -354,66 +246,7 @@ TEST(JSONSchema_compile_json, or_multiple_children) { "category": "value", "type": "type", "value": "array" - }, - "condition": [] - } - ], - "condition": [] - } - ])EOF")}; - - EXPECT_EQ(result, expected); -} - -TEST(JSONSchema_compile_json, or_empty_single_condition) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate condition{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; - - const SchemaCompilerTemplate steps{SchemaCompilerLogicalOr{ - Pointer{}, Pointer{}, "#", "", true, true, false, {}, condition}}; - - const JSON result{to_json(steps)}; - const JSON expected{parse(R"EOF([ - { - "category": "logical", - "type": "or", - "value": { - "category": "value", - "type": "boolean", - "value": false - }, - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "children": [], - "condition": [ - { - "category": "assertion", - "type": "type-strict", - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "value": { - "category": "value", - "type": "type", - "value": "string" - }, - "condition": [] + } } ] } @@ -432,7 +265,6 @@ TEST(JSONSchema_compile_json, and_empty) { true, true, SchemaCompilerValueNone{}, - {}, {}}}; const JSON result{to_json(steps)}; @@ -447,8 +279,7 @@ TEST(JSONSchema_compile_json, and_empty) { "dynamic": true, "report": true, "absoluteKeywordLocation": "#", - "children": [], - "condition": [] + "children": [] } ])EOF")}; @@ -459,25 +290,12 @@ TEST(JSONSchema_compile_json, and_single_child) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}}; const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalAnd{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - children, - {}}}; + SchemaCompilerLogicalAnd{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueNone{}, children}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -505,11 +323,9 @@ TEST(JSONSchema_compile_json, and_single_child) { "category": "value", "type": "type", "value": "string" - }, - "condition": [] + } } - ], - "condition": [] + ] } ])EOF")}; @@ -521,34 +337,15 @@ TEST(JSONSchema_compile_json, and_multiple_children) { const SchemaCompilerTemplate children{ SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}, + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::String}}, SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Array}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueType{JSON::Type::Array}}}; const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalAnd{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - children, - {}}}; + SchemaCompilerLogicalAnd{Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueNone{}, children}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -576,8 +373,7 @@ TEST(JSONSchema_compile_json, and_multiple_children) { "category": "value", "type": "type", "value": "string" - }, - "condition": [] + } }, { "category": "assertion", @@ -592,237 +388,7 @@ TEST(JSONSchema_compile_json, and_multiple_children) { "category": "value", "type": "type", "value": "array" - }, - "condition": [] - } - ], - "condition": [] - } - ])EOF")}; - - EXPECT_EQ(result, expected); -} - -TEST(JSONSchema_compile_json, and_empty_single_condition) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate condition{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; - - const SchemaCompilerTemplate steps{ - SchemaCompilerLogicalAnd{Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueNone{}, - {}, - condition}}; - - const JSON result{to_json(steps)}; - const JSON expected{parse(R"EOF([ - { - "category": "logical", - "type": "and", - "value": null, - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "children": [], - "condition": [ - { - "category": "assertion", - "type": "type-strict", - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "value": { - "category": "value", - "type": "type", - "value": "string" - }, - "condition": [] - } - ] - } - ])EOF")}; - - EXPECT_EQ(result, expected); -} - -TEST(JSONSchema_compile_json, public_annotation_without_condition) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate steps{SchemaCompilerAnnotationEmit{ - Pointer{"test"}, Pointer{}, "#/test", "", true, true, JSON{5}, {}}}; - - const JSON result{to_json(steps)}; - const JSON expected{parse(R"EOF([ - { - "category": "annotation", - "type": "emit", - "relativeSchemaLocation": "/test", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#/test", - "value": { - "category": "value", - "type": "json", - "value": 5 - }, - "condition": [] - } - ])EOF")}; - - EXPECT_EQ(result, expected); -} - -TEST(JSONSchema_compile_json, public_annotation_with_condition) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate condition{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; - - const SchemaCompilerTemplate steps{ - SchemaCompilerAnnotationEmit{Pointer{"test"}, Pointer{}, "#/test", "", - true, true, JSON{5}, condition}}; - - const JSON result{to_json(steps)}; - const JSON expected{parse(R"EOF([ - { - "category": "annotation", - "type": "emit", - "relativeSchemaLocation": "/test", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#/test", - "value": { - "category": "value", - "type": "json", - "value": 5 - }, - "condition": [ - { - "category": "assertion", - "type": "type-strict", - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "value": { - "category": "value", - "type": "type", - "value": "object" - }, - "condition": [] - } - ] - } - ])EOF")}; - - EXPECT_EQ(result, expected); -} - -TEST(JSONSchema_compile_json, loop_properties_with_children_and_condition) { - using namespace sourcemeta::jsontoolkit; - - const SchemaCompilerTemplate children{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::String}, - {}}}; - - const SchemaCompilerTemplate condition{SchemaCompilerAssertionTypeStrict{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueType{JSON::Type::Object}, - {}}}; - - const SchemaCompilerTemplate steps{SchemaCompilerLoopProperties{ - Pointer{"loop"}, Pointer{}, "#/loop", "", true, true, - SchemaCompilerValueNone{}, children, condition}}; - - const JSON result{to_json(steps)}; - const JSON expected{parse(R"EOF([ - { - "category": "loop", - "type": "properties", - "value": null, - "relativeSchemaLocation": "/loop", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#/loop", - "children": [ - { - "category": "assertion", - "type": "type-strict", - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "value": { - "category": "value", - "type": "type", - "value": "string" - }, - "condition": [] - } - ], - "condition": [ - { - "category": "assertion", - "type": "type-strict", - "relativeSchemaLocation": "", - "relativeInstanceLocation": "", - "schemaResource": "", - "dynamic": true, - "report": true, - "absoluteKeywordLocation": "#", - "value": { - "category": "value", - "type": "type", - "value": "object" - }, - "condition": [] + } } ] } @@ -834,14 +400,9 @@ TEST(JSONSchema_compile_json, loop_properties_with_children_and_condition) { TEST(JSONSchema_compile_json, regex_basic) { using namespace sourcemeta::jsontoolkit; const SchemaCompilerTemplate steps{SchemaCompilerAssertionRegex{ - Pointer{}, - Pointer{}, - "#", - "", - true, - true, - SchemaCompilerValueRegex{std::regex{"^a", std::regex::ECMAScript}, "^a"}, - {}}}; + Pointer{}, Pointer{}, "#", "", true, true, + SchemaCompilerValueRegex{std::regex{"^a", std::regex::ECMAScript}, + "^a"}}}; const JSON result{to_json(steps)}; const JSON expected{parse(R"EOF([ @@ -858,8 +419,7 @@ TEST(JSONSchema_compile_json, regex_basic) { "category": "value", "type": "regex", "value": "^a" - }, - "condition": [] + } } ])EOF")}; diff --git a/test/jsonschema/jsonschema_template_format_test.cc b/test/jsonschema/jsonschema_template_format_test.cc index fbafb1886..a9006690c 100644 --- a/test/jsonschema/jsonschema_template_format_test.cc +++ b/test/jsonschema/jsonschema_template_format_test.cc @@ -8,7 +8,6 @@ TEST(JSONSchema_compiler_template_format, example_1) { sourcemeta::jsontoolkit::parse(R"JSON({ "absoluteKeywordLocation": "#/properties", "category": "annotation", - "condition": [], "report": true, "dynamic": true, "type": "public", @@ -37,7 +36,6 @@ TEST(JSONSchema_compiler_template_format, example_1) { "relativeSchemaLocation": "", "relativeInstanceLocation": "", "report": true, - "dynamic": true, - "condition": [] + "dynamic": true })JSON"); }