SSX3LobbyServer/lib/base/network_order.hpp

48 lines
1.1 KiB
C++

#pragma once
#include <bit>
#include <base/types.hpp>
namespace base {
// required until C++23 support :(
namespace detail {
template <class T, class U>
constexpr T PunCast(U v) {
return *std::bit_cast<const T*>(&v);
}
template <class T>
constexpr T ByteSwap(T v) {
if constexpr(sizeof(T) == 2)
return static_cast<T>(__builtin_bswap16(PunCast<u16>(v)));
else if constexpr(sizeof(T) == 4)
return static_cast<T>(__builtin_bswap32(PunCast<u32>(v)));
else if constexpr(sizeof(T) == 8)
return static_cast<T>(__builtin_bswap64(PunCast<u64>(v)));
return v;
}
} // namespace detail
/// A network-order field, swapped automatically
template <class T>
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