Skip to content

Commit

Permalink
feat: tuple serialization (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
MistEO authored Dec 24, 2024
1 parent 2e5e8be commit 7daa578
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
80 changes: 80 additions & 0 deletions include/common/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ class basic_array
{
}

template <typename... elem_ts>
basic_array(const std::tuple<elem_ts...>& tup)
{
foreach_tuple(tup, std::make_index_sequence<std::tuple_size_v<std::tuple<elem_ts...>>>());
}
template <typename first_t, typename second_t>
basic_array(std::pair<first_t, second_t> pair)
: _array_data({ std::move(pair.first), std::move(pair.second) })
{
}

~basic_array() noexcept = default;

bool empty() const noexcept { return _array_data.empty(); }
Expand Down Expand Up @@ -104,6 +115,10 @@ class basic_array
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array>
fixed_array_t<value_t, Size> as_fixed_array() const;
template <typename... elem_ts>
std::tuple<elem_ts...> as_tuple() const;
template <typename first_t, typename second_t>
std::pair<first_t, second_t> as_pair() const;

// Usage: get(key_1, key_2, ..., default_value);
template <typename... key_then_default_value_t>
Expand Down Expand Up @@ -180,6 +195,18 @@ class basic_array
return as_fixed_array<value_t, Size, fixed_array_t>();
}

template <typename... elem_ts>
explicit operator std::tuple<elem_ts...>() const
{
return as_tuple<elem_ts...>();
}

template <typename elem1_t, typename elem2_t>
explicit operator std::pair<elem1_t, elem2_t>() const
{
return as_pair<elem1_t, elem2_t>();
}

template <
typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> =
Expand Down Expand Up @@ -217,6 +244,17 @@ class basic_array
template <typename value_t>
auto get_helper(const value_t& default_value, size_t pos) const;

template <typename tuple_t>
tuple_t as_tuple_templ() const;
template <size_t index, typename tuple_t>
void set_tuple(tuple_t& tup) const;

template <typename Tuple, std::size_t... Is>
void foreach_tuple(const Tuple& t, std::index_sequence<Is...>)
{
(_array_data.emplace_back(std::get<Is>(t)), ...);
}

string_t format(size_t indent, size_t indent_times) const;

private:
Expand Down Expand Up @@ -379,6 +417,48 @@ inline fixed_array_t<value_t, Size> basic_array<string_t>::as_fixed_array() cons
return result;
}

template <typename string_t>
template <size_t index, typename tuple_t>
inline void basic_array<string_t>::set_tuple(tuple_t& tup) const
{
using elem_t = std::tuple_element_t<index, tuple_t>;

if constexpr (index > 0) {
set_tuple<index - 1>(tup);
}

std::get<index>(tup) = static_cast<elem_t>(at(index));
}

template <typename string_t>
template <typename tuple_t>
inline tuple_t basic_array<string_t>::as_tuple_templ() const
{
constexpr size_t tuple_size = std::tuple_size_v<tuple_t>;

if (size() != tuple_size) {
throw exception("Wrong array size");
}

tuple_t result;
set_tuple<tuple_size - 1>(result);
return result;
}

template <typename string_t>
template <typename... elem_ts>
inline std::tuple<elem_ts...> basic_array<string_t>::as_tuple() const
{
return as_tuple_templ<std::tuple<elem_ts...>>();
}

template <typename string_t>
template <typename first_t, typename second_t>
inline std::pair<first_t, second_t> basic_array<string_t>::as_pair() const
{
return as_tuple_templ<std::pair<first_t, second_t>>();
}

template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_array<string_t>::get(key_then_default_value_t&&... keys_then_default_value) const
Expand Down
24 changes: 24 additions & 0 deletions include/common/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ class basic_value
{
}

template <typename... elem_ts>
basic_value(std::tuple<elem_ts...>&& tup)
: basic_value(basic_array<string_t>(std::forward<std::tuple<elem_ts...>>(tup)))
{
}

template <typename elem1_t, typename elem2_t>
basic_value(std::pair<elem1_t, elem2_t>&& pair)
: basic_value(basic_array<string_t>(std::pair<elem1_t, elem2_t>(pair)))
{
}

template <
typename value_t,
std::enable_if_t<!std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
Expand Down Expand Up @@ -349,6 +361,18 @@ class basic_value
return static_cast<enum_t>(static_cast<std::underlying_type_t<enum_t>>(*this));
}

template <typename... elem_ts>
explicit operator std::tuple<elem_ts...>() const
{
return as_array().template as_tuple<elem_ts...>();
}

template <typename elem1_t, typename elem2_t>
explicit operator std::pair<elem1_t, elem2_t>() const
{
return as_array().template as_pair<elem1_t, elem2_t>();
}

private:
friend class basic_array<string_t>;
friend class basic_object<string_t>;
Expand Down
19 changes: 19 additions & 0 deletions test/serializing_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,25 @@ bool jsonizing()
return false;
}

json::array tuple_arr;
tuple_arr.emplace_back(1);
tuple_arr.emplace_back("aaabbbccc");
auto t = tuple_arr.as_tuple<int, std::string>();
auto p = tuple_arr.as_pair<int, std::string>();
auto t2 = std::tuple<int, std::string>(tuple_arr);
auto p2 = std::pair<int, std::string>(tuple_arr);
json::value tuple_val = tuple_arr;
auto t3 = std::tuple<int, std::string>(tuple_val);
auto p3 = std::tuple<int, std::string>(tuple_val);

auto new_tuple_arr = (json::array)t;
auto new_tuple_val = (json::value)t;
new_tuple_val.as<std::tuple<int, std::string>>();
new_tuple_val.as<std::pair<int, std::string>>();

auto new_pair_arr = (json::array)p;
auto new_pair_val = (json::value)p;

return true;
}

Expand Down

0 comments on commit 7daa578

Please sign in to comment.