diff --git a/3rdparty/include/meojson/common/array.hpp b/3rdparty/include/meojson/common/array.hpp index b693e599c3..af6e2fbdc5 100644 --- a/3rdparty/include/meojson/common/array.hpp +++ b/3rdparty/include/meojson/common/array.hpp @@ -1,3 +1,5 @@ +// IWYU pragma: private, include + #pragma once #include @@ -37,37 +39,86 @@ public: // explicit basic_array(const basic_value& val); // explicit basic_array(basic_value&& val); - template && - std::is_constructible_v>, - bool> = true> + template < + typename collection_t, + std::enable_if_t< + _utils::is_collection + && std::is_constructible_v>, + bool> = true> basic_array(collection_t arr) : _array_data(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end())) - {} - template ::value, bool> = true> - basic_array(const jsonization_t& value) : basic_array(value.to_json()) - {} - template ::value, bool> = true> - basic_array(const jsonization_t& value) : basic_array(ext::jsonization().to_json(value)) - {} + { + } + + template < + typename fixed_array_t, + std::enable_if_t<_utils::is_fixed_array, bool> = true> + basic_array(const fixed_array_t& arr) + : _array_data(arr.begin(), arr.end()) + { + } + + template < + typename jsonization_t, + std::enable_if_t<_utils::has_to_json_in_member::value, bool> = true> + basic_array(const jsonization_t& value) + : basic_array(value.to_json()) + { + } + + template < + typename jsonization_t, + std::enable_if_t<_utils::has_to_json_in_templ_spec::value, bool> = true> + basic_array(const jsonization_t& value) + : basic_array(ext::jsonization().to_json(value)) + { + } + + template + basic_array(const std::tuple& tup) + { + foreach_tuple(tup, std::make_index_sequence>>()); + } + template + basic_array(std::pair pair) + : _array_data({ std::move(pair.first), std::move(pair.second) }) + { + } ~basic_array() noexcept = default; bool empty() const noexcept { return _array_data.empty(); } + size_t size() const noexcept { return _array_data.size(); } + bool contains(size_t pos) const { return pos < _array_data.size(); } + bool exists(size_t pos) const { return contains(pos); } + const basic_value& at(size_t pos) const; - string_t dumps(std::optional indent = std::nullopt) const { return indent ? format(*indent) : to_string(); } + string_t dumps(std::optional indent = std::nullopt) const + { + return indent ? format(*indent) : to_string(); + } + string_t to_string() const; + string_t format(size_t indent = 4) const { return format(indent, 0); } + template bool all() const; template typename collection_t = std::vector> collection_t as_collection() const; + template < + typename value_t, + size_t Size, + template typename fixed_array_t = std::array> + fixed_array_t as_fixed_array() const; + template + std::tuple as_tuple() const; + template + std::pair as_pair() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -112,23 +163,54 @@ public: basic_array& operator=(const basic_array&) = default; basic_array& operator=(basic_array&&) noexcept = default; - template >, bool> = true> + + template < + typename value_t, + std::enable_if_t>, bool> = true> basic_array& operator=(value_t rhs) { return *this = basic_array(std::move(rhs)); } bool operator==(const basic_array& rhs) const; + bool operator!=(const basic_array& rhs) const { return !(*this == rhs); } - template typename collection_t = std::vector, - std::enable_if_t<_utils::is_collection>, bool> = true> + template < + typename value_t, + template typename collection_t = std::vector, + std::enable_if_t<_utils::is_collection>, bool> = true> explicit operator collection_t() const { return as_collection(); } - template ::value, bool> = true> + + template < + typename value_t, + size_t Size, + template typename fixed_array_t = std::array, + std::enable_if_t<_utils::is_fixed_array>, bool> = true> + explicit operator fixed_array_t() const + { + return as_fixed_array(); + } + + template + explicit operator std::tuple() const + { + return as_tuple(); + } + + template + explicit operator std::pair() const + { + return as_pair(); + } + + template < + typename jsonization_t, + std::enable_if_t<_utils::has_from_json_in_member::value, bool> = + true> explicit operator jsonization_t() const { jsonization_t dst {}; @@ -137,8 +219,12 @@ public: } return dst; } - template ::value, bool> = true> + + template < + typename jsonization_t, + std::enable_if_t< + _utils::has_from_json_in_templ_spec::value, + bool> = true> explicit operator jsonization_t() const { jsonization_t dst {}; @@ -150,13 +236,25 @@ public: private: template - auto get(std::tuple keys_then_default_value, - std::index_sequence) const; + auto + get(std::tuple keys_then_default_value, + std::index_sequence) const; template auto get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const; template auto get_helper(const value_t& default_value, size_t pos) const; + template + tuple_t as_tuple_templ() const; + template + void set_tuple(tuple_t& tup) const; + + template + void foreach_tuple(const Tuple& t, std::index_sequence) + { + (_array_data.emplace_back(std::get(t)), ...); + } + string_t format(size_t indent, size_t indent_times) const; private: @@ -164,15 +262,20 @@ private: }; template -inline basic_array::basic_array(std::initializer_list init_list) : _array_data(init_list) -{} +inline basic_array::basic_array(std::initializer_list init_list) + : _array_data(init_list) +{ +} template -inline basic_array::basic_array(typename raw_array::size_type size) : _array_data(size) -{} +inline basic_array::basic_array(typename raw_array::size_type size) + : _array_data(size) +{ +} // template -// inline basic_array::basic_array(const basic_value& val) : basic_array(val.as_array()) +// inline basic_array::basic_array(const basic_value& val) : +// basic_array(val.as_array()) //{} // // template @@ -202,8 +305,9 @@ template template inline decltype(auto) basic_array::emplace_back(args_t&&... args) { - static_assert(std::is_constructible_v, - "Parameter can't be used to construct a raw_array::value_type"); + static_assert( + std::is_constructible_v, + "Parameter can't be used to construct a raw_array::value_type"); return _array_data.emplace_back(std::forward(args)...); } @@ -266,18 +370,18 @@ inline bool basic_array::all() const namespace _as_collection_helper { - template - class has_emplace_back - { - template - static auto test(int) -> decltype(std::declval().emplace_back(), std::true_type()); +template +class has_emplace_back +{ + template + static auto test(int) -> decltype(std::declval().emplace_back(), std::true_type()); - template - static std::false_type test(...); + template + static std::false_type test(...); - public: - static constexpr bool value = decltype(test(0))::value; - }; +public: + static constexpr bool value = decltype(test(0))::value; +}; } template @@ -298,31 +402,94 @@ inline collection_t basic_array::as_collection() const return result; } +template +template typename fixed_array_t> +inline fixed_array_t basic_array::as_fixed_array() const +{ + if (size() != Size) { + throw exception("Wrong array size"); + } + + fixed_array_t result; + for (size_t i = 0; i < Size; ++i) { + result.at(i) = _array_data.at(i).template as(); + } + return result; +} + +template +template +inline void basic_array::set_tuple(tuple_t& tup) const +{ + using elem_t = std::tuple_element_t; + + if constexpr (index > 0) { + set_tuple(tup); + } + + std::get(tup) = static_cast(at(index)); +} + +template +template +inline tuple_t basic_array::as_tuple_templ() const +{ + constexpr size_t tuple_size = std::tuple_size_v; + + if (size() != tuple_size) { + throw exception("Wrong array size"); + } + + tuple_t result; + set_tuple(result); + return result; +} + +template +template +inline std::tuple basic_array::as_tuple() const +{ + return as_tuple_templ>(); +} + +template +template +inline std::pair basic_array::as_pair() const +{ + return as_tuple_templ>(); +} + template template inline auto basic_array::get(key_then_default_value_t&&... keys_then_default_value) const { - return get(std::forward_as_tuple(keys_then_default_value...), - std::make_index_sequence {}); + return get( + std::forward_as_tuple(keys_then_default_value...), + std::make_index_sequence {}); } template template -inline auto basic_array::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_array::get( + std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; - return get_helper(std::get(keys_then_default_value), - std::get(keys_then_default_value)...); + return get_helper( + std::get(keys_then_default_value), + std::get(keys_then_default_value)...); } template template -inline auto basic_array::get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const +inline auto basic_array::get_helper( + const value_t& default_value, + size_t pos, + rest_keys_t&&... rest) const { - constexpr bool is_json = std::is_same_v, value_t> || - std::is_same_v, value_t> || - std::is_same_v, value_t>; + constexpr bool is_json = std::is_same_v, value_t> + || std::is_same_v, value_t> + || std::is_same_v, value_t>; constexpr bool is_string = std::is_constructible_v && !is_json; if (!contains(pos)) { @@ -341,9 +508,9 @@ template template inline auto basic_array::get_helper(const value_t& default_value, size_t pos) const { - constexpr bool is_json = std::is_same_v, value_t> || - std::is_same_v, value_t> || - std::is_same_v, value_t>; + constexpr bool is_json = std::is_same_v, value_t> + || std::is_same_v, value_t> + || std::is_same_v, value_t>; constexpr bool is_string = std::is_constructible_v && !is_json; if (!contains(pos)) { @@ -382,7 +549,8 @@ inline std::optional basic_array::find(size_t pos) const return std::nullopt; } const auto& val = _array_data.at(pos); - return val.template is() ? std::optional(val.template as()) : std::nullopt; + return val.template is() ? std::optional(val.template as()) + : std::nullopt; } template @@ -434,25 +602,29 @@ inline typename basic_array::reverse_iterator basic_array::r } template -inline typename basic_array::const_reverse_iterator basic_array::rbegin() const noexcept +inline typename basic_array::const_reverse_iterator + basic_array::rbegin() const noexcept { return _array_data.rbegin(); } template -inline typename basic_array::const_reverse_iterator basic_array::rend() const noexcept +inline typename basic_array::const_reverse_iterator + basic_array::rend() const noexcept { return _array_data.rend(); } template -inline typename basic_array::const_reverse_iterator basic_array::crbegin() const noexcept +inline typename basic_array::const_reverse_iterator + basic_array::crbegin() const noexcept { return _array_data.crbegin(); } template -inline typename basic_array::const_reverse_iterator basic_array::crend() const noexcept +inline typename basic_array::const_reverse_iterator + basic_array::crend() const noexcept { return _array_data.crend(); } @@ -470,7 +642,8 @@ inline const basic_value& basic_array::operator[](size_t pos } template -inline basic_array basic_array::operator+(const basic_array& rhs) const& +inline basic_array + basic_array::operator+(const basic_array& rhs) const& { basic_array temp = *this; temp._array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); @@ -481,8 +654,10 @@ template inline basic_array basic_array::operator+(basic_array&& rhs) const& { basic_array temp = *this; - temp._array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), - std::make_move_iterator(rhs.end())); + temp._array_data.insert( + _array_data.end(), + std::make_move_iterator(rhs.begin()), + std::make_move_iterator(rhs.end())); return temp; } @@ -496,7 +671,10 @@ inline basic_array basic_array::operator+(const basic_array< template inline basic_array basic_array::operator+(basic_array&& rhs) && { - _array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); + _array_data.insert( + _array_data.end(), + std::make_move_iterator(rhs.begin()), + std::make_move_iterator(rhs.end())); return std::move(*this); } @@ -510,7 +688,10 @@ inline basic_array& basic_array::operator+=(const basic_arra template inline basic_array& basic_array::operator+=(basic_array&& rhs) { - _array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); + _array_data.insert( + _array_data.end(), + std::make_move_iterator(rhs.begin()), + std::make_move_iterator(rhs.end())); return *this; } @@ -520,11 +701,14 @@ inline bool basic_array::operator==(const basic_array& rhs) return _array_data == rhs._array_data; } -template >, - typename enable_t = - std::enable_if_t || std::is_base_of_v>> +template < + typename ostream_t, + typename string_t, + typename std_ostream_t = std::basic_ostream< + typename string_t::value_type, + std::char_traits>, + typename enable_t = std::enable_if_t< + std::is_same_v || std::is_base_of_v>> ostream_t& operator<<(ostream_t& out, const basic_array& arr) { out << arr.format(); diff --git a/3rdparty/include/meojson/common/exception.hpp b/3rdparty/include/meojson/common/exception.hpp index 065acbcc06..ec102e1391 100644 --- a/3rdparty/include/meojson/common/exception.hpp +++ b/3rdparty/include/meojson/common/exception.hpp @@ -1,3 +1,5 @@ +// IWYU pragma: private, include + #pragma once #include @@ -9,7 +11,11 @@ class exception : public std::exception { public: exception() = default; - exception(const std::string& msg) : _what(msg) {} + + exception(const std::string& msg) + : _what(msg) + { + } exception(const exception&) = default; exception& operator=(const exception&) = default; @@ -18,7 +24,10 @@ public: virtual ~exception() noexcept override = default; - virtual const char* what() const noexcept override { return _what.empty() ? "Unknown exception" : _what.c_str(); } + virtual const char* what() const noexcept override + { + return _what.empty() ? "Unknown exception" : _what.c_str(); + } protected: std::string _what; diff --git a/3rdparty/include/meojson/common/object.hpp b/3rdparty/include/meojson/common/object.hpp index 56c327bbba..a2337ba031 100644 --- a/3rdparty/include/meojson/common/object.hpp +++ b/3rdparty/include/meojson/common/object.hpp @@ -1,3 +1,5 @@ +// IWYU pragma: private, include + #pragma once #include @@ -36,31 +38,54 @@ public: // explicit basic_object(const basic_value& val); // explicit basic_object(basic_value&& val); - template && - std::is_constructible_v>, - bool> = true> - basic_object(map_t map) : _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end())) - {} - template ::value, bool> = true> - basic_object(const jsonization_t& value) : basic_object(value.to_json()) - {} - template ::value, bool> = true> - basic_object(const jsonization_t& value) : basic_object(ext::jsonization().to_json(value)) - {} + template < + typename map_t, + std::enable_if_t< + _utils::is_map + && std::is_constructible_v>, + bool> = true> + basic_object(map_t map) + : _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end())) + { + } + + template < + typename jsonization_t, + std::enable_if_t<_utils::has_to_json_in_member::value, bool> = true> + basic_object(const jsonization_t& value) + : basic_object(value.to_json()) + { + } + + template < + typename jsonization_t, + std::enable_if_t<_utils::has_to_json_in_templ_spec::value, bool> = true> + basic_object(const jsonization_t& value) + : basic_object(ext::jsonization().to_json(value)) + { + } ~basic_object() = default; bool empty() const noexcept { return _object_data.empty(); } + size_t size() const noexcept { return _object_data.size(); } + bool contains(const string_t& key) const; + bool exists(const string_t& key) const { return contains(key); } + const basic_value& at(const string_t& key) const; - string_t dumps(std::optional indent = std::nullopt) const { return indent ? format(*indent) : to_string(); } + string_t dumps(std::optional indent = std::nullopt) const + { + return indent ? format(*indent) : to_string(); + } + string_t to_string() const; + string_t format(size_t indent = 4) const { return format(indent, 0); } + template bool all() const; template typename map_t = std::map> @@ -102,23 +127,32 @@ public: basic_object& operator=(const basic_object&) = default; basic_object& operator=(basic_object&&) = default; - template >, bool> = true> + + template < + typename value_t, + std::enable_if_t>, bool> = true> basic_object& operator=(value_t rhs) { return *this = basic_object(std::move(rhs)); } bool operator==(const basic_object& rhs) const; + bool operator!=(const basic_object& rhs) const { return !(*this == rhs); } - template typename map_t = std::map, - std::enable_if_t<_utils::is_map>, bool> = true> + template < + typename value_t, + template typename map_t = std::map, + std::enable_if_t<_utils::is_map>, bool> = true> explicit operator map_t() const { return as_map(); } - template ::value, bool> = true> + + template < + typename jsonization_t, + std::enable_if_t<_utils::has_from_json_in_member::value, bool> = + true> explicit operator jsonization_t() const { jsonization_t dst {}; @@ -127,8 +161,12 @@ public: } return dst; } - template ::value, bool> = true> + + template < + typename jsonization_t, + std::enable_if_t< + _utils::has_from_json_in_templ_spec::value, + bool> = true> explicit operator jsonization_t() const { jsonization_t dst {}; @@ -140,8 +178,9 @@ public: private: template - auto get(std::tuple keys_then_default_value, - std::index_sequence) const; + auto + get(std::tuple keys_then_default_value, + std::index_sequence) const; template auto get_helper(const value_t& default_value, const string_t& key, rest_keys_t&&... rest) const; template @@ -155,8 +194,11 @@ private: template inline basic_object::basic_object(std::initializer_list init_list) - : _object_data(std::make_move_iterator(init_list.begin()), std::make_move_iterator(init_list.end())) -{} + : _object_data( + std::make_move_iterator(init_list.begin()), + std::make_move_iterator(init_list.end())) +{ +} // template // inline basic_object::basic_object(const basic_value& val) : @@ -202,9 +244,10 @@ template template inline decltype(auto) basic_object::emplace(args_t&&... args) { - static_assert(std::is_constructible_v, - "Parameter can't be used to construct a raw_object::value_type"); - return _object_data.emplace(std::forward(args)...); + static_assert( + std::is_constructible_v, + "Parameter can't be used to construct a raw_object::value_type"); + return _object_data.insert_or_assign(std::forward(args)...); } template @@ -220,7 +263,8 @@ inline string_t basic_object::to_string() const string_t str { '{' }; for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) { const auto& [key, val] = *iter; - str += char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':' } + val.to_string(); + str += + char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':' } + val.to_string(); if (++iter != _object_data.cend()) { str += ','; } @@ -238,8 +282,8 @@ inline string_t basic_object::format(size_t indent, size_t indent_time string_t str { '{', '\n' }; for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) { const auto& [key, val] = *iter; - str += body_indent + char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':', ' ' } + - val.format(indent, indent_times + 1); + str += body_indent + char_t('"') + _utils::unescape_string(key) + + string_t { '\"', ':', ' ' } + val.format(indent, indent_times + 1); if (++iter != _object_data.cend()) { str += ','; } @@ -276,28 +320,33 @@ template template inline auto basic_object::get(key_then_default_value_t&&... keys_then_default_value) const { - return get(std::forward_as_tuple(keys_then_default_value...), - std::make_index_sequence {}); + return get( + std::forward_as_tuple(keys_then_default_value...), + std::make_index_sequence {}); } template template -inline auto basic_object::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_object::get( + std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; - return get_helper(std::get(keys_then_default_value), - std::get(keys_then_default_value)...); + return get_helper( + std::get(keys_then_default_value), + std::get(keys_then_default_value)...); } template template -inline auto basic_object::get_helper(const value_t& default_value, const string_t& key, - rest_keys_t&&... rest) const +inline auto basic_object::get_helper( + const value_t& default_value, + const string_t& key, + rest_keys_t&&... rest) const { - constexpr bool is_json = std::is_same_v, value_t> || - std::is_same_v, value_t> || - std::is_same_v, value_t>; + constexpr bool is_json = std::is_same_v, value_t> + || std::is_same_v, value_t> + || std::is_same_v, value_t>; constexpr bool is_string = std::is_constructible_v && !is_json; if (!contains(key)) { @@ -314,11 +363,12 @@ inline auto basic_object::get_helper(const value_t& default_value, con template template -inline auto basic_object::get_helper(const value_t& default_value, const string_t& key) const +inline auto + basic_object::get_helper(const value_t& default_value, const string_t& key) const { - constexpr bool is_json = std::is_same_v, value_t> || - std::is_same_v, value_t> || - std::is_same_v, value_t>; + constexpr bool is_json = std::is_same_v, value_t> + || std::is_same_v, value_t> + || std::is_same_v, value_t>; constexpr bool is_string = std::is_constructible_v && !is_json; if (!contains(key)) { @@ -358,7 +408,8 @@ inline std::optional basic_object::find(const string_t& key) return std::nullopt; } const auto& val = iter->second; - return val.template is() ? std::optional(val.template as()) : std::nullopt; + return val.template is() ? std::optional(val.template as()) + : std::nullopt; } template @@ -374,7 +425,8 @@ inline typename basic_object::iterator basic_object::end() n } template -inline typename basic_object::const_iterator basic_object::begin() const noexcept +inline typename basic_object::const_iterator + basic_object::begin() const noexcept { return _object_data.begin(); } @@ -386,7 +438,8 @@ inline typename basic_object::const_iterator basic_object::e } template -inline typename basic_object::const_iterator basic_object::cbegin() const noexcept +inline typename basic_object::const_iterator + basic_object::cbegin() const noexcept { return _object_data.cbegin(); } @@ -410,7 +463,8 @@ inline basic_value& basic_object::operator[](string_t&& key) } template -inline basic_object basic_object::operator|(const basic_object& rhs) const& +inline basic_object + basic_object::operator|(const basic_object& rhs) const& { basic_object temp = *this; temp._object_data.insert(rhs.begin(), rhs.end()); @@ -422,12 +476,15 @@ inline basic_object basic_object::operator|(basic_object temp = *this; // temp._object_data.merge(std::move(rhs._object_data)); - temp._object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); + temp._object_data.insert( + std::make_move_iterator(rhs.begin()), + std::make_move_iterator(rhs.end())); return temp; } template -inline basic_object basic_object::operator|(const basic_object& rhs) && +inline basic_object + basic_object::operator|(const basic_object& rhs) && { _object_data.insert(rhs.begin(), rhs.end()); return std::move(*this); @@ -461,11 +518,14 @@ inline bool basic_object::operator==(const basic_object& rhs return _object_data == rhs._object_data; } -template >, - typename enable_t = - std::enable_if_t || std::is_base_of_v>> +template < + typename ostream_t, + typename string_t, + typename std_ostream_t = std::basic_ostream< + typename string_t::value_type, + std::char_traits>, + typename enable_t = std::enable_if_t< + std::is_same_v || std::is_base_of_v>> ostream_t& operator<<(ostream_t& out, const basic_object& obj) { out << obj.format(); diff --git a/3rdparty/include/meojson/common/serialization.hpp b/3rdparty/include/meojson/common/serialization.hpp index cd02d621c7..445f8a1974 100644 --- a/3rdparty/include/meojson/common/serialization.hpp +++ b/3rdparty/include/meojson/common/serialization.hpp @@ -1,3 +1,5 @@ +// IWYU pragma: private, include + #pragma once #include @@ -9,96 +11,101 @@ namespace json { namespace _serialization_helper { - template - class is_serializable - { - template - static auto test(int) -> decltype(std::declval()(std::declval()), std::true_type()); +template +class is_serializable +{ + template + static auto test(int) + -> decltype(std::declval()(std::declval()), std::true_type()); - template - static std::false_type test(...); + template + static std::false_type test(...); - public: - static constexpr bool value = decltype(test(0))::value; - }; +public: + static constexpr bool value = decltype(test(0))::value; +}; - struct empty_serializer - { - // sample: - // json::value operator()(const type_1&) const { return ...; } - // json::value operator()(const type_2&) const { return ...; } - // json::value operator()(const type_3&) const { return ...; } - }; +struct empty_serializer +{ + // sample: + // json::value operator()(const type_1&) const { return ...; } + // json::value operator()(const type_2&) const { return ...; } + // json::value operator()(const type_3&) const { return ...; } +}; - template - void unable_to_serialize() - { - static_assert(!sizeof(T), "Unable to serialize T. " +template +void unable_to_serialize() +{ + static_assert( + !sizeof(T), + "Unable to serialize T. " #ifdef _MSC_VER - "See T below: " __FUNCSIG__ + "See T below: " __FUNCSIG__ #else - // "See T below: " __PRETTY_FUNCTION__ + // "See T below: " __PRETTY_FUNCTION__ #endif - ); - } + ); +} } namespace _serialization_helper { - template - class is_deserializable - { - template - static auto test(int) - -> decltype(std::declval()(std::declval>(), std::declval()), - std::true_type()); +template +class is_deserializable +{ + template + static auto test(int) + -> decltype(std::declval()(std::declval>(), std::declval()), std::true_type()); - template - static std::false_type test(...); + template + static std::false_type test(...); - public: - static constexpr bool value = decltype(test(0))::value; - }; +public: + static constexpr bool value = decltype(test(0))::value; +}; - struct empty_deserializer - { - // sample: - // bool operator()(const json::value&, type_1&) const { return ...; } - // bool operator()(const json::value&, type_2&) const { return ...; } - // bool operator()(const json::value&, type_3&) const { return ...; } - }; +struct empty_deserializer +{ + // sample: + // bool operator()(const json::value&, type_1&) const { return ...; } + // bool operator()(const json::value&, type_2&) const { return ...; } + // bool operator()(const json::value&, type_3&) const { return ...; } +}; - template - void unable_to_deserialize() - { - static_assert(!sizeof(T), "Unable to deserialize T. " +template +void unable_to_deserialize() +{ + static_assert( + !sizeof(T), + "Unable to deserialize T. " #ifdef _MSC_VER - "See T below: " __FUNCSIG__ + "See T below: " __FUNCSIG__ #else - // "See T below: " __PRETTY_FUNCTION__ + // "See T below: " __PRETTY_FUNCTION__ #endif - ); - } + ); +} } -template +template < + typename in_t, + typename serializer_t = _serialization_helper::empty_serializer, + typename string_t = default_string_t> basic_value serialize(in_t&& in, const serializer_t& serializer = {}) { if constexpr (_serialization_helper::is_serializable::value) { return serializer(std::forward(in)); } - else if constexpr (std::is_constructible_v, in_t>) { - return basic_value(std::forward(in)); - } - else if constexpr (_utils::is_collection>) { + else if constexpr ( + _utils::is_collection> || _utils::is_fixed_array>) { basic_array arr; for (auto&& elem : in) { using elem_t = decltype(elem); - auto j_elem = serialize(std::forward(elem), serializer); + auto j_elem = + serialize(std::forward(elem), serializer); arr.emplace_back(std::move(j_elem)); } return arr; @@ -109,27 +116,32 @@ basic_value serialize(in_t&& in, const serializer_t& serializer = {}) using key_t = decltype(key); using elem_t = decltype(elem); - auto j_elem = serialize(std::forward(elem), serializer); + auto j_elem = + serialize(std::forward(elem), serializer); obj.emplace(std::forward(key), std::move(j_elem)); } return obj; } + else if constexpr (std::is_constructible_v, in_t>) { + return basic_value(std::forward(in)); + } else { _serialization_helper::unable_to_serialize(); } } -template -bool deserialize(const basic_value& in, out_t& out, const deserializer_t& deserializer = {}) +template < + typename out_t, + typename deserializer_t = _serialization_helper::empty_deserializer, + typename string_t = default_string_t> +bool deserialize( + const basic_value& in, + out_t& out, + const deserializer_t& deserializer = {}) { if constexpr (_serialization_helper::is_deserializable::value) { return deserializer(in, out); } - else if constexpr (std::is_constructible_v>) { - out = out_t(in); - return true; - } else if constexpr (_utils::is_collection>) { if (!in.is_array()) { return false; @@ -149,20 +161,45 @@ bool deserialize(const basic_value& in, out_t& out, const deserializer } return true; } - else if constexpr (_utils::is_map>) { - if (!in.is_object()) { + else if constexpr (_utils::is_fixed_array>) { + if (!in.is_array()) { return false; } - for (auto&& [key, j_elem] : in.as_object()) { + auto&& in_as_arr = in.as_array(); + constexpr size_t out_size = _utils::fixed_array_size; + if (in_as_arr.size() != out_size) { + return false; + } + + for (size_t i = 0; i < out_size; ++i) { + auto&& j_elem = in_as_arr.at(i); using elem_t = typename out_t::value_type; elem_t elem {}; if (!deserialize(j_elem, elem, deserializer)) { return false; } - out.emplace(std::move(elem)); + out.at(i) = std::move(elem); } return true; } + else if constexpr (_utils::is_map>) { + if (!in.is_object()) { + return false; + } + for (auto&& [key, j_elem] : in.as_object()) { + using elem_t = typename out_t::mapped_type; + elem_t elem {}; + if (!deserialize(j_elem, elem, deserializer)) { + return false; + } + out.emplace(std::forward(key), std::move(elem)); + } + return true; + } + else if constexpr (std::is_constructible_v>) { + out = out_t(in); + return true; + } else { _serialization_helper::unable_to_deserialize(); } diff --git a/3rdparty/include/meojson/common/types.hpp b/3rdparty/include/meojson/common/types.hpp index 2f56328000..93f9e2c8af 100644 --- a/3rdparty/include/meojson/common/types.hpp +++ b/3rdparty/include/meojson/common/types.hpp @@ -1,5 +1,7 @@ +// IWYU pragma: private, include + #pragma once #include "array.hpp" #include "object.hpp" -#include "value.hpp" \ No newline at end of file +#include "value.hpp" diff --git a/3rdparty/include/meojson/common/utils.hpp b/3rdparty/include/meojson/common/utils.hpp index f4779afc7f..12281b3dea 100644 --- a/3rdparty/include/meojson/common/utils.hpp +++ b/3rdparty/include/meojson/common/utils.hpp @@ -1,7 +1,14 @@ +// IWYU pragma: private, include + #pragma once +#include +#include +#include #include #include +#include +#include namespace json { @@ -61,12 +68,38 @@ constexpr bool is_container constexpr bool is_map = false; template -constexpr bool is_map> = is_container; +constexpr bool is_map> = + is_container; + +template +constexpr bool is_fixed_array = false; +template