Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ _deps
Brewfile.lock.json
.DS_Store
/node_modules
/.cache
10 changes: 5 additions & 5 deletions DEPENDENCIES
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02
uwebsockets https://github.com/uNetworking/uWebSockets v20.74.0
core https://github.com/sourcemeta/core d78c8611797712b29c98b8e44d802baff930bc47
blaze https://github.com/sourcemeta/blaze 8dba65f8aebfe1ac976168b76e01c20dd406c517
jsonbinpack https://github.com/sourcemeta/jsonbinpack 8fae212dc7ec02af4bb0cd4e7fccd42a2471f1c1
hydra https://github.com/sourcemeta/hydra af9f2c54709d620872ead0c3f8f683c15a0fa702
jsonschema https://github.com/sourcemeta/jsonschema v14.0.1
core https://github.com/sourcemeta/core 991a4c86b6b22b73aedabe5734cba7108a781953
blaze https://github.com/sourcemeta/blaze 93342104a85814bc0fd11792d305c4e83de259c0
jsonbinpack https://github.com/sourcemeta/jsonbinpack 0c2340990bf31c630155991a93306990d9d94fd4
hydra https://github.com/sourcemeta/hydra c86d2165a2f27f838837af1a5af24b1055a35317
jsonschema https://github.com/sourcemeta/jsonschema 428e401d4c5d3d6405a5ad6ee3b5f8d3fb938829
bootstrap https://github.com/twbs/bootstrap v5.3.3
bootstrap-icons https://github.com/twbs/icons v1.11.3
collections/sourcemeta/std/v0 https://github.com/sourcemeta/std v0.4.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ConfigurationValidationError : public std::exception {
this->stacktrace_ = stream.str();
}

[[nodiscard]] auto what() const noexcept -> const char * {
[[nodiscard]] auto what() const noexcept -> const char * override {
return "Invalid configuration";
}

Expand All @@ -47,7 +47,7 @@ class ConfigurationReadError : public std::exception {
: from_{std::move(from)}, location_{std::move(location)},
target_{std::move(target)} {}

[[nodiscard]] auto what() const noexcept -> const char * {
[[nodiscard]] auto what() const noexcept -> const char * override {
return "Could not read referenced file";
}

Expand Down Expand Up @@ -77,7 +77,7 @@ class ConfigurationUnknownBuiltInCollectionError : public std::exception {
: from_{std::move(from)}, location_{std::move(location)},
identifier_{std::move(identifier)} {}

[[nodiscard]] auto what() const noexcept -> const char * {
[[nodiscard]] auto what() const noexcept -> const char * override {
return "Could not locate built-in collection";
}

Expand Down
4 changes: 2 additions & 2 deletions src/html/include/sourcemeta/one/html_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class HTML {
(child_elements.push_back(std::forward<Children>(children)), ...);
}

auto render() const -> std::string;
[[nodiscard]] auto render() const -> std::string;

auto push_back(const Node &child) -> HTML &;
auto push_back(Node &&child) -> HTML &;
Expand All @@ -90,7 +90,7 @@ class HTML {
std::vector<Node> child_elements;
bool self_closing;

auto render(const Node &child_element) const -> std::string;
[[nodiscard]] auto render(const Node &child_element) const -> std::string;
};

// Raw HTML content wrapper - DANGER: Content is NOT escaped!
Expand Down
18 changes: 10 additions & 8 deletions src/index/explorer.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,26 +108,28 @@ struct GENERATE_EXPLORER_SCHEMA_METADATA {
const auto timestamp_start{std::chrono::steady_clock::now()};
const auto schema{
sourcemeta::one::read_json_with_metadata(dependencies.front())};
auto id{sourcemeta::core::identify(
const auto id{sourcemeta::core::identify(
schema.data, [&callback, &context](const auto identifier) {
return std::get<0>(context).get()(identifier, callback);
})};
assert(id.has_value());
assert(!id.empty());
auto result{sourcemeta::core::JSON::make_object()};

result.assign("bytes", sourcemeta::core::JSON{schema.bytes});
result.assign("identifier", sourcemeta::core::JSON{std::move(id).value()});
result.assign("identifier", sourcemeta::core::JSON{std::string{id}});
result.assign("path",
sourcemeta::core::JSON{"/" + std::get<2>(context).string()});
const auto base_dialect{sourcemeta::core::base_dialect(
schema.data, [&callback, &context](const auto identifier) {
return std::get<0>(context).get()(identifier, callback);
})};
assert(base_dialect.has_value());
result.assign("baseDialect", sourcemeta::core::JSON{base_dialect.value()});
const auto dialect{sourcemeta::core::dialect(schema.data, base_dialect)};
assert(dialect.has_value());
result.assign("dialect", sourcemeta::core::JSON{dialect.value()});
result.assign("baseDialect",
sourcemeta::core::JSON{std::string{
sourcemeta::core::to_string(base_dialect.value())}});
const auto dialect{sourcemeta::core::dialect(schema.data)};
assert(!dialect.empty());
result.assign("dialect", sourcemeta::core::JSON{std::string{dialect}});

if (schema.data.is_object()) {
const auto title{schema.data.try_at("title")};
Expand All @@ -147,7 +149,7 @@ struct GENERATE_EXPLORER_SCHEMA_METADATA {
[&callback, &context](const auto identifier) {
return std::get<0>(context).get()(identifier, callback);
},
base_dialect.value(), dialect.value())};
base_dialect.value(), dialect)};
const auto &walker_result{
sourcemeta::core::schema_walker("examples", vocabularies)};
if (walker_result.type ==
Expand Down
28 changes: 15 additions & 13 deletions src/index/generators.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ struct GENERATE_MATERIALISED_SCHEMA {
auto schema{data.second.get()(data.first)};
assert(schema.has_value());
const auto dialect_identifier{sourcemeta::core::dialect(schema.value())};
assert(dialect_identifier.has_value());
const auto metaschema{data.second.get()(dialect_identifier.value())};
assert(!dialect_identifier.empty());
const auto metaschema{data.second.get()(dialect_identifier)};
assert(metaschema.has_value());

// Validate the schemas against their meta-schemas
sourcemeta::blaze::SimpleOutput output{schema.value()};
sourcemeta::blaze::Evaluator evaluator;
const auto result{evaluator.validate(
GENERATE_MATERIALISED_SCHEMA::compile(dialect_identifier.value(),
GENERATE_MATERIALISED_SCHEMA::compile(std::string{dialect_identifier},
metaschema.value(), data.second),
schema.value(), std::ref(output))};
if (!result) {
Expand All @@ -57,14 +57,14 @@ struct GENERATE_MATERIALISED_SCHEMA {
[&callback, &data](const auto identifier) {
return data.second.get()(identifier, callback);
},
dialect_identifier.value());
dialect_identifier);
const auto timestamp_end{std::chrono::steady_clock::now()};

std::filesystem::create_directories(destination.parent_path());
sourcemeta::one::write_pretty_json(
destination, schema.value(), "application/schema+json",
sourcemeta::one::Encoding::GZIP,
sourcemeta::core::JSON{dialect_identifier.value()},
sourcemeta::core::JSON{std::string{dialect_identifier}},
std::chrono::duration_cast<std::chrono::milliseconds>(timestamp_end -
timestamp_start));
}
Expand Down Expand Up @@ -192,11 +192,13 @@ struct GENERATE_DEPENDENCIES {
[&result](const auto &origin, const auto &pointer, const auto &target,
const auto &) {
auto trace{sourcemeta::core::JSON::make_object()};
trace.assign("from", sourcemeta::core::to_json(origin));
trace.assign("to", sourcemeta::core::to_json(target));
trace.assign("from", sourcemeta::core::JSON{std::string{origin}});
trace.assign("to", sourcemeta::core::JSON{std::string{target}});
trace.assign("at", sourcemeta::core::to_json(pointer));
result.push_back(std::move(trace));
});
// Otherwise we are returning non-sense
assert(result.unique());
const auto timestamp_end{std::chrono::steady_clock::now()};

std::filesystem::create_directories(destination.parent_path());
Expand Down Expand Up @@ -285,20 +287,20 @@ struct GENERATE_BUNDLE {
return resolver(identifier, callback);
});
const auto dialect_identifier{sourcemeta::core::dialect(schema)};
assert(dialect_identifier.has_value());
assert(!dialect_identifier.empty());
sourcemeta::core::format(
schema, sourcemeta::core::schema_walker,
[&callback, &resolver](const auto identifier) {
return resolver(identifier, callback);
},
dialect_identifier.value());
dialect_identifier);
const auto timestamp_end{std::chrono::steady_clock::now()};

std::filesystem::create_directories(destination.parent_path());
sourcemeta::one::write_pretty_json(
destination, schema, "application/schema+json",
sourcemeta::one::Encoding::GZIP,
sourcemeta::core::JSON{dialect_identifier.value()},
sourcemeta::core::JSON{std::string{dialect_identifier}},
std::chrono::duration_cast<std::chrono::milliseconds>(timestamp_end -
timestamp_start));
}
Expand All @@ -320,20 +322,20 @@ struct GENERATE_EDITOR {
return resolver(identifier, callback);
});
const auto dialect_identifier{sourcemeta::core::dialect(schema)};
assert(dialect_identifier.has_value());
assert(!dialect_identifier.empty());
sourcemeta::core::format(
schema, sourcemeta::core::schema_walker,
[&callback, &resolver](const auto identifier) {
return resolver(identifier, callback);
},
dialect_identifier.value());
dialect_identifier);
const auto timestamp_end{std::chrono::steady_clock::now()};

std::filesystem::create_directories(destination.parent_path());
sourcemeta::one::write_pretty_json(
destination, schema, "application/schema+json",
sourcemeta::one::Encoding::GZIP,
sourcemeta::core::JSON{dialect_identifier.value()},
sourcemeta::core::JSON{std::string{dialect_identifier}},
std::chrono::duration_cast<std::chrono::milliseconds>(timestamp_end -
timestamp_start));
}
Expand Down
10 changes: 5 additions & 5 deletions src/resolver/include/sourcemeta/one/resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class Resolver {
Resolver() = default;
// Just to prevent mistakes
Resolver(const Resolver &) = delete;
Resolver &operator=(const Resolver &) = delete;
auto operator=(const Resolver &) -> Resolver & = delete;
Resolver(Resolver &&) = delete;
Resolver &operator=(Resolver &&) = delete;
auto operator=(Resolver &&) -> Resolver & = delete;

using Callback = std::function<void(const std::filesystem::path &)>;

Expand All @@ -44,9 +44,9 @@ class Resolver {
auto cache_path(const sourcemeta::core::JSON::String &uri,
const std::filesystem::path &path) -> void;

auto begin() const -> auto { return this->views.begin(); }
auto end() const -> auto { return this->views.end(); }
auto size() const -> auto { return this->views.size(); }
[[nodiscard]] auto begin() const -> auto { return this->views.begin(); }
[[nodiscard]] auto end() const -> auto { return this->views.end(); }
[[nodiscard]] auto size() const -> auto { return this->views.size(); }

struct Entry {
std::optional<std::filesystem::path> cache_path;
Expand Down
4 changes: 2 additions & 2 deletions src/resolver/include/sourcemeta/one/resolver_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class ResolverOutsideBaseError : public std::exception {
}

private:
const sourcemeta::core::JSON::String uri_;
const sourcemeta::core::JSON::String base_;
sourcemeta::core::JSON::String uri_;
sourcemeta::core::JSON::String base_;
};

} // namespace sourcemeta::one
Expand Down
42 changes: 20 additions & 22 deletions src/resolver/resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <cassert> // assert
#include <cctype> // std::tolower
#include <mutex> // std::mutex, std::lock_guard
#include <sstream> // std::ostringstream

static auto rebase(const sourcemeta::one::Configuration::Collection &collection,
const sourcemeta::core::JSON::String &uri,
Expand Down Expand Up @@ -158,23 +157,21 @@ auto Resolver::operator()(

sourcemeta::core::SchemaFrame frame{
sourcemeta::core::SchemaFrame::Mode::Locations};
const auto has_identifier{sourcemeta::core::identify(
schema,
[this](const auto subidentifier) {
return this->operator()(subidentifier);
},
result->second.dialect)
.has_value()};
const auto identifier_result{sourcemeta::core::identify(
schema,
[this](const auto subidentifier) {
return this->operator()(subidentifier);
},
result->second.dialect)};
const auto has_identifier{!identifier_result.empty()};
frame.analyse(
schema, sourcemeta::core::schema_walker,
[this](const auto subidentifier) {
return this->operator()(subidentifier);
},
result->second.dialect,
// Otherwise we will loop over all locations twice
has_identifier
? std::optional<sourcemeta::core::JSON::String>{std::nullopt}
: result->second.original_identifier);
has_identifier ? std::string_view{} : result->second.original_identifier);

const auto ref_hash{schema.as_object().hash("$ref")};
const auto dynamic_ref_hash{schema.as_object().hash("$dynamicRef")};
Expand All @@ -195,7 +192,7 @@ auto Resolver::operator()(
}

if (entry.second.base_dialect ==
"https://json-schema.org/draft/2020-12/schema") {
sourcemeta::core::SchemaBaseDialect::JSON_Schema_2020_12) {
const auto maybe_dynamic_ref{
subschema.try_at("$dynamicRef", dynamic_ref_hash)};
if (maybe_dynamic_ref) {
Expand Down Expand Up @@ -238,6 +235,9 @@ auto Resolver::add(const sourcemeta::core::JSON::String &server_url,
const auto schema{sourcemeta::core::read_yaml_or_json(path)};
assert(sourcemeta::core::is_schema(schema));

const std::string default_dialect_str{
collection.default_dialect.value_or("")};

/////////////////////////////////////////////////////////////////////////////
// (2) Try our best to determine the identifier of the schema, defaulting to a
// file-system-based identifier based on the *current* URI
Expand All @@ -249,15 +249,13 @@ auto Resolver::add(const sourcemeta::core::JSON::String &server_url,
.string()))
.canonicalize()
.recompose()};
sourcemeta::core::URI identifier_uri{normalise_identifier(
sourcemeta::core::identify(
sourcemeta::core::URI identifier_uri{
normalise_identifier(sourcemeta::core::identify(
schema,
[this](const auto subidentifier) {
return this->operator()(subidentifier);
},
collection.default_dialect, default_identifier)
// We can safely assume this as we pass a default identifier
.value())};
default_dialect_str, default_identifier))};
identifier_uri.canonicalize();
auto identifier{
identifier_uri.is_relative()
Expand Down Expand Up @@ -293,19 +291,19 @@ auto Resolver::add(const sourcemeta::core::JSON::String &server_url,
// we rebase according to the one base URI, etc
/////////////////////////////////////////////////////////////////////////////
const auto raw_dialect{
sourcemeta::core::dialect(schema, collection.default_dialect)};
sourcemeta::core::dialect(schema, default_dialect_str)};
// If we couldn't determine the dialect, we would be in trouble!
assert(raw_dialect.has_value());
assert(!raw_dialect.empty());
// Don't modify references to official meta-schemas
// TODO: This line may be unnecessarily slow. We should have a different
// function that just checks for string equality in an `std::unordered_map`
// of official dialects without constructing the final object
const auto is_official_dialect{
sourcemeta::core::schema_resolver(raw_dialect.value()).has_value()};
sourcemeta::core::schema_resolver(raw_dialect).has_value()};
auto current_dialect{is_official_dialect
? raw_dialect.value()
? std::string{raw_dialect}
: rebase(collection,
normalise_identifier(raw_dialect.value()),
normalise_identifier(raw_dialect),
server_url, collection_relative_path)};
// Otherwise we messed things up
assert(!current_dialect.ends_with("#.json"));
Expand Down
6 changes: 4 additions & 2 deletions src/server/action_jsonschema_evaluate.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@ auto trace(sourcemeta::blaze::Evaluator &evaluator,
// Determine keyword vocabulary
const auto &current_location{
static_locations.at(instruction.keyword_location)};
const auto base_dialect_result{sourcemeta::core::to_base_dialect(
current_location.at("baseDialect").to_string())};
assert(base_dialect_result.has_value());
const auto vocabularies{sourcemeta::core::vocabularies(
sourcemeta::core::schema_resolver,
current_location.at("baseDialect").to_string(),
sourcemeta::core::schema_resolver, base_dialect_result.value(),
current_location.at("dialect").to_string())};
const auto &walker_result{sourcemeta::core::schema_walker(
evaluate_path.back().to_property(), vocabularies)};
Expand Down
4 changes: 3 additions & 1 deletion src/shared/include/sourcemeta/one/shared_encoding.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#ifndef SOURCEMETA_ONE_SHARED_ENCODING_H_
#define SOURCEMETA_ONE_SHARED_ENCODING_H_

#include <cstdint> // std::uint8_t

namespace sourcemeta::one {

enum class Encoding { Identity, GZIP };
enum class Encoding : std::uint8_t { Identity, GZIP };

} // namespace sourcemeta::one

Expand Down
Loading