diff --git a/DEPENDENCIES b/DEPENDENCIES index d131e6f..70452d7 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,4 +1,4 @@ vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a4140267959ae334d3ecf4 noa https://github.com/sourcemeta/noa 5ff4024902642afc9cc2f9a9e02ae9dff9d15d4f -jsontoolkit https://github.com/sourcemeta/jsontoolkit 72dde22434cfa827201dbde10af976c82bd99a43 +jsontoolkit https://github.com/sourcemeta/jsontoolkit 958d686c4bbcb1f232ed8d313956929e38af84d2 hydra https://github.com/sourcemeta/hydra d5e0c314dae88b0bf2ac4eeff2c7395910e2c7e9 diff --git a/src/command_test.cc b/src/command_test.cc index a4584ff..e9b1ffa 100644 --- a/src/command_test.cc +++ b/src/command_test.cc @@ -42,9 +42,14 @@ auto intelligence::jsonschema::cli::test( } if (options.contains("m") || options.contains("metaschema")) { - const auto metaschema_result{ - validate_against_metaschema(schema.value(), test_resolver)}; - if (metaschema_result) { + const auto metaschema_template{sourcemeta::jsontoolkit::compile( + sourcemeta::jsontoolkit::metaschema(schema.value(), test_resolver), + sourcemeta::jsontoolkit::default_schema_walker, test_resolver, + sourcemeta::jsontoolkit::default_schema_compiler)}; + if (sourcemeta::jsontoolkit::evaluate( + metaschema_template, schema.value(), + sourcemeta::jsontoolkit::SchemaCompilerEvaluationMode::Fast, + pretty_evaluate_callback)) { log_verbose(options) << "The schema is valid with respect to its metaschema\n"; } else { diff --git a/src/command_validate.cc b/src/command_validate.cc index 3d5d247..f3a4a88 100644 --- a/src/command_validate.cc +++ b/src/command_validate.cc @@ -27,9 +27,14 @@ auto intelligence::jsonschema::cli::validate( // TODO: If not instance is passed, just validate the schema against its // metaschema? if (options.contains("m") || options.contains("metaschema")) { - const auto metaschema_result{ - validate_against_metaschema(schema, custom_resolver)}; - if (metaschema_result) { + const auto metaschema_template{sourcemeta::jsontoolkit::compile( + sourcemeta::jsontoolkit::metaschema(schema, custom_resolver), + sourcemeta::jsontoolkit::default_schema_walker, custom_resolver, + sourcemeta::jsontoolkit::default_schema_compiler)}; + if (sourcemeta::jsontoolkit::evaluate( + metaschema_template, schema, + sourcemeta::jsontoolkit::SchemaCompilerEvaluationMode::Fast, + pretty_evaluate_callback)) { log_verbose(options) << "The schema is valid with respect to its metaschema\n"; } else { diff --git a/src/utils.cc b/src/utils.cc index 234824e..961d4a8 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -206,29 +206,4 @@ auto log_verbose(const std::map> &options) return null_stream; } -auto validate_against_metaschema( - const sourcemeta::jsontoolkit::JSON &schema, - const sourcemeta::jsontoolkit::SchemaResolver &resolver) -> bool { - const std::optional dialect{ - sourcemeta::jsontoolkit::dialect(schema)}; - if (!dialect.has_value()) { - throw std::runtime_error( - "Cannot determine the dialect of the input schema"); - } - - const auto metaschema{resolver(dialect.value()).get()}; - if (!metaschema.has_value()) { - throw sourcemeta::jsontoolkit::SchemaResolutionError( - dialect.value(), "Could not resolve metaschema"); - } - - const auto metaschema_template{sourcemeta::jsontoolkit::compile( - metaschema.value(), sourcemeta::jsontoolkit::default_schema_walker, - resolver, sourcemeta::jsontoolkit::default_schema_compiler)}; - return sourcemeta::jsontoolkit::evaluate( - metaschema_template, schema, - sourcemeta::jsontoolkit::SchemaCompilerEvaluationMode::Fast, - pretty_evaluate_callback); -} - } // namespace intelligence::jsonschema::cli diff --git a/src/utils.h b/src/utils.h index bcd223e..63a3259 100644 --- a/src/utils.h +++ b/src/utils.h @@ -45,10 +45,6 @@ auto resolver(const std::map> &options, auto log_verbose(const std::map> &options) -> std::ostream &; -auto validate_against_metaschema( - const sourcemeta::jsontoolkit::JSON &schema, - const sourcemeta::jsontoolkit::SchemaResolver &resolver) -> bool; - } // namespace intelligence::jsonschema::cli #endif diff --git a/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema.h b/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema.h index cd42097..218b043 100644 --- a/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema.h +++ b/vendor/jsontoolkit/src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema.h @@ -132,6 +132,35 @@ auto dialect(const JSON &schema, const std::optional &default_dialect = std::nullopt) -> std::optional; +/// @ingroup jsonschema +/// +/// Get the metaschema document that describes the given schema. For example: +/// +/// ```cpp +/// #include +/// #include +/// #include +/// +/// const sourcemeta::jsontoolkit::JSON document = +/// sourcemeta::jsontoolkit::parse(R"JSON({ +/// "$schema": "https://json-schema.org/draft/2020-12/schema", +/// "type": "object" +/// })JSON"); +/// +/// const sourcemeta::jsontoolkit::JSON metaschema{ +/// sourcemeta::jsontoolkit::metaschema( +/// document, sourcemeta::jsontoolkit::official_resolver)}; +/// +/// sourcemeta::jsontoolkit::prettify(metaschema, std::cout); +/// std::cout << std::endl; +/// ``` +/// +/// This function will throw if the metaschema cannot be determined or resolved. +SOURCEMETA_JSONTOOLKIT_JSONSCHEMA_EXPORT +auto metaschema( + const JSON &schema, const SchemaResolver &resolver, + const std::optional &default_dialect = std::nullopt) -> JSON; + /// @ingroup jsonschema /// /// Get the URI of the base dialect that applies to the given schema. If you set diff --git a/vendor/jsontoolkit/src/jsonschema/jsonschema.cc b/vendor/jsontoolkit/src/jsonschema/jsonschema.cc index 27361d1..3d25758 100644 --- a/vendor/jsontoolkit/src/jsonschema/jsonschema.cc +++ b/vendor/jsontoolkit/src/jsonschema/jsonschema.cc @@ -86,6 +86,27 @@ auto sourcemeta::jsontoolkit::dialect( return dialect.to_string(); } +auto sourcemeta::jsontoolkit::metaschema( + const sourcemeta::jsontoolkit::JSON &schema, + const sourcemeta::jsontoolkit::SchemaResolver &resolver, + const std::optional &default_dialect) -> JSON { + const auto maybe_dialect{ + sourcemeta::jsontoolkit::dialect(schema, default_dialect)}; + if (!maybe_dialect.has_value()) { + throw sourcemeta::jsontoolkit::SchemaError( + "Could not determine dialect of the schema"); + } + + const auto maybe_metaschema{resolver(maybe_dialect.value()).get()}; + if (!maybe_metaschema.has_value()) { + throw sourcemeta::jsontoolkit::SchemaResolutionError( + maybe_dialect.value(), + "Could not resolve the metaschema of the schema"); + } + + return maybe_metaschema.value(); +} + auto sourcemeta::jsontoolkit::base_dialect( const sourcemeta::jsontoolkit::JSON &schema, const sourcemeta::jsontoolkit::SchemaResolver &resolver,