num-traits/src/ops/bytes.rs

188 lines
5.3 KiB
Rust

use core::mem::transmute;
pub trait IntToFromBytes {
type Bytes;
/// Return the memory representation of this integer as a byte array in big-endian byte order.
///
/// # Examples
///
/// ```
/// use num_traits::IntToFromBytes;
///
/// let bytes = 0x12345678u32.to_be_bytes();
/// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
/// ```
fn to_be_bytes(self) -> Self::Bytes;
/// Return the memory representation of this integer as a byte array in little-endian byte order.
///
/// # Examples
///
/// ```
/// use num_traits::IntToFromBytes;
///
/// let bytes = 0x12345678u32.to_le_bytes();
/// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
/// ```
fn to_le_bytes(self) -> Self::Bytes;
/// Return the memory representation of this integer as a byte array in native byte order.
///
/// As the target platform's native endianness is used,
/// portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
///
/// [`to_be_bytes`]: #method.to_be_bytes
/// [`to_le_bytes`]: #method.to_le_bytes
///
/// # Examples
///
/// ```
/// use num_traits::IntToFromBytes;
///
/// let bytes = 0x12345678u32.to_ne_bytes();
/// assert_eq!(bytes, if cfg!(target_endian = "big") {
/// [0x12, 0x34, 0x56, 0x78]
/// } else {
/// [0x78, 0x56, 0x34, 0x12]
/// });
/// ```
fn to_ne_bytes(self) -> Self::Bytes;
/// Create an integer value from its representation as a byte array in big endian.
///
/// # Examples
///
/// ```
/// use num_traits::IntToFromBytes;
///
/// let value = u32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
/// assert_eq!(value, 0x12345678);
/// ```
fn from_be_bytes(bytes: Self::Bytes) -> Self;
/// Create an integer value from its representation as a byte array in little endian.
///
/// # Examples
///
/// ```
/// use num_traits::IntToFromBytes;
///
/// let value = u32::from_le_bytes([0x78, 0x56, 0x34, 0x12]);
/// assert_eq!(value, 0x12345678);
/// ```
fn from_le_bytes(bytes: Self::Bytes) -> Self;
/// Create an integer value from its memory representation as a byte array in native endianness.
///
/// As the target platform's native endianness is used,
/// portable code likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as appropriate instead.
///
/// [`from_be_bytes`]: #method.from_be_bytes
/// [`from_le_bytes`]: #method.from_le_bytes
///
/// # Examples
///
/// ```
/// use num_traits::IntToFromBytes;
///
/// let value = u32::from_ne_bytes(if cfg!(target_endian = "big") {
/// [0x12, 0x34, 0x56, 0x78]
/// } else {
/// [0x78, 0x56, 0x34, 0x12]
/// });
/// assert_eq!(value, 0x12345678);
/// ```
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
}
macro_rules! int_to_from_bytes_impl {
($T:ty, $L:expr) => {
#[cfg(feature = "int_to_from_bytes")]
impl IntToFromBytes for $T {
type Bytes = [u8; $L];
#[inline]
fn to_be_bytes(self) -> Self::Bytes {
<$T>::to_be_bytes(self)
}
#[inline]
fn to_le_bytes(self) -> Self::Bytes {
<$T>::to_le_bytes(self)
}
#[inline]
fn to_ne_bytes(self) -> Self::Bytes {
<$T>::to_ne_bytes(self)
}
#[inline]
fn from_be_bytes(bytes: Self::Bytes) -> Self {
<$T>::from_be_bytes(bytes)
}
#[inline]
fn from_le_bytes(bytes: Self::Bytes) -> Self {
<$T>::from_le_bytes(bytes)
}
#[inline]
fn from_ne_bytes(bytes: Self::Bytes) -> Self {
<$T>::from_ne_bytes(bytes)
}
}
#[cfg(not(feature = "int_to_from_bytes"))]
impl IntToFromBytes for $T {
type Bytes = [u8; $L];
#[inline]
fn to_be_bytes(self) -> Self::Bytes {
<$T>::to_ne_bytes(<$T>::to_be(self))
}
#[inline]
fn to_le_bytes(self) -> Self::Bytes {
<$T>::to_ne_bytes(<$T>::to_le(self))
}
#[inline]
fn to_ne_bytes(self) -> Self::Bytes {
unsafe { transmute(self) }
}
#[inline]
fn from_be_bytes(bytes: Self::Bytes) -> Self {
Self::from_be(Self::from_ne_bytes(bytes))
}
#[inline]
fn from_le_bytes(bytes: Self::Bytes) -> Self {
Self::from_le(Self::from_ne_bytes(bytes))
}
#[inline]
fn from_ne_bytes(bytes: Self::Bytes) -> Self {
unsafe { transmute(bytes) }
}
}
};
}
// int_to_from_bytes_impl!(type, signed, unsigned);
int_to_from_bytes_impl!(u8, 1);
int_to_from_bytes_impl!(u16, 2);
int_to_from_bytes_impl!(u32, 4);
int_to_from_bytes_impl!(u64, 8);
#[cfg(has_i128)]
int_to_from_bytes_impl!(u128, 16);
int_to_from_bytes_impl!(usize, 8);
int_to_from_bytes_impl!(i8, 1);
int_to_from_bytes_impl!(i16, 2);
int_to_from_bytes_impl!(i32, 4);
int_to_from_bytes_impl!(i64, 8);
#[cfg(has_i128)]
int_to_from_bytes_impl!(i128, 16);
int_to_from_bytes_impl!(isize, 8);