diff --git a/.gitignore b/.gitignore index cc3a2926..287ed2d6 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ __pycache__/ # Distribution / packaging .Python build/ +build-*/ develop-eggs/ dist/ downloads/ diff --git a/CMakeLists.txt b/CMakeLists.txt index fb1069ff..c2722454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ option(REFLECTCPP_BOOST_SERIALIZATION "Enable Boost.Serialization support" ${REF option(REFLECTCPP_BUILD_BENCHMARKS "Build benchmarks" OFF) option(REFLECTCPP_BUILD_TESTS "Build tests" OFF) option(REFLECTCPP_CHECK_HEADERS "Make sure that all headers are self-contained" OFF) +option(REFLECTCPP_BUILD_MODULES "Build experimental C++20 module interfaces" OFF) option(REFLECTCPP_USE_BUNDLED_DEPENDENCIES "Use the bundled dependencies" ON) @@ -460,6 +461,86 @@ set_target_properties(reflectcpp PROPERTIES LINKER_LANGUAGE CXX) target_sources(reflectcpp PRIVATE ${REFLECT_CPP_SOURCES}) target_precompile_headers(reflectcpp PRIVATE [["rfl.hpp"]] ) +if(REFLECTCPP_BUILD_MODULES) + if(CMAKE_VERSION VERSION_LESS 3.28) + message(FATAL_ERROR "REFLECTCPP_BUILD_MODULES requires CMake 3.28 or newer") + endif() + + if(CMAKE_GENERATOR MATCHES "Unix Makefiles") + message(FATAL_ERROR "REFLECTCPP_BUILD_MODULES requires a generator with C++ module dependency scanning support, such as Ninja") + endif() + + set(REFLECTCPP_MODULE_SOURCES + src/modules/rfl.cppm + src/modules/rfl.generic.cppm + src/modules/rfl.cli.cppm + ) + + if(REFLECTCPP_JSON) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.json.cppm) + endif() + if(REFLECTCPP_AVRO) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.avro.cppm) + endif() + if(REFLECTCPP_BSON) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.bson.cppm) + endif() + if(REFLECTCPP_CAPNPROTO) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.capnproto.cppm) + endif() + if(REFLECTCPP_CBOR) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.cbor.cppm) + endif() + if(REFLECTCPP_CEREAL) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.cereal.cppm) + endif() + if(REFLECTCPP_CSV) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.csv.cppm) + endif() + if(REFLECTCPP_FLEXBUFFERS) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.flexbuf.cppm) + endif() + if(REFLECTCPP_MSGPACK) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.msgpack.cppm) + endif() + if(REFLECTCPP_PARQUET) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.parquet.cppm) + endif() + if(REFLECTCPP_TOML) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.toml.cppm) + endif() + if(REFLECTCPP_UBJSON) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.ubjson.cppm) + endif() + if(REFLECTCPP_XML) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.xml.cppm) + endif() + if(REFLECTCPP_YAML) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.yaml.cppm) + endif() + if(REFLECTCPP_YAS) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.yas.cppm) + endif() + if(REFLECTCPP_BOOST_SERIALIZATION) + list(APPEND REFLECTCPP_MODULE_SOURCES src/modules/rfl.boost_serialization.cppm) + endif() + + target_sources(reflectcpp + PUBLIC + FILE_SET reflectcpp_modules + TYPE CXX_MODULES + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/modules + FILES ${REFLECTCPP_MODULE_SOURCES} + ) + set_source_files_properties(${REFLECTCPP_MODULE_SOURCES} + PROPERTIES SKIP_PRECOMPILE_HEADERS ON) + set_target_properties(reflectcpp PROPERTIES CXX_SCAN_FOR_MODULES ON) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(reflectcpp PUBLIC -fmodules-ts) + endif() +endif() + if (REFLECTCPP_BUILD_TESTS) add_library(reflectcpp_tests_crt INTERFACE) target_link_libraries(reflectcpp_tests_crt INTERFACE reflectcpp GTest::gtest_main) @@ -538,10 +619,17 @@ if (REFLECTCPP_INSTALL) FILES ${RFL_HEADERS} ) + if(REFLECTCPP_BUILD_MODULES) + set(_REFLECTCPP_MODULE_FILE_SET_INSTALL + FILE_SET reflectcpp_modules DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/reflectcpp/modules + ) + endif() + install( TARGETS reflectcpp EXPORT reflectcpp-exports FILE_SET reflectcpp_headers DESTINATION ${INCLUDE_INSTALL_DIR} + ${_REFLECTCPP_MODULE_FILE_SET_INSTALL} ) install( @@ -586,4 +674,3 @@ include(CPack) if (ament_cmake_FOUND) ament_package() endif() - diff --git a/include/rfl/capnproto/to_schema.hpp b/include/rfl/capnproto/to_schema.hpp index 2a6e96a2..525abd3e 100644 --- a/include/rfl/capnproto/to_schema.hpp +++ b/include/rfl/capnproto/to_schema.hpp @@ -38,7 +38,7 @@ struct SchemaHolder { }; template -static const SchemaHolder schema_holder = +inline const SchemaHolder schema_holder = SchemaHolder::make(); /// Returns the Cap'n Proto schema for a class. diff --git a/include/rfl/cli/Reader.hpp b/include/rfl/cli/Reader.hpp index 1d46e5d6..b10d47ed 100644 --- a/include/rfl/cli/Reader.hpp +++ b/include/rfl/cli/Reader.hpp @@ -2,8 +2,8 @@ #define RFL_CLI_READER_HPP_ #include -#include #include +#include #include #include #include @@ -20,15 +20,16 @@ namespace rfl::cli { /// Character used to separate nested field names in CLI arguments. /// Example: `--database.host` for nested field `database::host`. -static constexpr char path_separator = '.'; +inline constexpr char path_separator = '.'; /// Character used to delimit array elements in CLI argument values. /// Example: `--ports=8080,8081,8082` for an array of ports. -static constexpr char array_delimiter = ','; +inline constexpr char array_delimiter = ','; -/// Represents a CLI variable that can be a direct value or a path in the argument map. -/// The `path` represents the hierarchical key (e.g., "database.host"). -/// The `direct_value` is used when parsing array elements directly. +/// Represents a CLI variable that can be a direct value or a path in the +/// argument map. The `path` represents the hierarchical key (e.g., +/// "database.host"). The `direct_value` is used when parsing array elements +/// directly. struct CliVarType { const std::map* const args = nullptr; const std::string path; @@ -55,10 +56,10 @@ struct CliArrayType { /// @param _str The string to parse /// @param _path The CLI argument path (unused for strings) /// @return The string unchanged -template requires std::same_as -rfl::Result parse_value( - const std::string& _str, const std::string& -) noexcept { +template + requires std::same_as +rfl::Result parse_value(const std::string& _str, + const std::string&) noexcept { return _str; } @@ -68,22 +69,23 @@ rfl::Result parse_value( /// @param _str The string to parse /// @param _path The CLI argument path (for error messages) /// @return A Result containing the boolean value or an error -template requires std::same_as -rfl::Result parse_value( - const std::string& _str, const std::string& _path -) noexcept { +template + requires std::same_as +rfl::Result parse_value(const std::string& _str, + const std::string& _path) noexcept { if (_str.empty() || _str == "true" || _str == "1") { return true; } if (_str == "false" || _str == "0") { return false; } - return error( - "Could not cast '" + _str + "' to boolean for key '" + _path + "'."); + return error("Could not cast '" + _str + "' to boolean for key '" + _path + + "'."); } /// Parses a string value to a floating-point number. -/// Uses locale-independent parsing (C locale) to ensure "3.14" works consistently. +/// Uses locale-independent parsing (C locale) to ensure "3.14" works +/// consistently. /// @tparam T Must be a floating-point type (float, double, long double) /// @param _str The string to parse /// @param _path The CLI argument path (for error messages) @@ -92,10 +94,10 @@ rfl::Result parse_value( // std::strtod depends on the C locale (LC_NUMERIC), so "3.14" can fail // under locales that use comma as decimal separator. // Use strtod_l with an explicit "C" locale on all platforms for consistency. -template requires (std::is_floating_point_v) -rfl::Result parse_value( - const std::string& _str, const std::string& _path -) noexcept { +template + requires(std::is_floating_point_v) +rfl::Result parse_value(const std::string& _str, + const std::string& _path) noexcept { char* end = nullptr; #ifdef _WIN32 const auto c_locale = _create_locale(LC_NUMERIC, "C"); @@ -107,8 +109,8 @@ rfl::Result parse_value( freelocale(c_locale); #endif if (end != _str.c_str() + _str.size()) { - return error( - "Could not cast '" + _str + "' to floating point for key '" + _path + "'."); + return error("Could not cast '" + _str + "' to floating point for key '" + + _path + "'."); } return static_cast(value); } @@ -119,23 +121,24 @@ rfl::Result parse_value( /// @param _str The string to parse /// @param _path The CLI argument path (for error messages) /// @return A Result containing the parsed integer or an error -template requires (std::is_integral_v && !std::same_as) -rfl::Result parse_value( - const std::string& _str, const std::string& _path -) noexcept { +template + requires(std::is_integral_v && !std::same_as) +rfl::Result parse_value(const std::string& _str, + const std::string& _path) noexcept { T value; const auto [ptr, ec] = std::from_chars(_str.data(), _str.data() + _str.size(), value); if (ec != std::errc() || ptr != _str.data() + _str.size()) { - return error( - "Could not cast '" + _str + "' to integer for key '" + _path + "'."); + return error("Could not cast '" + _str + "' to integer for key '" + _path + + "'."); } return value; } /// Reader for command-line interface arguments. -/// Parses hierarchical key-value pairs from CLI arguments (e.g., --database.host=localhost). -/// Supports arrays through comma-delimited values (e.g., --ports=8080,8081). +/// Parses hierarchical key-value pairs from CLI arguments (e.g., +/// --database.host=localhost). Supports arrays through comma-delimited values +/// (e.g., --ports=8080,8081). struct Reader { using InputArrayType = CliArrayType; using InputObjectType = CliObjectType; @@ -147,31 +150,32 @@ struct Reader { /// Gets a specific element from a CLI array by index. /// @param _idx The index of the element to retrieve /// @param _arr The CLI array - /// @return A Result containing the element as a CliVarType or an error if out of bounds + /// @return A Result containing the element as a CliVarType or an error if out + /// of bounds rfl::Result get_field_from_array( const size_t _idx, const InputArrayType& _arr) const noexcept { if (_idx >= _arr.values.size()) { - return error( - std::string("Index ") + std::to_string(_idx) + " out of bounds."); + return error(std::string("Index ") + std::to_string(_idx) + + " out of bounds."); } return InputVarType{nullptr, "", _arr.values[_idx]}; } /// Gets a specific field from a CLI object by name. - /// Constructs a child path by appending the field name to the object's prefix. + /// Constructs a child path by appending the field name to the object's + /// prefix. /// @param _name The field name /// @param _obj The CLI object /// @return A Result containing a CliVarType for accessing the field rfl::Result get_field_from_object( const std::string& _name, const InputObjectType& _obj) const noexcept { - const auto child_path = _obj.prefix.empty() - ? _name - : _obj.prefix + _name; + const auto child_path = _obj.prefix.empty() ? _name : _obj.prefix + _name; return InputVarType{_obj.args, child_path, std::nullopt}; } /// Checks if a CLI variable is empty (has no value). - /// A variable is empty if there's no direct value and no matching key in the argument map. + /// A variable is empty if there's no direct value and no matching key in the + /// argument map. /// @param _var The CLI variable to check /// @return true if the variable is empty, false otherwise bool is_empty(const InputVarType& _var) const noexcept { @@ -186,23 +190,21 @@ struct Reader { } const auto prefix = _var.path + path_separator; const auto it = _var.args->lower_bound(prefix); - return it == _var.args->end() - || it->first.substr(0, prefix.size()) != prefix; + return it == _var.args->end() || + it->first.substr(0, prefix.size()) != prefix; } /// Reads all elements from a CLI array using the provided array reader. - /// @tparam ArrayReader The type of reader that processes individual array elements + /// @tparam ArrayReader The type of reader that processes individual array + /// elements /// @param _array_reader The reader object that processes each element /// @param _arr The CLI array to read from /// @return std::nullopt on success, or an Error if reading fails template - std::optional read_array( - const ArrayReader& _array_reader, - const InputArrayType& _arr - ) const noexcept { + std::optional read_array(const ArrayReader& _array_reader, + const InputArrayType& _arr) const noexcept { for (const auto& val : _arr.values) { - const auto err = _array_reader.read( - InputVarType{nullptr, "", val}); + const auto err = _array_reader.read(InputVarType{nullptr, "", val}); if (err) { return err; } @@ -211,36 +213,33 @@ struct Reader { } /// Reads all fields from a CLI object using the provided object reader. - /// Iterates through all arguments with the object's prefix and extracts child field names. - /// @tparam ObjectReader The type of reader that processes individual object fields + /// Iterates through all arguments with the object's prefix and extracts child + /// field names. + /// @tparam ObjectReader The type of reader that processes individual object + /// fields /// @param _object_reader The reader object that processes each field /// @param _obj The CLI object to read from /// @return std::nullopt on success, or an Error if reading fails template - std::optional read_object( - const ObjectReader& _object_reader, - const InputObjectType& _obj - ) const noexcept { + std::optional read_object(const ObjectReader& _object_reader, + const InputObjectType& _obj) const noexcept { std::set seen; - auto it = _obj.prefix.empty() - ? _obj.args->begin() - : _obj.args->lower_bound(_obj.prefix); + auto it = _obj.prefix.empty() ? _obj.args->begin() + : _obj.args->lower_bound(_obj.prefix); while (it != _obj.args->end()) { - if (!_obj.prefix.empty() - && it->first.substr(0, _obj.prefix.size()) != _obj.prefix) { + if (!_obj.prefix.empty() && + it->first.substr(0, _obj.prefix.size()) != _obj.prefix) { break; } const auto rest = std::string_view(it->first).substr(_obj.prefix.size()); const auto separator_pos = rest.find(path_separator); - const auto child = std::string( - separator_pos == std::string_view::npos - ? rest - : rest.substr(0, separator_pos)); + const auto child = std::string(separator_pos == std::string_view::npos + ? rest + : rest.substr(0, separator_pos)); if (!child.empty() && seen.insert(child).second) { const auto child_path = _obj.prefix + child; - _object_reader.read( - std::string_view(child), - InputVarType{_obj.args, child_path, std::nullopt}); + _object_reader.read(std::string_view(child), + InputVarType{_obj.args, child_path, std::nullopt}); } ++it; } @@ -279,14 +278,12 @@ struct Reader { rfl::Result to_object( const InputVarType& _var) const noexcept { if (!_var.args) { - return error("Cannot convert to object: no argument map available" - + (_var.path.empty() - ? std::string(".") - : " for key '" + _var.path + "'.")); + return error("Cannot convert to object: no argument map available" + + (_var.path.empty() ? std::string(".") + : " for key '" + _var.path + "'.")); } - const auto prefix = _var.path.empty() - ? std::string("") - : _var.path + path_separator; + const auto prefix = + _var.path.empty() ? std::string("") : _var.path + path_separator; return InputObjectType{_var.args, prefix}; } @@ -295,16 +292,13 @@ struct Reader { /// @param _var The CLI variable (unused) /// @return Always returns an error template - rfl::Result use_custom_constructor( - const InputVarType& - ) const noexcept { + rfl::Result use_custom_constructor(const InputVarType&) const noexcept { return error("Custom constructors are not supported for CLI parsing."); } private: static std::optional get_value( - const InputVarType& _var - ) noexcept { + const InputVarType& _var) noexcept { if (_var.direct_value) { return *_var.direct_value; } @@ -318,9 +312,7 @@ struct Reader { return it->second; } - static std::vector split( - const std::string& _str, char _delim - ) { + static std::vector split(const std::string& _str, char _delim) { std::vector result; if (_str.empty()) { return result; @@ -341,7 +333,6 @@ struct Reader { } return result; } - }; } // namespace rfl::cli diff --git a/include/rfl/default.hpp b/include/rfl/default.hpp index 752d1edf..d9ab02d5 100644 --- a/include/rfl/default.hpp +++ b/include/rfl/default.hpp @@ -3,13 +3,14 @@ namespace rfl { -/// Helper class that can be passed to a field to trigger the default value of the type. -/// Used as a sentinel value to indicate that the default-constructed value should be used. +/// Helper class that can be passed to a field to trigger the default value of +/// the type. Used as a sentinel value to indicate that the default-constructed +/// value should be used. struct Default {}; /// Convenience constant for the Default type. /// Can be used like: MyField field = rfl::default_value; -inline static const auto default_value = Default{}; +inline constexpr auto default_value = Default{}; } // namespace rfl diff --git a/include/rfl/internal/find_index.hpp b/include/rfl/internal/find_index.hpp index f32bc968..c5590aac 100644 --- a/include/rfl/internal/find_index.hpp +++ b/include/rfl/internal/find_index.hpp @@ -36,7 +36,7 @@ constexpr auto wrap_fields(std::integer_sequence) { /// Finds the index of the field signified by _field_name template -constexpr static int find_index() { +inline constexpr int find_index() { constexpr int ix = wrap_fields<_field_name, Fields>( std::make_integer_sequence>()); static_assert(rfl::tuple_element_t::name_ == _field_name, @@ -46,7 +46,7 @@ constexpr static int find_index() { /// Finds the index of the field signified by _field_name or -1. template -constexpr static int find_index_or_minus_one() { +inline constexpr int find_index_or_minus_one() { if constexpr (rfl::tuple_size_v == 0) { return -1; } else { diff --git a/include/rfl/internal/make_tag.hpp b/include/rfl/internal/make_tag.hpp index 6c5d12dd..46e2027e 100644 --- a/include/rfl/internal/make_tag.hpp +++ b/include/rfl/internal/make_tag.hpp @@ -14,7 +14,7 @@ namespace rfl::internal { template -static inline auto make_tag(const T& _t) noexcept { +inline auto make_tag(const T& _t) noexcept { if constexpr (internal::has_reflection_type_v) { return make_tag<_discriminator>(_t.reflection()); } else if constexpr (named_tuple_t::Names::template contains< diff --git a/include/rfl/internal/variant/is_alternative_type.hpp b/include/rfl/internal/variant/is_alternative_type.hpp index 2342e211..1ee86b50 100644 --- a/include/rfl/internal/variant/is_alternative_type.hpp +++ b/include/rfl/internal/variant/is_alternative_type.hpp @@ -8,7 +8,7 @@ namespace rfl::internal::variant { template -static constexpr bool is_alternative_type() { +inline constexpr bool is_alternative_type() { return internal::element_index, std::remove_cvref_t...>() != -1; diff --git a/include/rfl/internal/variant/is_convertible_to.hpp b/include/rfl/internal/variant/is_convertible_to.hpp index 8121bf74..2fdb7585 100644 --- a/include/rfl/internal/variant/is_convertible_to.hpp +++ b/include/rfl/internal/variant/is_convertible_to.hpp @@ -8,7 +8,7 @@ namespace rfl::internal::variant { template -static constexpr bool is_convertible_to() { +inline constexpr bool is_convertible_to() { return std::disjunction_v...>; } diff --git a/include/rfl/parsing/is_empty.hpp b/include/rfl/parsing/is_empty.hpp index 41d5b851..d14d0ea3 100644 --- a/include/rfl/parsing/is_empty.hpp +++ b/include/rfl/parsing/is_empty.hpp @@ -21,7 +21,7 @@ namespace parsing { * @return True if the variable is empty, false otherwise. */ template -static bool is_empty(const T& _var) { +inline bool is_empty(const T& _var) { using Type = std::remove_cvref_t; if constexpr (std::is_pointer_v) { return !_var || is_empty(*_var); diff --git a/include/rfl/parsing/make_type_name.hpp b/include/rfl/parsing/make_type_name.hpp index 35e9a554..9fa62f7b 100644 --- a/include/rfl/parsing/make_type_name.hpp +++ b/include/rfl/parsing/make_type_name.hpp @@ -26,7 +26,7 @@ inline std::string replace_non_alphanumeric(std::string _str) { * @return The type name. */ template -static std::string make_type_name() { +inline std::string make_type_name() { if constexpr (is_tagged_union_wrapper_v) { return replace_non_alphanumeric(type_name_t().str() + "__tagged"); diff --git a/include/rfl/thirdparty/ctre.hpp b/include/rfl/thirdparty/ctre.hpp index 41796262..14eaed25 100644 --- a/include/rfl/thirdparty/ctre.hpp +++ b/include/rfl/thirdparty/ctre.hpp @@ -341,7 +341,7 @@ constexpr length_value_t length_and_value_of_utf16_code_point(uint16_t first_uni struct construct_from_pointer_t { }; -constexpr auto construct_from_pointer = construct_from_pointer_t{}; +inline constexpr auto construct_from_pointer = construct_from_pointer_t{}; CTLL_EXPORT template struct fixed_string { char32_t content[N] = {}; @@ -3577,7 +3577,7 @@ template concept capture_group = requires(const T & cap) { struct capture_not_exists_tag { }; -constexpr auto capture_not_exists = capture_not_exists_tag{}; +inline constexpr auto capture_not_exists = capture_not_exists_tag{}; template struct captures; diff --git a/include/rfl/thirdparty/yyjson.h b/include/rfl/thirdparty/yyjson.h index 55676ed0..c85a1f71 100644 --- a/include/rfl/thirdparty/yyjson.h +++ b/include/rfl/thirdparty/yyjson.h @@ -330,7 +330,12 @@ /** inline function export */ #ifndef yyjson_api_inline -#define yyjson_api_inline static yyjson_inline +#define yyjson_api_inline inline +#endif + +/** constant export */ +#ifndef yyjson_api_const +#define yyjson_api_const inline constexpr #endif /** stdint (C89 compatible) */ @@ -709,7 +714,7 @@ typedef uint32_t yyjson_read_flag; - Report error if double number is infinity. - Report error if string contains invalid UTF-8 character or BOM. - Report error on trailing commas, comments, inf and nan literals. */ -static const yyjson_read_flag YYJSON_READ_NOFLAG = 0; +yyjson_api_const yyjson_read_flag YYJSON_READ_NOFLAG = 0; /** Read the input data in-situ. This option allows the reader to modify and use input data to store string @@ -717,27 +722,27 @@ static const yyjson_read_flag YYJSON_READ_NOFLAG = 0; The caller should hold the input data before free the document. The input data must be padded by at least `YYJSON_PADDING_SIZE` bytes. For example: `[1,2]` should be `[1,2]\0\0\0\0`, input length should be 5. */ -static const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0; +yyjson_api_const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0; /** Stop when done instead of issuing an error if there's additional content after a JSON document. This option may be used to parse small pieces of JSON in larger data, such as `NDJSON`. */ -static const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1; +yyjson_api_const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1; /** Allow single trailing comma at the end of an object or array, such as `[1,2,3,]`, `{"a":1,"b":2,}` (non-standard). */ -static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2; /** Allow C-style single-line and mult-line comments (non-standard). */ -static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3; /** Allow inf/nan number and literal, case-insensitive, such as 1e999, NaN, inf, -Infinity (non-standard). */ -static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4; /** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type), inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */ -static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; +yyjson_api_const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; /** Allow reading invalid unicode when parsing string values (non-standard). Invalid characters will be allowed to appear in the string values, but @@ -747,22 +752,22 @@ static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; @warning Strings in JSON values may contain incorrect encoding when this option is used, you need to handle these strings carefully to avoid security risks. */ -static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6; /** Read big numbers as raw strings. These big numbers include integers that cannot be represented by `int64_t` and `uint64_t`, and floating-point numbers that cannot be represented by finite `double`. The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */ -static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7; +yyjson_api_const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7; /** Allow UTF-8 BOM and skip it before parsing if any (non-standard). */ -static const yyjson_read_flag YYJSON_READ_ALLOW_BOM = 1 << 8; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_BOM = 1 << 8; /** Allow extended number formats (non-standard): - Hexadecimal numbers, such as `0x7B`. - Numbers with leading or trailing decimal point, such as `.123`, `123.`. - Numbers with a leading plus sign, such as `+123`. */ -static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_NUMBER = 1 << 9; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_EXT_NUMBER = 1 << 9; /** Allow extended escape sequences in strings (non-standard): - Additional escapes: `\a`, `\e`, `\v`, ``\'``, `\?`, `\0`. @@ -771,7 +776,7 @@ static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_NUMBER = 1 << 9; - Unknown escape: if backslash is followed by an unsupported character, the backslash will be removed and the character will be kept as-is. However, `\1`-`\9` will still trigger an error. */ -static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_ESCAPE = 1 << 10; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_EXT_ESCAPE = 1 << 10; /** Allow extended whitespace characters (non-standard): - Vertical tab `\v` and form feed `\f`. @@ -779,22 +784,22 @@ static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_ESCAPE = 1 << 10; - Non-breaking space `\xA0`. - Byte order mark: `\uFEFF`. - Other Unicode characters in the Zs (Separator, space) category. */ -static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_WHITESPACE = 1 << 11; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_EXT_WHITESPACE = 1 << 11; /** Allow strings enclosed in single quotes (non-standard), such as ``'ab'``. */ -static const yyjson_read_flag YYJSON_READ_ALLOW_SINGLE_QUOTED_STR = 1 << 12; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_SINGLE_QUOTED_STR = 1 << 12; /** Allow object keys without quotes (non-standard), such as `{a:1,b:2}`. This extends the ECMAScript IdentifierName rule by allowing any non-whitespace character with code point above `U+007F`. */ -static const yyjson_read_flag YYJSON_READ_ALLOW_UNQUOTED_KEY = 1 << 13; +yyjson_api_const yyjson_read_flag YYJSON_READ_ALLOW_UNQUOTED_KEY = 1 << 13; /** Allow JSON5 format, see: [https://json5.org]. This flag supports all JSON5 features with some additional extensions: - Accepts more escape sequences than JSON5 (e.g. `\a`, `\e`). - Unquoted keys are not limited to ECMAScript IdentifierName. - Allow case-insensitive `NaN`, `Inf` and `Infinity` literals. */ -static const yyjson_read_flag YYJSON_READ_JSON5 = +yyjson_api_const yyjson_read_flag YYJSON_READ_JSON5 = (1 << 2) | /* YYJSON_READ_ALLOW_TRAILING_COMMAS */ (1 << 3) | /* YYJSON_READ_ALLOW_COMMENTS */ (1 << 4) | /* YYJSON_READ_ALLOW_INF_AND_NAN */ @@ -808,49 +813,49 @@ static const yyjson_read_flag YYJSON_READ_JSON5 = typedef uint32_t yyjson_read_code; /** Success, no error. */ -static const yyjson_read_code YYJSON_READ_SUCCESS = 0; +yyjson_api_const yyjson_read_code YYJSON_READ_SUCCESS = 0; /** Invalid parameter, such as NULL input string or 0 input length. */ -static const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failed. */ -static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2; /** Input JSON string is empty. */ -static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3; /** Unexpected content after document, such as `[123]abc`. */ -static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4; /** Unexpected end of input, the parsed part is valid, such as `[123`. */ -static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5; /** Unexpected character inside the document, such as `[abc]`. */ -static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6; /** Invalid JSON structure, such as `[1,]`. */ -static const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7; /** Invalid comment, deprecated, use `UNEXPECTED_END` for unclosed comment. */ -static const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8; /** Invalid number, such as `123.e12`, `000`. */ -static const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9; /** Invalid string, such as invalid escaped character inside a string. */ -static const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10; /** Invalid JSON literal, such as `truu`. */ -static const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11; /** Failed to open a file. */ -static const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12; /** Failed to read a file. */ -static const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13; /** Incomplete input during incremental parsing; parsing state is preserved. */ -static const yyjson_read_code YYJSON_READ_ERROR_MORE = 14; +yyjson_api_const yyjson_read_code YYJSON_READ_ERROR_MORE = 14; /** Error information for JSON reader. */ typedef struct yyjson_read_err { @@ -1125,38 +1130,38 @@ typedef uint32_t yyjson_write_flag; - Report error on inf or nan number. - Report error on invalid UTF-8 string. - Do not escape unicode or slash. */ -static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0; /** Write JSON pretty with 4 space indent. */ -static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0; /** Escape unicode as `uXXXX`, make the output ASCII only. */ -static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1; /** Escape '/' as '\/'. */ -static const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2; /** Write inf and nan number as 'Infinity' and 'NaN' literal (non-standard). */ -static const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3; /** Write inf and nan number as null literal. This flag will override `YYJSON_WRITE_ALLOW_INF_AND_NAN` flag. */ -static const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4; /** Allow invalid unicode when encoding string values (non-standard). Invalid characters in string value will be copied byte by byte. If `YYJSON_WRITE_ESCAPE_UNICODE` flag is also set, invalid character will be escaped as `U+FFFD` (replacement character). This flag does not affect the performance of correctly encoded strings. */ -static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5; /** Write JSON pretty with 2 space indent. This flag will override `YYJSON_WRITE_PRETTY` flag. */ -static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6; /** Adds a newline character `\n` at the end of the JSON. This can be helpful for text editors or NDJSON. */ -static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7; +yyjson_api_const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7; /** The highest 8 bits of `yyjson_write_flag` and real number value's `tag` are reserved for controlling the output format of floating-point numbers. */ @@ -1182,28 +1187,28 @@ static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7; typedef uint32_t yyjson_write_code; /** Success, no error. */ -static const yyjson_write_code YYJSON_WRITE_SUCCESS = 0; +yyjson_api_const yyjson_write_code YYJSON_WRITE_SUCCESS = 0; /** Invalid parameter, such as NULL document. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2; /** Invalid value type in JSON document. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3; /** NaN or Infinity number occurs. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4; /** Failed to open a file. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5; /** Failed to write a file. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6; /** Invalid unicode in string. */ -static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7; +yyjson_api_const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7; /** Error information for JSON writer. */ typedef struct yyjson_write_err { @@ -3946,25 +3951,25 @@ yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, typedef uint32_t yyjson_ptr_code; /** No JSON pointer error. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0; /** Invalid input parameter, such as NULL input. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1; /** JSON pointer syntax error, such as invalid escape, token no prefix. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2; /** JSON pointer resolve failed, such as index out of range, key not found. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3; /** Document's root is NULL, but it is required for the function call. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4; /** Cannot set root as the target is not a document. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5; /** The memory allocation failed and a new value could not be created. */ -static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6; +yyjson_api_const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6; /** Error information for JSON pointer. */ typedef struct yyjson_ptr_err { @@ -4515,28 +4520,28 @@ yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx); typedef uint32_t yyjson_patch_code; /** Success, no error. */ -static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0; /** Invalid parameter, such as NULL input or non-array patch. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2; /** JSON patch operation is not object type. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3; /** JSON patch operation is missing a required key. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4; /** JSON patch operation member is invalid. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5; /** JSON patch operation `test` not equal. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6; /** JSON patch operation failed on JSON pointer. */ -static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7; +yyjson_api_const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7; /** Error information for JSON patch. */ typedef struct yyjson_patch_err { diff --git a/src/modules/rfl.avro.cppm b/src/modules/rfl.avro.cppm new file mode 100644 index 00000000..ca1f9dab --- /dev/null +++ b/src/modules/rfl.avro.cppm @@ -0,0 +1,26 @@ +module; + +#include "rfl/avro.hpp" + +export module rfl.avro; +export import rfl; + +export namespace rfl::avro { +using ::rfl::avro::InputObjectType; +using ::rfl::avro::InputVarType; +using ::rfl::avro::load; +using ::rfl::avro::Parser; +using ::rfl::avro::read; +using ::rfl::avro::Reader; +using ::rfl::avro::save; +using ::rfl::avro::Schema; +using ::rfl::avro::SchemaImpl; +using ::rfl::avro::to_json_representation; +using ::rfl::avro::to_schema; +using ::rfl::avro::write; +using ::rfl::avro::Writer; +} // namespace rfl::avro + +export namespace rfl::avro::schema { +using ::rfl::avro::schema::Type; +} diff --git a/src/modules/rfl.boost_serialization.cppm b/src/modules/rfl.boost_serialization.cppm new file mode 100644 index 00000000..24bedf7c --- /dev/null +++ b/src/modules/rfl.boost_serialization.cppm @@ -0,0 +1,18 @@ +module; + +#include "rfl/boost_serialization.hpp" + +export module rfl.boost_serialization; +export import rfl; + +export namespace rfl::boost_serialization { +using ::rfl::boost_serialization::load; +using ::rfl::boost_serialization::MemBuf; +using ::rfl::boost_serialization::Parser; +using ::rfl::boost_serialization::read; +using ::rfl::boost_serialization::read_from_archive; +using ::rfl::boost_serialization::Reader; +using ::rfl::boost_serialization::save; +using ::rfl::boost_serialization::write; +using ::rfl::boost_serialization::Writer; +} // namespace rfl::boost_serialization diff --git a/src/modules/rfl.bson.cppm b/src/modules/rfl.bson.cppm new file mode 100644 index 00000000..ecd11d4a --- /dev/null +++ b/src/modules/rfl.bson.cppm @@ -0,0 +1,19 @@ +module; + +#include "rfl/bson.hpp" + +export module rfl.bson; +export import rfl; + +export namespace rfl::bson { +using ::rfl::bson::InputObjectType; +using ::rfl::bson::InputVarType; +using ::rfl::bson::load; +using ::rfl::bson::Parser; +using ::rfl::bson::read; +using ::rfl::bson::Reader; +using ::rfl::bson::save; +using ::rfl::bson::to_buffer; +using ::rfl::bson::write; +using ::rfl::bson::Writer; +} // namespace rfl::bson diff --git a/src/modules/rfl.capnproto.cppm b/src/modules/rfl.capnproto.cppm new file mode 100644 index 00000000..c04df741 --- /dev/null +++ b/src/modules/rfl.capnproto.cppm @@ -0,0 +1,30 @@ +module; + +#include "rfl/capnproto.hpp" + +export module rfl.capnproto; +export import rfl; + +export namespace rfl::capnproto { +using ::rfl::capnproto::get_root_name; +using ::rfl::capnproto::InputObjectType; +using ::rfl::capnproto::InputVarType; +using ::rfl::capnproto::is_named_type; +using ::rfl::capnproto::load; +using ::rfl::capnproto::Parser; +using ::rfl::capnproto::read; +using ::rfl::capnproto::Reader; +using ::rfl::capnproto::save; +using ::rfl::capnproto::Schema; +using ::rfl::capnproto::SchemaHolder; +using ::rfl::capnproto::SchemaImpl; +using ::rfl::capnproto::to_schema; +using ::rfl::capnproto::to_string_representation; +using ::rfl::capnproto::write; +using ::rfl::capnproto::Writer; +} // namespace rfl::capnproto + +export namespace rfl::capnproto::schema { +using ::rfl::capnproto::schema::CapnProtoTypes; +using ::rfl::capnproto::schema::Type; +} // namespace rfl::capnproto::schema diff --git a/src/modules/rfl.cbor.cppm b/src/modules/rfl.cbor.cppm new file mode 100644 index 00000000..1980b500 --- /dev/null +++ b/src/modules/rfl.cbor.cppm @@ -0,0 +1,18 @@ +module; + +#include "rfl/cbor.hpp" + +export module rfl.cbor; +export import rfl; + +export namespace rfl::cbor { +using ::rfl::cbor::InputObjectType; +using ::rfl::cbor::InputVarType; +using ::rfl::cbor::load; +using ::rfl::cbor::Parser; +using ::rfl::cbor::read; +using ::rfl::cbor::Reader; +using ::rfl::cbor::save; +using ::rfl::cbor::write; +using ::rfl::cbor::Writer; +} // namespace rfl::cbor diff --git a/src/modules/rfl.cereal.cppm b/src/modules/rfl.cereal.cppm new file mode 100644 index 00000000..a355d93f --- /dev/null +++ b/src/modules/rfl.cereal.cppm @@ -0,0 +1,17 @@ +module; + +#include "rfl/cereal.hpp" + +export module rfl.cereal; +export import rfl; + +export namespace rfl::cereal { +using ::rfl::cereal::InputVarType; +using ::rfl::cereal::load; +using ::rfl::cereal::Parser; +using ::rfl::cereal::read; +using ::rfl::cereal::Reader; +using ::rfl::cereal::save; +using ::rfl::cereal::write; +using ::rfl::cereal::Writer; +} // namespace rfl::cereal diff --git a/src/modules/rfl.cli.cppm b/src/modules/rfl.cli.cppm new file mode 100644 index 00000000..6b3380fb --- /dev/null +++ b/src/modules/rfl.cli.cppm @@ -0,0 +1,23 @@ +module; + +#include "rfl/cli.hpp" + +export module rfl.cli; +export import rfl; +export import rfl.generic; + +export namespace rfl::cli { +using ::rfl::cli::array_delimiter; +using ::rfl::cli::CliArrayType; +using ::rfl::cli::CliObjectType; +using ::rfl::cli::CliVarType; +using ::rfl::cli::looks_like_option; +using ::rfl::cli::parse_argv; +using ::rfl::cli::parse_value; +using ::rfl::cli::ParsedArgs; +using ::rfl::cli::Parser; +using ::rfl::cli::path_separator; +using ::rfl::cli::read; +using ::rfl::cli::Reader; +using ::rfl::cli::resolve_args; +} // namespace rfl::cli diff --git a/src/modules/rfl.cppm b/src/modules/rfl.cppm new file mode 100644 index 00000000..651c4601 --- /dev/null +++ b/src/modules/rfl.cppm @@ -0,0 +1,155 @@ +module; + +#include "rfl.hpp" + +export module rfl; + +export namespace rfl { +using ::rfl::AddNamespacedTagsToVariants; +using ::rfl::AddStructName; +using ::rfl::AddTagsToVariants; +using ::rfl::AllOf; +using ::rfl::AllowRawPtrs; +using ::rfl::AlphaNumeric; +using ::rfl::always_false_v; +using ::rfl::AnyOf; +using ::rfl::apply; +using ::rfl::as; +using ::rfl::Attribute; +using ::rfl::Base64Encoded; +using ::rfl::Binary; +using ::rfl::Box; +using ::rfl::Bytestring; +using ::rfl::CamelCaseToSnakeCase; +using ::rfl::Commented; +using ::rfl::Copyability; +using ::rfl::CopyableBox; +using ::rfl::Default; +using ::rfl::default_value; +using ::rfl::DefaultIfMissing; +using ::rfl::DefaultVal; +using ::rfl::define_literal_t; +using ::rfl::define_named_tuple_t; +using ::rfl::define_tagged_union_t; +using ::rfl::define_variant_t; +using ::rfl::Description; +using ::rfl::Email; +using ::rfl::enum_to_string; +using ::rfl::Error; +using ::rfl::error; +using ::rfl::ExclusiveMaximum; +using ::rfl::ExclusiveMinimum; +using ::rfl::extract_discriminators_t; +using ::rfl::ExtraFields; +using ::rfl::Field; +using ::rfl::field_type_t; +using ::rfl::fields; +using ::rfl::Flatten; +using ::rfl::from_generic; +using ::rfl::from_named_tuple; +using ::rfl::Generic; +using ::rfl::get; +using ::rfl::get_enum_range; +using ::rfl::get_enumerator_array; +using ::rfl::get_enumerators; +using ::rfl::get_if; +using ::rfl::get_underlying_enumerator_array; +using ::rfl::get_underlying_enumerators; +using ::rfl::Hex; +using ::rfl::holds_alternative; +using ::rfl::Literal; +using ::rfl::LiteralHelper; +using ::rfl::make_box; +using ::rfl::make_copyable_box; +using ::rfl::make_field; +using ::rfl::make_from_tuple; +using ::rfl::make_named_tuple; +using ::rfl::make_ref; +using ::rfl::Maximum; +using ::rfl::Minimum; +using ::rfl::name_of; +using ::rfl::name_t; +using ::rfl::named_tuple_t; +using ::rfl::NamedTuple; +using ::rfl::NoExtraFields; +using ::rfl::NoFieldNames; +using ::rfl::NoOptionals; +using ::rfl::Nothing; +using ::rfl::Object; +using ::rfl::Oct; +using ::rfl::OneOf; +using ::rfl::Pattern; +using ::rfl::PatternValidator; +using ::rfl::Positional; +using ::rfl::PossibleTags; +using ::rfl::Processors; +using ::rfl::Ref; +using ::rfl::Rename; +using ::rfl::Result; +using ::rfl::Short; +using ::rfl::Size; +using ::rfl::Skip; +using ::rfl::SkipDeserialization; +using ::rfl::SkipSerialization; +using ::rfl::SnakeCaseToCamelCase; +using ::rfl::SnakeCaseToKebabCase; +using ::rfl::SnakeCaseToPascalCase; +using ::rfl::TaggedUnion; +using ::rfl::Timestamp; +using ::rfl::Tuple; +using ::rfl::UnderlyingEnums; +using ::rfl::Unexpected; +using ::rfl::UUIDv1; +using ::rfl::UUIDv2; +using ::rfl::UUIDv3; +using ::rfl::UUIDv4; +using ::rfl::Validator; +using ::rfl::Variant; +using ::rfl::Vectorstring; +using ::rfl::operator*; +using ::rfl::operator<<; +using ::rfl::operator<=>; +using ::rfl::possible_tags_t; +using ::rfl::remove_fields_t; +using ::rfl::replace; +using ::rfl::string_to_enum; +using ::rfl::to_array; +using ::rfl::to_bool; +using ::rfl::to_double; +using ::rfl::to_generic; +using ::rfl::to_int; +using ::rfl::to_int64; +using ::rfl::to_named_tuple; +using ::rfl::to_null; +using ::rfl::to_object; +using ::rfl::to_string; +using ::rfl::to_view; +using ::rfl::tuple_cat; +using ::rfl::tuple_element; +using ::rfl::tuple_element_t; +using ::rfl::tuple_size; +using ::rfl::tuple_size_v; +using ::rfl::type_name_t; +using ::rfl::value_of; +using ::rfl::variant_alternative; +using ::rfl::variant_alternative_t; +using ::rfl::variant_size; +using ::rfl::variant_size_v; +using ::rfl::view_t; +using ::rfl::visit; +} // namespace rfl + +export namespace rfl::atomic { +using ::rfl::atomic::is_atomic; +using ::rfl::atomic::is_atomic_v; +using ::rfl::atomic::remove_atomic_t; +using ::rfl::atomic::set_atomic; +} // namespace rfl::atomic + +export namespace rfl::concepts { +using ::rfl::concepts::BackInsertableByteContainer; +using ::rfl::concepts::ByteLike; +using ::rfl::concepts::ByteSpanLike; +using ::rfl::concepts::ContiguousByteContainer; +using ::rfl::concepts::MutableContiguousByteContainer; +} // namespace rfl::concepts diff --git a/src/modules/rfl.csv.cppm b/src/modules/rfl.csv.cppm new file mode 100644 index 00000000..0f4d2920 --- /dev/null +++ b/src/modules/rfl.csv.cppm @@ -0,0 +1,15 @@ +module; + +#include "rfl/csv.hpp" +#include "rfl/csv/Settings.hpp" + +export module rfl.csv; +export import rfl; + +export namespace rfl::csv { +using ::rfl::csv::load; +using ::rfl::csv::read; +using ::rfl::csv::save; +using ::rfl::csv::Settings; +using ::rfl::csv::write; +} // namespace rfl::csv diff --git a/src/modules/rfl.flexbuf.cppm b/src/modules/rfl.flexbuf.cppm new file mode 100644 index 00000000..3010c7ad --- /dev/null +++ b/src/modules/rfl.flexbuf.cppm @@ -0,0 +1,18 @@ +module; + +#include "rfl/flexbuf.hpp" + +export module rfl.flexbuf; +export import rfl; + +export namespace rfl::flexbuf { +using ::rfl::flexbuf::InputVarType; +using ::rfl::flexbuf::load; +using ::rfl::flexbuf::Parser; +using ::rfl::flexbuf::read; +using ::rfl::flexbuf::Reader; +using ::rfl::flexbuf::save; +using ::rfl::flexbuf::to_buffer; +using ::rfl::flexbuf::write; +using ::rfl::flexbuf::Writer; +} // namespace rfl::flexbuf diff --git a/src/modules/rfl.generic.cppm b/src/modules/rfl.generic.cppm new file mode 100644 index 00000000..39a5b7f0 --- /dev/null +++ b/src/modules/rfl.generic.cppm @@ -0,0 +1,18 @@ +module; + +#include "rfl/generic/Parser.hpp" +#include "rfl/generic/Reader.hpp" +#include "rfl/generic/Writer.hpp" +#include "rfl/generic/read.hpp" +#include "rfl/generic/write.hpp" + +export module rfl.generic; +export import rfl; + +export namespace rfl::generic { +using ::rfl::generic::Parser; +using ::rfl::generic::read; +using ::rfl::generic::Reader; +using ::rfl::generic::write; +using ::rfl::generic::Writer; +} // namespace rfl::generic diff --git a/src/modules/rfl.json.cppm b/src/modules/rfl.json.cppm new file mode 100644 index 00000000..fb2bc71e --- /dev/null +++ b/src/modules/rfl.json.cppm @@ -0,0 +1,27 @@ +module; + +#include "rfl/json.hpp" + +export module rfl.json; +export import rfl; + +export namespace rfl::json { +using ::rfl::json::InputObjectType; +using ::rfl::json::InputVarType; +using ::rfl::json::load; +using ::rfl::json::Parser; +using ::rfl::json::pretty; +using ::rfl::json::read; +using ::rfl::json::Reader; +using ::rfl::json::save; +using ::rfl::json::to_schema; +using ::rfl::json::to_schema_internal_schema; +using ::rfl::json::TypeHelper; +using ::rfl::json::write; +using ::rfl::json::Writer; +} // namespace rfl::json + +export namespace rfl::json::schema { +using ::rfl::json::schema::JSONSchema; +using ::rfl::json::schema::Type; +} // namespace rfl::json::schema diff --git a/src/modules/rfl.msgpack.cppm b/src/modules/rfl.msgpack.cppm new file mode 100644 index 00000000..9fd56489 --- /dev/null +++ b/src/modules/rfl.msgpack.cppm @@ -0,0 +1,18 @@ +module; + +#include "rfl/msgpack.hpp" + +export module rfl.msgpack; +export import rfl; + +export namespace rfl::msgpack { +using ::rfl::msgpack::InputObjectType; +using ::rfl::msgpack::InputVarType; +using ::rfl::msgpack::load; +using ::rfl::msgpack::Parser; +using ::rfl::msgpack::read; +using ::rfl::msgpack::Reader; +using ::rfl::msgpack::save; +using ::rfl::msgpack::write; +using ::rfl::msgpack::Writer; +} // namespace rfl::msgpack diff --git a/src/modules/rfl.parquet.cppm b/src/modules/rfl.parquet.cppm new file mode 100644 index 00000000..45c29d1b --- /dev/null +++ b/src/modules/rfl.parquet.cppm @@ -0,0 +1,16 @@ +module; + +#include "rfl/parquet.hpp" +#include "rfl/parquet/Settings.hpp" + +export module rfl.parquet; +export import rfl; + +export namespace rfl::parquet { +using ::rfl::parquet::Compression; +using ::rfl::parquet::load; +using ::rfl::parquet::read; +using ::rfl::parquet::save; +using ::rfl::parquet::Settings; +using ::rfl::parquet::write; +} // namespace rfl::parquet diff --git a/src/modules/rfl.toml.cppm b/src/modules/rfl.toml.cppm new file mode 100644 index 00000000..b00140f1 --- /dev/null +++ b/src/modules/rfl.toml.cppm @@ -0,0 +1,17 @@ +module; + +#include "rfl/toml.hpp" + +export module rfl.toml; +export import rfl; + +export namespace rfl::toml { +using ::rfl::toml::InputVarType; +using ::rfl::toml::load; +using ::rfl::toml::Parser; +using ::rfl::toml::read; +using ::rfl::toml::Reader; +using ::rfl::toml::save; +using ::rfl::toml::write; +using ::rfl::toml::Writer; +} // namespace rfl::toml diff --git a/src/modules/rfl.ubjson.cppm b/src/modules/rfl.ubjson.cppm new file mode 100644 index 00000000..3cf88c7e --- /dev/null +++ b/src/modules/rfl.ubjson.cppm @@ -0,0 +1,18 @@ +module; + +#include "rfl/ubjson.hpp" + +export module rfl.ubjson; +export import rfl; + +export namespace rfl::ubjson { +using ::rfl::ubjson::InputObjectType; +using ::rfl::ubjson::InputVarType; +using ::rfl::ubjson::load; +using ::rfl::ubjson::Parser; +using ::rfl::ubjson::read; +using ::rfl::ubjson::Reader; +using ::rfl::ubjson::save; +using ::rfl::ubjson::write; +using ::rfl::ubjson::Writer; +} // namespace rfl::ubjson diff --git a/src/modules/rfl.xml.cppm b/src/modules/rfl.xml.cppm new file mode 100644 index 00000000..64078dc6 --- /dev/null +++ b/src/modules/rfl.xml.cppm @@ -0,0 +1,17 @@ +module; + +#include "rfl/xml.hpp" + +export module rfl.xml; +export import rfl; + +export namespace rfl::xml { +using ::rfl::xml::InputVarType; +using ::rfl::xml::load; +using ::rfl::xml::Parser; +using ::rfl::xml::read; +using ::rfl::xml::Reader; +using ::rfl::xml::save; +using ::rfl::xml::write; +using ::rfl::xml::Writer; +} // namespace rfl::xml diff --git a/src/modules/rfl.yaml.cppm b/src/modules/rfl.yaml.cppm new file mode 100644 index 00000000..44e5e01a --- /dev/null +++ b/src/modules/rfl.yaml.cppm @@ -0,0 +1,17 @@ +module; + +#include "rfl/yaml.hpp" + +export module rfl.yaml; +export import rfl; + +export namespace rfl::yaml { +using ::rfl::yaml::InputVarType; +using ::rfl::yaml::load; +using ::rfl::yaml::Parser; +using ::rfl::yaml::read; +using ::rfl::yaml::Reader; +using ::rfl::yaml::save; +using ::rfl::yaml::write; +using ::rfl::yaml::Writer; +} // namespace rfl::yaml diff --git a/src/modules/rfl.yas.cppm b/src/modules/rfl.yas.cppm new file mode 100644 index 00000000..df4742e2 --- /dev/null +++ b/src/modules/rfl.yas.cppm @@ -0,0 +1,20 @@ +module; + +#include "rfl/yas.hpp" + +export module rfl.yas; +export import rfl; + +export namespace rfl::yas { +using ::rfl::yas::IArchive; +using ::rfl::yas::load; +using ::rfl::yas::OArchive; +using ::rfl::yas::Parser; +using ::rfl::yas::read; +using ::rfl::yas::read_from_archive; +using ::rfl::yas::Reader; +using ::rfl::yas::save; +using ::rfl::yas::write; +using ::rfl::yas::write_to_archive; +using ::rfl::yas::Writer; +} // namespace rfl::yas diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d68b3a0f..bc18574c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,9 @@ if (REFLECTCPP_JSON) add_subdirectory(json) add_subdirectory(json_c_arrays_and_inheritance) add_subdirectory(cli) + if(REFLECTCPP_BUILD_MODULES) + add_subdirectory(modules) + endif() endif () if (REFLECTCPP_AVRO) diff --git a/tests/modules/CMakeLists.txt b/tests/modules/CMakeLists.txt new file mode 100644 index 00000000..40769d66 --- /dev/null +++ b/tests/modules/CMakeLists.txt @@ -0,0 +1,28 @@ +project(reflect-cpp-modules-tests) + +add_executable( + reflect-cpp-modules-tests + test_modules.cpp +) + +target_link_libraries(reflect-cpp-modules-tests PRIVATE reflectcpp) +target_compile_definitions(reflect-cpp-modules-tests PRIVATE + REFLECTCPP_MODULE_TEST_AVRO=$ + REFLECTCPP_MODULE_TEST_BOOST_SERIALIZATION=$ + REFLECTCPP_MODULE_TEST_BSON=$ + REFLECTCPP_MODULE_TEST_CAPNPROTO=$ + REFLECTCPP_MODULE_TEST_CBOR=$ + REFLECTCPP_MODULE_TEST_CEREAL=$ + REFLECTCPP_MODULE_TEST_CSV=$ + REFLECTCPP_MODULE_TEST_FLEXBUFFERS=$ + REFLECTCPP_MODULE_TEST_MSGPACK=$ + REFLECTCPP_MODULE_TEST_PARQUET=$ + REFLECTCPP_MODULE_TEST_TOML=$ + REFLECTCPP_MODULE_TEST_UBJSON=$ + REFLECTCPP_MODULE_TEST_XML=$ + REFLECTCPP_MODULE_TEST_YAML=$ + REFLECTCPP_MODULE_TEST_YAS=$ +) +set_target_properties(reflect-cpp-modules-tests PROPERTIES CXX_SCAN_FOR_MODULES ON) + +add_test(NAME modules.json_roundtrip COMMAND reflect-cpp-modules-tests) diff --git a/tests/modules/test_modules.cpp b/tests/modules/test_modules.cpp new file mode 100644 index 00000000..09fc5338 --- /dev/null +++ b/tests/modules/test_modules.cpp @@ -0,0 +1,357 @@ +#include +#include + +import rfl; +import rfl.cli; +import rfl.generic; +import rfl.json; + +#if REFLECTCPP_MODULE_TEST_AVRO +import rfl.avro; +#endif +#if REFLECTCPP_MODULE_TEST_BOOST_SERIALIZATION +import rfl.boost_serialization; +#endif +#if REFLECTCPP_MODULE_TEST_BSON +import rfl.bson; +#endif +#if REFLECTCPP_MODULE_TEST_CAPNPROTO +import rfl.capnproto; +#endif +#if REFLECTCPP_MODULE_TEST_CBOR +import rfl.cbor; +#endif +#if REFLECTCPP_MODULE_TEST_CEREAL +import rfl.cereal; +#endif +#if REFLECTCPP_MODULE_TEST_CSV +import rfl.csv; +#endif +#if REFLECTCPP_MODULE_TEST_FLEXBUFFERS +import rfl.flexbuf; +#endif +#if REFLECTCPP_MODULE_TEST_MSGPACK +import rfl.msgpack; +#endif +#if REFLECTCPP_MODULE_TEST_PARQUET +import rfl.parquet; +#endif +#if REFLECTCPP_MODULE_TEST_TOML +import rfl.toml; +#endif +#if REFLECTCPP_MODULE_TEST_UBJSON +import rfl.ubjson; +#endif +#if REFLECTCPP_MODULE_TEST_XML +import rfl.xml; +#endif +#if REFLECTCPP_MODULE_TEST_YAML +import rfl.yaml; +#endif +#if REFLECTCPP_MODULE_TEST_YAS +import rfl.yas; +#endif + +namespace { + +struct Person { + std::string first_name; + int age; +}; + +struct Config { + std::string host_name; + int port; +}; + +bool is_person(const Person& person, const std::string& first_name, + const int age) { + return person.first_name == first_name && person.age == age; +} + +int test_core_module() { + const auto field = rfl::make_field<"first_name">(std::string("Marge")); + const auto named_tuple = field * rfl::make_field<"age">(42); + const rfl::Result result = rfl::get<"age">(named_tuple); + + if (!result) { + return 10; + } + if (*result != 42) { + return 11; + } + if (rfl::get<"first_name">(named_tuple) != "Marge") { + return 12; + } + return 0; +} + +int test_json_module() { + const auto json = rfl::json::write(Person{.first_name = "Homer", .age = 45}); + const auto person = rfl::json::read(json); + + if (!person) { + return 20; + } + if (!is_person(*person, "Homer", 45)) { + return 21; + } + return 0; +} + +int test_generic_module() { + const auto generic = + rfl::generic::write(Person{.first_name = "Lisa", .age = 8}); + const auto person = rfl::generic::read(generic); + + if (!person) { + return 30; + } + if (!is_person(*person, "Lisa", 8)) { + return 31; + } + return 0; +} + +int test_cli_module() { + char arg0[] = "reflect-cpp"; + char arg1[] = "--host-name=springfield"; + char arg2[] = "--port=742"; + char* argv[] = {arg0, arg1, arg2}; + + const auto config = rfl::cli::read(3, argv); + if (!config) { + return 40; + } + if (config->host_name != "springfield") { + return 41; + } + if (config->port != 742) { + return 42; + } + return 0; +} + +#if REFLECTCPP_MODULE_TEST_AVRO +int test_avro_module() { + const auto bytes = rfl::avro::write(Person{.first_name = "Apu", .age = 36}); + const auto person = rfl::avro::read(bytes); + return person && is_person(*person, "Apu", 36) ? 0 : 50; +} +#endif + +#if REFLECTCPP_MODULE_TEST_BOOST_SERIALIZATION +int test_boost_serialization_module() { + const auto bytes = rfl::boost_serialization::write( + Person{.first_name = "Barney", .age = 40}); + const auto person = rfl::boost_serialization::read(bytes); + return person && is_person(*person, "Barney", 40) ? 0 : 60; +} +#endif + +#if REFLECTCPP_MODULE_TEST_BSON +int test_bson_module() { + const auto bytes = rfl::bson::write(Person{.first_name = "Moe", .age = 48}); + const auto person = rfl::bson::read(bytes); + return person && is_person(*person, "Moe", 48) ? 0 : 70; +} +#endif + +#if REFLECTCPP_MODULE_TEST_CAPNPROTO +int test_capnproto_module() { + const auto bytes = + rfl::capnproto::write(Person{.first_name = "Patty", .age = 44}); + const auto person = rfl::capnproto::read(bytes); + return person && is_person(*person, "Patty", 44) ? 0 : 80; +} +#endif + +#if REFLECTCPP_MODULE_TEST_CBOR +int test_cbor_module() { + const auto bytes = rfl::cbor::write(Person{.first_name = "Selma", .age = 44}); + const auto person = rfl::cbor::read(bytes); + return person && is_person(*person, "Selma", 44) ? 0 : 90; +} +#endif + +#if REFLECTCPP_MODULE_TEST_CEREAL +int test_cereal_module() { + const auto bytes = rfl::cereal::write(Person{.first_name = "Ned", .age = 60}); + const auto person = rfl::cereal::read(bytes); + return person && is_person(*person, "Ned", 60) ? 0 : 100; +} +#endif + +#if REFLECTCPP_MODULE_TEST_CSV +int test_csv_module() { + const auto csv = rfl::csv::write(std::vector{{"Lenny", 38}}); + const auto people = rfl::csv::read>(csv); + return people && people->size() == 1 && + is_person(people->front(), "Lenny", 38) + ? 0 + : 110; +} +#endif + +#if REFLECTCPP_MODULE_TEST_FLEXBUFFERS +int test_flexbuf_module() { + const auto bytes = + rfl::flexbuf::write(Person{.first_name = "Carl", .age = 39}); + const auto person = rfl::flexbuf::read(bytes); + return person && is_person(*person, "Carl", 39) ? 0 : 120; +} +#endif + +#if REFLECTCPP_MODULE_TEST_MSGPACK +int test_msgpack_module() { + const auto bytes = + rfl::msgpack::write(Person{.first_name = "Milhouse", .age = 10}); + const auto person = rfl::msgpack::read(bytes); + return person && is_person(*person, "Milhouse", 10) ? 0 : 130; +} +#endif + +#if REFLECTCPP_MODULE_TEST_PARQUET +int test_parquet_module() { + const auto bytes = rfl::parquet::write(std::vector{{"Ralph", 8}}); + const auto people = rfl::parquet::read>(bytes); + return people && people->size() == 1 && is_person(people->front(), "Ralph", 8) + ? 0 + : 140; +} +#endif + +#if REFLECTCPP_MODULE_TEST_TOML +int test_toml_module() { + const auto toml = + rfl::toml::write(Person{.first_name = "Skinner", .age = 45}); + const auto person = rfl::toml::read(toml); + return person && is_person(*person, "Skinner", 45) ? 0 : 150; +} +#endif + +#if REFLECTCPP_MODULE_TEST_UBJSON +int test_ubjson_module() { + const auto bytes = + rfl::ubjson::write(Person{.first_name = "Nelson", .age = 12}); + const auto person = rfl::ubjson::read(bytes); + return person && is_person(*person, "Nelson", 12) ? 0 : 160; +} +#endif + +#if REFLECTCPP_MODULE_TEST_XML +int test_xml_module() { + const auto xml = rfl::xml::write(Person{.first_name = "Edna", .age = 41}); + const auto person = rfl::xml::read(xml); + return person && is_person(*person, "Edna", 41) ? 0 : 170; +} +#endif + +#if REFLECTCPP_MODULE_TEST_YAML +int test_yaml_module() { + const auto yaml = rfl::yaml::write(Person{.first_name = "Agnes", .age = 75}); + const auto person = rfl::yaml::read(yaml); + return person && is_person(*person, "Agnes", 75) ? 0 : 180; +} +#endif + +#if REFLECTCPP_MODULE_TEST_YAS +int test_yas_module() { + const auto bytes = rfl::yas::write(Person{.first_name = "Otto", .age = 29}); + const auto person = rfl::yas::read(bytes); + return person && is_person(*person, "Otto", 29) ? 0 : 190; +} +#endif + +} // namespace + +int main() { + if (const auto rc = test_core_module(); rc != 0) { + return rc; + } + if (const auto rc = test_json_module(); rc != 0) { + return rc; + } + if (const auto rc = test_generic_module(); rc != 0) { + return rc; + } + if (const auto rc = test_cli_module(); rc != 0) { + return rc; + } +#if REFLECTCPP_MODULE_TEST_AVRO + if (const auto rc = test_avro_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_BOOST_SERIALIZATION + if (const auto rc = test_boost_serialization_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_BSON + if (const auto rc = test_bson_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_CAPNPROTO + if (const auto rc = test_capnproto_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_CBOR + if (const auto rc = test_cbor_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_CEREAL + if (const auto rc = test_cereal_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_CSV + if (const auto rc = test_csv_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_FLEXBUFFERS + if (const auto rc = test_flexbuf_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_MSGPACK + if (const auto rc = test_msgpack_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_PARQUET + if (const auto rc = test_parquet_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_TOML + if (const auto rc = test_toml_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_UBJSON + if (const auto rc = test_ubjson_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_XML + if (const auto rc = test_xml_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_YAML + if (const auto rc = test_yaml_module(); rc != 0) { + return rc; + } +#endif +#if REFLECTCPP_MODULE_TEST_YAS + if (const auto rc = test_yas_module(); rc != 0) { + return rc; + } +#endif + return 0; +}