Skip to content

Commit

Permalink
Merge branch 'mit-dci:trunk' into osx-build
Browse files Browse the repository at this point in the history
  • Loading branch information
davebryson authored May 26, 2022
2 parents cd37fca + 7a2f3b8 commit 650e994
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 14 deletions.
37 changes: 23 additions & 14 deletions src/util/serialization/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,26 +399,35 @@ namespace cbdc {
return deser;
}

/// \brief Deserializes a variant where none of the alternatives are
/// default-constructible.
///
/// Each alternative type must provide a constructor of the form
/// \brief Deserializes a variant where the alternatives are
/// all default constructible or all are not default constructible
/// If all alternatives are default constructible ,
/// each type must provide a constructor of the form
/// T(serializer&) which deserializes the type from its argument.
/// \see \ref cbdc::operator<<(serializer&, const std::variant<Ts...>&)
template<typename... Ts>
[[nodiscard]] auto get_variant(serializer& deser) -> std::variant<Ts...> {
using S = uint8_t;
using T = typename std::variant<Ts...>;
using S = uint8_t;
static_assert(std::variant_size_v<T> < std::numeric_limits<S>::max());
S idx{};
deser >> idx;
auto i = static_cast<size_t>(idx);
assert(i < std::variant_size_v<T>);
static constexpr auto t = std::array{+[](serializer& d) {
return T{std::in_place_type<Ts>, d};
}...};
// TODO: deserialization error handling for variant indexes.
return t.at(i)(deser);
// Since if the variant holds only default constructiable types
// we will be only able to unpack it using >>
// thus we can't extract the index value from the deser
if constexpr((std::is_default_constructible_v<Ts> && ...)) {
T variants;
deser >> variants;
return variants;
} else {
S idx{};
deser >> idx;
auto i = static_cast<size_t>(idx);
assert(i < std::variant_size_v<T>);
static constexpr auto t = std::array{+[](serializer& d) {
return T{std::in_place_type<Ts>, d};
}...};
// TODO: deserialization error handling for variant indexes.
return t.at(i)(deser);
}
}

// TODO: use std::is_scoped_enum_v and std::to_underlying once C++23 is
Expand Down
50 changes: 50 additions & 0 deletions tests/unit/serialization/format_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "uhs/atomizer/watchtower/watchtower.hpp"
#include "util/raft/serialization.hpp"
#include "util/serialization/buffer_serializer.hpp"
#include "util/serialization/format.hpp"
Expand Down Expand Up @@ -414,3 +415,52 @@ TEST_F(format_test, malformed_unordered_sets_cannot_roundtrip) {
// member)
EXPECT_FALSE(deser);
}

TEST_F(format_test, get_variant_default_constructibles) {
// empty set
std::unordered_set<uint64_t> s0;
std::variant<std::unordered_set<uint64_t>, uint64_t> v0{s0};
ser << v0;
auto r0 = cbdc::get_variant<std::unordered_set<uint64_t>, uint64_t>(deser);
EXPECT_TRUE(deser);
ser.reset();
deser.reset();
EXPECT_TRUE(ser);
EXPECT_TRUE(std::holds_alternative<std::unordered_set<uint64_t>>(r0));

// non empty
std::unordered_set<uint64_t> s1;
s1.insert(0);
s1.insert(std::numeric_limits<uint64_t>::max());
s1.insert(1 << 13);
std::variant<std::unordered_set<uint64_t>, uint64_t> v1{s1};
ser << v1;
auto r1 = cbdc::get_variant<std::unordered_set<uint64_t>, uint64_t>(deser);
EXPECT_TRUE(std::holds_alternative<std::unordered_set<uint64_t>>(r1));
auto resulted_set = std::get<std::unordered_set<uint64_t>>(r1);
EXPECT_TRUE(deser);
for(const auto& k : resulted_set) {
EXPECT_TRUE(s1.find(k) != s1.end());
}
}
//
TEST_F(format_test, get_variant_nondefault_constructibles) {
cbdc::watchtower::best_block_height_response block_height_0{9};
std::variant<cbdc::watchtower::request,
cbdc::watchtower::best_block_height_response>
variant_0{block_height_0};
ser << variant_0;
auto r0 = cbdc::get_variant<cbdc::watchtower::request,
cbdc::watchtower::best_block_height_response>(
deser);
EXPECT_TRUE(deser);
ser.reset();
deser.reset();
EXPECT_TRUE(ser);
EXPECT_TRUE(
std::holds_alternative<cbdc::watchtower::best_block_height_response>(
r0));
EXPECT_TRUE(
std::get<cbdc::watchtower::best_block_height_response>(r0).height()
== block_height_0.height());
}

0 comments on commit 650e994

Please sign in to comment.