Skip to content

Commit

Permalink
#274: variant: add new serializer for std::variant
Browse files Browse the repository at this point in the history
  • Loading branch information
lifflander committed Jul 26, 2023
1 parent d848aaf commit e085d72
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/checkpoint/checkpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include "checkpoint/container/vector_serialize.h"
#include "checkpoint/container/unique_ptr_serialize.h"
#include "checkpoint/container/view_serialize.h"
#include "checkpoint/container/variant_serialize.h"

#include "checkpoint/container/kokkos_unordered_map_serialize.h"
#include "checkpoint/container/kokkos_pair_serialize.h"
Expand Down
102 changes: 102 additions & 0 deletions src/checkpoint/container/variant_serialize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
//@HEADER
// *****************************************************************************
//
// varaint_serialize.h
// DARMA/checkpoint => Serialization Library
//
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact [email protected]
//
// *****************************************************************************
//@HEADER
*/

#if !defined INCLUDED_CHECKPOINT_CONTAINER_VARIANT_SERIALIZE_H
#define INCLUDED_CHECKPOINT_CONTAINER_VARIANT_SERIALIZE_H

#include "checkpoint/common.h"
#include "checkpoint/serializers/serializers_headers.h"
#include "checkpoint/dispatch/allocator.h"

#include <variant>

namespace checkpoint {

template <typename... Args>
struct SerializeEntry;

template <typename Arg, typename... Args>
struct SerializeEntry<Arg, Args...> {

template <typename SerializerT, typename VariantT>
static void serialize(
SerializerT& s, VariantT& v, std::size_t entry, std::size_t cur
) {
if (entry == cur) {
if (s.isUnpacking()) {
using Alloc = dispatch::Allocator<Arg>;
using Reconstructor =
dispatch::Reconstructor<typename dispatch::CleanType<Arg>::CleanT>;
Alloc allocated;
auto* reconstructed = Reconstructor::construct(allocated.buf);
s | *reconstructed;
v = std::move(*reconstructed);
} else {
s | std::get<Arg>(v);
}
} else {
SerializeEntry<Args...>::serialize(s, v, entry, cur+1);
}
}
};

template <>
struct SerializeEntry<> {
template <typename SerializerT, typename VariantT>
static void serialize(
SerializerT& s, VariantT& v, std::size_t entry, std::size_t cur
) {
// base case
}
};

template <typename SerializerT, typename... Args>
void serialize(SerializerT& s, std::variant<Args...>& v) {
std::size_t entry = v.index();
s | entry;
SerializeEntry<Args...>::serialize(s, v, entry, 0);
}

} /* end namespace checkpoint */

#endif /*INCLUDED_CHECKPOINT_CONTAINER_VARIANT_SERIALIZE_H*/
123 changes: 123 additions & 0 deletions tests/unit/test_variant_serializer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
//@HEADER
// *****************************************************************************
//
// test_variant_serialize.cc
// DARMA Toolkit v. 1.0.0
// DARMA/checkpoint => Serialization Library
//
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact [email protected]
//
// *****************************************************************************
//@HEADER
*/

#include <gtest/gtest.h>
#include "test_harness.h"
#include <checkpoint/checkpoint.h>

#include <variant>
#include <string>

namespace checkpoint { namespace tests { namespace unit {

using VariantTest = TestHarness;

TEST_F(VariantTest, test_variant_basic) {
std::variant<int, double> v;
v = 10.0f;

auto ret = serialize(v);
auto deser = deserialize<decltype(v)>(ret->getBuffer());

EXPECT_EQ(deser->index(), 1);
EXPECT_EQ(std::get<double>(*deser), 10.0f);
}

TEST_F(VariantTest, test_variant_basic_string) {
std::variant<int, double, std::string> v;
v = "test";

auto ret = serialize(v);
auto deser = deserialize<decltype(v)>(ret->getBuffer());

EXPECT_EQ(deser->index(), 2);
EXPECT_EQ(std::get<std::string>(*deser), "test");
}

struct NotDefaultConstruct {
NotDefaultConstruct() = delete;
explicit NotDefaultConstruct(int a) : a_(a) { }
explicit NotDefaultConstruct(SERIALIZE_CONSTRUCT_TAG) { }
int a_ = 0;

template <typename SerializerT>
void serialize(SerializerT& s) { s | a_; }
};

TEST_F(VariantTest, test_variant_no_default_construct) {
std::variant<int, double, NotDefaultConstruct, std::string> v;
v = NotDefaultConstruct{10};

auto ret = serialize(v);
auto deser = deserialize<decltype(v)>(ret->getBuffer());

EXPECT_EQ(deser->index(), 2);
EXPECT_EQ(std::get<NotDefaultConstruct>(*deser).a_, 10);
}

struct NotCopyConstruct {
NotCopyConstruct() = delete;
explicit NotCopyConstruct(int a) : a_(a) { }
explicit NotCopyConstruct(SERIALIZE_CONSTRUCT_TAG) { }
NotCopyConstruct(NotCopyConstruct const&) = delete;
NotCopyConstruct(NotCopyConstruct&&) = default;
NotCopyConstruct& operator=(NotCopyConstruct&&) = default;
int a_ = 0;

template <typename SerializerT>
void serialize(SerializerT& s) { s | a_; }
};

TEST_F(VariantTest, test_variant_no_copy_construct) {
std::variant<int, double, NotCopyConstruct, std::string> v;
v.emplace<NotCopyConstruct>(10);

auto ret = serialize(v);
auto deser = deserialize<decltype(v)>(ret->getBuffer());

EXPECT_EQ(deser->index(), 2);
EXPECT_EQ(std::get<NotCopyConstruct>(*deser).a_, 10);
}

}}}

0 comments on commit e085d72

Please sign in to comment.