diff --git a/src/include/denc.h b/src/include/denc.h index 4ab51ddc4b52cf..6cc48de2667d54 100644 --- a/src/include/denc.h +++ b/src/include/denc.h @@ -935,6 +935,204 @@ struct denc_traits< } }; +namespace _denc { + template + struct indices {}; + + template + struct build_indices_helper; + template + struct build_indices_helper { + using type = indices; + }; + template + struct build_indices_helper { + using type = typename build_indices_helper::type; + }; + + template + struct build_indices { + using type = typename build_indices_helper::type; + }; + template<> + struct build_indices<0> { + using type = indices<>; + }; + template<> + struct build_indices<1> { + using type = indices<0>; + }; + + template + using build_indices_t = typename build_indices::type; + + template + struct tuple_traits; + template + struct tuple_traits { + static constexpr bool supported = (denc_traits::supported && + tuple_traits::supported); + static constexpr bool bounded = (denc_traits::bounded && + tuple_traits::bounded); + static constexpr bool featured = (denc_traits::featured || + tuple_traits::featured); + }; + template<> + struct tuple_traits<> { + static constexpr bool supported = true; + static constexpr bool bounded = true; + static constexpr bool featured = false; + }; +} + +template +struct denc_traits< + std::tuple, + typename std::enable_if<_denc::tuple_traits::supported != 0>::type> { +private: + static_assert(sizeof...(Ts) > 0, + "Zero-length tuples are not supported."); + using container = std::tuple; + + template + static void bound_encode_helper_nfnb(const T& s, size_t& p, + _denc::indices) { + denc(std::get(s), p); + bound_encode_helper_nfnb(s, p, _denc::indices{}); + } + template + static void bound_encode_helper_nfnb(const T& s, size_t& p, + _denc::indices) { + denc(std::get(s), p); + } + + template + static void bound_encode_helper_nfb(const T& s, size_t& p, + _denc::indices) { + denc(*(typename std::tuple_element::type *)nullptr, p); + bound_encode_helper_nfb(s, p, _denc::indices{}); + } + template + static void bound_encode_helper_nfb(const T& s, size_t& p, + _denc::indices) { + denc(*(typename std::tuple_element::type *)nullptr, p); + } + + template + static void bound_encode_helper_fnb(const T& s, size_t& p, uint64_t f, + _denc::indices) { + denc(std::get(s), p, f); + bound_encode_helper_fnb(s, p, f, _denc::indices{}); + } + template + static void bound_encode_helper_fnb(const T& s, size_t& p, uint64_t f, + _denc::indices) { + denc(std::get(s), p, f); + } + + template + static void bound_encode_helper_fb(const T& s, size_t& p, uint64_t f, + _denc::indices) { + denc(*(typename std::tuple_element::type *)nullptr, p); + bound_encode_helper_fb(s, p, f, _denc::indices{}); + } + template + static void bound_encode_helper_fb(const T& s, size_t& p, uint64_t f, + _denc::indices) { + denc(*(typename std::tuple_element::type *)nullptr, p, f); + } + + template + static void encode_helper_nf(const T& s, buffer::list::contiguous_appender& p, + _denc::indices) { + denc(std::get(s), p); + encode_helper_nf(s, p, _denc::indices{}); + } + template + static void encode_helper_nf(const T& s, buffer::list::contiguous_appender& p, + _denc::indices) { + denc(std::get(s), p); + } + + template + static void encode_helper_f(const T& s, buffer::list::contiguous_appender& p, + uint64_t f, _denc::indices) { + denc(std::get(s), p, f); + encode_helper_nf(s, p, f, _denc::indices{}); + } + template + static void encode_helper_f(const T& s, buffer::list::contiguous_appender& p, + uint64_t f, _denc::indices) { + denc(std::get(s), p, f); + } + + template + static void decode_helper(T& s, buffer::ptr::iterator& p, + _denc::indices) { + denc(std::get(s), p); + decode_helper(s, p, _denc::indices{}); + } + template + static void decode_helper(T& s, buffer::ptr::iterator& p, + _denc::indices) { + denc(std::get(s), p); + } + +public: + using traits = _denc::tuple_traits; + + enum { supported = true }; + enum { featured = traits::featured }; + enum { bounded = traits::bounded }; + + + template + static typename std::enable_if::type + bound_encode(const container& s, size_t& p) { + bound_encode_helper_nfnb(s, p, _denc::build_indices_t{}); + } + template + static typename std::enable_if::type + bound_encode(const container& s, size_t& p) { + bound_encode_helper_nfb(s, p, _denc::build_indices_t{}); + } + template + static typename std::enable_if::type + bound_encode(const container& s, size_t& p, uint64_t f) { + bound_encode_helper_fnb(s, p, _denc::build_indices_t{}); + } + template + static typename std::enable_if::type + bound_encode(const container& s, size_t& p, uint64_t f) { + bound_encode_helper_fb(s, p, _denc::build_indices_t{}); + } + + template + static typename std::enable_if::type + encode(const container& s, buffer::list::contiguous_appender& p) { + encode_helper_nf(s, p, _denc::build_indices_t{}); + } + template + static typename std::enable_if::type + encode(const container& s, buffer::list::contiguous_appender& p, + uint64_t f) { + encode_helper_f(s, p, f, _denc::build_indices_t{}); + } + + static void decode(container& s, buffer::ptr::iterator& p, uint64_t f = 0) { + decode_helper(s, p, _denc::build_indices_t{}); + } +}; // ---------------------------------------------------------------------- // class helpers diff --git a/src/test/test_denc.cc b/src/test/test_denc.cc index 4c3fc5cd6a5f84..6cace0914dac02 100644 --- a/src/test/test_denc.cc +++ b/src/test/test_denc.cc @@ -518,9 +518,25 @@ TEST(denc, array) std::array s = { 1UL, 2UL, 3UL }; test_denc(s); } +} + +TEST(denc, tuple) +{ { - cout << "std::array" << std::endl; - std::array s = { legacy_t(1), legacy_t(2) }; - test_encode_decode(s); + cout << "std::tuple" << std::endl; + std::tuple s(100ULL, 97UL); + counts.reset(); + test_denc(s); + } + { + cout << "std::tuple" << std::endl; + std::tuple s("foo", 97); + test_denc(s); + } + { + cout << "std::tuple>" << std::endl; + std::tuple> s( + "bar", std::set{uint32_t(1), uint32_t(2), uint32_t(3)}); + test_denc(s); } }