Skip to content

Commit

Permalink
Extract SchemaWalkerStrategy as KeywordType
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
  • Loading branch information
jviotti committed Jan 2, 2025
1 parent e3d4f14 commit c56aa68
Show file tree
Hide file tree
Showing 17 changed files with 888 additions and 900 deletions.
2 changes: 1 addition & 1 deletion src/jsonschema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include(./official_resolver.cmake)
noa_library(NAMESPACE sourcemeta PROJECT jsontoolkit NAME jsonschema
FOLDER "JSON Toolkit/JSON Schema"
PRIVATE_HEADERS anchor.h bundle.h resolver.h
walker.h reference.h frame.h error.h unevaluated.h
walker.h reference.h frame.h error.h unevaluated.h keywords.h
SOURCES jsonschema.cc default_walker.cc frame.cc
anchor.cc resolver.cc walker.cc bundle.cc unevaluated.cc
"${CMAKE_CURRENT_BINARY_DIR}/official_resolver.cc")
Expand Down
25 changes: 10 additions & 15 deletions src/jsonschema/default_walker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ auto sourcemeta::jsontoolkit::default_schema_walker(
-> sourcemeta::jsontoolkit::SchemaWalkerResult {
#define WALK(vocabulary, _keyword, strategy, ...) \
if (vocabularies.contains(vocabulary) && keyword == _keyword) \
return {sourcemeta::jsontoolkit::SchemaWalkerStrategy::strategy, \
return {sourcemeta::jsontoolkit::KeywordType::strategy, \
vocabulary, \
{__VA_ARGS__}};

Expand Down Expand Up @@ -261,9 +261,8 @@ auto sourcemeta::jsontoolkit::default_schema_walker(
// $ref also takes precedence over any unknown keyword
if (vocabularies.contains(HTTP_BASE "draft-07/schema#") &&
keyword != "$ref") {
return {sourcemeta::jsontoolkit::SchemaWalkerStrategy::Unknown,
std::nullopt,
{"$ref"}};
return {
sourcemeta::jsontoolkit::KeywordType::Unknown, std::nullopt, {"$ref"}};
}

// Draft6
Expand Down Expand Up @@ -327,9 +326,8 @@ auto sourcemeta::jsontoolkit::default_schema_walker(
// $ref also takes precedence over any unknown keyword
if (vocabularies.contains(HTTP_BASE "draft-06/schema#") &&
keyword != "$ref") {
return {sourcemeta::jsontoolkit::SchemaWalkerStrategy::Unknown,
std::nullopt,
{"$ref"}};
return {
sourcemeta::jsontoolkit::KeywordType::Unknown, std::nullopt, {"$ref"}};
}

// Draft4
Expand Down Expand Up @@ -381,9 +379,8 @@ auto sourcemeta::jsontoolkit::default_schema_walker(
// $ref also takes precedence over any unknown keyword
if (vocabularies.contains(HTTP_BASE "draft-04/schema#") &&
keyword != "$ref") {
return {sourcemeta::jsontoolkit::SchemaWalkerStrategy::Unknown,
std::nullopt,
{"$ref"}};
return {
sourcemeta::jsontoolkit::KeywordType::Unknown, std::nullopt, {"$ref"}};
}

// Draft3
Expand Down Expand Up @@ -427,9 +424,8 @@ auto sourcemeta::jsontoolkit::default_schema_walker(
// $ref also takes precedence over any unknown keyword
if (vocabularies.contains(HTTP_BASE "draft-03/schema#") &&
keyword != "$ref") {
return {sourcemeta::jsontoolkit::SchemaWalkerStrategy::Unknown,
std::nullopt,
{"$ref"}};
return {
sourcemeta::jsontoolkit::KeywordType::Unknown, std::nullopt, {"$ref"}};
}

// Draft2
Expand Down Expand Up @@ -552,6 +548,5 @@ auto sourcemeta::jsontoolkit::default_schema_walker(
#undef HTTP_BASE
#undef WALK
#undef WALK_MAYBE_DEPENDENT
return {
sourcemeta::jsontoolkit::SchemaWalkerStrategy::Unknown, std::nullopt, {}};
return {sourcemeta::jsontoolkit::KeywordType::Unknown, std::nullopt, {}};
}
1 change: 1 addition & 0 deletions src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <sourcemeta/jsontoolkit/jsonschema_bundle.h>
#include <sourcemeta/jsontoolkit/jsonschema_error.h>
#include <sourcemeta/jsontoolkit/jsonschema_frame.h>
#include <sourcemeta/jsontoolkit/jsonschema_keywords.h>
#include <sourcemeta/jsontoolkit/jsonschema_reference.h>
#include <sourcemeta/jsontoolkit/jsonschema_resolver.h>
#include <sourcemeta/jsontoolkit/jsonschema_unevaluated.h>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#ifndef SOURCEMETA_JSONTOOLKIT_JSONSCHEMA_KEYWORDS_H_
#define SOURCEMETA_JSONTOOLKIT_JSONSCHEMA_KEYWORDS_H_

#include <cstdint> // std::uint8_t

namespace sourcemeta::jsontoolkit {

#if defined(__GNUC__)
#pragma GCC diagnostic push
// For some strange reason, GCC on Debian 11 believes that a member of
// an enum class (which is namespaced by definition), can shadow an
// alias defined even on a different namespace.
#pragma GCC diagnostic ignored "-Wshadow"
#endif
/// @ingroup jsonschema
/// Determines the type of a JSON Schema keyword
enum class KeywordType : std::uint8_t {
/// The JSON Schema keyword is unknown
Unknown,
/// The JSON Schema keyword is a non-applicator assertion
Assertion,
/// The JSON Schema keyword is a non-applicator annotation
Annotation,
/// The JSON Schema keyword is a reference
Reference,
/// The JSON Schema keyword is known but doesn't match any other type
Other,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument
ApplicatorValue,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument but its evaluation follows
/// special rules
ApplicatorValueOther,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument without affecting the
/// instance location
ApplicatorValueInPlace,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument
ApplicatorElements,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location
ApplicatorElementsInPlace,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location and that can be
/// statically inlined
ApplicatorElementsInline,
/// The JSON Schema keyword is an applicator that potentially
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions
ApplicatorMembers,
/// The JSON Schema keyword is an applicator that potentially
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions without affecting the instance location
ApplicatorMembersInPlace,
/// The JSON Schema keyword is an applicator that may take a JSON Schema
/// definition or an array of potentially JSON Schema definitions
/// as an argument
ApplicatorValueOrElements,
/// The JSON Schema keyword is an applicator that may take a JSON Schema
/// definition or an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location
ApplicatorValueOrElementsInPlace,
/// The JSON Schema keyword is an applicator that may take an array of
/// potentially JSON Schema definitions or an object whose values are
/// potentially JSON Schema definitions as an argument
ApplicatorElementsOrMembers,
/// The JSON Schema keyword is a reserved location that potentially
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions
LocationMembers,
};
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

} // namespace sourcemeta::jsontoolkit

#endif
81 changes: 4 additions & 77 deletions src/jsonschema/include/sourcemeta/jsontoolkit/jsonschema_walker.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

#include <sourcemeta/jsontoolkit/json.h>
#include <sourcemeta/jsontoolkit/jsonpointer.h>
#include <sourcemeta/jsontoolkit/jsonschema_keywords.h>
#include <sourcemeta/jsontoolkit/jsonschema_resolver.h>

#include <cstdint> // std::uint8_t
#include <cstdint> // std::uint64_t
#include <functional> // std::function
#include <map> // std::map
#include <optional> // std::optional
Expand All @@ -20,85 +21,11 @@

namespace sourcemeta::jsontoolkit {

#if defined(__GNUC__)
#pragma GCC diagnostic push
// For some strange reason, GCC on Debian 11 believes that a member of
// an enum class (which is namespaced by definition), can shadow an
// alias defined even on a different namespace.
#pragma GCC diagnostic ignored "-Wshadow"
#endif
// TODO: Extract this into a more generic keyword identification enumeration
/// @ingroup jsonschema
/// Determines the possible states of a schema walk strategy
enum class SchemaWalkerStrategy : std::uint8_t {
/// The JSON Schema keyword is unknown
Unknown,
/// The JSON Schema keyword is a non-applicator assertion
Assertion,
/// The JSON Schema keyword is a non-applicator annotation
Annotation,
/// The JSON Schema keyword is a reference
Reference,
/// The JSON Schema keyword is known but doesn't match any other type
Other,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument
ApplicatorValue,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument but its evaluation follows
/// special rules
ApplicatorValueOther,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument without affecting the
/// instance location
ApplicatorValueInPlace,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument
ApplicatorElements,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location
ApplicatorElementsInPlace,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location and that can be
/// statically inlined
ApplicatorElementsInline,
/// The JSON Schema keyword is an applicator that potentially
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions
ApplicatorMembers,
/// The JSON Schema keyword is an applicator that potentially
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions without affecting the instance location
ApplicatorMembersInPlace,
/// The JSON Schema keyword is an applicator that may take a JSON Schema
/// definition or an array of potentially JSON Schema definitions
/// as an argument
ApplicatorValueOrElements,
/// The JSON Schema keyword is an applicator that may take a JSON Schema
/// definition or an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location
ApplicatorValueOrElementsInPlace,
/// The JSON Schema keyword is an applicator that may take an array of
/// potentially JSON Schema definitions or an object whose values are
/// potentially JSON Schema definitions as an argument
ApplicatorElementsOrMembers,
/// The JSON Schema keyword is a reserved location that potentially
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions
LocationMembers,
};
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

/// @ingroup jsonschema
/// A structure that encapsulates the result of walker over a specific keyword
struct SchemaWalkerResult {
/// The walker strategy to continue traversing across the schema
const SchemaWalkerStrategy strategy;
const KeywordType type;
/// The vocabulary associated with the keyword, if any
const std::optional<std::string> vocabulary;
/// The keywords a given keyword depends on (if any) during the evaluation
Expand Down Expand Up @@ -127,7 +54,7 @@ SOURCEMETA_JSONTOOLKIT_JSONSCHEMA_EXPORT
inline auto schema_walker_none(std::string_view,
const std::map<std::string, bool> &)
-> sourcemeta::jsontoolkit::SchemaWalkerResult {
return {SchemaWalkerStrategy::Unknown, std::nullopt, {}};
return {KeywordType::Unknown, std::nullopt, {}};
}

/// @ingroup jsonschema
Expand Down
16 changes: 7 additions & 9 deletions src/jsonschema/unevaluated.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ auto find_adjacent_dependencies(
continue;
}

const auto strategy{
walker(property.first, subschema_vocabularies).strategy};
switch (strategy) {
switch (walker(property.first, subschema_vocabularies).type) {
// References
case SchemaWalkerStrategy::Reference:
case KeywordType::Reference:
if (references.contains({ReferenceType::Static,
entry.pointer.concat({property.first})})) {
const auto &reference{references.at(
Expand All @@ -82,7 +80,7 @@ auto find_adjacent_dependencies(
break;

// Static
case SchemaWalkerStrategy::ApplicatorElementsInline:
case KeywordType::ApplicatorElementsInline:
for (std::size_t index = 0; index < property.second.size(); index++) {
find_adjacent_dependencies(
current, schema, frame, references, walker, resolver, keywords,
Expand All @@ -93,7 +91,7 @@ auto find_adjacent_dependencies(
break;

// Dynamic
case SchemaWalkerStrategy::ApplicatorElementsInPlace:
case KeywordType::ApplicatorElementsInPlace:
if (property.second.is_array()) {
for (std::size_t index = 0; index < property.second.size(); index++) {
find_adjacent_dependencies(
Expand All @@ -104,7 +102,7 @@ auto find_adjacent_dependencies(
}

break;
case SchemaWalkerStrategy::ApplicatorValueInPlace:
case KeywordType::ApplicatorValueInPlace:
if (is_schema(property.second)) {
find_adjacent_dependencies(
current, schema, frame, references, walker, resolver, keywords,
Expand All @@ -113,7 +111,7 @@ auto find_adjacent_dependencies(
}

break;
case SchemaWalkerStrategy::ApplicatorValueOrElementsInPlace:
case KeywordType::ApplicatorValueOrElementsInPlace:
if (property.second.is_array()) {
for (std::size_t index = 0; index < property.second.size(); index++) {
find_adjacent_dependencies(
Expand All @@ -129,7 +127,7 @@ auto find_adjacent_dependencies(
}

break;
case SchemaWalkerStrategy::ApplicatorMembersInPlace:
case KeywordType::ApplicatorMembersInPlace:
if (property.second.is_object()) {
for (const auto &pair : property.second.as_object()) {
find_adjacent_dependencies(
Expand Down
Loading

0 comments on commit c56aa68

Please sign in to comment.