feat(reflect-cpp): Switched from glaze -> reflect cpp
A bug was discovered in glaze which prevented valid toml output. We have switched to toml++ and reflect-cpp. The interface has remained the same so this should not break any code
This commit is contained in:
36
build-config/reflect-cpp/src/reflectcpp.cpp
Normal file
36
build-config/reflect-cpp/src/reflectcpp.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// This file include all other source files, so that the user of the library
|
||||
// don't need to add multiple source files into their build.
|
||||
// Also, this speeds up compile time, compared to multiple separate .cpp files
|
||||
// compilation.
|
||||
|
||||
#include "rfl/Generic.cpp"
|
||||
#include "rfl/generic/Writer.cpp"
|
||||
#include "rfl/internal/strings/strings.cpp"
|
||||
#include "rfl/parsing/schema/Type.cpp"
|
||||
#include "rfl/parsing/schemaful/tuple_to_object.cpp"
|
||||
33
build-config/reflect-cpp/src/reflectcpp_json.cpp
Normal file
33
build-config/reflect-cpp/src/reflectcpp_json.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// This file include all other source files, so that the user of the library
|
||||
// don't need to add multiple source files into their build.
|
||||
// Also, this speeds up compile time, compared to multiple separate .cpp files
|
||||
// compilation.
|
||||
|
||||
#include "rfl/json/Writer.cpp"
|
||||
#include "rfl/json/to_schema.cpp"
|
||||
32
build-config/reflect-cpp/src/reflectcpp_toml.cpp
Normal file
32
build-config/reflect-cpp/src/reflectcpp_toml.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// This file include all other source files, so that the user of the library
|
||||
// don't need to add multiple source files into their build.
|
||||
// Also, this speeds up compile time, compared to multiple separate .cpp files
|
||||
// compilation.
|
||||
|
||||
#include "rfl/toml/Writer.cpp"
|
||||
77
build-config/reflect-cpp/src/rfl/Generic.cpp
Normal file
77
build-config/reflect-cpp/src/rfl/Generic.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "rfl/Generic.hpp"
|
||||
|
||||
namespace rfl {
|
||||
|
||||
Generic::Generic() : value_(std::nullopt) {}
|
||||
|
||||
Generic::Generic(Generic&& _other) noexcept = default;
|
||||
|
||||
Generic::Generic(const Generic& _other) = default;
|
||||
|
||||
Generic::Generic(const VariantType& _value) : value_(_value) {}
|
||||
|
||||
Generic::Generic(VariantType&& _value) noexcept : value_(std::move(_value)) {}
|
||||
|
||||
Generic::Generic(const ReflectionType& _r) : value_(from_reflection_type(_r)) {}
|
||||
|
||||
Generic::~Generic() = default;
|
||||
|
||||
Generic::VariantType Generic::from_reflection_type(
|
||||
const ReflectionType& _r) noexcept {
|
||||
if (!_r) {
|
||||
return std::nullopt;
|
||||
} else {
|
||||
return std::visit([](const auto& _v) -> VariantType { return _v; }, *_r);
|
||||
}
|
||||
}
|
||||
|
||||
bool Generic::is_null() const noexcept {
|
||||
return std::get_if<std::nullopt_t>(&value_) && true;
|
||||
}
|
||||
|
||||
Generic& Generic::operator=(const VariantType& _value) {
|
||||
value_ = _value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Generic& Generic::operator=(VariantType&& _value) noexcept {
|
||||
value_ = std::move(_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Generic& Generic::operator=(const Generic& _other) = default;
|
||||
|
||||
Generic& Generic::operator=(Generic&& _other) = default;
|
||||
|
||||
Generic::ReflectionType Generic::reflection() const noexcept {
|
||||
return std::visit([](const auto& _v) -> ReflectionType { return _v; },
|
||||
value_);
|
||||
}
|
||||
|
||||
} // namespace rfl
|
||||
90
build-config/reflect-cpp/src/rfl/generic/Writer.cpp
Normal file
90
build-config/reflect-cpp/src/rfl/generic/Writer.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "rfl/generic/Writer.hpp"
|
||||
|
||||
namespace rfl::generic {
|
||||
|
||||
Writer::OutputArrayType Writer::array_as_root(
|
||||
const size_t /*_size*/) const noexcept {
|
||||
root_ = Generic::Array();
|
||||
return OutputArray{get_if<Generic::Array>(&root_.variant())};
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::object_as_root(
|
||||
const size_t /*_size*/) const noexcept {
|
||||
root_ = Generic::Object();
|
||||
return OutputObject{get_if<Generic::Object>(&root_.variant())};
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::null_as_root() const noexcept {
|
||||
root_ = Generic::Null;
|
||||
return root_;
|
||||
}
|
||||
|
||||
Writer::OutputArrayType Writer::add_array_to_array(
|
||||
const size_t /*_size*/, OutputArrayType* _parent) const noexcept {
|
||||
_parent->val_->push_back(Generic(Generic::Array()));
|
||||
return OutputArrayType{
|
||||
get_if<Generic::Array>(&_parent->val_->rbegin()->variant())};
|
||||
}
|
||||
|
||||
Writer::OutputArrayType Writer::add_array_to_object(
|
||||
const std::string_view& _name, const size_t /*_size*/,
|
||||
OutputObjectType* _parent) const noexcept {
|
||||
_parent->val_->insert(_name, Generic(Generic::Array()));
|
||||
return OutputArrayType{
|
||||
get_if<Generic::Array>(&_parent->val_->rbegin()->second.variant())};
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::add_object_to_array(
|
||||
const size_t /*_size*/, OutputArrayType* _parent) const noexcept {
|
||||
_parent->val_->push_back(Generic(Generic::Object()));
|
||||
return OutputObjectType{
|
||||
get_if<Generic::Object>(&_parent->val_->rbegin()->variant())};
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::add_object_to_object(
|
||||
const std::string_view& _name, const size_t /*_size*/,
|
||||
OutputObjectType* _parent) const noexcept {
|
||||
_parent->val_->insert(_name, Generic(Generic::Object()));
|
||||
return OutputObjectType{
|
||||
get_if<Generic::Object>(&_parent->val_->rbegin()->second.variant())};
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::add_null_to_array(
|
||||
OutputArrayType* _parent) const noexcept {
|
||||
_parent->val_->push_back(Generic(Generic::Null));
|
||||
return Generic::Null;
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::add_null_to_object(
|
||||
const std::string_view& _name, OutputObjectType* _parent) const noexcept {
|
||||
_parent->val_->insert(_name, Generic(Generic::Null));
|
||||
return Generic::Null;
|
||||
}
|
||||
|
||||
} // namespace rfl::generic
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "rfl/internal/strings/strings.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace rfl ::internal ::strings {
|
||||
|
||||
char to_lower(const char ch) {
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
return ch + ('a' - 'A');
|
||||
} else {
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
char to_upper(const char ch) {
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
return ch + ('A' - 'a');
|
||||
} else {
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
std::string join(const std::string& _delimiter,
|
||||
const std::vector<std::string>& _strings) {
|
||||
if (_strings.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
auto res = _strings[0];
|
||||
for (size_t i = 1; i < _strings.size(); ++i) {
|
||||
res += _delimiter + _strings[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string replace_all(const std::string& _str, const std::string& _from,
|
||||
const std::string& _to) {
|
||||
auto str = _str;
|
||||
|
||||
size_t pos = 0;
|
||||
while ((pos = str.find(_from, pos)) != std::string::npos) {
|
||||
str.replace(pos, _from.length(), _to);
|
||||
pos += _to.length();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& _str,
|
||||
const std::string& _delimiter) {
|
||||
auto str = _str;
|
||||
size_t pos = 0;
|
||||
std::vector<std::string> result;
|
||||
while ((pos = str.find(_delimiter)) != std::string::npos) {
|
||||
result.emplace_back(str.substr(0, pos));
|
||||
str.erase(0, pos + _delimiter.length());
|
||||
}
|
||||
result.emplace_back(std::move(str));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string to_camel_case(const std::string& _str) {
|
||||
std::string result;
|
||||
bool capitalize = false;
|
||||
for (const char ch : _str) {
|
||||
if (ch == '_') {
|
||||
capitalize = true;
|
||||
} else if (capitalize) {
|
||||
result.push_back(to_upper(ch));
|
||||
capitalize = false;
|
||||
} else {
|
||||
result.push_back(ch);
|
||||
}
|
||||
}
|
||||
if (result.size() > 0) {
|
||||
result[0] = to_lower(result[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string to_pascal_case(const std::string& _str) {
|
||||
auto result = to_camel_case("_" + _str);
|
||||
if (result.size() > 0) {
|
||||
result[0] = to_upper(result[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace rfl::internal::strings
|
||||
125
build-config/reflect-cpp/src/rfl/json/Writer.cpp
Normal file
125
build-config/reflect-cpp/src/rfl/json/Writer.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "rfl/json/Writer.hpp"
|
||||
|
||||
namespace rfl::json {
|
||||
|
||||
Writer::Writer()
|
||||
: doc_(std::shared_ptr<yyjson_mut_doc>(yyjson_mut_doc_new(NULL),
|
||||
yyjson_mut_doc_free)) {}
|
||||
|
||||
Writer::OutputArrayType Writer::array_as_root(const size_t) const noexcept {
|
||||
const auto arr = yyjson_mut_arr(doc());
|
||||
yyjson_mut_doc_set_root(doc(), arr);
|
||||
return OutputArrayType(arr);
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::object_as_root(const size_t) const noexcept {
|
||||
const auto obj = yyjson_mut_obj(doc());
|
||||
yyjson_mut_doc_set_root(doc(), obj);
|
||||
return OutputObjectType(obj);
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::null_as_root() const noexcept {
|
||||
const auto null = yyjson_mut_null(doc());
|
||||
yyjson_mut_doc_set_root(doc(), null);
|
||||
return OutputVarType(null);
|
||||
}
|
||||
|
||||
Writer::OutputArrayType Writer::add_array_to_array(
|
||||
const size_t, OutputArrayType* _parent) const {
|
||||
const auto arr = yyjson_mut_arr(doc());
|
||||
const bool ok = yyjson_mut_arr_add_val(_parent->val_, arr);
|
||||
if (!ok) {
|
||||
throw std::runtime_error("Adding an array to an array failed.");
|
||||
}
|
||||
return OutputArrayType(arr);
|
||||
}
|
||||
|
||||
Writer::OutputArrayType Writer::add_array_to_object(
|
||||
const std::string_view& _name, const size_t,
|
||||
OutputObjectType* _parent) const {
|
||||
const auto arr = yyjson_mut_arr(doc());
|
||||
const bool ok = yyjson_mut_obj_add(
|
||||
_parent->val_, yyjson_mut_strcpy(doc(), _name.data()), arr);
|
||||
if (!ok) {
|
||||
throw std::runtime_error("Could not add field '" + std::string(_name) +
|
||||
"' to object.");
|
||||
}
|
||||
return OutputArrayType(arr);
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::add_object_to_array(
|
||||
const size_t, OutputArrayType* _parent) const {
|
||||
const auto obj = yyjson_mut_obj(doc());
|
||||
const bool ok = yyjson_mut_arr_add_val(_parent->val_, obj);
|
||||
if (!ok) {
|
||||
throw std::runtime_error("Adding an object to an array failed.");
|
||||
}
|
||||
return OutputObjectType(obj);
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::add_object_to_object(
|
||||
const std::string_view& _name, const size_t,
|
||||
OutputObjectType* _parent) const {
|
||||
const auto obj = yyjson_mut_obj(doc());
|
||||
const auto ok = yyjson_mut_obj_add(
|
||||
_parent->val_, yyjson_mut_strcpy(doc(), _name.data()), obj);
|
||||
if (!ok) {
|
||||
throw std::runtime_error("Could not add field '" + std::string(_name) +
|
||||
"' to object.");
|
||||
}
|
||||
return OutputObjectType(obj);
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::add_null_to_array(
|
||||
OutputArrayType* _parent) const {
|
||||
const auto null = yyjson_mut_null(doc());
|
||||
const bool ok = yyjson_mut_arr_add_val(_parent->val_, null);
|
||||
if (!ok) {
|
||||
throw std::runtime_error("Adding null to an array failed.");
|
||||
}
|
||||
return OutputVarType(null);
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::add_null_to_object(
|
||||
const std::string_view& _name, OutputObjectType* _parent) const {
|
||||
const auto null = yyjson_mut_null(doc());
|
||||
const bool ok = yyjson_mut_obj_add(
|
||||
_parent->val_, yyjson_mut_strcpy(doc(), _name.data()), null);
|
||||
if (!ok) {
|
||||
throw std::runtime_error("Could not add field '" + std::string(_name) +
|
||||
"' to object.");
|
||||
}
|
||||
return OutputVarType(null);
|
||||
}
|
||||
|
||||
void Writer::end_array(OutputArrayType*) const noexcept {}
|
||||
|
||||
void Writer::end_object(OutputObjectType*) const noexcept {}
|
||||
|
||||
} // namespace rfl::json
|
||||
323
build-config/reflect-cpp/src/rfl/json/to_schema.cpp
Normal file
323
build-config/reflect-cpp/src/rfl/json/to_schema.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "rfl/json/to_schema.hpp"
|
||||
|
||||
#include "rfl/json/schema/Type.hpp"
|
||||
#include "rfl/json/write.hpp"
|
||||
|
||||
namespace rfl::json {
|
||||
|
||||
schema::Type type_to_json_schema_type(const parsing::schema::Type& _type,
|
||||
const bool _no_required);
|
||||
|
||||
bool is_optional(const parsing::schema::Type& _t) {
|
||||
return _t.variant_.visit([&](const auto& _v) -> bool {
|
||||
using T = std::remove_cvref_t<decltype(_v)>;
|
||||
if constexpr (std::is_same_v<T, parsing::schema::Type::Description>) {
|
||||
return is_optional(*_v.type_);
|
||||
|
||||
} else if constexpr (std::is_same_v<T, parsing::schema::Type::Validated>) {
|
||||
return is_optional(*_v.type_);
|
||||
|
||||
} else {
|
||||
return std::is_same_v<T, parsing::schema::Type::Optional>;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::string numeric_type_to_string(const parsing::schema::Type& _type) {
|
||||
const auto handle_variant = [](const auto& _t) -> std::string {
|
||||
using T = std::remove_cvref_t<decltype(_t)>;
|
||||
using Type = parsing::schema::Type;
|
||||
if constexpr (std::is_same<T, Type::Int32>() ||
|
||||
std::is_same<T, Type::Int64>() ||
|
||||
std::is_same<T, Type::UInt32>() ||
|
||||
std::is_same<T, Type::UInt64>() ||
|
||||
std::is_same<T, Type::Integer>()) {
|
||||
return schema::Type::Integer{}.type.str();
|
||||
} else {
|
||||
return schema::Type::Number{}.type.str();
|
||||
}
|
||||
};
|
||||
return rfl::visit(handle_variant, _type.variant_);
|
||||
}
|
||||
|
||||
schema::Type handle_validation_type(
|
||||
const parsing::schema::Type& _type,
|
||||
const parsing::schema::ValidationType& _validation_type,
|
||||
const bool _no_required) {
|
||||
auto handle_variant = [&](const auto& _v) -> schema::Type {
|
||||
using T = std::remove_cvref_t<decltype(_v)>;
|
||||
using ValidationType = parsing::schema::ValidationType;
|
||||
if constexpr (std::is_same<T, ValidationType::AllOf>()) {
|
||||
auto all_of = std::vector<schema::Type>();
|
||||
for (const auto& t : _v.types_) {
|
||||
all_of.emplace_back(handle_validation_type(_type, t, _no_required));
|
||||
}
|
||||
return schema::Type{.value = schema::Type::AllOf{.allOf = all_of}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::AnyOf>()) {
|
||||
auto any_of = std::vector<schema::Type>();
|
||||
for (const auto& t : _v.types_) {
|
||||
any_of.emplace_back(handle_validation_type(_type, t, _no_required));
|
||||
}
|
||||
return schema::Type{.value = schema::Type::AnyOf{.anyOf = any_of}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::OneOf>()) {
|
||||
auto one_of = std::vector<schema::Type>();
|
||||
for (const auto& t : _v.types_) {
|
||||
one_of.emplace_back(handle_validation_type(_type, t, _no_required));
|
||||
}
|
||||
return schema::Type{.value = schema::Type::OneOf{.oneOf = one_of}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::Regex>()) {
|
||||
return schema::Type{.value = schema::Type::Regex{.pattern = _v.pattern_}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::Size>()) {
|
||||
auto t = type_to_json_schema_type(_type, _no_required);
|
||||
const auto to_size = [](const auto _val) {
|
||||
return static_cast<size_t>(_val);
|
||||
};
|
||||
auto handle_size_variant = [&](auto& _t, const auto& _size_limit) {
|
||||
using U = std::remove_cvref_t<decltype(_t)>;
|
||||
using V = std::remove_cvref_t<decltype(_size_limit)>;
|
||||
if constexpr (std::is_same<U, schema::Type::TypedArray>() ||
|
||||
std::is_same<U, schema::Type::String>()) {
|
||||
if constexpr (std::is_same<V, ValidationType::Minimum>()) {
|
||||
_t.minSize = _size_limit.value_.visit(to_size);
|
||||
return t;
|
||||
|
||||
} else if constexpr (std::is_same<V, ValidationType::Maximum>()) {
|
||||
_t.maxSize = _size_limit.value_.visit(to_size);
|
||||
return t;
|
||||
|
||||
} else if constexpr (std::is_same<V, ValidationType::EqualTo>()) {
|
||||
_t.minSize = _size_limit.value_.visit(to_size);
|
||||
_t.maxSize = _size_limit.value_.visit(to_size);
|
||||
return t;
|
||||
|
||||
} else if constexpr (std::is_same<V, ValidationType::AnyOf>() ||
|
||||
std::is_same<V, ValidationType::AllOf>()) {
|
||||
V v;
|
||||
for (const auto& limiter : _size_limit.types_) {
|
||||
v.types_.push_back(ValidationType{ValidationType::Size{
|
||||
.size_limit_ = rfl::Ref<ValidationType>::make(limiter)}});
|
||||
}
|
||||
return handle_validation_type(_type, ValidationType{.variant_ = v},
|
||||
_no_required);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
return rfl::visit(handle_size_variant, t.value, _v.size_limit_->variant_);
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::ExclusiveMaximum>()) {
|
||||
return schema::Type{.value = schema::Type::ExclusiveMaximum{
|
||||
.exclusiveMaximum = _v.value_,
|
||||
.type = numeric_type_to_string(_type)}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::ExclusiveMinimum>()) {
|
||||
return schema::Type{.value = schema::Type::ExclusiveMinimum{
|
||||
.exclusiveMinimum = _v.value_,
|
||||
.type = numeric_type_to_string(_type)}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::Maximum>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::Maximum{
|
||||
.maximum = _v.value_, .type = numeric_type_to_string(_type)}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::Minimum>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::Minimum{
|
||||
.minimum = _v.value_, .type = numeric_type_to_string(_type)}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::EqualTo>()) {
|
||||
const auto maximum = schema::Type{
|
||||
.value = schema::Type::Maximum{
|
||||
.maximum = _v.value_, .type = numeric_type_to_string(_type)}};
|
||||
const auto minimum = schema::Type{
|
||||
.value = schema::Type::Minimum{
|
||||
.minimum = _v.value_, .type = numeric_type_to_string(_type)}};
|
||||
return schema::Type{.value =
|
||||
schema::Type::AllOf{.allOf = {maximum, minimum}}};
|
||||
|
||||
} else if constexpr (std::is_same<T, ValidationType::NotEqualTo>()) {
|
||||
const auto excl_maximum =
|
||||
schema::Type{.value = schema::Type::ExclusiveMaximum{
|
||||
.exclusiveMaximum = _v.value_,
|
||||
.type = numeric_type_to_string(_type)}};
|
||||
const auto excl_minimum =
|
||||
schema::Type{.value = schema::Type::ExclusiveMinimum{
|
||||
.exclusiveMinimum = _v.value_,
|
||||
.type = numeric_type_to_string(_type)}};
|
||||
return schema::Type{
|
||||
.value = schema::Type::AnyOf{.anyOf = {excl_maximum, excl_minimum}}};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Not all cases were covered.");
|
||||
}
|
||||
};
|
||||
|
||||
return rfl::visit(handle_variant, _validation_type.variant_);
|
||||
}
|
||||
|
||||
schema::Type type_to_json_schema_type(const parsing::schema::Type& _type,
|
||||
const bool _no_required) {
|
||||
auto handle_variant = [&](const auto& _t) -> schema::Type {
|
||||
using T = std::remove_cvref_t<decltype(_t)>;
|
||||
using Type = parsing::schema::Type;
|
||||
if constexpr (std::is_same<T, Type::Boolean>()) {
|
||||
return schema::Type{.value = schema::Type::Boolean{}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Int32>() ||
|
||||
std::is_same<T, Type::Int64>() ||
|
||||
std::is_same<T, Type::UInt32>() ||
|
||||
std::is_same<T, Type::UInt64>() ||
|
||||
std::is_same<T, Type::Integer>()) {
|
||||
return schema::Type{.value = schema::Type::Integer{}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Float>() ||
|
||||
std::is_same<T, Type::Double>()) {
|
||||
return schema::Type{.value = schema::Type::Number{}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::String>() ||
|
||||
std::is_same<T, Type::Bytestring>() ||
|
||||
std::is_same<T, Type::Vectorstring>()) {
|
||||
return schema::Type{.value = schema::Type::String{}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::AnyOf>()) {
|
||||
auto any_of = std::vector<schema::Type>();
|
||||
for (const auto& t : _t.types_) {
|
||||
any_of.emplace_back(type_to_json_schema_type(t, _no_required));
|
||||
}
|
||||
return schema::Type{.value = schema::Type::AnyOf{.anyOf = any_of}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Description>()) {
|
||||
auto res = type_to_json_schema_type(*_t.type_, _no_required);
|
||||
const auto update_prediction = [&](auto _v) -> schema::Type {
|
||||
_v.description = _t.description_;
|
||||
return schema::Type{_v};
|
||||
};
|
||||
return rfl::visit(update_prediction, res.value);
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::FixedSizeTypedArray>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::FixedSizeTypedArray{
|
||||
.items = Ref<schema::Type>::make(
|
||||
type_to_json_schema_type(*_t.type_, _no_required)),
|
||||
.minItems = _t.size_,
|
||||
.maxItems = _t.size_}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Literal>()) {
|
||||
return schema::Type{.value =
|
||||
schema::Type::StringEnum{.values = _t.values_}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Object>()) {
|
||||
auto properties = rfl::Object<schema::Type>();
|
||||
auto required = std::vector<std::string>();
|
||||
for (const auto& [k, v] : _t.types_) {
|
||||
properties[k] = type_to_json_schema_type(v, _no_required);
|
||||
if (!is_optional(v) && !_no_required) {
|
||||
required.push_back(k);
|
||||
}
|
||||
}
|
||||
auto additional_properties =
|
||||
_t.additional_properties_
|
||||
? std::make_shared<schema::Type>(type_to_json_schema_type(
|
||||
*_t.additional_properties_, _no_required))
|
||||
: std::shared_ptr<schema::Type>();
|
||||
return schema::Type{.value = schema::Type::Object{
|
||||
.properties = properties,
|
||||
.required = required,
|
||||
.additionalProperties = additional_properties}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Optional>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::AnyOf{
|
||||
.anyOf = {type_to_json_schema_type(*_t.type_, _no_required),
|
||||
schema::Type{schema::Type::Null{}}}}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Reference>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::Reference{.ref = "#/$defs/" + _t.name_}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::StringMap>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::StringMap{
|
||||
.additionalProperties = Ref<schema::Type>::make(
|
||||
type_to_json_schema_type(*_t.value_type_, _no_required))}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Tuple>()) {
|
||||
auto items = std::vector<schema::Type>();
|
||||
for (const auto& t : _t.types_) {
|
||||
items.emplace_back(type_to_json_schema_type(t, _no_required));
|
||||
}
|
||||
return schema::Type{.value = schema::Type::Tuple{.prefixItems = items}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::TypedArray>()) {
|
||||
return schema::Type{
|
||||
.value = schema::Type::TypedArray{
|
||||
.items = Ref<schema::Type>::make(
|
||||
type_to_json_schema_type(*_t.type_, _no_required))}};
|
||||
|
||||
} else if constexpr (std::is_same<T, Type::Validated>()) {
|
||||
return handle_validation_type(*_t.type_, _t.validation_, _no_required);
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Not all cases were covered.");
|
||||
}
|
||||
};
|
||||
|
||||
return rfl::visit(handle_variant, _type.variant_);
|
||||
}
|
||||
|
||||
std::string to_schema_internal_schema(
|
||||
const parsing::schema::Definition& internal_schema,
|
||||
const yyjson_write_flag _flag, const bool _no_required,
|
||||
const std::string& comment) {
|
||||
auto definitions = std::map<std::string, schema::Type>();
|
||||
for (const auto& [k, v] : internal_schema.definitions_) {
|
||||
definitions[k] = type_to_json_schema_type(v, _no_required);
|
||||
}
|
||||
using JSONSchemaType =
|
||||
typename TypeHelper<schema::Type::ReflectionType>::JSONSchemaType;
|
||||
const auto to_schema = [&](auto&& _root) -> JSONSchemaType {
|
||||
using U = std::decay_t<decltype(_root)>;
|
||||
return schema::JSONSchema<U>{
|
||||
.comment =
|
||||
!comment.empty() ? std::optional(std::move(comment)) : std::nullopt,
|
||||
.root = std::forward<decltype(_root)>(_root),
|
||||
.definitions = definitions,
|
||||
};
|
||||
};
|
||||
auto root = type_to_json_schema_type(internal_schema.root_, _no_required);
|
||||
const auto json_schema = rfl::visit(to_schema, std::move(root.value));
|
||||
return write(json_schema, _flag);
|
||||
}
|
||||
|
||||
} // namespace rfl::json
|
||||
40
build-config/reflect-cpp/src/rfl/parsing/schema/Type.cpp
Normal file
40
build-config/reflect-cpp/src/rfl/parsing/schema/Type.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023-2024 Code17 GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "rfl/parsing/schema/Type.hpp"
|
||||
|
||||
namespace rfl::parsing::schema {
|
||||
|
||||
/// Requires a lot of template instantiation, so we do not want this to be
|
||||
/// inlined.
|
||||
|
||||
Type::Type() : variant_() {}
|
||||
|
||||
Type::Type(const VariantType& _variant) : variant_(_variant) {}
|
||||
|
||||
Type::~Type() = default;
|
||||
|
||||
} // namespace rfl::parsing::schema
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "rfl/parsing/schemaful/tuple_to_object.hpp"
|
||||
|
||||
namespace rfl::parsing::schemaful {
|
||||
|
||||
std::string to_field_name(const size_t _i) {
|
||||
return std::string({'f', static_cast<char>('0' + ((_i / 100) % 10)),
|
||||
static_cast<char>('0' + ((_i / 10) % 10)),
|
||||
static_cast<char>('0' + (_i % 10))});
|
||||
}
|
||||
|
||||
schema::Type::Object tuple_to_object(const schema::Type::Tuple& _tup) {
|
||||
auto obj = schema::Type::Object{};
|
||||
for (size_t i = 0; i < _tup.types_.size(); ++i) {
|
||||
obj.types_[to_field_name(i)] = _tup.types_[i];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
} // namespace rfl::parsing::schemaful
|
||||
59
build-config/reflect-cpp/src/rfl/toml/Writer.cpp
Normal file
59
build-config/reflect-cpp/src/rfl/toml/Writer.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "rfl/toml/Writer.hpp"
|
||||
|
||||
namespace rfl::toml {
|
||||
|
||||
Writer::Writer(::toml::table* _root) : root_(_root) {}
|
||||
|
||||
Writer::~Writer() = default;
|
||||
|
||||
Writer::OutputObjectType Writer::object_as_root(const size_t /*_size*/) const {
|
||||
return OutputObjectType{root_};
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::null_as_root() const { return OutputVarType{}; }
|
||||
|
||||
Writer::OutputArrayType Writer::add_array_to_array(
|
||||
const size_t /*_size*/, OutputArrayType* _parent) const {
|
||||
const auto i = _parent->val_->size();
|
||||
_parent->val_->push_back(::toml::array());
|
||||
return OutputArrayType{_parent->val_->at(i).as_array()};
|
||||
}
|
||||
|
||||
Writer::OutputArrayType Writer::add_array_to_object(
|
||||
const std::string_view& _name, const size_t /*_size*/,
|
||||
OutputObjectType* _parent) const {
|
||||
_parent->val_->emplace(_name, ::toml::array());
|
||||
return OutputArrayType{_parent->val_->at_path(_name).as_array()};
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::add_object_to_array(
|
||||
const size_t /*_size*/, OutputArrayType* _parent) const {
|
||||
const auto i = _parent->val_->size();
|
||||
_parent->val_->push_back(::toml::table());
|
||||
return OutputObjectType{_parent->val_->at(i).as_table()};
|
||||
}
|
||||
|
||||
Writer::OutputObjectType Writer::add_object_to_object(
|
||||
const std::string_view& _name, const size_t /*_size*/,
|
||||
OutputObjectType* _parent) const {
|
||||
_parent->val_->emplace(_name, ::toml::table());
|
||||
return OutputObjectType{_parent->val_->at_path(_name).as_table()};
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::add_null_to_array(
|
||||
OutputArrayType* _parent) const {
|
||||
_parent->val_->push_back(std::string(""));
|
||||
return OutputVarType{};
|
||||
}
|
||||
|
||||
Writer::OutputVarType Writer::add_null_to_object(
|
||||
const std::string_view& _name, OutputObjectType* _parent) const {
|
||||
_parent->val_->emplace(_name, ::toml::value(std::string("")));
|
||||
return OutputVarType{};
|
||||
}
|
||||
|
||||
void Writer::end_array(OutputArrayType* /*_arr*/) const {}
|
||||
|
||||
void Writer::end_object(OutputObjectType* /*_obj*/) const {}
|
||||
|
||||
} // namespace rfl::toml
|
||||
11069
build-config/reflect-cpp/src/yyjson.c
Normal file
11069
build-config/reflect-cpp/src/yyjson.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user