]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
denc: Support std::optional
authorAdam C. Emerson <aemerson@redhat.com>
Tue, 9 Jan 2018 20:37:46 +0000 (15:37 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Fri, 12 Jan 2018 04:16:07 +0000 (23:16 -0500)
Since we'll probably want to use it at some point.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/include/denc.h
src/test/test_denc.cc

index fdc058a972573bd8631d9c4f839a55dc69a49026..3cc31234f5b0fa8927f3b75861d449e0ed6f7bdf 100644 (file)
@@ -27,6 +27,7 @@
 #include <array>
 #include <cstring>
 #include <map>
+#include <optional>
 #include <set>
 #include <string>
 #include <type_traits>
@@ -1469,6 +1470,114 @@ struct denc_traits<boost::none_t> {
   }
 };
 
+//
+// std::optional<T>
+//
+template<typename T>
+struct denc_traits<
+  std::optional<T>,
+  std::enable_if_t<denc_traits<T>::supported>> {
+  using traits = denc_traits<T>;
+
+  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<typename U = T>
+  static std::enable_if_t<!!sizeof(U)>
+  bound_encode(const std::optional<T>& 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<typename U = T>
+  static std::enable_if_t<!!sizeof(U)>
+  encode(const std::optional<T>& 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<T>& 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<typename U = T>
+  static std::enable_if_t<!!sizeof(U) && !need_contiguous>
+  decode(std::optional<T>& v, buffer::list::iterator& p) {
+    bool x;
+    denc(x, p);
+    if (x) {
+      v = T{};
+      denc(*v, p);
+    } else {
+      v = std::nullopt;
+    }
+  }
+
+  template<typename U = T>
+  static std::enable_if_t<!!sizeof(U)>
+  encode_nohead(const std::optional<T>& 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<T>& 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<std::nullopt_t> {
+  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
 
index 178f56030f117fc9ed8a70347d666958c651e946..a147a626e995838fc9bc5e7194ecebf273852905 100644 (file)
@@ -582,6 +582,44 @@ TEST(denc, optional)
   }
 }
 
+TEST(denc, stdoptional)
+{
+  {
+    cout << "std::optional<uint64_t>" << std::endl;
+    std::optional<uint64_t> s = 97, t = std::nullopt;
+    counts.reset();
+    test_denc(s);
+    test_denc(t);
+  }
+  {
+    cout << "std::optional<std::string>" << std::endl;
+    std::optional<std::string> 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<uint32_t> 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;