From 74948b5cd8c8d5b6894569e387b1d43572be938f Mon Sep 17 00:00:00 2001 From: "Adam C. Emerson" Date: Tue, 9 Jan 2018 15:37:46 -0500 Subject: [PATCH] denc: Support std::optional Since we'll probably want to use it at some point. Signed-off-by: Adam C. Emerson --- src/include/denc.h | 109 ++++++++++++++++++++++++++++++++++++++++++ src/test/test_denc.cc | 38 +++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/src/include/denc.h b/src/include/denc.h index fdc058a9725..3cc31234f5b 100644 --- a/src/include/denc.h +++ b/src/include/denc.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1469,6 +1470,114 @@ struct denc_traits { } }; +// +// std::optional +// +template +struct denc_traits< + std::optional, + std::enable_if_t::supported>> { + using traits = denc_traits; + + static constexpr bool supported = true; + static constexpr bool featured = traits::featured; + static constexpr bool bounded = false; + static constexpr bool need_contiguous = traits::need_contiguous; + + template + static std::enable_if_t + bound_encode(const std::optional& v, size_t& p, uint64_t f = 0) { + p += sizeof(bool); + if (v) { + if constexpr (featured) { + denc(*v, p, f); + } else { + denc(*v, p); + } + } + } + + template + static std::enable_if_t + encode(const std::optional& v, bufferlist::contiguous_appender& p, + uint64_t f = 0) { + denc((bool)v, p); + if (v) { + if constexpr (featured) { + denc(*v, p, f); + } else { + denc(*v, p); + } + } + } + + static void decode(std::optional& v, buffer::ptr::iterator& p, + uint64_t f = 0) { + bool x; + denc(x, p, f); + if (x) { + v = T{}; + denc(*v, p, f); + } else { + v = std::nullopt; + } + } + + template + static std::enable_if_t + decode(std::optional& v, buffer::list::iterator& p) { + bool x; + denc(x, p); + if (x) { + v = T{}; + denc(*v, p); + } else { + v = std::nullopt; + } + } + + template + static std::enable_if_t + encode_nohead(const std::optional& v, + bufferlist::contiguous_appender& p, + uint64_t f = 0) { + if (v) { + if constexpr (featured) { + denc(*v, p, f); + } else { + denc(*v, p); + } + } + } + + static void decode_nohead(bool num, std::optional& v, + buffer::ptr::iterator& p, uint64_t f = 0) { + if (num) { + v = T(); + denc(*v, p, f); + } else { + v = std::nullopt; + } + } +}; + +template<> +struct denc_traits { + static constexpr bool supported = true; + static constexpr bool featured = false; + static constexpr bool bounded = true; + static constexpr bool need_contiguous = false; + + static void bound_encode(const std::nullopt_t& v, size_t& p) { + p += sizeof(bool); + } + + static void encode(const std::nullopt_t& v, + bufferlist::contiguous_appender& p) { + denc(false, p); + } +}; + // ---------------------------------------------------------------------- // class helpers diff --git a/src/test/test_denc.cc b/src/test/test_denc.cc index 178f56030f1..a147a626e99 100644 --- a/src/test/test_denc.cc +++ b/src/test/test_denc.cc @@ -582,6 +582,44 @@ TEST(denc, optional) } } +TEST(denc, stdoptional) +{ + { + cout << "std::optional" << std::endl; + std::optional s = 97, t = std::nullopt; + counts.reset(); + test_denc(s); + test_denc(t); + } + { + cout << "std::optional" << std::endl; + std::optional s = std::string("Meow"), t = std::nullopt; + counts.reset(); + test_denc(s); + test_denc(t); + } + { + size_t s = 0; + denc(std::nullopt, s); + ASSERT_NE(s, 0u); + + // encode + bufferlist bl; + { + auto a = bl.get_contiguous_appender(s); + denc(std::nullopt, a); + } + ASSERT_LE(bl.length(), s); + + bl.rebuild(); + std::optional out = 5; + auto bpi = bl.front().begin(); + denc(out, bpi); + ASSERT_FALSE(!!out); + ASSERT_EQ(bpi.get_pos(), bl.c_str() + bl.length()); + } +} + // unlike legacy_t, Legacy supports denc() also. struct Legacy { static unsigned n_denc; -- 2.39.5