aboutsummaryrefslogtreecommitdiff
path: root/src/serialization
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2021-01-12 18:24:55 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2021-03-05 23:42:33 +0000
commitf9b5b521e82b9dc08325bc65f25f8e4e446270fc (patch)
tree4da9913a90cae3b0f2011254466c2a62ee1ca3ae /src/serialization
parentMerge pull request #7381 (diff)
downloadmonero-f9b5b521e82b9dc08325bc65f25f8e4e446270fc.tar.xz
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.
Diffstat (limited to 'src/serialization')
-rw-r--r--src/serialization/binary_archive.h9
-rw-r--r--src/serialization/container.h23
-rw-r--r--src/serialization/json_archive.h2
-rw-r--r--src/serialization/pair.h19
4 files changed, 40 insertions, 13 deletions
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<false> : public binary_archive_base<std::istream, false>
{
- 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<false> : public binary_archive_base<std::istream, false>
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<true> : public binary_archive_base<std::ostream, true>
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 <typename Archive, class T>
- bool serialize_container_element(Archive& ar, T& e)
+ template<typename T>
+ inline constexpr bool use_container_varint() noexcept
{
- return ::do_serialize(ar, e);
+ return std::is_integral<T>::value && std::is_unsigned<T>::value && sizeof(T) > 1;
}
- template <typename Archive>
- bool serialize_container_element(Archive& ar, uint32_t& e)
+ template <typename Archive, class T>
+ typename std::enable_if<!use_container_varint<T>(), bool>::type
+ serialize_container_element(Archive& ar, T& e)
{
- ar.serialize_varint(e);
- return true;
+ return ::do_serialize(ar, e);
}
- template <typename Archive>
- bool serialize_container_element(Archive& ar, uint64_t& e)
+ template<typename Archive, typename T>
+ typename std::enable_if<use_container_varint<T>(), bool>::type
+ serialize_container_element(Archive& ar, T& e)
{
+ static constexpr const bool previously_varint = std::is_same<uint64_t, T>() || std::is_same<uint32_t, T>();
+
+ 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 <memory>
+#include <boost/type_traits/make_unsigned.hpp>
#include "serialization.h"
namespace serialization
{
namespace detail
{
+ template<typename T>
+ inline constexpr bool use_pair_varint() noexcept
+ {
+ return std::is_integral<T>::value && std::is_unsigned<T>::value && sizeof(T) > 1;
+ }
+
template <typename Archive, class T>
- bool serialize_pair_element(Archive& ar, T& e)
+ typename std::enable_if<!use_pair_varint<T>(), bool>::type
+ serialize_pair_element(Archive& ar, T& e)
{
return ::do_serialize(ar, e);
}
- template <typename Archive>
- bool serialize_pair_element(Archive& ar, uint64_t& e)
+ template<typename Archive, typename T>
+ typename std::enable_if<use_pair_varint<T>(), bool>::type
+ serialize_pair_element(Archive& ar, T& e)
{
+ static constexpr const bool previously_varint = std::is_same<uint64_t, T>();
+
+ if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
+ return ::do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}