--- /dev/null
+#![warn(\r
+ missing_docs, unused,\r
+ trivial_numeric_casts,\r
+ future_incompatible,\r
+ rust_2018_compatibility,\r
+ rust_2018_idioms,\r
+ clippy::all\r
+)]\r
+\r
+#![doc(html_root_url = "https://docs.rs/lebe/0.5.0")]\r
+\r
+//! Dead simple endianness conversions.\r
+//! The following operations are implemented on\r
+//! `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `f32`, `f64`:\r
+//!\r
+//!\r
+//! ### Read Numbers\r
+//! ```rust\r
+//! use lebe::prelude::*;\r
+//! let mut reader: &[u8] = &[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];\r
+//!\r
+//! let number : u64 = reader.read_from_little_endian()?;\r
+//! let number = u64::read_from_big_endian(&mut reader)?;\r
+//! # Ok::<(), std::io::Error>(())\r
+//! ```\r
+//!\r
+//! ### Read Slices\r
+//! ```rust\r
+//! use std::io::Read;\r
+//! use lebe::prelude::*;\r
+//! let mut reader: &[u8] = &[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];\r
+//!\r
+//! let mut numbers: &mut [u64] = &mut [0, 0];\r
+//! reader.read_from_little_endian_into(numbers)?;\r
+//! # Ok::<(), std::io::Error>(())\r
+//! ```\r
+//!\r
+//! ### Write Numbers\r
+//! ```rust\r
+//! use std::io::Read;\r
+//! use lebe::prelude::*;\r
+//! let mut writer: Vec<u8> = Vec::new();\r
+//!\r
+//! let number: u64 = 1237691;\r
+//! writer.write_as_big_endian(&number)?;\r
+//! # Ok::<(), std::io::Error>(())\r
+//! ```\r
+//!\r
+//! ### Write Slices\r
+//! ```rust\r
+//! use std::io::Write;\r
+//! use lebe::prelude::*;\r
+//! let mut writer: Vec<u8> = Vec::new();\r
+//!\r
+//! let numbers: &[u64] = &[1_u64, 234545_u64];\r
+//! writer.write_as_little_endian(numbers)?;\r
+//! # Ok::<(), std::io::Error>(())\r
+//! ```\r
+//!\r
+\r
+\r
+/// Exports some of the most common types.\r
+pub mod prelude {\r
+ pub use super::Endian;\r
+ pub use super::io::{ WriteEndian, ReadEndian, ReadPrimitive };\r
+}\r
+\r
+/// Represents values that can swap their bytes to reverse their endianness.\r
+///\r
+/// Supports converting values in-place using [`swap_bytes`] or [`convert_current_to_little_endian`]:\r
+/// Supports converting while transferring ownership using\r
+/// [`from_little_endian_into_current`] or [`from_current_into_little_endian`].\r
+///\r
+///\r
+/// For the types `u8`, `i8`, `&[u8]` and `&[i8]`, this trait will never transform any data,\r
+/// as they are just implemented for completeness.\r
+pub trait Endian {\r
+\r
+ /// Swaps all bytes in this value, inverting its endianness.\r
+ fn swap_bytes(&mut self);\r
+\r
+ /// On a little endian machine, this does nothing.\r
+ /// On a big endian machine, the bytes of this value are reversed.\r
+ #[inline] fn convert_current_to_little_endian(&mut self) {\r
+ #[cfg(target_endian = "big")] {\r
+ self.swap_bytes();\r
+ }\r
+ }\r
+\r
+ /// On a big endian machine, this does nothing.\r
+ /// On a little endian machine, the bytes of this value are reversed.\r
+ #[inline] fn convert_current_to_big_endian(&mut self) {\r
+ #[cfg(target_endian = "little")] {\r
+ self.swap_bytes();\r
+ }\r
+ }\r
+\r
+ /// On a little endian machine, this does nothing.\r
+ /// On a big endian machine, the bytes of this value are reversed.\r
+ #[inline] fn convert_little_endian_to_current(&mut self) {\r
+ #[cfg(target_endian = "big")] {\r
+ self.swap_bytes();\r
+ }\r
+ }\r
+\r
+ /// On a big endian machine, this does nothing.\r
+ /// On a little endian machine, the bytes of this value are reversed.\r
+ #[inline] fn convert_big_endian_to_current(&mut self) {\r
+ #[cfg(target_endian = "little")] {\r
+ self.swap_bytes();\r
+ }\r
+ }\r
+\r
+ /// On a little endian machine, this does nothing.\r
+ /// On a big endian machine, the bytes of this value are reversed.\r
+ #[inline] fn from_current_into_little_endian(mut self) -> Self where Self: Sized {\r
+ self.convert_current_to_little_endian();\r
+ self\r
+ }\r
+\r
+ /// On a big endian machine, this does nothing.\r
+ /// On a little endian machine, the bytes of this value are reversed.\r
+ #[inline] fn from_current_into_big_endian(mut self) -> Self where Self: Sized {\r
+ self.convert_current_to_big_endian();\r
+ self\r
+ }\r
+\r
+ /// On a little endian machine, this does nothing.\r
+ /// On a big endian machine, the bytes of this value are reversed.\r
+ #[inline] fn from_little_endian_into_current(mut self) -> Self where Self: Sized {\r
+ self.convert_little_endian_to_current();\r
+ self\r
+ }\r
+\r
+ /// On a big endian machine, this does nothing.\r
+ /// On a little endian machine, the bytes of this value are reversed.\r
+ #[inline] fn from_big_endian_into_current(mut self) -> Self where Self: Sized {\r
+ self.convert_big_endian_to_current();\r
+ self\r
+ }\r
+}\r
+\r
+\r
+// call a macro for each argument\r
+macro_rules! call_single_arg_macro_for_each {\r
+ ($macro: ident, $( $arguments: ident ),* ) => {\r
+ $( $macro! { $arguments } )*\r
+ };\r
+}\r
+\r
+// implement this interface for primitive signed and unsigned integers\r
+macro_rules! implement_simple_primitive_endian {\r
+ ($type: ident) => {\r
+ impl Endian for $type {\r
+ fn swap_bytes(&mut self) {\r
+ *self = $type::swap_bytes(*self);\r
+ }\r
+ }\r
+ };\r
+}\r
+\r
+\r
+call_single_arg_macro_for_each! {\r
+ implement_simple_primitive_endian,\r
+ u16, u32, u64, u128, i16, i32, i64, i128\r
+}\r
+\r
+// no-op implementations\r
+impl Endian for u8 { fn swap_bytes(&mut self) {} }\r
+impl Endian for i8 { fn swap_bytes(&mut self) {} }\r
+impl Endian for [u8] { fn swap_bytes(&mut self) {} }\r
+impl Endian for [i8] { fn swap_bytes(&mut self) {} }\r
+\r
+// implement this interface for primitive floats, because they do not have a `swap_bytes()` in `std`\r
+macro_rules! implement_float_primitive_by_bits {\r
+ ($type: ident) => {\r
+ impl Endian for $type {\r
+ fn swap_bytes(&mut self) {\r
+ *self = Self::from_bits(self.to_bits().swap_bytes());\r
+ }\r
+ }\r
+ };\r
+}\r
+\r
+\r
+implement_float_primitive_by_bits!(f32);\r
+implement_float_primitive_by_bits!(f64);\r
+\r
+macro_rules! implement_slice_by_element {\r
+ ($type: ident) => {\r
+ impl Endian for [$type] {\r
+ fn swap_bytes(&mut self) {\r
+ for number in self.iter_mut() { // TODO SIMD?\r
+ number.swap_bytes();\r
+ }\r
+ }\r
+ }\r
+ };\r
+}\r
+\r
+call_single_arg_macro_for_each! {\r
+ implement_slice_by_element,\r
+ u16, u32, u64, u128,\r
+ i16, i32, i64, i128,\r
+ f64, f32\r
+}\r
+\r
+/// Easily write primitives and slices of primitives to\r
+/// binary `std::io::Write` streams and easily read from binary `std::io::Read` streams.\r
+///\r
+/// Also contains the unsafe `bytes` module for reinterpreting values as byte slices and vice versa.\r
+pub mod io {\r
+ use super::Endian;\r
+ use std::io::{Read, Write, Result};\r
+\r
+ /// Reinterpret values as byte slices and byte slices as values unsafely.\r
+ pub mod bytes {\r
+ use std::io::{Read, Write, Result};\r
+\r
+ /// View this slice of values as a slice of bytes.\r
+ #[inline]\r
+ pub unsafe fn slice_as_bytes<T>(value: &[T]) -> &[u8] {\r
+ std::slice::from_raw_parts(\r
+ value.as_ptr() as *const u8,\r
+ value.len() * std::mem::size_of::<T>()\r
+ )\r
+ }\r
+\r
+ /// View this slice of values as a mutable slice of bytes.\r
+ #[inline]\r
+ pub unsafe fn slice_as_bytes_mut<T>(value: &mut [T]) -> &mut [u8] {\r
+ std::slice::from_raw_parts_mut(\r
+ value.as_mut_ptr() as *mut u8,\r
+ value.len() * std::mem::size_of::<T>()\r
+ )\r
+ }\r
+\r
+ /// View this reference as a slice of bytes.\r
+ #[inline]\r
+ pub unsafe fn value_as_bytes<T: Sized>(value: &T) -> &[u8] {\r
+ std::slice::from_raw_parts(\r
+ value as *const T as *const u8,\r
+ std::mem::size_of::<T>()\r
+ )\r
+ }\r
+\r
+ /// View this reference as a mutable slice of bytes.\r
+ #[inline]\r
+ pub unsafe fn value_as_bytes_mut<T: Sized>(value: &mut T) ->&mut [u8] {\r
+ std::slice::from_raw_parts_mut(\r
+ value as *mut T as *mut u8,\r
+ std::mem::size_of::<T>()\r
+ )\r
+ }\r
+\r
+ /// View this slice as a mutable slice of bytes and write it.\r
+ #[inline]\r
+ pub unsafe fn write_slice<T>(write: &mut impl Write, value: &[T]) -> Result<()> {\r
+ write.write_all(slice_as_bytes(value))\r
+ }\r
+\r
+ /// Read a slice of bytes into the specified slice.\r
+ #[inline]\r
+ pub unsafe fn read_slice<T>(read: &mut impl Read, value: &mut [T]) -> Result<()> {\r
+ read.read_exact(slice_as_bytes_mut(value))\r
+ }\r
+\r
+ /// View this reference as a mutable slice of bytes and write it.\r
+ #[inline]\r
+ pub unsafe fn write_value<T: Sized>(write: &mut impl Write, value: &T) -> Result<()> {\r
+ write.write_all(value_as_bytes(value))\r
+ }\r
+\r
+ /// Read a slice of bytes into the specified reference.\r
+ #[inline]\r
+ pub unsafe fn read_value<T: Sized>(read: &mut impl Read, value: &mut T) -> Result<()> {\r
+ read.read_exact(value_as_bytes_mut(value))\r
+ }\r
+ }\r
+\r
+ /// A `std::io::Write` output stream which supports writing any primitive values as bytes.\r
+ /// Will encode the values to be either little endian or big endian, as desired.\r
+ ///\r
+ /// This extension trait is implemented for all `Write` types.\r
+ /// Add `use lebe::io::WriteEndian;` to your code\r
+ /// to automatically unlock this functionality for all types that implement `Write`.\r
+ pub trait WriteEndian<T: ?Sized> {\r
+\r
+ /// Write the byte value of the specified reference, converting it to little endianness\r
+ fn write_as_little_endian(&mut self, value: &T) -> Result<()>;\r
+\r
+ /// Write the byte value of the specified reference, converting it to big endianness\r
+ fn write_as_big_endian(&mut self, value: &T) -> Result<()>;\r
+\r
+ /// Write the byte value of the specified reference, not converting it\r
+ fn write_as_native_endian(&mut self, value: &T) -> Result<()> {\r
+ #[cfg(target_endian = "little")] { self.write_as_little_endian(value) }\r
+ #[cfg(target_endian = "big")] { self.write_as_big_endian(value) }\r
+ }\r
+ }\r
+\r
+ /// A `std::io::Read` input stream which supports reading any primitive values from bytes.\r
+ /// Will decode the values from either little endian or big endian, as desired.\r
+ ///\r
+ /// This extension trait is implemented for all `Read` types.\r
+ /// Add `use lebe::io::ReadEndian;` to your code\r
+ /// to automatically unlock this functionality for all types that implement `Read`.\r
+ pub trait ReadEndian<T: ?Sized> {\r
+\r
+ /// Read into the supplied reference. Acts the same as `std::io::Read::read_exact`.\r
+ fn read_from_little_endian_into(&mut self, value: &mut T) -> Result<()>;\r
+\r
+ /// Read into the supplied reference. Acts the same as `std::io::Read::read_exact`.\r
+ fn read_from_big_endian_into(&mut self, value: &mut T) -> Result<()>;\r
+\r
+ /// Read into the supplied reference. Acts the same as `std::io::Read::read_exact`.\r
+ fn read_from_native_endian_into(&mut self, value: &mut T) -> Result<()> {\r
+ #[cfg(target_endian = "little")] { self.read_from_little_endian_into(value) }\r
+ #[cfg(target_endian = "big")] { self.read_from_big_endian_into(value) }\r
+ }\r
+\r
+ /// Read the byte value of the inferred type\r
+ #[inline]\r
+ fn read_from_little_endian(&mut self) -> Result<T> where T: Sized + Default {\r
+ let mut value = T::default();\r
+ self.read_from_little_endian_into(&mut value)?;\r
+ Ok(value)\r
+ }\r
+\r
+ /// Read the byte value of the inferred type\r
+ #[inline]\r
+ fn read_from_big_endian(&mut self) -> Result<T> where T: Sized + Default {\r
+ let mut value = T::default();\r
+ self.read_from_big_endian_into(&mut value)?;\r
+ Ok(value)\r
+ }\r
+\r
+ /// Read the byte value of the inferred type\r
+ #[inline]\r
+ fn read_from_native_endian(&mut self) -> Result<T> where T: Sized + Default {\r
+ #[cfg(target_endian = "little")] { self.read_from_little_endian() }\r
+ #[cfg(target_endian = "big")] { self.read_from_big_endian() }\r
+ }\r
+ }\r
+\r
+ // implement primitive for all types that are implemented by `Read`\r
+ impl<R: Read + ReadEndian<P>, P: Default> ReadPrimitive<R> for P {}\r
+\r
+\r
+ /// Offers a prettier versions of reading a primitive number.\r
+ ///\r
+ /// The default way of reading a value is:\r
+ /// ```rust\r
+ /// # use std::io::Read;\r
+ /// # use lebe::prelude::*;\r
+ /// # let mut reader : &[u8] = &[2, 1];\r
+ ///\r
+ /// let number: u16 = reader.read_from_little_endian()?;\r
+ /// println!("{}", number);\r
+ /// # Ok::<(), std::io::Error>(())\r
+ ///\r
+ /// ```\r
+ ///\r
+ /// This trait enables you to use expressions:\r
+ /// ```rust\r
+ /// # use std::io::Read;\r
+ /// # use lebe::prelude::*;\r
+ /// # let mut reader : &[u8] = &[2, 1];\r
+ ///\r
+ /// println!("{}", u16::read_from_little_endian(&mut reader)?);\r
+ /// # Ok::<(), std::io::Error>(())\r
+ /// ```\r
+ /// .\r
+ ///\r
+ pub trait ReadPrimitive<R: Read + ReadEndian<Self>> : Sized + Default {\r
+ /// Read this value from the supplied reader. Same as `ReadEndian::read_from_little_endian()`.\r
+ fn read_from_little_endian(read: &mut R) -> Result<Self> {\r
+ read.read_from_little_endian()\r
+ }\r
+\r
+ /// Read this value from the supplied reader. Same as `ReadEndian::read_from_big_endian()`.\r
+ fn read_from_big_endian(read: &mut R) -> Result<Self> {\r
+ read.read_from_big_endian()\r
+ }\r
+\r
+ /// Read this value from the supplied reader. Same as `ReadEndian::read_from_native_endian()`.\r
+ fn read_from_native_endian(read: &mut R) -> Result<Self> {\r
+ read.read_from_native_endian()\r
+ }\r
+ }\r
+\r
+ macro_rules! implement_simple_primitive_write {\r
+ ($type: ident) => {\r
+ impl<W: Write> WriteEndian<$type> for W {\r
+ fn write_as_little_endian(&mut self, value: &$type) -> Result<()> {\r
+ unsafe { bytes::write_value(self, &value.from_current_into_little_endian()) }\r
+ }\r
+\r
+ fn write_as_big_endian(&mut self, value: &$type) -> Result<()> {\r
+ unsafe { bytes::write_value(self, &value.from_current_into_big_endian()) }\r
+ }\r
+ }\r
+\r
+ impl<R: Read> ReadEndian<$type> for R {\r
+ #[inline]\r
+ fn read_from_little_endian_into(&mut self, value: &mut $type) -> Result<()> {\r
+ unsafe { bytes::read_value(self, value)?; }\r
+ value.convert_little_endian_to_current();\r
+ Ok(())\r
+ }\r
+\r
+ #[inline]\r
+ fn read_from_big_endian_into(&mut self, value: &mut $type) -> Result<()> {\r
+ unsafe { bytes::read_value(self, value)?; }\r
+ value.convert_big_endian_to_current();\r
+ Ok(())\r
+ }\r
+ }\r
+ };\r
+ }\r
+\r
+ call_single_arg_macro_for_each! {\r
+ implement_simple_primitive_write,\r
+ u8, u16, u32, u64, u128,\r
+ i8, i16, i32, i64, i128,\r
+ f32, f64\r
+ }\r
+\r
+\r
+ macro_rules! implement_slice_io {\r
+ ($type: ident) => {\r
+ impl<W: Write> WriteEndian<[$type]> for W {\r
+ fn write_as_little_endian(&mut self, value: &[$type]) -> Result<()> {\r
+ #[cfg(target_endian = "big")] {\r
+ for number in value { // TODO SIMD!\r
+ self.write_as_little_endian(number)?;\r
+ }\r
+ }\r
+\r
+ // else write whole slice\r
+ #[cfg(target_endian = "little")]\r
+ unsafe { bytes::write_slice(self, value)?; }\r
+\r
+ Ok(())\r
+ }\r
+\r
+ fn write_as_big_endian(&mut self, value: &[$type]) -> Result<()> {\r
+ #[cfg(target_endian = "little")] {\r
+ for number in value { // TODO SIMD!\r
+ self.write_as_big_endian(number)?;\r
+ }\r
+ }\r
+\r
+ // else write whole slice\r
+ #[cfg(target_endian = "big")]\r
+ unsafe { bytes::write_slice(self, value)?; }\r
+\r
+ Ok(())\r
+ }\r
+ }\r
+\r
+ impl<R: Read> ReadEndian<[$type]> for R {\r
+ fn read_from_little_endian_into(&mut self, value: &mut [$type]) -> Result<()> {\r
+ unsafe { bytes::read_slice(self, value)? };\r
+ value.convert_little_endian_to_current();\r
+ Ok(())\r
+ }\r
+\r
+ fn read_from_big_endian_into(&mut self, value: &mut [$type]) -> Result<()> {\r
+ unsafe { bytes::read_slice(self, value)? };\r
+ value.convert_big_endian_to_current();\r
+ Ok(())\r
+ }\r
+ }\r
+ };\r
+ }\r
+\r
+ call_single_arg_macro_for_each! {\r
+ implement_slice_io,\r
+ u8, u16, u32, u64, u128,\r
+ i8, i16, i32, i64, i128,\r
+ f64, f32\r
+ }\r
+\r
+\r
+\r
+ // TODO: SIMD\r
+ /*impl<R: Read> ReadEndian<[f32]> for R {\r
+ fn read_from_little_endian_into(&mut self, value: &mut [f32]) -> Result<()> {\r
+ unsafe { bytes::read_slice(self, value)? };\r
+ value.convert_little_endian_to_current();\r
+ Ok(())\r
+ }\r
+\r
+ fn read_from_big_endian_into(&mut self, value: &mut [f32]) -> Result<()> {\r
+ unsafe { bytes::read_slice(self, value)? };\r
+ value.convert_big_endian_to_current();\r
+ Ok(())\r
+ }\r
+ }\r
+\r
+ impl<W: Write> WriteEndian<[f32]> for W {\r
+ fn write_as_big_endian(&mut self, value: &[f32]) -> Result<()> {\r
+ if cfg!(target_endian = "little") {\r
+\r
+ // FIX ME this SIMD optimization makes no difference ... why? like, ZERO difference, not even worse\r
+// #[cfg(feature = "simd")]\r
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]\r
+ unsafe {\r
+ if is_x86_feature_detected!("avx2") {\r
+ write_bytes_avx(self, value);\r
+ return Ok(());\r
+ }\r
+ }\r
+\r
+ // otherwise (no avx2 available)\r
+// for number in value {\r
+// self.write_as_little_endian(number);\r
+// }\r
+//\r
+// return Ok(());\r
+ unimplemented!();\r
+\r
+ #[target_feature(enable = "avx2")]\r
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]\r
+ unsafe fn write_bytes_avx(write: &mut impl Write, slice: &[f32]) -> Result<()> {\r
+ #[cfg(target_arch = "x86")] use std::arch::x86 as mm;\r
+ #[cfg(target_arch = "x86_64")] use std::arch::x86_64 as mm;\r
+\r
+ let bytes: &[u8] = crate::io::bytes::slice_as_bytes(slice);\r
+ let mut chunks = bytes.chunks_exact(32);\r
+\r
+ let indices = mm::_mm256_set_epi8(\r
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\r
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\r
+// 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12,\r
+// 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12\r
+ );\r
+\r
+ for chunk in &mut chunks {\r
+ let data = mm::_mm256_loadu_si256(chunk.as_ptr() as _);\r
+ let result = mm::_mm256_shuffle_epi8(data, indices);\r
+ let mut out = [0_u8; 32];\r
+ mm::_mm256_storeu_si256(out.as_mut_ptr() as _, result);\r
+ write.write_all(&out)?;\r
+ }\r
+\r
+ let remainder = chunks.remainder();\r
+\r
+ { // copy remainder into larger slice, with zeroes at the end\r
+ let mut last_chunk = [0_u8; 32];\r
+ last_chunk[0..remainder.len()].copy_from_slice(remainder);\r
+ let data = mm::_mm256_loadu_si256(last_chunk.as_ptr() as _);\r
+ let result = mm::_mm256_shuffle_epi8(data, indices);\r
+ mm::_mm256_storeu_si256(last_chunk.as_mut_ptr() as _, result);\r
+ write.write_all(&last_chunk[0..remainder.len()])?;\r
+ }\r
+\r
+ Ok(())\r
+ }\r
+ }\r
+\r
+ else {\r
+ unsafe { bytes::write_slice(self, value)?; }\r
+ Ok(())\r
+ }\r
+ }\r
+\r
+ fn write_as_little_endian(&mut self, value: &[f32]) -> Result<()> {\r
+ for number in value {\r
+ self.write_as_little_endian(number)?;\r
+ }\r
+\r
+ Ok(())\r
+ }\r
+ }*/\r
+}\r
+\r
--- /dev/null
+extern crate lebe;\r
+\r
+use lebe::prelude::*;\r
+use std::mem;\r
+\r
+use byteorder::{WriteBytesExt, LittleEndian, BigEndian, ReadBytesExt};\r
+\r
+#[test]\r
+fn make_le_u32_slice() {\r
+ // as seen on https://doc.rust-lang.org/std/primitive.u32.html#method.to_le\r
+ let n = 0x1Au32;\r
+\r
+ let mut n_le = [n];\r
+ n_le.convert_current_to_little_endian();\r
+\r
+ if cfg!(target_endian = "little") {\r
+ assert_eq!(n_le, [n])\r
+ }\r
+ else {\r
+ assert_eq!(n_le, [u32::swap_bytes(n)])\r
+ }\r
+\r
+// assert_eq!(n_le, byteorder::LittleEndian::from_)\r
+}\r
+\r
+#[test]\r
+fn make_be_u32_slice() {\r
+ // as seen on https://doc.rust-lang.org/std/primitive.u32.html#method.to_be\r
+ let n = 0x1Au32;\r
+\r
+ let mut n_be = [n];\r
+ n_be.convert_current_to_big_endian();\r
+\r
+ if cfg!(target_endian = "big") {\r
+ assert_eq!(n_be, [n])\r
+ }\r
+ else {\r
+ assert_eq!(n_be, [n.swap_bytes()])\r
+ }\r
+}\r
+\r
+#[test]\r
+fn make_le_u16_slice() {\r
+ // as seen on https://doc.rust-lang.org/std/primitive.u16.html#method.to_le\r
+ let n = 0x1Au16;\r
+\r
+ let mut n_le = [n];\r
+ n_le.convert_current_to_little_endian();\r
+\r
+ if cfg!(target_endian = "little") {\r
+ assert_eq!(n_le, [n])\r
+ }\r
+ else {\r
+ assert_eq!(n_le, [n.swap_bytes()])\r
+ }\r
+}\r
+\r
+#[test]\r
+fn make_le_i64_slice() {\r
+ // as seen on https://doc.rust-lang.org/std/primitive.u64.html#method.to_be\r
+ let n1 = 0x14F3EEBCCD93895A_i64;\r
+ let n2 = 0x114F3EF99B81CC5A_i64;\r
+\r
+ let mut n_be = [n1, n2];\r
+ n_be.convert_current_to_big_endian();\r
+\r
+ if cfg!(target_endian = "big") {\r
+ assert_eq!(n_be, [n1, n2])\r
+ }\r
+ else {\r
+ assert_eq!(n_be, [n1.swap_bytes(), n2.swap_bytes()])\r
+ }\r
+}\r
+\r
+#[test]\r
+fn make_be_f64() {\r
+ let i = 0x14F3EEBCCD93895A_u64;\r
+\r
+ let mut f: f64 = unsafe { mem::transmute(i) };\r
+ f.convert_current_to_big_endian();\r
+\r
+ assert_eq!(f, unsafe { mem::transmute(i.to_be()) })\r
+}\r
+\r
+#[test]\r
+fn into_be_f64() {\r
+ let i = 0x14F3EEBCCD93895A_u64;\r
+\r
+ let f: f64 = unsafe { mem::transmute(i) };\r
+ let f = f.from_current_into_big_endian();\r
+\r
+ assert_eq!(f, unsafe { mem::transmute(i.to_be()) })\r
+}\r
+\r
+#[test]\r
+fn into_be_i16() {\r
+ let i = 0x195A_i16;\r
+ let be = i.from_current_into_big_endian();\r
+\r
+ if cfg!(target_endian = "big") {\r
+ assert_eq!(be, i)\r
+ }\r
+ else {\r
+ assert_eq!(be, i.swap_bytes())\r
+ }\r
+}\r
+\r
+#[test]\r
+fn into_be_u32() {\r
+ let i = 0x1220943_u32;\r
+ let be = i.from_current_into_big_endian();\r
+\r
+ if cfg!(target_endian = "big") {\r
+ assert_eq!(be, i)\r
+ }\r
+ else {\r
+ assert_eq!(be, i.swap_bytes())\r
+ }\r
+}\r
+\r
+#[test]\r
+fn cmp_read_be_u16() {\r
+ let read: &[u8] = &[0x33, 0xbb];\r
+ let a = u16::read_from_big_endian(&mut read.clone()).unwrap();\r
+ let b: u16 = read.clone().read_from_big_endian().unwrap();\r
+ let c = read.clone().read_u16::<BigEndian>().unwrap();\r
+\r
+ assert_eq!(a, b);\r
+ assert_eq!(a, c);\r
+}\r
+\r
+#[test]\r
+fn cmp_read_le_u16() {\r
+ let read: &[u8] = &[0x33, 0xbb];\r
+ let a = u16::read_from_little_endian(&mut read.clone()).unwrap();\r
+ let b: u16 = read.clone().read_from_little_endian().unwrap();\r
+ let c = read.clone().read_u16::<LittleEndian>().unwrap();\r
+\r
+ assert_eq!(a, b);\r
+ assert_eq!(a, c);\r
+}\r
+\r
+#[test]\r
+fn cmp_read_le_f32() {\r
+ let read: &[u8] = &[0x33, 0xBB, 0x44, 0xCC];\r
+ let a = f32::read_from_little_endian(&mut read.clone()).unwrap();\r
+ let b: f32 = read.clone().read_from_little_endian().unwrap();\r
+ let c = read.clone().read_f32::<LittleEndian>().unwrap();\r
+\r
+ assert_eq!(a, b);\r
+ assert_eq!(a, c);\r
+}\r
+\r
+#[test]\r
+fn cmp_read_be_slice() {\r
+ let mut write_expected = Vec::new();\r
+ let mut write_actual = Vec::new();\r
+\r
+ let data: Vec<f32> = (0..31*31).map(|i| i as f32).collect();\r
+\r
+ for number in &data {\r
+ write_expected.write_f32::<BigEndian>(*number).unwrap();\r
+ }\r
+\r
+ write_actual.write_as_big_endian(data.as_slice()).unwrap();\r
+ assert_eq!(write_actual, write_expected);\r
+}\r
+\r
+#[test]\r
+fn cmp_write_le_slice() {\r
+ let mut write_expected = Vec::new();\r
+ let mut write_actual = Vec::new();\r
+\r
+ let data: Vec<f32> = (0..31*31).map(|i| i as f32).collect();\r
+\r
+ for number in &data {\r
+ write_expected.write_f32::<LittleEndian>(*number).unwrap();\r
+ }\r
+\r
+ write_actual.write_as_little_endian(data.as_slice()).unwrap();\r
+\r
+ assert_eq!(write_actual, write_expected);\r
+}\r
+\r
+#[test]\r
+fn cmp_write_le_u32() {\r
+ let mut write_expected = Vec::new();\r
+ let mut write_actual = Vec::new();\r
+\r
+ let data = 0x23573688_u32;\r
+ write_expected.write_u32::<LittleEndian>(data).unwrap();\r
+ write_actual.write_as_little_endian(&data).unwrap();\r
+\r
+ assert_eq!(write_actual, write_expected);\r
+}\r
+\r
+\r
+\r
+#[test]\r
+fn cmp_write_le_slice_u64() {\r
+ let mut write_expected = Vec::new();\r
+ let mut write_actual = Vec::new();\r
+\r
+ let data: Vec<u64> = (1000..1000+310*31).map(|i| i as u64).collect();\r
+\r
+ for number in &data {\r
+ write_expected.write_u64::<LittleEndian>(*number).unwrap();\r
+ }\r
+\r
+ write_actual.write_as_little_endian(data.as_slice()).unwrap();\r
+\r
+ assert_eq!(write_actual, write_expected);\r
+}
\ No newline at end of file