Skip to content

Commit

Permalink
serialization: replace char-is-int8_t autoconf detection with c++20 c…
Browse files Browse the repository at this point in the history
…oncept

This removes the only remaining autoconf macro in our serialization code,
so it can now be used trivially and safely out-of-tree.
  • Loading branch information
theuni committed Feb 27, 2024
1 parent 4d7d7fd commit ad7584d
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 18 deletions.
8 changes: 0 additions & 8 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1174,14 +1174,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
[ AC_MSG_RESULT([no])]
)

AC_MSG_CHECKING([for if type char equals int8_t])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>
#include <type_traits>]],
[[ static_assert(std::is_same<int8_t, char>::value, ""); ]])],
[ AC_MSG_RESULT([yes]); AC_DEFINE([CHAR_EQUALS_INT8], [1], [Define this symbol if type char equals int8_t]) ],
[ AC_MSG_RESULT([no])]
)

AC_MSG_CHECKING([for fdatasync])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]],
[[ fdatasync(0); ]])],
Expand Down
20 changes: 10 additions & 10 deletions src/serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@
#ifndef BITCOIN_SERIALIZE_H
#define BITCOIN_SERIALIZE_H

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <attributes.h>
#include <compat/assumptions.h> // IWYU pragma: keep
#include <compat/endian.h>
#include <prevector.h>
#include <span.h>

#include <algorithm>
#include <concepts>
#include <cstdint>
#include <cstring>
#include <ios>
Expand Down Expand Up @@ -263,9 +260,14 @@ const Out& AsBase(const In& x)
// i.e. anything that supports .read(Span<std::byte>) and .write(Span<const std::byte>)
//
// clang-format off
#ifndef CHAR_EQUALS_INT8
template <typename Stream> void Serialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t
#endif

// Typically int8_t and char are distinct types, but some systems may define int8_t
// in terms of char. Forbid serialization of char in the typical case, but allow it if
// it's the only way to describe an int8_t.
template<class T>
concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;

template <typename Stream, CharNotInt8 V> void Serialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t
template <typename Stream> void Serialize(Stream& s, std::byte a) { ser_writedata8(s, uint8_t(a)); }
template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
Expand All @@ -279,9 +281,7 @@ template <typename Stream, BasicByte B, int N> void Serialize(Stream& s, const B
template <typename Stream, BasicByte B, std::size_t N> void Serialize(Stream& s, const std::array<B, N>& a) { s.write(MakeByteSpan(a)); }
template <typename Stream, BasicByte B> void Serialize(Stream& s, Span<B> span) { s.write(AsBytes(span)); }

#ifndef CHAR_EQUALS_INT8
template <typename Stream> void Unserialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t
#endif
template <typename Stream, CharNotInt8 V> void Unserialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t
template <typename Stream> void Unserialize(Stream& s, std::byte& a) { a = std::byte{ser_readdata8(s)}; }
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
Expand Down

0 comments on commit ad7584d

Please sign in to comment.