vocabulary.h 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #pragma once
  2. #include <string_view>
  3. #include <unordered_map>
  4. #include <unordered_set>
  5. #include <jvalidate/enum.h>
  6. #include <jvalidate/forward.h>
  7. namespace jvalidate::detail {
  8. template <Adapter A> struct ParserContext;
  9. template <Adapter A> class Vocabulary {
  10. public:
  11. friend class ConstraintFactory<A>;
  12. using pConstraint = std::unique_ptr<constraint::Constraint>;
  13. using MakeConstraint = std::function<pConstraint(ParserContext<A> const &)>;
  14. private:
  15. schema::Version version_;
  16. std::unordered_map<std::string_view, MakeConstraint> make_;
  17. std::unordered_set<std::string_view> special_keywords_;
  18. // TODO(samjaffe): Migrate this back to constraintsfactory
  19. std::unordered_set<std::string_view> keywords_{"$defs",
  20. "additionalItems",
  21. "additionalProperties",
  22. "allOf",
  23. "anyOf",
  24. "definitions",
  25. "dependencies",
  26. "dependentSchemas",
  27. "else",
  28. "if",
  29. "items",
  30. "not",
  31. "oneOf",
  32. "patternProperties",
  33. "prefixItems",
  34. "properties",
  35. "then",
  36. "unevaluatedItems",
  37. "unevaluatedProperties"};
  38. std::unordered_set<std::string_view> property_keywords_{
  39. "$defs", "definitions", "dependencies", "dependentSchemas", "patternProperties",
  40. "properties"};
  41. std::unordered_set<std::string_view> post_constraints_{"unevaluatedItems",
  42. "unevaluatedProperties"};
  43. public:
  44. Vocabulary() = default;
  45. Vocabulary(schema::Version version, std::unordered_map<std::string_view, MakeConstraint> make)
  46. : version_(version), make_(std::move(make)) {}
  47. void restrict(std::unordered_set<std::string> const & permitted_keywords) & {
  48. for (auto it = make_.begin(); it != make_.end();) {
  49. if (permitted_keywords.contains(std::string(it->first))) {
  50. ++it;
  51. } else {
  52. it = make_.erase(it);
  53. }
  54. }
  55. }
  56. schema::Version version() const { return version_; }
  57. /**
  58. * @brief Is the given "key"word actually a keyword? As in, would
  59. * I expect to resolve a constraint out of it.
  60. */
  61. bool is_keyword(std::string_view word) const {
  62. return make_.contains(word) && keywords_.contains(word);
  63. }
  64. /**
  65. * @brief Does the given "key"word represent a property object - that is to
  66. * say, an object containing some number of schemas mapped by arbitrary keys
  67. */
  68. bool is_property_keyword(std::string_view word) const {
  69. return is_keyword(word) && property_keywords_.contains(word);
  70. }
  71. bool is_constraint(std::string_view word) const { return make_.contains(word) && make_.at(word); }
  72. auto constraint(std::string_view word, ParserContext<A> const & context) const {
  73. return std::make_pair(is_constraint(word) ? make_.at(word)(context) : nullptr,
  74. post_constraints_.contains(word));
  75. }
  76. };
  77. }