Skip to content

Commit 55d6860

Browse files
authored
Add a compile() overload that takes an existing schema frame (#404)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 02a246f commit 55d6860

5 files changed

Lines changed: 94 additions & 16 deletions

File tree

DEPENDENCIES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a4140267959ae334d3ecf4
2-
core https://github.com/sourcemeta/core 89c1394849a488667f03ec5ee1844326570f486d
2+
core https://github.com/sourcemeta/core 78c8548ce280f2bf88a1f21eb509046ac54f1532
33
jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite 4ba013d58e747ecaf48c8bb7cf248cb0d564afbc

src/compiler/compile.cc

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,11 @@ namespace sourcemeta::blaze {
103103
auto compile(const sourcemeta::core::JSON &schema,
104104
const sourcemeta::core::SchemaWalker &walker,
105105
const sourcemeta::core::SchemaResolver &resolver,
106-
const Compiler &compiler, const Mode mode,
106+
const Compiler &compiler,
107+
const sourcemeta::core::SchemaFrame &frame, const Mode mode,
107108
const std::optional<std::string> &default_dialect) -> Template {
108109
assert(is_schema(schema));
109110

110-
// Make sure the input schema is bundled, otherwise we won't be able to
111-
// resolve remote references here
112-
const sourcemeta::core::JSON result{
113-
sourcemeta::core::bundle(schema, walker, resolver, default_dialect)};
114-
115-
// Perform framing to resolve references later on
116-
sourcemeta::core::SchemaFrame frame{
117-
sourcemeta::core::SchemaFrame::Mode::References};
118-
frame.analyse(result, walker, resolver, default_dialect);
119-
120111
const std::string base{sourcemeta::core::URI{
121112
sourcemeta::core::identify(
122113
schema, resolver,
@@ -144,7 +135,7 @@ auto compile(const sourcemeta::core::JSON &schema,
144135

145136
SchemaContext schema_context{
146137
sourcemeta::core::empty_pointer,
147-
result,
138+
schema,
148139
vocabularies(schema, resolver, root_frame_entry.dialect),
149140
sourcemeta::core::URI{root_frame_entry.base}.canonicalize().recompose(),
150141
{},
@@ -207,10 +198,10 @@ auto compile(const sourcemeta::core::JSON &schema,
207198
}
208199

209200
auto unevaluated{
210-
sourcemeta::core::unevaluated(result, frame, walker, resolver)};
201+
sourcemeta::core::unevaluated(schema, frame, walker, resolver)};
211202

212-
const Context context{result,
213-
std::move(frame),
203+
const Context context{schema,
204+
frame,
214205
std::move(resources),
215206
walker,
216207
resolver,
@@ -275,6 +266,27 @@ auto compile(const sourcemeta::core::JSON &schema,
275266
}
276267
}
277268

269+
auto compile(const sourcemeta::core::JSON &schema,
270+
const sourcemeta::core::SchemaWalker &walker,
271+
const sourcemeta::core::SchemaResolver &resolver,
272+
const Compiler &compiler, const Mode mode,
273+
const std::optional<std::string> &default_dialect) -> Template {
274+
assert(is_schema(schema));
275+
276+
// Make sure the input schema is bundled, otherwise we won't be able to
277+
// resolve remote references here
278+
const sourcemeta::core::JSON result{
279+
sourcemeta::core::bundle(schema, walker, resolver, default_dialect)};
280+
281+
// Perform framing to resolve references later on
282+
sourcemeta::core::SchemaFrame frame{
283+
sourcemeta::core::SchemaFrame::Mode::References};
284+
frame.analyse(result, walker, resolver, default_dialect);
285+
286+
return compile(result, walker, resolver, compiler, frame, mode,
287+
default_dialect);
288+
}
289+
278290
auto compile(const Context &context, const SchemaContext &schema_context,
279291
const DynamicContext &dynamic_context,
280292
const sourcemeta::core::Pointer &schema_suffix,

src/compiler/include/sourcemeta/blaze/compiler.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,24 @@ compile(const sourcemeta::core::JSON &schema,
148148
const std::optional<std::string> &default_dialect = std::nullopt)
149149
-> Template;
150150

151+
/// @ingroup compiler
152+
///
153+
/// This function compiles an input JSON Schema into a template that can be
154+
/// later evaluated, but given an existing schema frame. The schema frame must
155+
/// contain reference information for the given schema and the input schema must
156+
/// be bundled. If those pre-conditions are not met, you will hit undefined
157+
/// behavior.
158+
///
159+
/// Don't use this function unless you know what you are doing.
160+
auto SOURCEMETA_BLAZE_COMPILER_EXPORT
161+
compile(const sourcemeta::core::JSON &schema,
162+
const sourcemeta::core::SchemaWalker &walker,
163+
const sourcemeta::core::SchemaResolver &resolver,
164+
const Compiler &compiler, const sourcemeta::core::SchemaFrame &frame,
165+
const Mode mode = Mode::FastValidation,
166+
const std::optional<std::string> &default_dialect = std::nullopt)
167+
-> Template;
168+
151169
/// @ingroup compiler
152170
///
153171
/// This function compiles a single subschema into a compiler template as

test/evaluator/evaluator_test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,51 @@ TEST(Evaluator, cross_2012_12_ref_2019_09_without_id) {
126126
EXPECT_TRUE(evaluator.validate(compiled_schema, instance));
127127
}
128128

129+
TEST(Evaluator, explicit_frame) {
130+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
131+
"$schema": "https://json-schema.org/draft/2020-12/schema",
132+
"allOf": [ { "$ref": "https://json-schema.org/draft/2020-12/schema" } ]
133+
})JSON")};
134+
135+
const sourcemeta::core::JSON result{
136+
sourcemeta::core::bundle(schema, sourcemeta::core::schema_official_walker,
137+
sourcemeta::core::schema_official_resolver)};
138+
sourcemeta::core::SchemaFrame frame{
139+
sourcemeta::core::SchemaFrame::Mode::References};
140+
frame.analyse(result, sourcemeta::core::schema_official_walker,
141+
sourcemeta::core::schema_official_resolver);
142+
143+
const auto compiled_schema{sourcemeta::blaze::compile(
144+
result, sourcemeta::core::schema_official_walker,
145+
sourcemeta::core::schema_official_resolver,
146+
sourcemeta::blaze::default_schema_compiler, frame)};
147+
148+
sourcemeta::blaze::Evaluator evaluator;
149+
const sourcemeta::core::JSON instance{true};
150+
EXPECT_TRUE(evaluator.validate(compiled_schema, instance));
151+
}
152+
153+
TEST(Evaluator, explicit_frame_locations_only) {
154+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
155+
"$schema": "https://json-schema.org/draft/2020-12/schema",
156+
"allOf": [ { "$ref": "https://json-schema.org/draft/2020-12/schema" } ]
157+
})JSON")};
158+
159+
const sourcemeta::core::JSON result{
160+
sourcemeta::core::bundle(schema, sourcemeta::core::schema_official_walker,
161+
sourcemeta::core::schema_official_resolver)};
162+
sourcemeta::core::SchemaFrame frame{
163+
sourcemeta::core::SchemaFrame::Mode::Locations};
164+
frame.analyse(result, sourcemeta::core::schema_official_walker,
165+
sourcemeta::core::schema_official_resolver);
166+
167+
EXPECT_THROW(sourcemeta::blaze::compile(
168+
result, sourcemeta::core::schema_official_walker,
169+
sourcemeta::core::schema_official_resolver,
170+
sourcemeta::blaze::default_schema_compiler, frame),
171+
sourcemeta::core::SchemaReferenceError);
172+
}
173+
129174
TEST(Evaluator, is_annotation) {
130175
EXPECT_TRUE(sourcemeta::blaze::is_annotation(
131176
sourcemeta::blaze::InstructionIndex::AnnotationBasenameToParent));

vendor/core/src/core/jsonschema/include/sourcemeta/core/jsonschema_frame.h

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)