#pragma once #include #include namespace base { // required until C++23 support :( namespace detail { template constexpr T PunCast(U v) { return *std::bit_cast(&v); } template constexpr T ByteSwap(T v) { if constexpr(sizeof(T) == 2) return static_cast(__builtin_bswap16(PunCast(v))); else if constexpr(sizeof(T) == 4) return static_cast(__builtin_bswap32(PunCast(v))); else if constexpr(sizeof(T) == 8) return static_cast(__builtin_bswap64(PunCast(v))); return v; } } // namespace detail /// A network-order field, swapped automatically template struct [[gnu::packed]] NetworkOrder { constexpr NetworkOrder() = default; constexpr NetworkOrder(T v) : field(SwapIfRequired(v)) {} operator T() const { return SwapIfRequired(field); } private: constexpr static T SwapIfRequired(T value) { if constexpr(std::endian::native == std::endian::little) return detail::ByteSwap(value); return value; } T field; }; } // namespace base