diff options
Diffstat (limited to 'src/serialization/tuple.h')
-rw-r--r-- | src/serialization/tuple.h | 162 |
1 files changed, 57 insertions, 105 deletions
diff --git a/src/serialization/tuple.h b/src/serialization/tuple.h index d9592bc96..b1ef94097 100644 --- a/src/serialization/tuple.h +++ b/src/serialization/tuple.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023, The Monero Project +// Copyright (c) 2014-2024, The Monero Project // // All rights reserved. // @@ -29,7 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #pragma once -#include <memory> +#include <tuple> #include "serialization.h" namespace serialization @@ -51,119 +51,71 @@ namespace serialization } } -template <template <bool> class Archive, class E0, class E1, class E2> -inline bool do_serialize(Archive<false>& ar, std::tuple<E0,E1,E2>& p) +template <size_t I, bool BackwardsCompat, bool W, template <bool> class Archive, typename... Ts> +bool do_serialize_tuple_nth(Archive<W>& ar, std::tuple<Ts...>& v) { - size_t cnt; - ar.begin_array(cnt); - if (!ar.good()) - return false; - if (cnt != 3) - return false; + static constexpr const size_t tuple_size = std::tuple_size<std::tuple<Ts...>>(); + static_assert(I <= tuple_size, "bad call"); - if (!::serialization::detail::serialize_tuple_element(ar, std::get<0>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if (!::serialization::detail::serialize_tuple_element(ar, std::get<1>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if (!::serialization::detail::serialize_tuple_element(ar, std::get<2>(p))) - return false; - if (!ar.good()) - return false; + if constexpr (I == 0) + { + // If BackwardsCompat is true, we serialize the size of 3-tuples and 4-tuples + if constexpr (BackwardsCompat && (tuple_size == 3 || tuple_size == 4)) + { + size_t cnt = tuple_size; + ar.begin_array(cnt); + if (cnt != tuple_size) + return false; + } + else + { + ar.begin_array(); + } + } + else if constexpr (I < tuple_size) + { + ar.delimit_array(); + } - ar.end_array(); - return true; + if constexpr (I == tuple_size) + { + ar.end_array(); + return ar.good(); + } + else + { + if (!::serialization::detail::serialize_tuple_element(ar, std::get<I>(v)) + || !ar.good()) + return false; + + return do_serialize_tuple_nth<I + 1, BackwardsCompat>(ar, v); + } } -template <template <bool> class Archive, class E0, class E1, class E2> -inline bool do_serialize(Archive<true>& ar, std::tuple<E0,E1,E2>& p) +template <bool BackwardsCompat, bool W, template <bool> class Archive, typename... Ts> +bool do_serialize_tuple(Archive<W>& ar, std::tuple<Ts...>& v) { - ar.begin_array(3); - if (!ar.good()) - return false; - if(!::serialization::detail::serialize_tuple_element(ar, std::get<0>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if(!::serialization::detail::serialize_tuple_element(ar, std::get<1>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if(!::serialization::detail::serialize_tuple_element(ar, std::get<2>(p))) - return false; - if (!ar.good()) - return false; - ar.end_array(); - return true; + return do_serialize_tuple_nth<0, BackwardsCompat>(ar, v); } -template <template <bool> class Archive, class E0, class E1, class E2, class E3> -inline bool do_serialize(Archive<false>& ar, std::tuple<E0,E1,E2,E3>& p) +template <bool W, template <bool> class Archive, typename... Ts> +bool do_serialize(Archive<W>& ar, std::tuple<Ts...>& v) { - size_t cnt; - ar.begin_array(cnt); - if (!ar.good()) - return false; - if (cnt != 4) - return false; + return do_serialize_tuple<true>(ar, v); +} - if (!::serialization::detail::serialize_tuple_element(ar, std::get<0>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if (!::serialization::detail::serialize_tuple_element(ar, std::get<1>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if (!::serialization::detail::serialize_tuple_element(ar, std::get<2>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if (!::serialization::detail::serialize_tuple_element(ar, std::get<3>(p))) - return false; - if (!ar.good()) - return false; +#define TUPLE_COMPACT_FIELDS(v) \ + do { \ + if (!do_serialize_tuple<false>(ar, v) || !ar.good()) \ + return false; \ + } while (0); - ar.end_array(); - return true; -} +#define TUPLE_COMPACT_FIELD_N(t, v) \ + do { \ + ar.tag(t); \ + TUPLE_COMPACT_FIELDS(v); \ + } while (0); -template <template <bool> class Archive, class E0, class E1, class E2, class E3> -inline bool do_serialize(Archive<true>& ar, std::tuple<E0,E1,E2,E3>& p) -{ - ar.begin_array(4); - if (!ar.good()) - return false; - if(!::serialization::detail::serialize_tuple_element(ar, std::get<0>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if(!::serialization::detail::serialize_tuple_element(ar, std::get<1>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if(!::serialization::detail::serialize_tuple_element(ar, std::get<2>(p))) - return false; - if (!ar.good()) - return false; - ar.delimit_array(); - if(!::serialization::detail::serialize_tuple_element(ar, std::get<3>(p))) - return false; - if (!ar.good()) - return false; - ar.end_array(); - return true; -} +#define TUPLE_COMPACT_FIELD(f) TUPLE_COMPACT_FIELD_N(#f, f) +#define TUPLE_COMPACT_FIELD_F(f) TUPLE_COMPACT_FIELD_N(#f, v.f) |