vocabulary.h 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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> permitted_;
  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. "extends",
  29. "if",
  30. "items",
  31. "not",
  32. "oneOf",
  33. "patternProperties",
  34. "prefixItems",
  35. "properties",
  36. "then",
  37. "unevaluatedItems",
  38. "unevaluatedProperties"};
  39. std::unordered_set<std::string_view> property_keywords_{
  40. "$defs", "definitions", "dependencies", "dependentSchemas", "patternProperties",
  41. "properties"};
  42. std::unordered_set<std::string_view> post_constraints_{"unevaluatedItems",
  43. "unevaluatedProperties"};
  44. public:
  45. Vocabulary() = default;
  46. Vocabulary(schema::Version version, std::unordered_map<std::string_view, MakeConstraint> make)
  47. : version_(version), make_(std::move(make)) {
  48. for (auto const & [keyword, _] : make_) {
  49. permitted_.emplace(keyword);
  50. }
  51. }
  52. void restrict(std::unordered_set<std::string> const & permitted_keywords) & {
  53. permitted_.clear();
  54. for (auto const & [keyword, _] : make_) {
  55. if (permitted_keywords.contains(std::string(keyword))) {
  56. permitted_.insert(keyword);
  57. }
  58. }
  59. }
  60. schema::Version version() const { return version_; }
  61. /**
  62. * @brief Is the given "key"word actually a keyword? As in, would
  63. * I expect to resolve a constraint out of it.
  64. */
  65. bool is_keyword(std::string_view word) const {
  66. return permitted_.contains(word) && make_.contains(word) && keywords_.contains(word);
  67. }
  68. /**
  69. * @brief Does the given "key"word represent a property object - that is to
  70. * say, an object containing some number of schemas mapped by arbitrary keys
  71. */
  72. bool is_property_keyword(std::string_view word) const {
  73. return is_keyword(word) && property_keywords_.contains(word);
  74. }
  75. bool is_constraint(std::string_view word) const {
  76. return permitted_.contains(word) && make_.contains(word) && make_.at(word);
  77. }
  78. auto constraint(std::string_view word, ParserContext<A> const & context) const {
  79. return std::make_pair(is_constraint(word) ? make_.at(word)(context) : nullptr,
  80. post_constraints_.contains(word));
  81. }
  82. };
  83. }