|
|
@@ -20,6 +20,7 @@
|
|
|
#include <jvalidate/detail/vocabulary.h>
|
|
|
#include <jvalidate/enum.h>
|
|
|
#include <jvalidate/forward.h>
|
|
|
+#include <jvalidate/vocabulary.h>
|
|
|
|
|
|
namespace jvalidate {
|
|
|
/**
|
|
|
@@ -42,32 +43,12 @@ namespace jvalidate {
|
|
|
template <Adapter A> class ConstraintFactory {
|
|
|
public:
|
|
|
using pConstraint = std::unique_ptr<constraint::Constraint>;
|
|
|
- // ParserContext<A> => pConstraint
|
|
|
- using MakeConstraint = typename detail::Vocabulary<A>::MakeConstraint;
|
|
|
-
|
|
|
- using Object = decltype(std::declval<A>().as_object());
|
|
|
- enum KeywordType { Keyword, Removed };
|
|
|
-
|
|
|
- /**
|
|
|
- * @brief This type represents a union of three different "parsing handler"
|
|
|
- * states:
|
|
|
- * 1) "Removed" - this schema token is not a keyword, and does not generate
|
|
|
- * a constraint.
|
|
|
- * 2) "Keyword" - this schema token represents a keyword, but does not
|
|
|
- * have a constraint associated with it. For example: "$defs" or "$comment"
|
|
|
- * 3) "Make" - this schema token is a keyword with an associated constant
|
|
|
- * generating function.
|
|
|
- */
|
|
|
- struct Make {
|
|
|
- Make(KeywordType t) : is_keyword(t == Keyword) {}
|
|
|
- template <typename F> Make(F make) : make(make), is_keyword(true) {}
|
|
|
-
|
|
|
- explicit operator bool() const { return make || is_keyword; }
|
|
|
- operator MakeConstraint() const { return make; }
|
|
|
-
|
|
|
- MakeConstraint make = nullptr;
|
|
|
- bool is_keyword = false;
|
|
|
- };
|
|
|
+ using DependentKeyword = vocabulary::DependentKeyword;
|
|
|
+ static constexpr auto Removed = vocabulary::Removed;
|
|
|
+ static constexpr auto Literal = vocabulary::Literal;
|
|
|
+ static constexpr auto Keyword = vocabulary::Keyword;
|
|
|
+ static constexpr auto KeywordMap = vocabulary::KeywordMap;
|
|
|
+ static constexpr auto PostConstraint = vocabulary::PostConstraint;
|
|
|
|
|
|
/**
|
|
|
* @brief In order to support multiple schema versions in a single instance of
|
|
|
@@ -101,11 +82,13 @@ public:
|
|
|
* {schema::Version::Draft2020_12, &Self::additionalItems}}}
|
|
|
*/
|
|
|
struct Versioned {
|
|
|
- template <typename M> Versioned(M make) : data{{schema::Version::Earliest, make}} {}
|
|
|
- template <typename M> Versioned(schema::Version version, M make) : data{{version, make}} {}
|
|
|
- Versioned(std::initializer_list<std::pair<schema::Version const, Make>> init) : data(init) {}
|
|
|
+ template <typename M = vocabulary::Metadata<A>>
|
|
|
+ Versioned(M make) : data{{schema::Version::Earliest, make}} {}
|
|
|
+ Versioned(schema::Version version, vocabulary::Metadata<A> make) : data{{version, make}} {}
|
|
|
+ Versioned(std::initializer_list<std::pair<schema::Version const, vocabulary::Metadata<A>>> init)
|
|
|
+ : data(init) {}
|
|
|
|
|
|
- std::map<schema::Version, Make, std::greater<>> data;
|
|
|
+ std::map<schema::Version, vocabulary::Metadata<A>, std::greater<>> data;
|
|
|
};
|
|
|
using Store = std::unordered_map<std::string_view, Versioned>;
|
|
|
|
|
|
@@ -114,34 +97,34 @@ private:
|
|
|
|
|
|
private:
|
|
|
std::unordered_map<std::string_view, Versioned> constraints_{
|
|
|
- {"$defs", {schema::Version::Draft2019_09, Keyword}},
|
|
|
+ {"$defs", {schema::Version::Draft2019_09, KeywordMap}},
|
|
|
{"additionalItems",
|
|
|
- {{schema::Version::Earliest, &Self::additionalItems},
|
|
|
+ {{schema::Version::Earliest, {&Self::additionalItems, Keyword}},
|
|
|
{schema::Version::Draft2020_12, Removed}}},
|
|
|
- {"additionalProperties", &Self::additionalProperties},
|
|
|
- {"allOf", {schema::Version::Draft04, &Self::allOf}},
|
|
|
- {"anyOf", {schema::Version::Draft04, &Self::anyOf}},
|
|
|
+ {"additionalProperties", {{&Self::additionalProperties, Keyword}}},
|
|
|
+ {"allOf", {schema::Version::Draft04, {&Self::allOf, Keyword}}},
|
|
|
+ {"anyOf", {schema::Version::Draft04, {&Self::anyOf, Keyword}}},
|
|
|
{"const", {schema::Version::Draft06, &Self::isConstant}},
|
|
|
{"contains", {schema::Version::Draft06, &Self::contains}},
|
|
|
- {"definitions", Keyword},
|
|
|
- {"dependencies", &Self::dependencies},
|
|
|
+ {"definitions", KeywordMap},
|
|
|
+ {"dependencies", {{&Self::dependencies, KeywordMap}}},
|
|
|
{"dependentRequired", {schema::Version::Draft2019_09, &Self::dependentRequired}},
|
|
|
- {"dependentSchemas", {schema::Version::Draft2019_09, &Self::dependentSchemas}},
|
|
|
+ {"dependentSchemas", {schema::Version::Draft2019_09, {&Self::dependentSchemas, KeywordMap}}},
|
|
|
{"disallow",
|
|
|
{{schema::Version::Earliest, &Self::disallowDraft3}, {schema::Version::Draft04, Removed}}},
|
|
|
{"divisibleBy",
|
|
|
{{schema::Version::Earliest, &Self::multipleOf}, {schema::Version::Draft04, Removed}}},
|
|
|
- {"else", {{schema::Version::Draft07, Keyword}}},
|
|
|
+ {"else", {{schema::Version::Draft07, DependentKeyword{"if"}}}},
|
|
|
{"enum", &Self::isInEnumuration},
|
|
|
{"exclusiveMaximum", {schema::Version::Draft06, &Self::exclusiveMaximum}},
|
|
|
{"exclusiveMinimum", {schema::Version::Draft06, &Self::exclusiveMinimum}},
|
|
|
{"extends",
|
|
|
{{schema::Version::Earliest, &Self::extendsDraft3}, {schema::Version::Draft04, Removed}}},
|
|
|
{"format", &Self::format},
|
|
|
- {"if", {schema::Version::Draft07, &Self::ifThenElse}},
|
|
|
+ {"if", {schema::Version::Draft07, {&Self::ifThenElse, Keyword}}},
|
|
|
{"items",
|
|
|
- {{schema::Version::Earliest, &Self::itemsTupleOrVector},
|
|
|
- {schema::Version::Draft2020_12, &Self::additionalItems}}},
|
|
|
+ {{schema::Version::Earliest, {&Self::itemsTupleOrVector, Keyword}},
|
|
|
+ {schema::Version::Draft2020_12, {&Self::additionalItems, Keyword}}}},
|
|
|
{"maxItems", &Self::maxItems},
|
|
|
{"maxLength", &Self::maxLength},
|
|
|
{"maxProperties", {schema::Version::Draft04, &Self::maxProperties}},
|
|
|
@@ -151,21 +134,23 @@ private:
|
|
|
{"minProperties", {schema::Version::Draft04, &Self::minProperties}},
|
|
|
{"minimum", &Self::minimum},
|
|
|
{"multipleOf", {schema::Version::Draft04, &Self::multipleOf}},
|
|
|
- {"not", {schema::Version::Draft04, &Self::isNot}},
|
|
|
- {"oneOf", {schema::Version::Draft04, &Self::oneOf}},
|
|
|
+ {"not", {schema::Version::Draft04, {&Self::isNot, Keyword}}},
|
|
|
+ {"oneOf", {schema::Version::Draft04, {&Self::oneOf, Keyword}}},
|
|
|
{"pattern", &Self::pattern},
|
|
|
- {"patternProperties", &Self::patternProperties},
|
|
|
- {"prefixItems", {schema::Version::Draft2020_12, &Self::prefixItems}},
|
|
|
+ {"patternProperties", {{&Self::patternProperties, KeywordMap}}},
|
|
|
+ {"prefixItems", {schema::Version::Draft2020_12, {&Self::prefixItems, Keyword}}},
|
|
|
{"properties",
|
|
|
- {{schema::Version::Earliest, &Self::propertiesDraft3},
|
|
|
- {schema::Version::Draft04, &Self::properties}}},
|
|
|
+ {{schema::Version::Earliest, {&Self::propertiesDraft3, KeywordMap}},
|
|
|
+ {schema::Version::Draft04, {&Self::properties, KeywordMap}}}},
|
|
|
{"propertyNames", {schema::Version::Draft06, &Self::propertyNames}},
|
|
|
{"required", {schema::Version::Draft04, &Self::required}},
|
|
|
- {"then", {schema::Version::Draft07, Keyword}},
|
|
|
+ {"then", {schema::Version::Draft07, DependentKeyword{"if"}}},
|
|
|
{"type",
|
|
|
{{schema::Version::Earliest, &Self::typeDraft3}, {schema::Version::Draft04, &Self::type}}},
|
|
|
- {"unevaluatedItems", {schema::Version::Draft2019_09, &Self::unevaluatedItems}},
|
|
|
- {"unevaluatedProperties", {schema::Version::Draft2019_09, &Self::unevaluatedProperties}},
|
|
|
+ {"unevaluatedItems",
|
|
|
+ {schema::Version::Draft2019_09, {&Self::unevaluatedItems, PostConstraint}}},
|
|
|
+ {"unevaluatedProperties",
|
|
|
+ {schema::Version::Draft2019_09, {&Self::unevaluatedProperties, PostConstraint}}},
|
|
|
{"uniqueItems", &Self::uniqueItems},
|
|
|
};
|
|
|
|
|
|
@@ -219,7 +204,7 @@ public:
|
|
|
}
|
|
|
|
|
|
detail::Vocabulary<A> keywords(schema::Version version) const {
|
|
|
- std::unordered_map<std::string_view, MakeConstraint> rval;
|
|
|
+ std::unordered_map<std::string_view, vocabulary::Metadata<A>> rval;
|
|
|
for (auto const & [key, versions] : constraints_) {
|
|
|
if (auto it = versions.data.lower_bound(version); it != versions.data.end() && it->second) {
|
|
|
rval.emplace(key, it->second);
|
|
|
@@ -868,7 +853,7 @@ public:
|
|
|
std::string const prefix =
|
|
|
context.vocab->version() >= schema::Version::Draft2020_12 ? "prefixItems" : "items";
|
|
|
|
|
|
- Object const & parent = *context.parent;
|
|
|
+ auto const & parent = *context.parent;
|
|
|
// Before Draft 2020-12, the "items" could be either a subschema or a tuple.
|
|
|
// When not provided, we therefore treat it as an "accept-all" schema, and
|
|
|
// thus will never have additionalItems to process. Similarly - if it is an
|
|
|
@@ -1174,7 +1159,7 @@ public:
|
|
|
std::unordered_set<std::string> properties;
|
|
|
std::vector<std::string> patterns;
|
|
|
|
|
|
- Object const & parent = *context.parent;
|
|
|
+ auto const & parent = *context.parent;
|
|
|
if (parent.contains("properties")) {
|
|
|
for (auto [key, _] : parent["properties"].as_object()) {
|
|
|
properties.insert(key);
|