#pragma once #include #include namespace BAN { template constexpr T swap_endianness(T value) { if constexpr(sizeof(T) == 1) return value; if constexpr(sizeof(T) == 2) return (((value >> 8) & 0xFF) << 0) | (((value >> 0) & 0xFF) << 8); if constexpr(sizeof(T) == 4) return (((value >> 24) & 0xFF) << 0) | (((value >> 16) & 0xFF) << 8) | (((value >> 8) & 0xFF) << 16) | (((value >> 0) & 0xFF) << 24); if constexpr(sizeof(T) == 8) return (((value >> 56) & 0xFF) << 0) | (((value >> 48) & 0xFF) << 8) | (((value >> 40) & 0xFF) << 16) | (((value >> 32) & 0xFF) << 24) | (((value >> 24) & 0xFF) << 32) | (((value >> 16) & 0xFF) << 40) | (((value >> 8) & 0xFF) << 48) | (((value >> 0) & 0xFF) << 56); T result { 0 }; for (size_t i = 0; i < sizeof(T); i++) result |= ((value >> (i * 8)) & 0xFF) << ((sizeof(T) - i - 1) * 8); return result; } template constexpr T host_to_little_endian(T value) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ return value; #else return swap_endianness(value); #endif } template constexpr T host_to_big_endian(T value) { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return value; #else return swap_endianness(value); #endif } template struct LittleEndian { constexpr operator T() const { return host_to_little_endian(raw); } private: T raw; }; template struct BigEndian { constexpr operator T() const { return host_to_big_endian(raw); } private: T raw; }; }