diff --git a/include/sqlgen/internal/from_str.hpp b/include/sqlgen/internal/from_str.hpp index 81f88b9..601fe48 100644 --- a/include/sqlgen/internal/from_str.hpp +++ b/include/sqlgen/internal/from_str.hpp @@ -6,58 +6,14 @@ #include #include "../Result.hpp" -#include "../parsing/has_reflection_method.hpp" -#include "../parsing/is_nullable.hpp" +#include "../parsing/Parser.hpp" namespace sqlgen::internal { template Result from_str(const std::optional& _str) { using Type = std::remove_cvref_t; - - if constexpr (parsing::has_reflection_method) { - return from_str(_str).transform( - [](auto&& _v) { return Type(std::move(_v)); }); - - } else if constexpr (parsing::is_nullable_v) { - if (!_str) { - return Type(); - } - - if constexpr (parsing::is_ptr::value) { - return from_str(_str).transform( - [](auto&& _v) { return Type(std::move(_v)); }); - - } else { - return from_str(_str).transform( - [](auto&& _v) { return Type(std::move(_v)); }); - } - - } else { - if (!_str) { - return error("Encountered NULL value."); - } - - if constexpr (std::is_same_v) { - return *_str; - - } else { - try { - if constexpr (std::is_floating_point_v) { - return static_cast(std::stod(*_str)); - } else if constexpr (std::is_integral_v) { - return static_cast(std::stoll(*_str)); - } else if (std::is_same_v) { - return std::stoi(*_str) != 0; - } else { - static_assert(rfl::always_false, "Unsupported type"); - } - - } catch (std::exception& e) { - return error(e.what()); - } - } - } + return Parser::read(_str); } } // namespace sqlgen::internal diff --git a/include/sqlgen/internal/to_str.hpp b/include/sqlgen/internal/to_str.hpp index f45f496..228cf44 100644 --- a/include/sqlgen/internal/to_str.hpp +++ b/include/sqlgen/internal/to_str.hpp @@ -5,30 +5,14 @@ #include #include -#include "../parsing/has_reflection_method.hpp" -#include "../parsing/is_nullable.hpp" +#include "../parsing/Parser.hpp" namespace sqlgen::internal { template std::optional to_str(const T& _val) { using Type = std::remove_cvref_t; - if constexpr (parsing::is_nullable_v) { - if (!_val) { - return std::nullopt; - } else { - return to_str(*_val); - } - - } else if constexpr (parsing::has_reflection_method) { - return to_str(_val.reflection()); - - } else if constexpr (std::is_same_v) { - return _val; - - } else { - return std::to_string(_val); - } + return parsing::Parser::write(_val); } } // namespace sqlgen::internal diff --git a/include/sqlgen/parsing/Parser.hpp b/include/sqlgen/parsing/Parser.hpp new file mode 100644 index 0000000..ba9f2c0 --- /dev/null +++ b/include/sqlgen/parsing/Parser.hpp @@ -0,0 +1,12 @@ +#ifndef SQLGEN_PARSING_PARSER_HPP_ +#define SQLGEN_PARSING_PARSER_HPP_ + +#include "Parser_base.hpp" +#include "Parser_default.hpp" +#include "Parser_optional.hpp" +#include "Parser_primary_key.hpp" +#include "Parser_shared_ptr.hpp" +#include "Parser_string.hpp" +#include "Parser_unique_ptr.hpp" + +#endif diff --git a/include/sqlgen/parsing/Parser_base.hpp b/include/sqlgen/parsing/Parser_base.hpp new file mode 100644 index 0000000..d205549 --- /dev/null +++ b/include/sqlgen/parsing/Parser_base.hpp @@ -0,0 +1,11 @@ +#ifndef SQLGEN_PARSING_PARSER_BASE_HPP_ +#define SQLGEN_PARSING_PARSER_BASE_HPP_ + +namespace sqlgen::parsing { + +template +struct Parser; + +} + +#endif diff --git a/include/sqlgen/parsing/Parser_default.hpp b/include/sqlgen/parsing/Parser_default.hpp new file mode 100644 index 0000000..ff510e5 --- /dev/null +++ b/include/sqlgen/parsing/Parser_default.hpp @@ -0,0 +1,119 @@ +#ifndef SQLGEN_PARSING_PARSER_DEFAULT_HPP_ +#define SQLGEN_PARSING_PARSER_DEFAULT_HPP_ + +#include +#include +#include + +#include "../Result.hpp" +#include "../dynamic/Type.hpp" +#include "../dynamic/types.hpp" +#include "Parser_base.hpp" +#include "has_reflection_method.hpp" + +namespace sqlgen::parsing { + +template +struct Parser { + using Type = std::remove_cvref_t; + + static Result read(const std::optional& _str) noexcept { + if constexpr (has_reflection_method) { + return Parser>::read( + _str) + .transform([](auto&& _t) { return Type(std::move(_t)); }); + + } else { + if (!_str) { + return error("NULL value encounted: Numeric value cannot be NULL."); + } + + try { + if constexpr (std::is_floating_point_v) { + return static_cast(std::stod(*_str)); + } else if constexpr (std::is_integral_v) { + return static_cast(std::stoll(*_str)); + } else if (std::is_same_v) { + return std::stoi(*_str) != 0; + } else { + static_assert(rfl::always_false_v, "Unsupported type"); + } + + } catch (std::exception& e) { + return error(e.what()); + } + } + } + + static std::optional write(const T& _t) noexcept { + if constexpr (has_reflection_method) { + return Parser>::write( + _t.reflection()); + } else { + return std::to_string(_t); + } + } + + static dynamic::Type to_type() noexcept { + if constexpr (has_reflection_method) { + return Parser< + std::remove_cvref_t>::to_type(); + + } else if constexpr (std::is_same_v) { + return dynamic::types::Boolean{}; + + } else if constexpr (std::is_integral_v && std::is_signed_v) { + if constexpr (sizeof(T) == 1) { + return dynamic::types::Int8{}; + + } else if constexpr (sizeof(T) == 2) { + return dynamic::types::Int16{}; + + } else if constexpr (sizeof(T) == 4) { + return dynamic::types::Int32{}; + + } else if constexpr (sizeof(T) == 8) { + return dynamic::types::Int64{}; + + } else { + static_assert(rfl::always_false_v, "Unsupported signed integer."); + } + + } else if constexpr (std::is_integral_v && !std::is_signed_v) { + if constexpr (sizeof(T) == 1) { + return dynamic::types::UInt8{}; + + } else if constexpr (sizeof(T) == 2) { + return dynamic::types::UInt16{}; + + } else if constexpr (sizeof(T) == 4) { + return dynamic::types::UInt32{}; + + } else if constexpr (sizeof(T) == 8) { + return dynamic::types::UInt64{}; + + } else { + static_assert(rfl::always_false_v, "Unsupported unsigned integer."); + } + + } else if constexpr (std::is_floating_point_v) { + if constexpr (sizeof(T) == 4) { + return dynamic::types::Float32{}; + + } else if constexpr (sizeof(T) == 8) { + return dynamic::types::Float64{}; + + } else { + static_assert(rfl::always_false_v, + "Unsupported floating point value."); + } + + } else { + static_assert(rfl::always_false_v, "Unsupported type."); + } + } +}; + +} // namespace sqlgen::parsing + +#endif diff --git a/include/sqlgen/parsing/Parser_optional.hpp b/include/sqlgen/parsing/Parser_optional.hpp new file mode 100644 index 0000000..17a408b --- /dev/null +++ b/include/sqlgen/parsing/Parser_optional.hpp @@ -0,0 +1,45 @@ +#ifndef SQLGEN_PARSING_PARSER_OPTIONAL_HPP_ +#define SQLGEN_PARSING_PARSER_OPTIONAL_HPP_ + +#include +#include +#include + +#include "../Result.hpp" +#include "../dynamic/Type.hpp" +#include "Parser_base.hpp" + +namespace sqlgen::parsing { + +template +struct Parser> { + static Result> read( + const std::optional& _str) noexcept { + if (!_str) { + return std::optional(); + } + return Parser>::read(_str).transform( + [](auto&& _t) -> std::optional { + return std::make_optional(std::move(_t)); + }); + } + + static std::optional write(const std::optional& _o) noexcept { + if (!_o) { + return std::nullopt; + } + return Parser>::write(*_o); + } + + static dynamic::Type to_type() noexcept { + return Parser>::to_type().visit( + [](auto _t) -> dynamic::Type { + _t.properties.nullable = true; + return _t; + }); + } +}; + +} // namespace sqlgen::parsing + +#endif diff --git a/include/sqlgen/parsing/Parser_primary_key.hpp b/include/sqlgen/parsing/Parser_primary_key.hpp new file mode 100644 index 0000000..4e1aa91 --- /dev/null +++ b/include/sqlgen/parsing/Parser_primary_key.hpp @@ -0,0 +1,39 @@ +#ifndef SQLGEN_PARSING_PARSER_PRIMARY_KEY_HPP_ +#define SQLGEN_PARSING_PARSER_PRIMARY_KEY_HPP_ + +#include +#include + +#include "../PrimaryKey.hpp" +#include "../Result.hpp" +#include "../dynamic/Type.hpp" +#include "Parser_base.hpp" + +namespace sqlgen::parsing { + +template +struct Parser> { + static Result> read( + const std::optional& _str) noexcept { + return Parser>::read(_str).transform( + [](auto&& _t) -> PrimaryKey { + return PrimaryKey(std::move(_t)); + }); + } + + static std::optional write(const PrimaryKey& _p) noexcept { + return Parser>::write(_p.value()); + } + + static dynamic::Type to_type() noexcept { + return Parser>::to_type().visit( + [](auto _t) -> dynamic::Type { + _t.properties.primary = true; + return _t; + }); + } +}; + +} // namespace sqlgen::parsing + +#endif diff --git a/include/sqlgen/parsing/Parser_shared_ptr.hpp b/include/sqlgen/parsing/Parser_shared_ptr.hpp new file mode 100644 index 0000000..0e8cb31 --- /dev/null +++ b/include/sqlgen/parsing/Parser_shared_ptr.hpp @@ -0,0 +1,46 @@ +#ifndef SQLGEN_PARSING_PARSER_SHARED_PTR_HPP_ +#define SQLGEN_PARSING_PARSER_SHARED_PTR_HPP_ + +#include +#include +#include + +#include "../Result.hpp" +#include "../dynamic/Type.hpp" +#include "Parser_base.hpp" + +namespace sqlgen::parsing { + +template +struct Parser> { + static Result> read( + const std::optional& _str) noexcept { + if (!_str) { + return std::shared_ptr(); + } + return Parser>::read(_str).transform( + [](auto&& _t) -> std::shared_ptr { + return std::make_shared(std::move(_t)); + }); + } + + static std::optional write( + const std::shared_ptr& _ptr) noexcept { + if (!_ptr) { + return std::nullopt; + } + return Parser>::write(*_ptr); + } + + static dynamic::Type to_type() noexcept { + return Parser>::to_type().visit( + [](auto _t) -> dynamic::Type { + _t.properties.nullable = true; + return _t; + }); + } +}; + +} // namespace sqlgen::parsing + +#endif diff --git a/include/sqlgen/parsing/Parser_string.hpp b/include/sqlgen/parsing/Parser_string.hpp new file mode 100644 index 0000000..66ab60d --- /dev/null +++ b/include/sqlgen/parsing/Parser_string.hpp @@ -0,0 +1,33 @@ +#ifndef SQLGEN_PARSING_PARSER_STRING_HPP_ +#define SQLGEN_PARSING_PARSER_STRING_HPP_ + +#include +#include + +#include "../Result.hpp" +#include "../dynamic/Type.hpp" +#include "../dynamic/types.hpp" +#include "Parser_base.hpp" + +namespace sqlgen::parsing { + +template <> +struct Parser { + static Result read( + const std::optional& _str) noexcept { + if (!_str) { + return error("NULL value encounted: String value cannot be NULL."); + } + return *_str; + } + + static std::optional write(const std::string& _str) noexcept { + return _str; + } + + static dynamic::Type to_type() noexcept { return dynamic::types::Text{}; } +}; + +} // namespace sqlgen::parsing + +#endif diff --git a/include/sqlgen/parsing/Parser_unique_ptr.hpp b/include/sqlgen/parsing/Parser_unique_ptr.hpp new file mode 100644 index 0000000..cb114d9 --- /dev/null +++ b/include/sqlgen/parsing/Parser_unique_ptr.hpp @@ -0,0 +1,46 @@ +#ifndef SQLGEN_PARSING_PARSER_UNIQUE_PTR_HPP_ +#define SQLGEN_PARSING_PARSER_UNIQUE_PTR_HPP_ + +#include +#include +#include + +#include "../Result.hpp" +#include "../dynamic/Type.hpp" +#include "Parser_base.hpp" + +namespace sqlgen::parsing { + +template +struct Parser> { + static Result> read( + const std::optional& _str) noexcept { + if (!_str) { + return std::unique_ptr(); + } + return Parser>::read(_str).transform( + [](auto&& _t) -> std::unique_ptr { + return std::make_unique(std::move(_t)); + }); + } + + static std::optional write( + const std::unique_ptr& _ptr) noexcept { + if (!_ptr) { + return std::nullopt; + } + return Parser>::write(*_ptr); + } + + static dynamic::Type to_type() noexcept { + return Parser>::to_type().visit( + [](auto _t) -> dynamic::Type { + _t.properties.nullable = true; + return _t; + }); + } +}; + +} // namespace sqlgen::parsing + +#endif diff --git a/include/sqlgen/parsing/make_columns.hpp b/include/sqlgen/parsing/make_columns.hpp index d7dd9e4..59089bf 100644 --- a/include/sqlgen/parsing/make_columns.hpp +++ b/include/sqlgen/parsing/make_columns.hpp @@ -8,6 +8,7 @@ #include "../dynamic/Column.hpp" #include "../dynamic/Type.hpp" #include "../dynamic/types.hpp" +#include "Parser.hpp" #include "has_reflection_method.hpp" #include "is_nullable.hpp" #include "is_primary_key.hpp" @@ -22,76 +23,7 @@ std::string to_colname() { template dynamic::Type to_type() { using T = std::remove_cvref_t; - if constexpr (is_primary_key_v) { - return to_type().visit( - [](auto _t) -> dynamic::Type { - _t.properties.primary = true; - return _t; - }); - - } else if constexpr (is_nullable_v) { - const auto set_nullable = [](auto _t) -> dynamic::Type { - _t.properties.nullable = true; - return _t; - }; - if constexpr (is_ptr::value) { - return to_type().visit(set_nullable); - } else { - return to_type().visit(set_nullable); - } - - } else if constexpr (has_reflection_method) { - return to_type(); - - } else if constexpr (std::is_same_v) { - return dynamic::types::Boolean{}; - - } else if constexpr (std::is_integral_v && std::is_signed_v) { - if constexpr (sizeof(T) == 1) { - return dynamic::types::Int8{}; - - } else if constexpr (sizeof(T) == 2) { - return dynamic::types::Int16{}; - - } else if constexpr (sizeof(T) == 4) { - return dynamic::types::Int32{}; - - } else if constexpr (sizeof(T) == 8) { - return dynamic::types::Int64{}; - - } else { - static_assert(rfl::always_false_v, "Unsupported signed integer."); - } - } else if constexpr (std::is_integral_v && !std::is_signed_v) { - if constexpr (sizeof(T) == 1) { - return dynamic::types::UInt8{}; - - } else if constexpr (sizeof(T) == 2) { - return dynamic::types::UInt16{}; - - } else if constexpr (sizeof(T) == 4) { - return dynamic::types::UInt32{}; - - } else if constexpr (sizeof(T) == 8) { - return dynamic::types::UInt64{}; - - } else { - static_assert(rfl::always_false_v, "Unsupported unsigned integer."); - } - } else if constexpr (std::is_floating_point_v) { - if constexpr (sizeof(T) == 4) { - return dynamic::types::Float32{}; - - } else if constexpr (sizeof(T) == 8) { - return dynamic::types::Float64{}; - - } else { - static_assert(rfl::always_false_v, - "Unsupported floating point value."); - } - } else if constexpr (std::is_same_v) { - return dynamic::types::Text{}; - } + return Parser::to_type(); } template