#pragma once #include #include #include #include "ki/pclass/Value.h" #include "ki/util/BitTypes.h" #include "ki/pclass/types/EnumType.h" namespace ki { namespace pclass { namespace detail { /** * Determines whether a type can be assigned to a * nlohmann::json object. */ template struct is_json_assignable : std::false_type {}; /** * All fundamental types can be assigned to a json object. */ template struct is_json_assignable< SrcT, typename std::enable_if::value>::type > : std::true_type {}; /** * std::string can be assigned to a json object. */ template <> struct is_json_assignable : std::true_type {}; /** * std::u16string can be assigned to a json object. */ template <> struct is_json_assignable : std::true_type {}; /** * value_caster specialization for the generic case of casting * any json-assignable value to a json object. */ template struct value_caster< SrcT, nlohmann::json, typename std::enable_if::value>::type > : value_caster_impl { nlohmann::json cast_value(const SrcT &value) const override { return value; } }; /** * value_caster specialization for casting bit integers (bi and bui) * to a json object. */ template struct value_caster< BitInteger, nlohmann::json > : value_caster_impl, nlohmann::json> { using type = typename std::conditional< Unsigned, typename bits::uint_type, typename bits::int_type >::type; nlohmann::json cast_value( const BitInteger &value) const override { return static_cast(value); } }; /** * value_caster specialization for casting enum to bit integer types * (bi and bui). */ template struct value_caster< SrcT, BitInteger, typename std::enable_if::value>::type > : value_caster_impl> { using underlying_type = typename std::underlying_type::type; BitInteger cast_value(const SrcT &value) const override { return static_cast(value); } }; /** * value_caster specialization for casting enums to a json object. */ template struct value_caster< SrcT, nlohmann::json, typename std::enable_if::value>::type > : value_caster_impl { using underlying_type = typename std::underlying_type::type; nlohmann::json cast_value(const SrcT &value) const override { return static_cast(value); } }; template struct string_cast_t { using type = T; }; /** * Writing a int8_t or uint8_t value to a stream will * write a ASCII character, rather than an integer, so * we cast to int16_t/uint16_t before writing. */ template <> struct string_cast_t { using type = int16_t; }; template <> struct string_cast_t { using type = uint16_t; }; /** * Enums should be written as 32-bit integers. */ template struct string_cast_t< T, typename std::enable_if::value>::type > { using type = enum_value_t; }; /** * Caster implementation for casting any type to string * via std::ostringstream. */ template struct value_caster : value_caster_impl { std::string cast_value(const SrcT &value) const override { std::ostringstream oss; auto casted_value = static_cast< typename string_cast_t::type>(value); oss << casted_value; return oss.str(); } }; /** * Caster implementation for casting from json to any * primitive type. */ template struct value_caster : value_caster_impl { DestT cast_value(const nlohmann::json &value) const override { return value; } }; /** * Caster implementation for casting from json to a * std::string. */ template <> struct value_caster : value_caster_impl { std::string cast_value(const nlohmann::json &value) const override { return value; } }; /** * A utility to call ValueCaster::declare with * bi and bui as the destination type. * * N is automatically decremented until it reaches 0. */ template struct bit_integer_declarer { static void declare() { bit_integer_declarer::declare(); ValueCaster::declare>(); ValueCaster::declare>(); } }; /** * Specialization for bit_integer_declarer. * Stop decrementing N when it reaches 0. */ template struct bit_integer_declarer { static void declare() {} }; /** * Utility class used by TypeSystem to declare casters for each * primitive type. */ template struct caster_declarer { static void declare() {} }; /** * caster_declarer specialization for all integral types. * Integers can cast to other integer types, as well as floating point * integers, std::string and nlohmann::json. */ template struct caster_declarer< T, typename std::enable_if::value>::type > { static void declare() { ValueCaster::declare(); bit_integer_declarer::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare>(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare>(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); } }; /** * caster_declarer specialization for all floating point types. * Floating point integers can cast to all integer types, as well as * std::string and nlohmann::json. */ template struct caster_declarer< T, typename std::enable_if::value>::type > { static void declare() { ValueCaster::declare(); bit_integer_declarer::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare>(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare>(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); } }; /** * caster_declarer specialization for enum types. * Enums can be cast to any integer type, as well as std::string, * and nlohmann::json. */ template struct caster_declarer< T, typename std::enable_if::value>::type > { static void declare() { ValueCaster::declare(); bit_integer_declarer::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare>(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare>(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); ValueCaster::declare(); } }; /** * caster_declarer specialization for string. * Strings can be cast to UTF-16 strings, and json objects. */ template <> struct caster_declarer { static void declare() { // TODO: Casting string to u16string ValueCaster::declare(); } }; /** * caster_declarer specialization for UTF-16 strings. * UTF-16 strings can be cast to strings, and json objects. */ template <> struct caster_declarer { static void declare() { // TODO: Casting u16string to string ValueCaster::declare(); } }; } } }