From 291b191bd70b2afc285b71187c2f7eb85197f9f0 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 28 Mar 2016 00:16:22 -0600 Subject: [PATCH] Add serialization for primitive boost::optional. --- src/serialize.h | 54 ++++++++++++++++++++++++++++++++++++ src/test/serialize_tests.cpp | 27 ++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/serialize.h b/src/serialize.h index 8db53ecfd..0644a852e 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -21,6 +21,7 @@ #include #include +#include class CScript; @@ -508,6 +509,13 @@ extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVe template void Serialize(Stream& os, const CScript& v, int nType, int nVersion); template void Unserialize(Stream& is, CScript& v, int nType, int nVersion); +/** + * optional + */ +template unsigned int GetSerializeSize(const boost::optional &item, int nType, int nVersion); +template void Serialize(Stream& os, const boost::optional& item, int nType, int nVersion); +template void Unserialize(Stream& is, boost::optional& item, int nType, int nVersion); + /** * array */ @@ -707,6 +715,52 @@ void Unserialize(Stream& is, CScript& v, int nType, int nVersion) } + +/** + * optional + */ +template +unsigned int GetSerializeSize(const boost::optional &item, int nType, int nVersion) +{ + if (item) { + return 1 + GetSerializeSize(*item, nType, nVersion); + } else { + return 1; + } +} + +template +void Serialize(Stream& os, const boost::optional& item, int nType, int nVersion) +{ + // If the value is there, put 0x01 and then serialize the value. + // If it's not, put 0x00. + if (item) { + unsigned char discriminant = 0x01; + Serialize(os, discriminant, nType, nVersion); + Serialize(os, *item, nType, nVersion); + } else { + unsigned char discriminant = 0x00; + Serialize(os, discriminant, nType, nVersion); + } +} + +template +void Unserialize(Stream& is, boost::optional& item, int nType, int nVersion) +{ + unsigned char discriminant = 0x00; + Unserialize(is, discriminant, nType, nVersion); + + if (discriminant == 0x00) { + item = boost::none; + } else { + T object; + Unserialize(is, object, nType, nVersion); + item = object; + } +} + + + /** * array */ diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 56c9db2fd..f7240e4e3 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -11,11 +11,38 @@ #include #include +#include using namespace std; + +template +void check_ser_rep(T thing, std::vector expected) +{ + CDataStream ss(SER_DISK, 0); + ss << thing; + + BOOST_CHECK(GetSerializeSize(thing, 0, 0) == ss.size()); + + std::vector serialized_representation(ss.begin(), ss.end()); + + BOOST_CHECK(serialized_representation == expected); + + T thing_deserialized; + ss >> thing_deserialized; + + BOOST_CHECK(thing_deserialized == thing); +} + BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup) +BOOST_AUTO_TEST_CASE(boost_optional) +{ + check_ser_rep>(0xff, {0x01, 0xff}); + check_ser_rep>(boost::none, {0x00}); + check_ser_rep>(std::string("Test"), {0x01, 0x04, 'T', 'e', 's', 't'}); +} + BOOST_AUTO_TEST_CASE(boost_arrays) { boost::array test_case = {string("zub"), string("baz")};