forward.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #pragma once
  2. #include <functional>
  3. #include <string>
  4. #include <type_traits>
  5. #include <variant>
  6. #define DISCARD1_IMPL(_, ...) __VA_ARGS__
  7. #define DISCARD1(...) DISCARD1_IMPL(__VA_ARGS__)
  8. #define FORWARD_DECLARE_STRUCT(TYPE) struct TYPE;
  9. #define COMMA_NAME(X) , X
  10. namespace jvalidate {
  11. class Schema;
  12. class Status;
  13. class URI;
  14. struct ValidationConfig;
  15. class ValidationResult;
  16. }
  17. namespace jvalidate::adapter {
  18. enum class Type : int8_t;
  19. class Adapter;
  20. class Const;
  21. using AdapterCallback = std::function<Status(adapter::Adapter const &)>;
  22. using ObjectAdapterCallback = std::function<Status(std::string const &, adapter::Adapter const &)>;
  23. template <typename> struct AdapterTraits;
  24. template <typename V> struct AdapterTraits<V const> : AdapterTraits<V> {};
  25. template <typename JSON> using AdapterFor = typename AdapterTraits<JSON>::template Adapter<JSON>;
  26. }
  27. namespace jvalidate::schema {
  28. enum class Version : int;
  29. class Node;
  30. }
  31. namespace jvalidate::constraint {
  32. #define CONSTRAINT_IMPLEMENTATION_LIST(X) \
  33. /* General Constraints - See jvalidate/constraint/general_constraint.h */ \
  34. X(TypeConstraint) \
  35. X(EnumConstraint) \
  36. X(AllOfConstraint) \
  37. X(AnyOfConstraint) \
  38. X(OneOfConstraint) \
  39. X(NotConstraint) \
  40. X(ConditionalConstraint) \
  41. /* Number Constraints - See jvalidate/constraint/number_constraint.h */ \
  42. X(MaximumConstraint) \
  43. X(MinimumConstraint) \
  44. X(MultipleOfConstraint) \
  45. /* String Constraints - See jvalidate/constraint/string_constraint.h */ \
  46. X(MaxLengthConstraint) \
  47. X(MinLengthConstraint) \
  48. X(PatternConstraint) \
  49. X(FormatConstraint) \
  50. /* Array Constraints - See jvalidate/constraint/array_constraint.h */ \
  51. X(AdditionalItemsConstraint) \
  52. X(ContainsConstraint) \
  53. X(MaxItemsConstraint) \
  54. X(MinItemsConstraint) \
  55. X(TupleConstraint) \
  56. X(UnevaluatedItemsConstraint) \
  57. X(UniqueItemsConstraint) \
  58. /* Object Constraints - See jvalidate/constraint/object_constraint.h */ \
  59. X(AdditionalPropertiesConstraint) \
  60. X(DependenciesConstraint) \
  61. X(MaxPropertiesConstraint) \
  62. X(MinPropertiesConstraint) \
  63. X(PatternPropertiesConstraint) \
  64. X(PropertiesConstraint) \
  65. X(PropertyNamesConstraint) \
  66. X(RequiredConstraint) \
  67. X(UnevaluatedPropertiesConstraint) \
  68. /* ExtensionConstraint - A special constraint for all user-defined constraints */ \
  69. X(ExtensionConstraint)
  70. CONSTRAINT_IMPLEMENTATION_LIST(FORWARD_DECLARE_STRUCT);
  71. using Constraint = std::variant<DISCARD1(CONSTRAINT_IMPLEMENTATION_LIST(COMMA_NAME))>;
  72. using SubConstraint = std::variant<schema::Node const *, std::unique_ptr<Constraint>>;
  73. }
  74. namespace jvalidate {
  75. template <typename It>
  76. concept ArrayIterator =
  77. std::forward_iterator<It> and std::is_default_constructible_v<It> and requires(It const it) {
  78. { *it } -> std::convertible_to<adapter::Adapter const &>;
  79. };
  80. template <typename It>
  81. concept ObjectIterator =
  82. std::forward_iterator<It> and std::is_default_constructible_v<It> and requires(It const it) {
  83. { it->first } -> std::convertible_to<std::string_view>;
  84. { it->second } -> std::convertible_to<adapter::Adapter const &>;
  85. };
  86. template <typename A>
  87. concept ArrayAdapter = requires(A const a) {
  88. { a.size() } -> std::convertible_to<std::size_t>;
  89. { a[0UL] } -> std::convertible_to<adapter::Adapter const &>;
  90. { a.begin() } -> ArrayIterator;
  91. { a.end() } -> ArrayIterator;
  92. };
  93. template <typename A>
  94. concept ObjectAdapter = requires(A const a) {
  95. { a.size() } -> std::convertible_to<std::size_t>;
  96. { a.contains("") } -> std::same_as<bool>;
  97. { a[""] } -> std::convertible_to<adapter::Adapter const &>;
  98. { a.begin() } -> ObjectIterator;
  99. { a.end() } -> ObjectIterator;
  100. };
  101. /**
  102. * @brief A concept representing the actual adapter form. Used in most code
  103. * that actually cares to interact with JSON, instead of having to define a
  104. * template like AdapterInterface<ArrayAdapter, ObjectAdapter> for the basic
  105. * adapter, or return pointers-to-interfaces in order to access array/object
  106. * data.
  107. *
  108. * This concept functionally defines an Adapter being an AdapterInterface with
  109. * an as_array and as_object method added on.
  110. */
  111. template <typename A>
  112. concept Adapter = std::is_base_of_v<adapter::Adapter, A> && requires(A const a) {
  113. typename A::value_type;
  114. { a.type() } -> std::same_as<adapter::Type>;
  115. { a.as_boolean() } -> std::same_as<bool>;
  116. { a.as_integer() } -> std::convertible_to<int64_t>;
  117. { a.as_number() } -> std::convertible_to<double>;
  118. { a.as_number() } -> std::floating_point;
  119. { a.as_object() } -> ObjectAdapter;
  120. { a.as_array() } -> ArrayAdapter;
  121. { a.array_size() } -> std::convertible_to<size_t>;
  122. { a.object_size() } -> std::convertible_to<size_t>;
  123. };
  124. template <typename A>
  125. concept MutableObject = ObjectAdapter<A> && requires(A const a) {
  126. { a.assign("", std::declval<adapter::Const>()) };
  127. };
  128. /**
  129. * @brief An extension of Adapter that is capable of altering the underlying
  130. * JSON node. In general, that means that a non-const ref is captured when
  131. * building an Adapter.
  132. *
  133. * Requires that we can assign both to "this", and to values at a key (in the
  134. * case of object type).
  135. * Implies that as_array is also a wrapper for mutable JSON.
  136. */
  137. template <typename A>
  138. concept MutableAdapter = Adapter<A> && requires(A const a) {
  139. { a.assign(std::declval<adapter::Const>()) };
  140. { a.assign(std::declval<adapter::Adapter>()) };
  141. { a.as_object() } -> MutableObject;
  142. };
  143. template <typename R>
  144. concept RegexEngine = std::constructible_from<std::string> && requires(R const regex) {
  145. { regex.search("") } -> std::same_as<bool>;
  146. };
  147. }
  148. namespace jvalidate {
  149. template <Adapter A> class ConstraintFactory;
  150. template <Adapter A> class DocumentCache;
  151. template <RegexEngine RE> class ValidationVisitor;
  152. template <RegexEngine RE> class ValidatorT;
  153. class Validator;
  154. template <Adapter A> using URIResolver = bool (*)(URI const &, typename A::value_type &);
  155. template <typename T, typename S>
  156. concept Not = not std::is_convertible_v<std::decay_t<S>, T>;
  157. }
  158. #undef FORWARD_DECLARE_STRUCT
  159. #undef COMMA_NAME
  160. #undef DISCARD1_IMPL
  161. #undef DISCARD1