Blaze 0.0.1
The ultra high-performance JSON Schema evaluator
Loading...
Searching...
No Matches
configuration.h
1#ifndef SOURCEMETA_BLAZE_CONFIGURATION_H_
2#define SOURCEMETA_BLAZE_CONFIGURATION_H_
3
12
13#ifndef SOURCEMETA_BLAZE_CONFIGURATION_EXPORT
14#include <sourcemeta/blaze/configuration_export.h>
15#endif
16
17// NOLINTBEGIN(misc-include-cleaner)
18#include <sourcemeta/blaze/configuration_error.h>
19// NOLINTEND(misc-include-cleaner)
20
21#include <sourcemeta/core/json.h>
22#include <sourcemeta/core/jsonschema.h>
23#include <sourcemeta/core/uri.h>
24
25#include <cstddef> // std::size_t
26#include <cstdint> // std::uint8_t
27#include <exception> // std::exception_ptr
28#include <filesystem> // std::filesystem
29#include <functional> // std::function
30#include <map> // std::map
31#include <optional> // std::optional
32#include <string> // std::string
33#include <string_view> // std::string_view
34#include <unordered_map> // std::unordered_map
35// TODO(C++23): Consider std::flat_map/std::flat_set when available in libc++
36#include <unordered_set> // std::unordered_set
37#include <vector> // std::vector
38
39namespace sourcemeta::blaze {
40
41// Exporting symbols that depends on the standard C++ library is considered
42// safe.
43// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4275?view=msvc-170&redirectedfrom=MSDN
44#if defined(_MSC_VER)
45#pragma warning(disable : 4251 4275)
46#endif
47
50struct SOURCEMETA_BLAZE_CONFIGURATION_EXPORT Configuration {
51 std::optional<sourcemeta::core::JSON::String> title;
52 std::optional<sourcemeta::core::JSON::String> description;
53 std::optional<sourcemeta::core::JSON::String> email;
54 std::optional<sourcemeta::core::JSON::String> github;
55 std::optional<sourcemeta::core::JSON::String> website;
56 std::filesystem::path absolute_path;
57 bool absolute_path_explicit{false};
58 std::filesystem::path base_path;
59 sourcemeta::core::JSON::String base;
60 sourcemeta::core::URI base_uri;
61 std::optional<sourcemeta::core::JSON::String> default_dialect;
62 std::unordered_set<sourcemeta::core::JSON::String> extension{".json", ".yml",
63 ".yaml"};
64 std::unordered_map<sourcemeta::core::JSON::String,
65 sourcemeta::core::JSON::String>
66 resolve;
67 // Ordered to guarantee deterministic iteration
68 std::map<sourcemeta::core::JSON::String, std::filesystem::path> dependencies;
69 std::vector<std::filesystem::path> ignore;
70
71 struct Lint {
72 struct Rule {
73 std::filesystem::path path;
74 bool top_level{false};
75 };
76
77 std::vector<Rule> rules;
78 std::unordered_set<sourcemeta::core::JSON::String> exclude;
79 };
80
81 Lint lint;
82 sourcemeta::core::JSON extra = sourcemeta::core::JSON::make_object();
83
86 // TODO(C++23): Use std::move_only_function when available in libc++
87 std::function<std::string(const std::filesystem::path &)>;
88
90 class SOURCEMETA_BLAZE_CONFIGURATION_EXPORT Lock {
91 public:
92 struct Entry {
93 std::filesystem::path path;
94 // TODO: Separately store the server ETag for exploiting HTTP caching?
95 sourcemeta::core::JSON::String hash;
96 enum class HashAlgorithm : std::uint8_t { SHA256 };
97 HashAlgorithm hash_algorithm;
98 enum class Status : std::uint8_t {
99 Untracked,
100 FileMissing,
101 Mismatched,
102 PathMismatch,
103 UpToDate
104 };
105 };
106
107 using const_iterator =
108 std::map<sourcemeta::core::JSON::String, Entry>::const_iterator;
109
110 auto
111 emplace(const sourcemeta::core::JSON::String &uri,
112 const std::filesystem::path &path,
113 const sourcemeta::core::JSON::String &hash,
114 Entry::HashAlgorithm hash_algorithm = Entry::HashAlgorithm::SHA256)
115 -> void;
116 auto erase(const sourcemeta::core::JSON::String &uri) -> void;
117
118 [[nodiscard]] auto size() const noexcept -> std::size_t;
119 [[nodiscard]] auto at(const sourcemeta::core::JSON::String &uri) const
120 -> std::optional<std::reference_wrapper<const Entry>>;
121 [[nodiscard]] auto begin() const noexcept -> const_iterator;
122 [[nodiscard]] auto end() const noexcept -> const_iterator;
123
124 [[nodiscard]]
125 auto check(const sourcemeta::core::JSON::String &uri,
126 const std::filesystem::path &expected_path,
127 const ReadCallback &reader) const -> Entry::Status;
128 [[nodiscard]]
129 static auto from_json(const sourcemeta::core::JSON &value,
130 const std::filesystem::path &lock_base_path) -> Lock;
131 [[nodiscard]]
132 auto to_json(const std::filesystem::path &lock_base_path) const
133 -> sourcemeta::core::JSON;
134
135 private:
136 // Ordered to guarantee deterministic iteration
137 std::map<sourcemeta::core::JSON::String, Entry> entries_;
138 };
139
141 struct FetchEvent {
142 enum class Type : std::uint8_t {
143 FetchStart,
144 FetchEnd,
145 BundleStart,
146 BundleEnd,
147 WriteStart,
148 WriteEnd,
149 VerifyStart,
150 VerifyEnd,
151 UpToDate,
152 FileMissing,
153 Orphaned,
154 Mismatched,
155 PathMismatch,
156 Untracked,
157 Error
158 };
159
160 Type type;
161 std::string uri;
162 std::filesystem::path path;
163 std::size_t index;
164 std::size_t total;
165 std::string details;
166 std::exception_ptr exception;
167
168 using Callback = std::function<bool(const FetchEvent &)>;
169 };
170
173 std::function<sourcemeta::core::JSON(std::string_view uri)>;
174
176 using WriteCallback = std::function<void(const std::filesystem::path &,
177 const sourcemeta::core::JSON &)>;
178
180 enum class FetchMode : std::uint8_t {
182 Missing,
184 All
185 };
186
188 auto fetch(Lock &lock, const FetchCallback &fetcher,
189 const sourcemeta::core::SchemaResolver &resolver,
190 const ReadCallback &reader, const WriteCallback &writer,
191 const FetchEvent::Callback &on_event, FetchMode mode,
192 // TODO: Make this work for real
193 std::size_t concurrency = 1) const -> void;
194
196 auto fetch(const Lock &lock, const FetchCallback &fetcher,
197 const sourcemeta::core::SchemaResolver &resolver,
198 const ReadCallback &reader, const WriteCallback &writer,
199 const FetchEvent::Callback &on_event, bool dry_run = false,
200 // TODO: Make this work for real
201 std::size_t concurrency = 1) const -> void;
202
204 auto add_dependency(const sourcemeta::core::URI &uri,
205 const std::filesystem::path &path) -> void;
206
209 [[nodiscard]]
210 auto applies_to(const std::filesystem::path &path) const -> bool;
211
213 [[nodiscard]]
214 static auto from_json(const sourcemeta::core::JSON &value,
215 const std::filesystem::path &base_path)
216 -> Configuration;
217
219 [[nodiscard]]
220 auto to_json() const -> sourcemeta::core::JSON;
221
223 [[nodiscard]]
224 static auto read_json(const std::filesystem::path &path,
225 const ReadCallback &reader) -> Configuration;
226
228 [[nodiscard]]
229 static auto find(const std::filesystem::path &path)
230 -> std::optional<std::filesystem::path>;
231};
232
233#if defined(_MSC_VER)
234#pragma warning(default : 4251 4275)
235#endif
236
237} // namespace sourcemeta::blaze
238
239#endif
A lock file that tracks fetched dependency hashes.
Definition configuration.h:90
static auto find(const std::filesystem::path &path) -> std::optional< std::filesystem::path >
A nearest ancestor configuration lookup.
static auto read_json(const std::filesystem::path &path, const ReadCallback &reader) -> Configuration
Read and parse a configuration file.
std::function< void(const std::filesystem::path &, const sourcemeta::core::JSON &)> WriteCallback
A callback to write a JSON Schema to a path.
Definition configuration.h:176
std::function< std::string(const std::filesystem::path &)> ReadCallback
A callback to read file contents from a path.
Definition configuration.h:85
auto to_json() const -> sourcemeta::core::JSON
Serialize a configuration to JSON.
auto applies_to(const std::filesystem::path &path) const -> bool
FetchMode
The mode for fetching dependencies with a mutable lock.
Definition configuration.h:180
auto fetch(Lock &lock, const FetchCallback &fetcher, const sourcemeta::core::SchemaResolver &resolver, const ReadCallback &reader, const WriteCallback &writer, const FetchEvent::Callback &on_event, FetchMode mode, std::size_t concurrency=1) const -> void
Fetch dependencies, modifying the lock in-place.
static auto from_json(const sourcemeta::core::JSON &value, const std::filesystem::path &base_path) -> Configuration
Parse a configuration file from its contents.
auto add_dependency(const sourcemeta::core::URI &uri, const std::filesystem::path &path) -> void
Add a dependency to the configuration.
std::function< sourcemeta::core::JSON(std::string_view uri)> FetchCallback
A callback to fetch a JSON Schema from a URI.
Definition configuration.h:172
Definition configuration.h:50
std::function< void( const EvaluationType, bool, const Instruction &, const InstructionExtra &, const sourcemeta::core::WeakPointer &, const sourcemeta::core::WeakPointer &, const sourcemeta::core::JSON &)> Callback
Definition evaluator.h:77
An event emitted during dependency fetching.
Definition configuration.h:141
Definition configuration.h:71