Byte Conversions

Description

The library provides functions for converting safe integer types to and from big-endian or little-endian byte order. These operate on the non-bounded unsigned types (u8, u16, u32, u64, u128) and their verified counterparts.

For big-endian conversions (to_be/from_be): on big-endian platforms these are no-ops; on little-endian platforms they delegate to byteswap.

For little-endian conversions (to_le/from_le): on little-endian platforms these are no-ops; on big-endian platforms they delegate to byteswap.

#include <boost/safe_numbers/byte_conversions.hpp>

to_be

Converts a value from the native byte order to big-endian byte order.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto to_be(const T value) noexcept -> T;

Parameters

  • value — The value to convert.

Return Value

If std::endian::native == std::endian::big, returns value unchanged. Otherwise, returns byteswap(value).

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto be_val = to_be(u32{0x01020304});
// On little-endian: be_val == u32{0x04030201}
// On big-endian:    be_val == u32{0x01020304}

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto to_be(const verified_type_basis<T> value) noexcept -> verified_type_basis<T>;

Compile-time only overload for verified types.

Since to_be is consteval for verified types, the result is guaranteed to be a compile-time constant.

Example

using namespace boost::safe_numbers;

constexpr auto be_val = to_be(verified_u32{u32{0x01020304}});

from_be

Converts a value from big-endian byte order to the native byte order.

This is the inverse of to_be. Since byte swapping is its own inverse, from_be delegates directly to to_be.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto from_be(const T value) noexcept -> T;

Parameters

  • value — The big-endian value to convert to native byte order.

Return Value

The value in native byte order. Equivalent to to_be(value).

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto native_val = from_be(to_be(u64{0x0123456789ABCDEF}));
// native_val == u64{0x0123456789ABCDEF}  (round-trip)

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto from_be(const verified_type_basis<T> value) noexcept -> verified_type_basis<T>;

Compile-time only overload for verified types.

Since from_be is consteval for verified types, the result is guaranteed to be a compile-time constant.

Example

using namespace boost::safe_numbers;

constexpr auto val = verified_u32{u32{0xDEADBEEF}};
constexpr auto round_tripped = from_be(to_be(val));
static_assert(round_tripped == val);

to_le

Converts a value from the native byte order to little-endian byte order.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto to_le(const T value) noexcept -> T;

Parameters

  • value — The value to convert.

Return Value

If std::endian::native == std::endian::little, returns value unchanged. Otherwise, returns byteswap(value).

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto le_val = to_le(u32{0x01020304});
// On little-endian: le_val == u32{0x01020304}  (identity)
// On big-endian:    le_val == u32{0x04030201}

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto to_le(const verified_type_basis<T> value) noexcept -> verified_type_basis<T>;

Compile-time only overload for verified types.

Since to_le is consteval for verified types, the result is guaranteed to be a compile-time constant.

Example

using namespace boost::safe_numbers;

constexpr auto le_val = to_le(verified_u32{u32{0x01020304}});

from_le

Converts a value from little-endian byte order to the native byte order.

This is the inverse of to_le. Since byte swapping is its own inverse, from_le delegates directly to to_le.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto from_le(const T value) noexcept -> T;

Parameters

  • value — The little-endian value to convert to native byte order.

Return Value

The value in native byte order. Equivalent to to_le(value).

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto native_val = from_le(to_le(u64{0x0123456789ABCDEF}));
// native_val == u64{0x0123456789ABCDEF}  (round-trip)

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto from_le(const verified_type_basis<T> value) noexcept -> verified_type_basis<T>;

Compile-time only overload for verified types.

Since from_le is consteval for verified types, the result is guaranteed to be a compile-time constant.

Example

using namespace boost::safe_numbers;

constexpr auto val = verified_u32{u32{0xDEADBEEF}};
constexpr auto round_tripped = from_le(to_le(val));
static_assert(round_tripped == val);

to_be_bytes

Converts a safe integer value to a big-endian byte array. The value is first converted to big-endian byte order using to_be, then reinterpreted as an array of std::byte.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto to_be_bytes(const T value) noexcept -> std::array<std::byte, sizeof(T)>;

Parameters

  • value — The value to convert.

Return Value

A std::array<std::byte, sizeof(T)> containing the value’s bytes in big-endian order (most significant byte first).

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto bytes = to_be_bytes(u32{0x01020304});
// bytes == {0x01, 0x02, 0x03, 0x04}

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto to_be_bytes(const verified_type_basis<T> value) noexcept -> std::array<std::byte, sizeof(T)>;

Compile-time only overload for verified types.

Example

using namespace boost::safe_numbers;

constexpr auto bytes = to_be_bytes(verified_u32{u32{0x01020304}});
// bytes == {0x01, 0x02, 0x03, 0x04}

from_be_bytes

Reconstructs a safe integer value from a big-endian byte array. The bytes are reinterpreted as the underlying type and then converted from big-endian to native byte order using from_be.

Runtime Overload

template <non_bounded_integral_library_type T, std::size_t N>
    requires (!is_verified_type_v<T>)
constexpr auto from_be_bytes(const std::span<const std::byte, N> bytes) -> T;

Parameters

  • bytes — A span of bytes in big-endian order. May have a fixed extent or std::dynamic_extent.

Return Value

The reconstructed safe integer value in native byte order.

Extent Matching

The function validates that the number of input bytes matches sizeof(T):

  • Fixed extent matches sizeof(T): Compiles and executes normally.

  • Fixed extent does not match sizeof(T): Produces a static_assert failure at compile time.

  • Dynamic extent: Checks at runtime and throws std::domain_error if the sizes do not match.

Complexity

O(1).

Example

using namespace boost::safe_numbers;

// From a fixed-extent span
std::array<std::byte, 4> bytes {std::byte{0x01}, std::byte{0x02}, std::byte{0x03}, std::byte{0x04}};
auto val = from_be_bytes<u32>(std::span<const std::byte, 4>{bytes});
// val == u32{0x01020304}

// Round-trip
auto original = u32{0xDEADBEEF};
auto reconstructed = from_be_bytes<u32>(std::span<const std::byte, 4>{to_be_bytes(original)});
// reconstructed == original

Verified Overload

template <verified_type T, std::size_t N>
consteval auto from_be_bytes(const std::span<const std::byte, N> bytes) -> T;

Compile-time only overload for verified types. The span must have a fixed extent matching sizeof(T); a mismatched extent produces a static_assert failure.

Example

using namespace boost::safe_numbers;

constexpr std::array<std::byte, 4> bytes {std::byte{0x01}, std::byte{0x02}, std::byte{0x03}, std::byte{0x04}};
constexpr auto val = from_be_bytes<verified_u32>(std::span<const std::byte, 4>{bytes});
// val == verified_u32{u32{0x01020304}}

// Round-trip
constexpr auto original = verified_u32{u32{0xDEADBEEF}};
constexpr auto reconstructed = from_be_bytes<verified_u32>(std::span<const std::byte, 4>{to_be_bytes(original)});
static_assert(reconstructed == original);

to_le_bytes

Converts a safe integer value to a little-endian byte array. The value is first converted to little-endian byte order using to_le, then reinterpreted as an array of std::byte.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto to_le_bytes(const T value) noexcept -> std::array<std::byte, sizeof(T)>;

Parameters

  • value — The value to convert.

Return Value

A std::array<std::byte, sizeof(T)> containing the value’s bytes in little-endian order (least significant byte first).

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto bytes = to_le_bytes(u32{0x01020304});
// bytes == {0x04, 0x03, 0x02, 0x01}

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto to_le_bytes(const verified_type_basis<T> value) noexcept -> std::array<std::byte, sizeof(T)>;

Compile-time only overload for verified types.

Example

using namespace boost::safe_numbers;

constexpr auto bytes = to_le_bytes(verified_u32{u32{0x01020304}});
// bytes == {0x04, 0x03, 0x02, 0x01}

from_le_bytes

Reconstructs a safe integer value from a little-endian byte array. The bytes are reinterpreted as the underlying type and then converted from little-endian to native byte order using from_le.

Runtime Overload

template <non_bounded_integral_library_type T, std::size_t N>
    requires (!is_verified_type_v<T>)
constexpr auto from_le_bytes(const std::span<const std::byte, N> bytes) -> T;

Parameters

  • bytes — A span of bytes in little-endian order. May have a fixed extent or std::dynamic_extent.

Return Value

The reconstructed safe integer value in native byte order.

Extent Matching

The function validates that the number of input bytes matches sizeof(T):

  • Fixed extent matches sizeof(T): Compiles and executes normally.

  • Fixed extent does not match sizeof(T): Produces a static_assert failure at compile time.

  • Dynamic extent: Checks at runtime and throws std::domain_error if the sizes do not match.

Complexity

O(1).

Example

using namespace boost::safe_numbers;

// From a fixed-extent span
std::array<std::byte, 4> bytes {std::byte{0x04}, std::byte{0x03}, std::byte{0x02}, std::byte{0x01}};
auto val = from_le_bytes<u32>(std::span<const std::byte, 4>{bytes});
// val == u32{0x01020304}

// Round-trip
auto original = u32{0xDEADBEEF};
auto reconstructed = from_le_bytes<u32>(std::span<const std::byte, 4>{to_le_bytes(original)});
// reconstructed == original

Verified Overload

template <verified_type T, std::size_t N>
consteval auto from_le_bytes(const std::span<const std::byte, N> bytes) -> T;

Compile-time only overload for verified types. The span must have a fixed extent matching sizeof(T); a mismatched extent produces a static_assert failure.

Example

using namespace boost::safe_numbers;

constexpr std::array<std::byte, 4> bytes {std::byte{0x04}, std::byte{0x03}, std::byte{0x02}, std::byte{0x01}};
constexpr auto val = from_le_bytes<verified_u32>(std::span<const std::byte, 4>{bytes});
// val == verified_u32{u32{0x01020304}}

// Round-trip
constexpr auto original = verified_u32{u32{0xDEADBEEF}};
constexpr auto reconstructed = from_le_bytes<verified_u32>(std::span<const std::byte, 4>{to_le_bytes(original)});
static_assert(reconstructed == original);

to_ne_bytes

Converts a safe integer value to a native-endian byte array. Delegates to to_le_bytes on little-endian platforms and to_be_bytes on big-endian platforms.

The result is equivalent to std::bit_cast<std::array<std::byte, sizeof(T)>>(value) — i.e., the raw in-memory representation.

Runtime Overload

template <non_bounded_integral_library_type T>
    requires (!is_verified_type_v<T>)
constexpr auto to_ne_bytes(const T value) noexcept -> std::array<std::byte, sizeof(T)>;

Parameters

  • value — The value to convert.

Return Value

A std::array<std::byte, sizeof(T)> containing the value’s bytes in native byte order.

Complexity

O(1).

Example

using namespace boost::safe_numbers;

auto bytes = to_ne_bytes(u32{0x01020304});
// On little-endian: bytes == {0x04, 0x03, 0x02, 0x01}
// On big-endian:    bytes == {0x01, 0x02, 0x03, 0x04}

Verified Overload

template <non_bounded_integral_library_type T>
consteval auto to_ne_bytes(const verified_type_basis<T> value) noexcept -> std::array<std::byte, sizeof(T)>;

Compile-time only overload for verified types.

Example

using namespace boost::safe_numbers;

constexpr auto bytes = to_ne_bytes(verified_u32{u32{0x01020304}});

from_ne_bytes

Reconstructs a safe integer value from a native-endian byte array. Delegates to from_le_bytes on little-endian platforms and from_be_bytes on big-endian platforms.

Runtime Overload

template <non_bounded_integral_library_type T, std::size_t N>
    requires (!is_verified_type_v<T>)
constexpr auto from_ne_bytes(const std::span<const std::byte, N> bytes) -> T;

Parameters

  • bytes — A span of bytes in native byte order. May have a fixed extent or std::dynamic_extent.

Return Value

The reconstructed safe integer value.

Extent Matching

The function validates that the number of input bytes matches sizeof(T):

  • Fixed extent matches sizeof(T): Compiles and executes normally.

  • Fixed extent does not match sizeof(T): Produces a static_assert failure at compile time.

  • Dynamic extent: Checks at runtime and throws std::domain_error if the sizes do not match.

Complexity

O(1).

Example

using namespace boost::safe_numbers;

// Round-trip
auto original = u32{0xDEADBEEF};
auto reconstructed = from_ne_bytes<u32>(std::span<const std::byte, 4>{to_ne_bytes(original)});
// reconstructed == original

Verified Overload

template <verified_type T, std::size_t N>
consteval auto from_ne_bytes(const std::span<const std::byte, N> bytes) -> T;

Compile-time only overload for verified types. The span must have a fixed extent matching sizeof(T); a mismatched extent produces a static_assert failure.

Example

using namespace boost::safe_numbers;

constexpr auto original = verified_u32{u32{0xDEADBEEF}};
constexpr auto reconstructed = from_ne_bytes<verified_u32>(std::span<const std::byte, 4>{to_ne_bytes(original)});
static_assert(reconstructed == original);

Example

For a complete example demonstrating all byte conversion functions, see Byte Conversions.