Blaze 0.0.1
The ultra high-performance JSON Schema evaluator
Loading...
Searching...
No Matches
alterschema_transformer.h
1#ifndef SOURCEMETA_BLAZE_ALTERSCHEMA_TRANSFORMER_H_
2#define SOURCEMETA_BLAZE_ALTERSCHEMA_TRANSFORMER_H_
3
4#ifndef SOURCEMETA_BLAZE_ALTERSCHEMA_EXPORT
5#include <sourcemeta/blaze/alterschema_export.h>
6#endif
7
8#include <sourcemeta/core/json.h>
9#include <sourcemeta/core/jsonpointer.h>
10#include <sourcemeta/core/jsonschema.h>
11
12#include <cassert> // assert
13#include <concepts> // std::derived_from, std::same_as
14#include <cstdint> // std::uint8_t
15#include <functional> // std::function
16#include <iterator> // std::make_move_iterator, std::begin, std::end
17#include <memory> // std::make_unique, std::unique_ptr
18#include <optional> // std::optional, std::nullopt
19#include <set> // std::set
20#include <string> // std::string
21#include <string_view> // std::string_view
22#include <tuple> // std::tuple
23#include <type_traits> // std::is_same_v, std::true_type
24#include <utility> // std::move, std::forward
25#include <vector> // std::vector
26
27namespace sourcemeta::blaze {
28
34class SOURCEMETA_BLAZE_ALTERSCHEMA_EXPORT SchemaTransformRule {
35public:
36 SchemaTransformRule(const std::string_view name,
37 const std::string_view message);
38
39 virtual ~SchemaTransformRule() = default;
40
41 SchemaTransformRule(const SchemaTransformRule &) = delete;
42 SchemaTransformRule(SchemaTransformRule &&) = delete;
43 auto operator=(const SchemaTransformRule &) -> SchemaTransformRule & = delete;
44 auto operator=(SchemaTransformRule &&) -> SchemaTransformRule & = delete;
45
47 auto operator==(const SchemaTransformRule &other) const -> bool;
48
50 [[nodiscard]] auto name() const noexcept -> std::string_view;
51
53 [[nodiscard]] auto message() const noexcept -> std::string_view;
54
56 struct Result {
57 Result(const bool outcome) : applies{outcome} {}
58 Result(const sourcemeta::core::Pointer &pointer)
59 : applies{true}, locations{pointer} {
60 assert(this->locations.size() == 1);
61 }
62
63 template <typename T>
64 requires std::same_as<typename T::value_type, sourcemeta::core::Pointer>
65 Result(T &&container) : applies{true} {
66 auto &&input = std::forward<T>(container);
67 if constexpr (requires { input.size(); }) {
68 locations.reserve(input.size());
69 }
70
71#if __cpp_lib_containers_ranges >= 202202L
72 locations.assign_range(input);
73#else
74 locations.assign(std::make_move_iterator(std::begin(input)),
75 std::make_move_iterator(std::end(input)));
76#endif
77 }
78
79 Result(std::vector<sourcemeta::core::Pointer> &&pointers,
80 sourcemeta::core::JSON::String &&message)
81 : applies{true}, locations{std::move(pointers)},
82 description{std::move(message)} {}
83
84 bool applies;
85 std::vector<sourcemeta::core::Pointer> locations;
86 std::optional<sourcemeta::core::JSON::String> description;
87 };
88
90 [[nodiscard]] auto
91 check(const sourcemeta::core::JSON &schema,
92 const sourcemeta::core::JSON &root,
93 const sourcemeta::core::SchemaVocabularies &vocabularies,
94 const sourcemeta::core::SchemaWalker &walker,
95 const sourcemeta::core::SchemaResolver &resolver,
96 const sourcemeta::core::SchemaFrame &frame,
97 const sourcemeta::core::SchemaFrame::Location &location,
98 const sourcemeta::core::JSON::String &exclude_keyword) const -> Result;
99
102 [[nodiscard]] virtual auto
103 rereference(const std::string_view reference,
104 const sourcemeta::core::Pointer &origin,
105 const sourcemeta::core::Pointer &target,
106 const sourcemeta::core::Pointer &current) const
107 -> sourcemeta::core::Pointer;
108
110 [[nodiscard]] virtual auto condition(
111 const sourcemeta::core::JSON &schema, const sourcemeta::core::JSON &root,
112 const sourcemeta::core::SchemaVocabularies &vocabularies,
113 const sourcemeta::core::SchemaFrame &frame,
114 const sourcemeta::core::SchemaFrame::Location &location,
115 const sourcemeta::core::SchemaWalker &walker,
116 const sourcemeta::core::SchemaResolver &resolver) const -> Result = 0;
117
120 virtual auto transform(sourcemeta::core::JSON &schema,
121 const Result &result) const -> void;
122
123private:
124// Exporting symbols that depends on the standard C++ library is considered
125// safe.
126// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4275?view=msvc-170&redirectedfrom=MSDN
127#if defined(_MSC_VER)
128#pragma warning(disable : 4251)
129#endif
130 const std::string name_{};
131 const std::string message_{};
132#if defined(_MSC_VER)
133#pragma warning(default : 4251)
134#endif
135};
136
142class SOURCEMETA_BLAZE_ALTERSCHEMA_EXPORT SchemaTransformer {
143public:
144 SchemaTransformer() = default;
145
146#if !defined(DOXYGEN)
147 SchemaTransformer(const SchemaTransformer &) = delete;
148 auto operator=(const SchemaTransformer &) -> SchemaTransformer & = delete;
149 SchemaTransformer(SchemaTransformer &&) = default;
150 auto operator=(SchemaTransformer &&) -> SchemaTransformer & = default;
151#endif
152
155 template <std::derived_from<SchemaTransformRule> T, typename... Args>
156 auto add(Args &&...args) -> std::string_view {
157 static_assert(requires { typename T::mutates; });
158 static_assert(requires { typename T::reframe_after_transform; });
159 static_assert(
160 std::is_same_v<typename T::mutates, std::true_type> ||
161 std::is_same_v<typename T::reframe_after_transform, std::false_type>);
162 auto &entry{this->rules_.emplace_back(
163 std::make_unique<T>(std::forward<Args>(args)...),
164 std::is_same_v<typename T::mutates, std::true_type>,
165 std::is_same_v<typename T::reframe_after_transform, std::true_type>)};
166 return std::get<0>(entry)->name();
167 }
168
170 auto remove(const std::string_view name) -> bool;
171
173 using Callback = std::function<void(
174 const sourcemeta::core::Pointer &, const std::string_view,
175 const std::string_view, const SchemaTransformRule::Result &, const bool)>;
176
180 using Framer = std::function<const sourcemeta::core::SchemaFrame &(
181 const sourcemeta::core::JSON &)>;
182
184 [[nodiscard]] auto
185 apply(sourcemeta::core::JSON &schema,
186 const sourcemeta::core::SchemaWalker &walker,
187 const sourcemeta::core::SchemaResolver &resolver,
188 const Callback &callback, std::string_view default_dialect = "",
189 std::string_view default_id = "",
190 const sourcemeta::core::JSON::String &exclude_keyword = "") const
191 -> std::pair<bool, std::uint8_t>;
192
195 [[nodiscard]] auto
196 apply(sourcemeta::core::JSON &document, const Framer &framer,
197 const sourcemeta::core::SchemaWalker &walker,
198 const sourcemeta::core::SchemaResolver &resolver,
199 const Callback &callback,
200 const sourcemeta::core::JSON::String &exclude_keyword = "") const
201 -> std::pair<bool, std::uint8_t>;
202
205 [[nodiscard]] auto
206 check(const sourcemeta::core::JSON &schema,
207 const sourcemeta::core::SchemaWalker &walker,
208 const sourcemeta::core::SchemaResolver &resolver,
209 const Callback &callback, std::string_view default_dialect = "",
210 std::string_view default_id = "",
211 const sourcemeta::core::JSON::String &exclude_keyword = "") const
212 -> std::pair<bool, std::uint8_t>;
213
216 [[nodiscard]] auto
217 check(const sourcemeta::core::JSON &document,
218 const sourcemeta::core::SchemaFrame &frame,
219 const sourcemeta::core::SchemaWalker &walker,
220 const sourcemeta::core::SchemaResolver &resolver,
221 const Callback &callback,
222 const sourcemeta::core::JSON::String &exclude_keyword = "") const
223 -> std::pair<bool, std::uint8_t>;
224
225 [[nodiscard]] auto begin() const -> auto { return this->rules_.cbegin(); }
226 [[nodiscard]] auto end() const -> auto { return this->rules_.cend(); }
227
228private:
229#if defined(_MSC_VER)
230#pragma warning(disable : 4251)
231#endif
232 std::vector<std::tuple<std::unique_ptr<SchemaTransformRule>, bool, bool>>
233 rules_;
234#if defined(_MSC_VER)
235#pragma warning(default : 4251)
236#endif
237};
238
239} // namespace sourcemeta::blaze
240
241#endif
auto check(const sourcemeta::core::JSON &schema, const sourcemeta::core::SchemaWalker &walker, const sourcemeta::core::SchemaResolver &resolver, const Callback &callback, std::string_view default_dialect="", std::string_view default_id="", const sourcemeta::core::JSON::String &exclude_keyword="") const -> std::pair< bool, std::uint8_t >
virtual auto transform(sourcemeta::core::JSON &schema, const Result &result) const -> void
std::function< void( const sourcemeta::core::Pointer &, const std::string_view, const std::string_view, const SchemaTransformRule::Result &, const bool)> Callback
The callback that is called whenever the condition of a rule holds true.
Definition alterschema_transformer.h:173
auto check(const sourcemeta::core::JSON &schema, const sourcemeta::core::JSON &root, const sourcemeta::core::SchemaVocabularies &vocabularies, const sourcemeta::core::SchemaWalker &walker, const sourcemeta::core::SchemaResolver &resolver, const sourcemeta::core::SchemaFrame &frame, const sourcemeta::core::SchemaFrame::Location &location, const sourcemeta::core::JSON::String &exclude_keyword) const -> Result
Check if the rule applies to a schema.
auto remove(const std::string_view name) -> bool
Remove a rule from the bundle.
auto message() const noexcept -> std::string_view
Fetch the message of a rule.
virtual auto rereference(const std::string_view reference, const sourcemeta::core::Pointer &origin, const sourcemeta::core::Pointer &target, const sourcemeta::core::Pointer &current) const -> sourcemeta::core::Pointer
virtual auto condition(const sourcemeta::core::JSON &schema, const sourcemeta::core::JSON &root, const sourcemeta::core::SchemaVocabularies &vocabularies, const sourcemeta::core::SchemaFrame &frame, const sourcemeta::core::SchemaFrame::Location &location, const sourcemeta::core::SchemaWalker &walker, const sourcemeta::core::SchemaResolver &resolver) const -> Result=0
The rule condition.
auto operator==(const SchemaTransformRule &other) const -> bool
Compare a rule against another rule.
auto add(Args &&...args) -> std::string_view
Definition alterschema_transformer.h:156
auto apply(sourcemeta::core::JSON &schema, const sourcemeta::core::SchemaWalker &walker, const sourcemeta::core::SchemaResolver &resolver, const Callback &callback, std::string_view default_dialect="", std::string_view default_id="", const sourcemeta::core::JSON::String &exclude_keyword="") const -> std::pair< bool, std::uint8_t >
Apply the bundle of rules to a schema.
auto name() const noexcept -> std::string_view
Fetch the name of a rule.
std::function< const sourcemeta::core::SchemaFrame &( const sourcemeta::core::JSON &)> Framer
Definition alterschema_transformer.h:180
The result of evaluating a rule.
Definition alterschema_transformer.h:56