vocabulary.h 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. "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. for (auto const & [keyword, _] : make_) {
  48. permitted_.emplace(keyword);
  49. }
  50. }
  51. void restrict(std::unordered_set<std::string> const & permitted_keywords) & {
  52. permitted_.clear();
  53. for (auto const & [keyword, _] : make_) {
  54. if (permitted_keywords.contains(std::string(keyword))) {
  55. permitted_.insert(keyword);
  56. }
  57. }
  58. }
  59. schema::Version version() const { return version_; }
  60. /**
  61. * @brief Is the given "key"word actually a keyword? As in, would
  62. * I expect to resolve a constraint out of it.
  63. */
  64. bool is_keyword(std::string_view word) const {
  65. return permitted_.contains(word) && make_.contains(word) && keywords_.contains(word);
  66. }
  67. /**
  68. * @brief Does the given "key"word represent a property object - that is to
  69. * say, an object containing some number of schemas mapped by arbitrary keys
  70. */
  71. bool is_property_keyword(std::string_view word) const {
  72. return is_keyword(word) && property_keywords_.contains(word);
  73. }
  74. bool is_constraint(std::string_view word) const {
  75. return permitted_.contains(word) && make_.contains(word) && make_.at(word);
  76. }
  77. auto constraint(std::string_view word, ParserContext<A> const & context) const {
  78. return std::make_pair(is_constraint(word) ? make_.at(word)(context) : nullptr,
  79. post_constraints_.contains(word));
  80. }
  81. };
  82. }