aboutsummaryrefslogtreecommitdiff
path: root/vendor/num-traits/src/ops/bytes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/num-traits/src/ops/bytes.rs')
-rw-r--r--vendor/num-traits/src/ops/bytes.rs403
1 files changed, 403 insertions, 0 deletions
diff --git a/vendor/num-traits/src/ops/bytes.rs b/vendor/num-traits/src/ops/bytes.rs
new file mode 100644
index 0000000..4df9ecd
--- /dev/null
+++ b/vendor/num-traits/src/ops/bytes.rs
@@ -0,0 +1,403 @@
+use core::borrow::{Borrow, BorrowMut};
+use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
+use core::fmt::Debug;
+use core::hash::Hash;
+#[cfg(not(has_int_to_from_bytes))]
+use core::mem::transmute;
+
+pub trait NumBytes:
+ Debug
+ + AsRef<[u8]>
+ + AsMut<[u8]>
+ + PartialEq
+ + Eq
+ + PartialOrd
+ + Ord
+ + Hash
+ + Borrow<[u8]>
+ + BorrowMut<[u8]>
+{
+}
+
+impl<T> NumBytes for T where
+ T: Debug
+ + AsRef<[u8]>
+ + AsMut<[u8]>
+ + PartialEq
+ + Eq
+ + PartialOrd
+ + Ord
+ + Hash
+ + Borrow<[u8]>
+ + BorrowMut<[u8]>
+ + ?Sized
+{
+}
+
+pub trait ToBytes {
+ type Bytes: NumBytes;
+
+ /// Return the memory representation of this number as a byte array in big-endian byte order.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::ToBytes;
+ ///
+ /// let bytes = ToBytes::to_be_bytes(&0x12345678u32);
+ /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
+ /// ```
+ fn to_be_bytes(&self) -> Self::Bytes;
+
+ /// Return the memory representation of this number as a byte array in little-endian byte order.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::ToBytes;
+ ///
+ /// let bytes = ToBytes::to_le_bytes(&0x12345678u32);
+ /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
+ /// ```
+ fn to_le_bytes(&self) -> Self::Bytes;
+
+ /// Return the memory representation of this number 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::ToBytes;
+ ///
+ /// #[cfg(target_endian = "big")]
+ /// let expected = [0x12, 0x34, 0x56, 0x78];
+ ///
+ /// #[cfg(target_endian = "little")]
+ /// let expected = [0x78, 0x56, 0x34, 0x12];
+ ///
+ /// let bytes = ToBytes::to_ne_bytes(&0x12345678u32);
+ /// assert_eq!(bytes, expected)
+ /// ```
+ fn to_ne_bytes(&self) -> Self::Bytes {
+ #[cfg(target_endian = "big")]
+ let bytes = self.to_be_bytes();
+ #[cfg(target_endian = "little")]
+ let bytes = self.to_le_bytes();
+ bytes
+ }
+}
+
+pub trait FromBytes: Sized {
+ type Bytes: NumBytes + ?Sized;
+
+ /// Create a number from its representation as a byte array in big endian.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::FromBytes;
+ ///
+ /// let value: u32 = FromBytes::from_be_bytes(&[0x12, 0x34, 0x56, 0x78]);
+ /// assert_eq!(value, 0x12345678);
+ /// ```
+ fn from_be_bytes(bytes: &Self::Bytes) -> Self;
+
+ /// Create a number from its representation as a byte array in little endian.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::FromBytes;
+ ///
+ /// let value: u32 = FromBytes::from_le_bytes(&[0x78, 0x56, 0x34, 0x12]);
+ /// assert_eq!(value, 0x12345678);
+ /// ```
+ fn from_le_bytes(bytes: &Self::Bytes) -> Self;
+
+ /// Create a number 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::FromBytes;
+ ///
+ /// #[cfg(target_endian = "big")]
+ /// let bytes = [0x12, 0x34, 0x56, 0x78];
+ ///
+ /// #[cfg(target_endian = "little")]
+ /// let bytes = [0x78, 0x56, 0x34, 0x12];
+ ///
+ /// let value: u32 = FromBytes::from_ne_bytes(&bytes);
+ /// assert_eq!(value, 0x12345678)
+ /// ```
+ fn from_ne_bytes(bytes: &Self::Bytes) -> Self {
+ #[cfg(target_endian = "big")]
+ let this = Self::from_be_bytes(bytes);
+ #[cfg(target_endian = "little")]
+ let this = Self::from_le_bytes(bytes);
+ this
+ }
+}
+
+macro_rules! float_to_from_bytes_impl {
+ ($T:ty, $L:expr) => {
+ #[cfg(has_float_to_from_bytes)]
+ impl ToBytes 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)
+ }
+ }
+
+ #[cfg(has_float_to_from_bytes)]
+ impl FromBytes for $T {
+ type Bytes = [u8; $L];
+
+ #[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(has_float_to_from_bytes))]
+ impl ToBytes for $T {
+ type Bytes = [u8; $L];
+
+ #[inline]
+ fn to_be_bytes(&self) -> Self::Bytes {
+ ToBytes::to_be_bytes(&self.to_bits())
+ }
+
+ #[inline]
+ fn to_le_bytes(&self) -> Self::Bytes {
+ ToBytes::to_le_bytes(&self.to_bits())
+ }
+
+ #[inline]
+ fn to_ne_bytes(&self) -> Self::Bytes {
+ ToBytes::to_ne_bytes(&self.to_bits())
+ }
+ }
+
+ #[cfg(not(has_float_to_from_bytes))]
+ impl FromBytes for $T {
+ type Bytes = [u8; $L];
+
+ #[inline]
+ fn from_be_bytes(bytes: &Self::Bytes) -> Self {
+ Self::from_bits(FromBytes::from_be_bytes(bytes))
+ }
+
+ #[inline]
+ fn from_le_bytes(bytes: &Self::Bytes) -> Self {
+ Self::from_bits(FromBytes::from_le_bytes(bytes))
+ }
+
+ #[inline]
+ fn from_ne_bytes(bytes: &Self::Bytes) -> Self {
+ Self::from_bits(FromBytes::from_ne_bytes(bytes))
+ }
+ }
+ };
+}
+
+macro_rules! int_to_from_bytes_impl {
+ ($T:ty, $L:expr) => {
+ #[cfg(has_int_to_from_bytes)]
+ impl ToBytes 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)
+ }
+ }
+
+ #[cfg(has_int_to_from_bytes)]
+ impl FromBytes for $T {
+ type Bytes = [u8; $L];
+
+ #[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(has_int_to_from_bytes))]
+ impl ToBytes for $T {
+ type Bytes = [u8; $L];
+
+ #[inline]
+ fn to_be_bytes(&self) -> Self::Bytes {
+ <$T as ToBytes>::to_ne_bytes(&<$T>::to_be(*self))
+ }
+
+ #[inline]
+ fn to_le_bytes(&self) -> Self::Bytes {
+ <$T as ToBytes>::to_ne_bytes(&<$T>::to_le(*self))
+ }
+
+ #[inline]
+ fn to_ne_bytes(&self) -> Self::Bytes {
+ unsafe { transmute(*self) }
+ }
+ }
+
+ #[cfg(not(has_int_to_from_bytes))]
+ impl FromBytes for $T {
+ type Bytes = [u8; $L];
+
+ #[inline]
+ fn from_be_bytes(bytes: &Self::Bytes) -> Self {
+ Self::from_be(<Self as FromBytes>::from_ne_bytes(bytes))
+ }
+
+ #[inline]
+ fn from_le_bytes(bytes: &Self::Bytes) -> Self {
+ Self::from_le(<Self as FromBytes>::from_ne_bytes(bytes))
+ }
+
+ #[inline]
+ fn from_ne_bytes(bytes: &Self::Bytes) -> Self {
+ unsafe { transmute(*bytes) }
+ }
+ }
+ };
+}
+
+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);
+int_to_from_bytes_impl!(u128, 16);
+#[cfg(target_pointer_width = "64")]
+int_to_from_bytes_impl!(usize, 8);
+#[cfg(target_pointer_width = "32")]
+int_to_from_bytes_impl!(usize, 4);
+
+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);
+int_to_from_bytes_impl!(i128, 16);
+#[cfg(target_pointer_width = "64")]
+int_to_from_bytes_impl!(isize, 8);
+#[cfg(target_pointer_width = "32")]
+int_to_from_bytes_impl!(isize, 4);
+
+float_to_from_bytes_impl!(f32, 4);
+float_to_from_bytes_impl!(f64, 8);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ macro_rules! check_to_from_bytes {
+ ($( $ty:ty )+) => {$({
+ let n = 1;
+ let be = <$ty as ToBytes>::to_be_bytes(&n);
+ let le = <$ty as ToBytes>::to_le_bytes(&n);
+ let ne = <$ty as ToBytes>::to_ne_bytes(&n);
+
+ assert_eq!(*be.last().unwrap(), 1);
+ assert_eq!(*le.first().unwrap(), 1);
+ if cfg!(target_endian = "big") {
+ assert_eq!(*ne.last().unwrap(), 1);
+ } else {
+ assert_eq!(*ne.first().unwrap(), 1);
+ }
+
+ assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n);
+ assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n);
+ if cfg!(target_endian = "big") {
+ assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n);
+ } else {
+ assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n);
+ }
+ })+}
+ }
+
+ #[test]
+ fn convert_between_int_and_bytes() {
+ check_to_from_bytes!(u8 u16 u32 u64 u128 usize);
+ check_to_from_bytes!(i8 i16 i32 i64 i128 isize);
+ }
+
+ #[test]
+ fn convert_between_float_and_bytes() {
+ macro_rules! check_to_from_bytes {
+ ($( $ty:ty )+) => {$(
+ let n: $ty = 3.14;
+
+ let be = <$ty as ToBytes>::to_be_bytes(&n);
+ let le = <$ty as ToBytes>::to_le_bytes(&n);
+ let ne = <$ty as ToBytes>::to_ne_bytes(&n);
+
+ assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n);
+ assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n);
+ if cfg!(target_endian = "big") {
+ assert_eq!(ne, be);
+ assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n);
+ } else {
+ assert_eq!(ne, le);
+ assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n);
+ }
+ )+}
+ }
+
+ check_to_from_bytes!(f32 f64);
+ }
+}