Browse Source

util/saveload: implement default saveload for std::optional

ionagamed 1 year ago
parent
commit
824bccde52
2 changed files with 43 additions and 0 deletions
  1. 22 0
      util/ysaveload.h
  2. 21 0
      util/ysaveload_ut.cpp

+ 22 - 0
util/ysaveload.h

@@ -12,6 +12,7 @@
 
 #ifndef __NVCC__
     // cuda is compiled in C++14 mode at the time
+    #include <optional>
     #include <variant>
 #endif
 
@@ -642,6 +643,27 @@ public:
 
 #ifndef __NVCC__
 
+template <typename T>
+struct TSerializer<std::optional<T>> {
+    static inline void Save(IOutputStream* os, const std::optional<T>& v) {
+        ::Save(os, v.has_value());
+        if (v.has_value()) {
+            ::Save(os, *v);
+        }
+    }
+
+    static inline void Load(IInputStream* is, std::optional<T>& v) {
+        v.reset();
+
+        bool hasValue;
+        ::Load(is, hasValue);
+
+        if (hasValue) {
+            ::Load(is, v.emplace());
+        }
+    }
+};
+
 namespace NPrivate {
     template <class Variant, class T, size_t I>
     void LoadVariantAlternative(IInputStream* is, Variant& v) {

+ 21 - 0
util/ysaveload_ut.cpp

@@ -27,6 +27,7 @@ class TSaveLoadTest: public TTestBase {
     UNIT_TEST(TestList)
     UNIT_TEST(TestTuple)
     UNIT_TEST(TestVariant)
+    UNIT_TEST(TestOptional)
     UNIT_TEST(TestInheritNonVirtualClass)
     UNIT_TEST(TestInheritVirtualClass)
     UNIT_TEST_SUITE_END();
@@ -429,6 +430,26 @@ private:
         UNIT_ASSERT_EXCEPTION(::Load(&s, v2), TLoadEOF);
     }
 
+    template <class T>
+    void TestOptionalImpl(const std::optional<T>& v) {
+        std::optional<T> loaded;
+        TBufferStream s;
+        ::Save(&s, v);
+        ::Load(&s, loaded);
+
+        UNIT_ASSERT_VALUES_EQUAL(v.has_value(), loaded.has_value());
+        if (v.has_value()) {
+            UNIT_ASSERT_VALUES_EQUAL(*v, *loaded);
+        }
+    }
+
+    void TestOptional() {
+        TestOptionalImpl(std::optional<ui64>(42ull));
+        TestOptionalImpl(std::optional<bool>(true));
+        TestOptionalImpl(std::optional<TString>("abacaba"));
+        TestOptionalImpl(std::optional<ui64>(std::nullopt));
+    }
+
     //  tests serialization of class with three public string members
     template <class TDerived, class TInterface = TDerived>
     void TestInheritClassImpl() {