From 4a9ae3eb8b9a6d7a2e64f360fda2d5790c8e3321 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 12 Jan 2021 18:24:55 +0000 Subject: fix serialization being different on mac On Mac, size_t is a distinct type from uint64_t, and some types (in wallet cache as well as cold/hot wallet transfer data) use pairs/containers with size_t as fields. Mac would save those as full size, while other platforms would save them as varints. Might apply to other platforms where the types are distinct. There's a nasty hack for backward compatibility, which can go after a couple forks. --- src/serialization/binary_archive.h | 9 ++++++++- src/serialization/container.h | 23 ++++++++++++++--------- src/serialization/json_archive.h | 2 ++ src/serialization/pair.h | 19 ++++++++++++++++--- 4 files changed, 40 insertions(+), 13 deletions(-) (limited to 'src/serialization') diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h index 80104c8f7..49ca8aa57 100644 --- a/src/serialization/binary_archive.h +++ b/src/serialization/binary_archive.h @@ -98,7 +98,7 @@ template <> struct binary_archive : public binary_archive_base { - explicit binary_archive(stream_type &s) : base_type(s) { + explicit binary_archive(stream_type &s) : base_type(s), varint_bug_backward_compatibility_(false) { stream_type::pos_type pos = stream_.tellg(); stream_.seekg(0, std::ios_base::end); eof_pos_ = stream_.tellg(); @@ -173,8 +173,13 @@ struct binary_archive : public binary_archive_base assert(stream_.tellg() <= eof_pos_); return eof_pos_ - stream_.tellg(); } + + void enable_varint_bug_backward_compatibility() { varint_bug_backward_compatibility_ = true; } + bool varint_bug_backward_compatibility_enabled() const { return varint_bug_backward_compatibility_; } + protected: std::streamoff eof_pos_; + bool varint_bug_backward_compatibility_; }; template <> @@ -227,6 +232,8 @@ struct binary_archive : public binary_archive_base void write_variant_tag(variant_tag_type t) { serialize_int(t); } + + bool varint_bug_backward_compatibility_enabled() const { return false; } }; POP_WARNINGS diff --git a/src/serialization/container.h b/src/serialization/container.h index d5e75bb4f..a4997c8ae 100644 --- a/src/serialization/container.h +++ b/src/serialization/container.h @@ -32,22 +32,27 @@ namespace serialization { namespace detail { - template - bool serialize_container_element(Archive& ar, T& e) + template + inline constexpr bool use_container_varint() noexcept { - return ::do_serialize(ar, e); + return std::is_integral::value && std::is_unsigned::value && sizeof(T) > 1; } - template - bool serialize_container_element(Archive& ar, uint32_t& e) + template + typename std::enable_if(), bool>::type + serialize_container_element(Archive& ar, T& e) { - ar.serialize_varint(e); - return true; + return ::do_serialize(ar, e); } - template - bool serialize_container_element(Archive& ar, uint64_t& e) + template + typename std::enable_if(), bool>::type + serialize_container_element(Archive& ar, T& e) { + static constexpr const bool previously_varint = std::is_same() || std::is_same(); + + if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving()) + return ::do_serialize(ar, e); ar.serialize_varint(e); return true; } diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h index 50dd5bbd0..3f98b5101 100644 --- a/src/serialization/json_archive.h +++ b/src/serialization/json_archive.h @@ -84,6 +84,8 @@ struct json_archive_base void end_variant() { end_object(); } Stream &stream() { return stream_; } + bool varint_bug_backward_compatibility_enabled() const { return false; } + protected: void make_indent() { diff --git a/src/serialization/pair.h b/src/serialization/pair.h index 18280d837..44aafa04d 100644 --- a/src/serialization/pair.h +++ b/src/serialization/pair.h @@ -30,21 +30,34 @@ #pragma once #include +#include #include "serialization.h" namespace serialization { namespace detail { + template + inline constexpr bool use_pair_varint() noexcept + { + return std::is_integral::value && std::is_unsigned::value && sizeof(T) > 1; + } + template - bool serialize_pair_element(Archive& ar, T& e) + typename std::enable_if(), bool>::type + serialize_pair_element(Archive& ar, T& e) { return ::do_serialize(ar, e); } - template - bool serialize_pair_element(Archive& ar, uint64_t& e) + template + typename std::enable_if(), bool>::type + serialize_pair_element(Archive& ar, T& e) { + static constexpr const bool previously_varint = std::is_same(); + + if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving()) + return ::do_serialize(ar, e); ar.serialize_varint(e); return true; } -- cgit v1.2.3