Repository: BurntSushi/byteorder (language: rust)

Issue:
Release 1.0.1 with i128 feature
It would be nice if we could change our git dependencies to version dependencies on crates.io
Would it make sense to add copy_from_slice() like functions?
I use byteorder in my rawloader crate to read binary files with specific orderings. For example here's the code to read 16bit unpacked little-endian:

https://github.com/pedrocr/rawloader/blob/8f1a100e8f8d611efabd3c14db8e5050e9f0ebbe/src/decoders/basics.rs#L376-L384

On little-endian machines this could just be a memcpy. Currently rustc isn't able to optimize loops into memcpy but maybe it would make sense to have an explicit API for this inside byteorder, the same way copy_from_slice already allows that in standard types. That way I could call a LittleEndian::read_u16s(from, to, n) function in byteorder and if the architecture matches it does a memcpy, if not does a loop or even uses a BSWAP instruction. Would that make sense as part of the scope for this crate?


Discussion / hints:

I think I'd be open to this, and it seems like it could be implemented purely in new default methods on the `ByteOrder` trait so that there wouldn't be any breaking changes.

What are the downsides of these APIs? Do endian encoding/decoding libraries in other languages have an analogous API?
I don't think it can be done through existing methods in zero-cost fashion. Will it surely break backward compatibility if we add new required methods, implemented by both enums? If yes, then we'll have to introduce additional trait, something like `ByteOrderSliceExt`.

I will create PR with the draft shortly.
I think we want the `ByteOrder` trait to be sealed, so adding new required methods should be fine.

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index b6dbd0a..4c52744 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,3 +17,6 @@ script:
       cargo bench --verbose --features i128;
       cargo bench --verbose --no-default-features --features i128;
     fi
+branches:
+  only:
+    - master
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..0909791
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,36 @@
+1.1.0
+=====
+This release of `byteorder` features a number of fixes and improvements, mostly
+as a result of the
+[Litz Blitz evaluation](https://public.etherpad-mozilla.org/p/rust-crate-eval-byteorder).
+
+Feature enhancements:
+
+* [FEATURE #63](https://github.com/BurntSushi/byteorder/issues/63):
+  Add methods for reading/writing slices of numbers for a specific
+  endianness.
+* [FEATURE #65](https://github.com/BurntSushi/byteorder/issues/65):
+  Add support for `u128`/`i128` types. (Behind the nightly only `i128`
+  feature.)
+* [FEATURE #72](https://github.com/BurntSushi/byteorder/issues/72):
+  Add "panics" and "errors" sections for each relevant public API item.
+* [FEATURE #74](https://github.com/BurntSushi/byteorder/issues/74):
+  Add CI badges to Cargo.toml.
+* [FEATURE #75](https://github.com/BurntSushi/byteorder/issues/75):
+  Add more examples to public API items.
+* Add 24-bit read/write methods.
+* Add `BE` and `LE` type aliases for `BigEndian` and `LittleEndian`,
+  respectively.
+
+Bug fixes:
+
+* [BUG #68](https://github.com/BurntSushi/byteorder/issues/68):
+  Panic in {BigEndian,LittleEndian}::default.
+* [BUG #69](https://github.com/BurntSushi/byteorder/issues/69):
+  Seal the `ByteOrder` trait to prevent out-of-crate implementations.
+* [BUG #71](https://github.com/BurntSushi/byteorder/issues/71):
+  Guarantee that the results of `read_f32`/`read_f64` are always defined.
+* [BUG #73](https://github.com/BurntSushi/byteorder/issues/73):
+  Add crates.io categories.
+* [BUG #77](https://github.com/BurntSushi/byteorder/issues/77):
+  Add `html_root` doc attribute.
diff --git a/benches/bench.rs b/benches/bench.rs
index c03c5c2..845e489 100644
--- a/benches/bench.rs
+++ b/benches/bench.rs
@@ -2,6 +2,7 @@
 #![feature(test)]
 
 extern crate byteorder;
+extern crate rand;
 extern crate test;
 
 macro_rules! bench_num {
@@ -252,3 +253,68 @@ bench_num!(int128_15, read_int128,
 #[cfg(feature = "i128")]
 bench_num!(int128_16, read_int128,
     16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+
+
+macro_rules! bench_slice {
+    ($name:ident, $numty:ty, $read:ident, $write:ident) => {
+        mod $name {
+            use std::mem::size_of;
+
+            use byteorder::{ByteOrder, BigEndian, LittleEndian};
+            use rand::{self, Rng};
+            use test::Bencher;
+
+            #[bench]
+            fn read_big_endian(b: &mut Bencher) {
+                let mut numbers: Vec<$numty> =
+                    rand::thread_rng().gen_iter().take(100000).collect();
+                let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
+                BigEndian::$write(&numbers, &mut bytes);
+
+                b.bytes = bytes.len() as u64;
+                b.iter(|| {
+                    BigEndian::$read(&bytes, &mut numbers);
+                });
+            }
+
+            #[bench]
+            fn read_little_endian(b: &mut Bencher) {
+                let mut numbers: Vec<$numty> =
+                    rand::thread_rng().gen_iter().take(100000).collect();
+                let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
+                LittleEndian::$write(&numbers, &mut bytes);
+
+                b.bytes = bytes.len() as u64;
+                b.iter(|| {
+                    LittleEndian::$read(&bytes, &mut numbers);
+                });
+            }
+
+            #[bench]
+            fn write_big_endian(b: &mut Bencher) {
+                let numbers: Vec<$numty> =
+                    rand::thread_rng().gen_iter().take(100000).collect();
+                let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
+
+                b.bytes = bytes.len() as u64;
+                b.iter(|| {
+                    BigEndian::$write(&numbers, &mut bytes);
+                });
+            }
+
+            #[bench]
+            fn write_little_endian(b: &mut Bencher) {
+                let numbers: Vec<$numty> =
+                    rand::thread_rng().gen_iter().take(100000).collect();
+                let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
+
+                b.bytes = bytes.len() as u64;
+                b.iter(|| {
+                    LittleEndian::$write(&numbers, &mut bytes);
+                });
+            }
+        }
+    }
+}
+
+bench_slice!(slice_u64, u64, read_u64_into, write_u64_into);
diff --git a/src/new.rs b/src/io.rs
similarity index 63%
rename from src/new.rs
rename to src/io.rs
index 1650823..208596a 100644
--- a/src/new.rs
+++ b/src/io.rs
@@ -1,4 +1,6 @@
 use std::io::{self, Result};
+use std::slice;
+// use std::mem::transmute;
 
 use ByteOrder;
 
@@ -431,12 +433,16 @@ pub trait ReadBytesExt: io::Read {
     /// Read a big-endian single-precision floating point number from a `Read`:
     ///
     /// ```rust
+    /// use std::f32;
     /// use std::io::Cursor;
+    ///
     /// use byteorder::{BigEndian, ReadBytesExt};
-    /// use std::f32::consts;
     ///
-    /// let mut rdr = Cursor::new(vec![0x40, 0x49, 0x0f, 0xdb]);
-    /// assert_eq!(consts::PI, rdr.read_f32::<BigEndian>().unwrap());
+    /// let mut rdr = Cursor::new(vec![
+    ///     0x40, 0x49, 0x0f, 0xdb,
+    /// ]);
+    /// assert_eq!(f32::consts::PI, rdr.read_f32::<BigEndian>().unwrap());
+    /// ```
     #[inline]
     fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
         let mut buf = [0; 4];
@@ -446,7 +452,6 @@ pub trait ReadBytesExt: io::Read {
 
     /// Reads a IEEE754 double-precision (8 bytes) floating point number from
     /// the underlying reader.
-    #[inline]
     ///
     /// # Errors
     ///
@@ -459,17 +464,426 @@ pub trait ReadBytesExt: io::Read {
     /// Read a big-endian double-precision floating point number from a `Read`:
     ///
     /// ```rust
+    /// use std::f64;
     /// use std::io::Cursor;
+    ///
     /// use byteorder::{BigEndian, ReadBytesExt};
-    /// use std::f64::consts;
     ///
-    /// let mut rdr = Cursor::new(vec![0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18]);
-    /// assert_eq!(consts::PI, rdr.read_f64::<BigEndian>().unwrap());
+    /// let mut rdr = Cursor::new(vec![
+    ///     0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18,
+    /// ]);
+    /// assert_eq!(f64::consts::PI, rdr.read_f64::<BigEndian>().unwrap());
+    /// ```
+    #[inline]
     fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
         let mut buf = [0; 8];
         try!(self.read_exact(&mut buf));
         Ok(T::read_f64(&buf))
     }
+
+    /// Reads a sequence of unsigned 16 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of unsigned 16 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_u16_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[inline]
+    fn read_u16_into<T: ByteOrder>(&mut self, dst: &mut [u16]) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_u16(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of unsigned 32 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of unsigned 32 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![0, 0, 2, 5, 0, 0, 3, 0]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_u32_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[inline]
+    fn read_u32_into<T: ByteOrder>(&mut self, dst: &mut [u32]) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_u32(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of unsigned 64 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of unsigned 64 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![
+    ///     0, 0, 0, 0, 0, 0, 2, 5,
+    ///     0, 0, 0, 0, 0, 0, 3, 0,
+    /// ]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_u64_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[inline]
+    fn read_u64_into<T: ByteOrder>(&mut self, dst: &mut [u64]) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_u64(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of unsigned 128 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of unsigned 128 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![
+    ///     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5,
+    ///     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+    /// ]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_u128_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn read_u128_into<T: ByteOrder>(
+        &mut self,
+        dst: &mut [u128],
+    ) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_u128(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of signed 16 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of signed 16 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_i16_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[inline]
+    fn read_i16_into<T: ByteOrder>(&mut self, dst: &mut [i16]) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_i16(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of signed 32 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of signed 32 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![0, 0, 2, 5, 0, 0, 3, 0]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_i32_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[inline]
+    fn read_i32_into<T: ByteOrder>(&mut self, dst: &mut [i32]) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_i32(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of signed 64 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of signed 64 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![
+    ///     0, 0, 0, 0, 0, 0, 2, 5,
+    ///     0, 0, 0, 0, 0, 0, 3, 0,
+    /// ]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_i64_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[inline]
+    fn read_i64_into<T: ByteOrder>(&mut self, dst: &mut [i64]) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_i64(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of signed 128 bit integers from the underlying
+    /// reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of signed 128 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![
+    ///     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5,
+    ///     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+    /// ]);
+    /// let mut dst = [0; 2];
+    /// rdr.read_i128_into::<BigEndian>(&mut dst).unwrap();
+    /// assert_eq!([517, 768], dst);
+    /// ```
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn read_i128_into<T: ByteOrder>(
+        &mut self,
+        dst: &mut [i128],
+    ) -> Result<()> {
+        {
+            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_i128(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of IEEE754 single-precision (4 bytes) floating
+    /// point numbers from the underlying reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Safety
+    ///
+    /// This method is unsafe because there are no guarantees made about the
+    /// floating point values. In particular, this method does not check for
+    /// signaling NaNs, which may result in undefined behavior.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of big-endian single-precision floating point number
+    /// from a `Read`:
+    ///
+    /// ```rust
+    /// use std::f32;
+    /// use std::io::Cursor;
+    ///
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![
+    ///     0x40, 0x49, 0x0f, 0xdb,
+    ///     0x3f, 0x80, 0x00, 0x00,
+    /// ]);
+    /// let mut dst = [0.0; 2];
+    /// unsafe {
+    ///     rdr.read_f32_into_unchecked::<BigEndian>(&mut dst).unwrap();
+    /// }
+    /// assert_eq!([f32::consts::PI, 1.0], dst);
+    /// ```
+    #[inline]
+    unsafe fn read_f32_into_unchecked<T: ByteOrder>(
+        &mut self,
+        dst: &mut [f32],
+    ) -> Result<()> {
+        {
+            let mut buf = slice_to_u8_mut(dst);
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_f32(dst);
+        Ok(())
+    }
+
+    /// Reads a sequence of IEEE754 double-precision (8 bytes) floating
+    /// point numbers from the underlying reader.
+    ///
+    /// The given buffer is either filled completely or an error is returned.
+    /// If an error is returned, the contents of `dst` are unspecified.
+    ///
+    /// # Safety
+    ///
+    /// This method is unsafe because there are no guarantees made about the
+    /// floating point values. In particular, this method does not check for
+    /// signaling NaNs, which may result in undefined behavior.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read a sequence of big-endian single-precision floating point number
+    /// from a `Read`:
+    ///
+    /// ```rust
+    /// use std::f64;
+    /// use std::io::Cursor;
+    ///
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![
+    ///     0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18,
+    ///     0x3f, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /// ]);
+    /// let mut dst = [0.0; 2];
+    /// unsafe {
+    ///     rdr.read_f64_into_unchecked::<BigEndian>(&mut dst).unwrap();
+    /// }
+    /// assert_eq!([f64::consts::PI, 1.0], dst);
+    /// ```
+    #[inline]
+    unsafe fn read_f64_into_unchecked<T: ByteOrder>(
+        &mut self,
+        dst: &mut [f64],
+    ) -> Result<()> {
+        {
+            let mut buf = slice_to_u8_mut(dst);
+            try!(self.read_exact(buf));
+        }
+        T::from_slice_f64(dst);
+        Ok(())
+    }
 }
 
 /// All types that implement `Read` get methods defined in `ReadBytesExt`
@@ -761,3 +1175,15 @@ pub trait WriteBytesExt: io::Write {
 /// All types that implement `Write` get methods defined in `WriteBytesExt`
 /// for free.
 impl<W: io::Write + ?Sized> WriteBytesExt for W {}
+
+/// Convert a slice of T (where T is plain old data) to its mutable binary
+/// representation.
+///
+/// This function is wildly unsafe because it permits arbitrary modification of
+/// the binary representation of any `Copy` type. Use with care.
+unsafe fn slice_to_u8_mut<T: Copy>(slice: &mut [T]) -> &mut [u8] {
+    use std::mem::size_of;
+
+    let len = size_of::<T>() * slice.len();
+    slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut u8, len)
+}
diff --git a/src/lib.rs b/src/lib.rs
index 7b86779..b60fe7c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -51,10 +51,10 @@ use core::mem::transmute;
 use core::ptr::copy_nonoverlapping;
 
 #[cfg(feature = "std")]
-pub use new::{ReadBytesExt, WriteBytesExt};
+pub use io::{ReadBytesExt, WriteBytesExt};
 
 #[cfg(feature = "std")]
-mod new;
+mod io;
 
 #[inline]
 fn extend_sign(val: u64, nbytes: usize) -> i64 {
@@ -142,7 +142,8 @@ fn pack_size128(n: u128) -> usize {
 }
 
 mod private {
-    /// Sealed stops crates other than byteorder from implementing any traits that use it.
+    /// Sealed stops crates other than byteorder from implementing any traits
+    /// that use it.
     pub trait Sealed{}
     impl Sealed for super::LittleEndian {}
     impl Sealed for super::BigEndian {}
@@ -181,7 +182,9 @@ mod private {
 /// assert_eq!(-50_000, BigEndian::read_i16(&buf));
 /// ```
 pub trait ByteOrder
-    : Clone + Copy + Debug + Default + Eq + Hash + Ord + PartialEq + PartialOrd + private::Sealed {
+    : Clone + Copy + Debug + Default + Eq + Hash + Ord + PartialEq + PartialOrd
+    + private::Sealed
+{
     /// Reads an unsigned 16 bit integer from `buf`.
     ///
     /// # Panics
@@ -608,7 +611,8 @@ pub trait ByteOrder
 
     /// Reads a IEEE754 single-precision (4 bytes) floating point number.
     ///
-    /// The return value is always defined; signaling NaN's may be turned into quiet NaN's.
+    /// The return value is always defined; signaling NaN's may be turned into
+    /// quiet NaN's.
     ///
     /// # Panics
     ///
@@ -633,7 +637,8 @@ pub trait ByteOrder
 
     /// Reads a IEEE754 double-precision (8 bytes) floating point number.
     ///
-    /// The return value is always defined; signaling NaN's may be turned into quiet NaN's.
+    /// The return value is always defined; signaling NaN's may be turned into
+    /// quiet NaN's.
     ///
     /// # Panics
     ///
@@ -859,6 +864,748 @@ pub trait ByteOrder
     fn write_f64(buf: &mut [u8], n: f64) {
         Self::write_u64(buf, unsafe { transmute(n) })
     }
+
+    /// Reads unsigned 16 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 2*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u16` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 8];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u16_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u16_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn read_u16_into(src: &[u8], dst: &mut [u16]);
+
+    /// Reads unsigned 32 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 4*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u32` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 16];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u32_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u32_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn read_u32_into(src: &[u8], dst: &mut [u32]);
+
+    /// Reads unsigned 64 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 8*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 32];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u64_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u64_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn read_u64_into(src: &[u8], dst: &mut [u64]);
+
+    /// Reads unsigned 128 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 16*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u128` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 64];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u128_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[cfg(feature = "i128")]
+    fn read_u128_into(src: &[u8], dst: &mut [u128]);
+
+    /// Reads signed 16 bit integers from `src` to `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `buf.len() != 2*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i16` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 8];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i16_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i16_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[inline]
+    fn read_i16_into(src: &[u8], dst: &mut [i16]) {
+        Self::read_u16_into(src, unsafe { transmute(dst) });
+    }
+
+    /// Reads signed 32 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 4*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i32` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 16];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i32_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i32_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[inline]
+    fn read_i32_into(src: &[u8], dst: &mut [i32]) {
+        Self::read_u32_into(src, unsafe { transmute(dst) });
+    }
+
+    /// Reads signed 64 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 8*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 32];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i64_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i64_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[inline]
+    fn read_i64_into(src: &[u8], dst: &mut [i64]) {
+        Self::read_u64_into(src, unsafe { transmute(dst) });
+    }
+
+    /// Reads signed 128 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 16*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i128` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 64];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i128_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn read_i128_into(src: &[u8], dst: &mut [i128]) {
+        Self::read_u128_into(src, unsafe { transmute(dst) });
+    }
+
+    /// Reads IEEE754 single-precision (4 bytes) floating point numbers from
+    /// `src` into `dst`.
+    ///
+    /// Note that this does not perform any checks on the floating point
+    /// conversion. In particular, if the `src` data encodes an undefined
+    /// floating point value for your environment, then the result may be
+    /// undefined behavior. For example, this function may produce signaling
+    /// NaN floating point values.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 4*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `f32` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 16];
+    /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
+    /// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0.0; 4];
+    /// unsafe {
+    ///     LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got);
+    /// }
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[inline]
+    unsafe fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) {
+        Self::read_u32_into(src, transmute(dst));
+    }
+
+    /// Reads IEEE754 single-precision (4 bytes) floating point numbers from
+    /// `src` into `dst`.
+    ///
+    /// Note that this does not perform any checks on the floating point
+    /// conversion. In particular, if the `src` data encodes an undefined
+    /// floating point value for your environment, then the result may be
+    /// undefined behavior. For example, this function may produce signaling
+    /// NaN floating point values.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 8*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `f64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 32];
+    /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
+    /// LittleEndian::write_f64_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0.0; 4];
+    /// unsafe {
+    ///     LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got);
+    /// }
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[inline]
+    unsafe fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) {
+        Self::read_u64_into(src, transmute(dst));
+    }
+
+    /// Writes unsigned 16 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 2*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u16` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 8];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u16_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u16_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_u16_into(src: &[u16], dst: &mut [u8]);
+
+    /// Writes unsigned 32 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 4*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u32` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 16];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u32_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u32_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_u32_into(src: &[u32], dst: &mut [u8]);
+
+    /// Writes unsigned 64 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 8*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 32];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u64_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u64_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_u64_into(src: &[u64], dst: &mut [u8]);
+
+    /// Writes unsigned 128 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 16*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `u128` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 64];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_u128_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[cfg(feature = "i128")]
+    fn write_u128_into(src: &[u128], dst: &mut [u8]);
+
+    /// Writes signed 16 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `buf.len() != 2*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i16` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 8];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i16_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i16_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_i16_into(src: &[i16], dst: &mut [u8]) {
+        Self::write_u16_into(unsafe { transmute(src) }, dst);
+    }
+
+    /// Writes signed 32 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 4*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i32` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 16];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i32_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i32_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_i32_into(src: &[i32], dst: &mut [u8]) {
+        Self::write_u32_into(unsafe { transmute(src) }, dst);
+    }
+
+    /// Writes signed 64 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 8*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 32];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i64_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i64_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_i64_into(src: &[i64], dst: &mut [u8]) {
+        Self::write_u64_into(unsafe { transmute(src) }, dst);
+    }
+
+    /// Writes signed 128 bit integers from `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `dst.len() != 16*src.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `i128` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 64];
+    /// let numbers_given = [1, 2, 0xf00f, 0xffee];
+    /// LittleEndian::write_i128_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0; 4];
+    /// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    #[cfg(feature = "i128")]
+    fn write_i128_into(src: &[i128], dst: &mut [u8]) {
+        Self::write_u128_into(unsafe { transmute(src) }, dst);
+    }
+
+    /// Writes IEEE754 single-precision (4 bytes) floating point numbers from
+    /// `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 4*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `f32` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 16];
+    /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
+    /// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0.0; 4];
+    /// unsafe {
+    ///     LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got);
+    /// }
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_f32_into(src: &[f32], dst: &mut [u8]) {
+        Self::write_u32_into(unsafe { transmute(src) }, dst);
+    }
+
+    /// Writes IEEE754 double-precision (8 bytes) floating point numbers from
+    /// `src` into `dst`.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `src.len() != 8*dst.len()`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read `f64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut bytes = [0; 32];
+    /// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
+    /// LittleEndian::write_f64_into(&numbers_given, &mut bytes);
+    ///
+    /// let mut numbers_got = [0.0; 4];
+    /// unsafe {
+    ///     LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got);
+    /// }
+    /// assert_eq!(numbers_given, numbers_got);
+    /// ```
+    fn write_f64_into(src: &[f64], dst: &mut [u8]) {
+        Self::write_u64_into(unsafe { transmute(src) }, dst);
+    }
+
+    /// Converts the given slice of unsigned 16 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_u16(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5u16.swap_bytes(), 65000u16.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    fn from_slice_u16(numbers: &mut [u16]);
+
+    /// Converts the given slice of unsigned 32 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_u32(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5u32.swap_bytes(), 65000u32.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    fn from_slice_u32(numbers: &mut [u32]);
+
+    /// Converts the given slice of unsigned 64 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_u64(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5u64.swap_bytes(), 65000u64.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    fn from_slice_u64(numbers: &mut [u64]);
+
+    /// Converts the given slice of unsigned 128 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// #![feature(i128_type)]
+    ///
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_u128(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5u128.swap_bytes(), 65000u128.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    #[cfg(feature = "i128")]
+    fn from_slice_u128(numbers: &mut [u128]);
+
+    /// Converts the given slice of signed 16 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_i16(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5i16.swap_bytes(), 65000i16.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    #[inline]
+    fn from_slice_i16(numbers: &mut [i16]) {
+        Self::from_slice_u16(unsafe { transmute(numbers) });
+    }
+
+    /// Converts the given slice of signed 32 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_i32(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5i32.swap_bytes(), 65000i32.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    #[inline]
+    fn from_slice_i32(numbers: &mut [i32]) {
+        Self::from_slice_u32(unsafe { transmute(numbers) });
+    }
+
+    /// Converts the given slice of signed 64 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_i64(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5i64.swap_bytes(), 65000i64.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    #[inline]
+    fn from_slice_i64(numbers: &mut [i64]) {
+        Self::from_slice_u64(unsafe { transmute(numbers) });
+    }
+
+    /// Converts the given slice of signed 128 bit integers to a particular
+    /// endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// # Examples
+    ///
+    /// Convert the host platform's endianness to big-endian:
+    ///
+    /// ```rust
+    /// #![feature(i128_type)]
+    ///
+    /// use byteorder::{ByteOrder, BigEndian};
+    ///
+    /// let mut numbers = [5, 65000];
+    /// BigEndian::from_slice_i128(&mut numbers);
+    /// if cfg!(target_endian = "little") {
+    ///     assert_eq!(numbers, [5i128.swap_bytes(), 65000i128.swap_bytes()]);
+    /// } else {
+    ///     assert_eq!(numbers, [5, 65000]);
+    /// }
+    /// ```
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn from_slice_i128(numbers: &mut [i128]) {
+        Self::from_slice_u128(unsafe { transmute(numbers) });
+    }
+
+    /// Converts the given slice of IEEE754 single-precision (4 bytes) floating
+    /// point numbers to a particular endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// Note that the results of this operation are guaranteed to be defined.
+    /// In particular, this method may replace signaling NaN values with
+    /// quiet NaN values.
+    fn from_slice_f32(numbers: &mut [f32]);
+
+    /// Converts the given slice of IEEE754 double-precision (8 bytes) floating
+    /// point numbers to a particular endianness.
+    ///
+    /// If the endianness matches the endianness of the host platform, then
+    /// this is a no-op.
+    ///
+    /// Note that the results of this operation are guaranteed to be defined.
+    /// In particular, this method may replace signaling NaN values with
+    /// quiet NaN values.
+    fn from_slice_f64(numbers: &mut [f64]);
 }
 
 /// Defines big-endian serialization.
@@ -886,6 +1633,9 @@ impl Default for BigEndian {
     }
 }
 
+/// A type alias for `BigEndian`.
+pub type BE = BigEndian;
+
 /// Defines little-endian serialization.
 ///
 /// Note that this type has no value constructor. It is used purely at the
@@ -911,6 +1661,9 @@ impl Default for LittleEndian {
     }
 }
 
+/// A type alias for `LittleEndian`.
+pub type LE = LittleEndian;
+
 /// Defines network byte order serialization.
 ///
 /// Network byte order is defined by [RFC 1700][1] to be big-endian, and is
@@ -975,6 +1728,47 @@ macro_rules! write_num_bytes {
     });
 }
 
+macro_rules! read_slice {
+    ($src:expr, $dst:expr, $size:expr, $which:ident) => {{
+        assert_eq!($src.len(), $size * $dst.len());
+
+        unsafe {
+            copy_nonoverlapping(
+                $src.as_ptr(),
+                $dst.as_mut_ptr() as *mut u8,
+                $src.len());
+        }
+        for v in $dst.iter_mut() {
+            *v = v.$which();
+        }
+    }};
+}
+
+macro_rules! write_slice_native {
+    ($src:expr, $dst:expr, $ty:ty, $size:expr) => {{
+        assert!($size == ::core::mem::size_of::<$ty>());
+        assert_eq!($size * $src.len(), $dst.len());
+
+        unsafe {
+            copy_nonoverlapping(
+                $src.as_ptr() as *const u8,
+                $dst.as_mut_ptr(),
+                $dst.len());
+        }
+    }};
+}
+
+macro_rules! write_slice {
+    ($src:expr, $dst:expr, $ty:ty, $size:expr, $write:expr) => ({
+        assert!($size == ::core::mem::size_of::<$ty>());
+        assert_eq!($size * $src.len(), $dst.len());
+
+        for (&n, chunk) in $src.iter().zip($dst.chunks_mut($size)) {
+            $write(chunk, n);
+        }
+    });
+}
+
 impl ByteOrder for BigEndian {
     #[inline]
     fn read_u16(buf: &[u8]) -> u16 {
@@ -1069,6 +1863,121 @@ impl ByteOrder for BigEndian {
                 nbytes);
         }
     }
+
+    #[inline]
+    fn read_u16_into(src: &[u8], dst: &mut [u16]) {
+        read_slice!(src, dst, 2, to_be);
+    }
+
+    #[inline]
+    fn read_u32_into(src: &[u8], dst: &mut [u32]) {
+        read_slice!(src, dst, 4, to_be);
+    }
+
+    #[inline]
+    fn read_u64_into(src: &[u8], dst: &mut [u64]) {
+        read_slice!(src, dst, 8, to_be);
+    }
+
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn read_u128_into(src: &[u8], dst: &mut [u128]) {
+        read_slice!(src, dst, 16, to_be);
+    }
+
+    #[inline]
+    fn write_u16_into(src: &[u16], dst: &mut [u8]) {
+        if cfg!(target_endian = "big") {
+            write_slice_native!(src, dst, u16, 2);
+        } else {
+            write_slice!(src, dst, u16, 2, Self::write_u16);
+        }
+    }
+
+    #[inline]
+    fn write_u32_into(src: &[u32], dst: &mut [u8]) {
+        if cfg!(target_endian = "big") {
+            write_slice_native!(src, dst, u32, 4);
+        } else {
+            write_slice!(src, dst, u32, 4, Self::write_u32);
+        }
+    }
+
+    #[inline]
+    fn write_u64_into(src: &[u64], dst: &mut [u8]) {
+        if cfg!(target_endian = "big") {
+            write_slice_native!(src, dst, u64, 8);
+        } else {
+            write_slice!(src, dst, u64, 8, Self::write_u64);
+        }
+    }
+
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn write_u128_into(src: &[u128], dst: &mut [u8]) {
+        if cfg!(target_endian = "big") {
+            write_slice_native!(src, dst, u128, 16);
+        } else {
+            write_slice!(src, dst, u128, 16, Self::write_u128);
+        }
+    }
+
+    #[inline]
+    fn from_slice_u16(numbers: &mut [u16]) {
+        if cfg!(target_endian = "little") {
+            for n in numbers {
+                *n = n.to_be();
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_u32(numbers: &mut [u32]) {
+        if cfg!(target_endian = "little") {
+            for n in numbers {
+                *n = n.to_be();
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_u64(numbers: &mut [u64]) {
+        if cfg!(target_endian = "little") {
+            for n in numbers {
+                *n = n.to_be();
+            }
+        }
+    }
+
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn from_slice_u128(numbers: &mut [u128]) {
+        if cfg!(target_endian = "little") {
+            for n in numbers {
+                *n = n.to_be();
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_f32(numbers: &mut [f32]) {
+        if cfg!(target_endian = "little") {
+            for n in numbers {
+                let int: u32 = unsafe { transmute(*n) };
+                *n = safe_u32_bits_to_f32(int.to_be());
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_f64(numbers: &mut [f64]) {
+        if cfg!(target_endian = "little") {
+            for n in numbers {
+                let int: u64 = unsafe { transmute(*n) };
+                *n = safe_u64_bits_to_f64(int.to_be());
+            }
+        }
+    }
 }
 
 impl ByteOrder for LittleEndian {
@@ -1157,6 +2066,121 @@ impl ByteOrder for LittleEndian {
             copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes);
         }
     }
+
+    #[inline]
+    fn read_u16_into(src: &[u8], dst: &mut [u16]) {
+        read_slice!(src, dst, 2, to_le);
+    }
+
+    #[inline]
+    fn read_u32_into(src: &[u8], dst: &mut [u32]) {
+        read_slice!(src, dst, 4, to_le);
+    }
+
+    #[inline]
+    fn read_u64_into(src: &[u8], dst: &mut [u64]) {
+        read_slice!(src, dst, 8, to_le);
+    }
+
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn read_u128_into(src: &[u8], dst: &mut [u128]) {
+        read_slice!(src, dst, 16, to_le);
+    }
+
+    #[inline]
+    fn write_u16_into(src: &[u16], dst: &mut [u8]) {
+        if cfg!(target_endian = "little") {
+            write_slice_native!(src, dst, u16, 2);
+        } else {
+            write_slice!(src, dst, u16, 2, Self::write_u16);
+        }
+    }
+
+    #[inline]
+    fn write_u32_into(src: &[u32], dst: &mut [u8]) {
+        if cfg!(target_endian = "little") {
+            write_slice_native!(src, dst, u32, 4);
+        } else {
+            write_slice!(src, dst, u32, 4, Self::write_u32);
+        }
+    }
+
+    #[inline]
+    fn write_u64_into(src: &[u64], dst: &mut [u8]) {
+        if cfg!(target_endian = "little") {
+            write_slice_native!(src, dst, u64, 8);
+        } else {
+            write_slice!(src, dst, u64, 8, Self::write_u64);
+        }
+    }
+
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn write_u128_into(src: &[u128], dst: &mut [u8]) {
+        if cfg!(target_endian = "little") {
+            write_slice_native!(src, dst, u128, 16);
+        } else {
+            write_slice!(src, dst, u128, 16, Self::write_u128);
+        }
+    }
+
+    #[inline]
+    fn from_slice_u16(numbers: &mut [u16]) {
+        if cfg!(target_endian = "big") {
+            for n in numbers {
+                *n = n.to_le();
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_u32(numbers: &mut [u32]) {
+        if cfg!(target_endian = "big") {
+            for n in numbers {
+                *n = n.to_le();
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_u64(numbers: &mut [u64]) {
+        if cfg!(target_endian = "big") {
+            for n in numbers {
+                *n = n.to_le();
+            }
+        }
+    }
+
+    #[cfg(feature = "i128")]
+    #[inline]
+    fn from_slice_u128(numbers: &mut [u128]) {
+        if cfg!(target_endian = "big") {
+            for n in numbers {
+                *n = n.to_le();
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_f32(numbers: &mut [f32]) {
+        if cfg!(target_endian = "big") {
+            for n in numbers {
+                let int: u32 = unsafe { transmute(*n) };
+                *n = safe_u32_bits_to_f32(int.to_le());
+            }
+        }
+    }
+
+    #[inline]
+    fn from_slice_f64(numbers: &mut [f64]) {
+        if cfg!(target_endian = "big") {
+            for n in numbers {
+                let int: u64 = unsafe { transmute(*n) };
+                *n = safe_u64_bits_to_f64(int.to_le());
+            }
+        }
+    }
 }
 
 #[inline]
@@ -1202,9 +2226,9 @@ mod test {
     extern crate quickcheck;
     extern crate rand;
 
-    use self::rand::thread_rng;
     use self::quickcheck::{QuickCheck, StdGen, Testable};
-    #[cfg(feature = "i128")] use self::quickcheck::{ Arbitrary, Gen };
+    use self::rand::thread_rng;
+    #[cfg(feature = "i128")] use self::quickcheck::{Arbitrary, Gen};
 
     pub const U24_MAX: u32 = 16_777_215;
     pub const I24_MAX: i32 = 8_388_607;
@@ -1668,6 +2692,104 @@ mod test {
     #[cfg(feature = "i128")]
     too_small!(small_int128_15, 15, read_int128);
 
+    // Test that reading/writing slices enforces the correct lengths.
+    macro_rules! slice_lengths {
+        ($name:ident, $read:ident, $write:ident,
+         $num_bytes:expr, $numbers:expr) => {
+            mod $name {
+                use {ByteOrder, BigEndian, NativeEndian, LittleEndian};
+
+                #[test]
+                #[should_panic]
+                fn read_big_endian() {
+                    let bytes = [0; $num_bytes];
+                    let mut numbers = $numbers;
+                    BigEndian::$read(&bytes, &mut numbers);
+                }
+
+                #[test]
+                #[should_panic]
+                fn read_little_endian() {
+                    let bytes = [0; $num_bytes];
+                    let mut numbers = $numbers;
+                    LittleEndian::$read(&bytes, &mut numbers);
+                }
+
+                #[test]
+                #[should_panic]
+                fn read_native_endian() {
+                    let bytes = [0; $num_bytes];
+                    let mut numbers = $numbers;
+                    NativeEndian::$read(&bytes, &mut numbers);
+                }
+
+                #[test]
+                #[should_panic]
+                fn write_big_endian() {
+                    let mut bytes = [0; $num_bytes];
+                    let numbers = $numbers;
+                    BigEndian::$write(&numbers, &mut bytes);
+                }
+
+                #[test]
+                #[should_panic]
+                fn write_little_endian() {
+                    let mut bytes = [0; $num_bytes];
+                    let numbers = $numbers;
+                    LittleEndian::$write(&numbers, &mut bytes);
+                }
+
+                #[test]
+                #[should_panic]
+                fn write_native_endian() {
+                    let mut bytes = [0; $num_bytes];
+                    let numbers = $numbers;
+                    NativeEndian::$write(&numbers, &mut bytes);
+                }
+            }
+        }
+    }
+
+    slice_lengths!(
+        slice_len_too_small_u16, read_u16_into, write_u16_into, 3, [0, 0]);
+    slice_lengths!(
+        slice_len_too_big_u16, read_u16_into, write_u16_into, 5, [0, 0]);
+    slice_lengths!(
+        slice_len_too_small_i16, read_i16_into, write_i16_into, 3, [0, 0]);
+    slice_lengths!(
+        slice_len_too_big_i16, read_i16_into, write_i16_into, 5, [0, 0]);
+
+    slice_lengths!(
+        slice_len_too_small_u32, read_u32_into, write_u32_into, 7, [0, 0]);
+    slice_lengths!(
+        slice_len_too_big_u32, read_u32_into, write_u32_into, 9, [0, 0]);
+    slice_lengths!(
+        slice_len_too_small_i32, read_i32_into, write_i32_into, 7, [0, 0]);
+    slice_lengths!(
+        slice_len_too_big_i32, read_i32_into, write_i32_into, 9, [0, 0]);
+
+    slice_lengths!(
+        slice_len_too_small_u64, read_u64_into, write_u64_into, 15, [0, 0]);
+    slice_lengths!(
+        slice_len_too_big_u64, read_u64_into, write_u64_into, 17, [0, 0]);
+    slice_lengths!(
+        slice_len_too_small_i64, read_i64_into, write_i64_into, 15, [0, 0]);
+    slice_lengths!(
+        slice_len_too_big_i64, read_i64_into, write_i64_into, 17, [0, 0]);
+
+    #[cfg(feature = "i128")]
+    slice_lengths!(
+        slice_len_too_small_u128, read_u128_into, write_u128_into, 31, [0, 0]);
+    #[cfg(feature = "i128")]
+    slice_lengths!(
+        slice_len_too_big_u128, read_u128_into, write_u128_into, 33, [0, 0]);
+    #[cfg(feature = "i128")]
+    slice_lengths!(
+        slice_len_too_small_i128, read_i128_into, write_i128_into, 31, [0, 0]);
+    #[cfg(feature = "i128")]
+    slice_lengths!(
+        slice_len_too_big_i128, read_i128_into, write_i128_into, 33, [0, 0]);
+
     #[test]
     fn uint_bigger_buffer() {
         use {ByteOrder, LittleEndian};
@@ -1708,6 +2830,21 @@ mod test {
 #[cfg(test)]
 #[cfg(feature = "std")]
 mod stdtests {
+    extern crate quickcheck;
+    extern crate rand;
+
+    use self::quickcheck::{QuickCheck, StdGen, Testable};
+    use self::rand::thread_rng;
+
+    fn qc_unsized<A: Testable>(f: A) {
+
+        QuickCheck::new()
+            .gen(StdGen::new(thread_rng(), 16))
+            .tests(1_00)
+            .max_tests(10_000)
+            .quickcheck(f);
+    }
+
     macro_rules! calc_max {
         ($max:expr, $bytes:expr) => { ($max - 1) >> (8 * (8 - $bytes)) };
     }
@@ -1721,7 +2858,7 @@ mod stdtests {
                     ReadBytesExt, WriteBytesExt,
                     BigEndian, NativeEndian, LittleEndian,
                 };
-                #[allow(unused_imports)] use test::{ qc_sized, Wi128 };
+                #[allow(unused_imports)] use test::{qc_sized, Wi128};
 
                 #[test]
                 fn big_endian() {
@@ -1766,7 +2903,7 @@ mod stdtests {
                     ReadBytesExt, WriteBytesExt,
                     BigEndian, NativeEndian, LittleEndian,
                 };
-                #[allow(unused_imports)] use test::{ qc_sized, Wi128 };
+                #[allow(unused_imports)] use test::{qc_sized, Wi128};
 
                 #[test]
                 fn big_endian() {
@@ -1957,4 +3094,98 @@ mod stdtests {
     #[cfg(feature = "i128")]
     qc_bytes_ext!(prop_ext_int128_16,
         Wi128<i128>, 16, 16, read_int128, write_i128);
+
+    // Test slice serialization/deserialization.
+    macro_rules! qc_slice {
+        ($name:ident, $ty_int:ty, $read:ident, $write:ident, $zero:expr) => {
+            mod $name {
+                use core::mem::size_of;
+                use {ByteOrder, BigEndian, NativeEndian, LittleEndian};
+                use super::qc_unsized;
+                #[allow(unused_imports)]
+                use test::Wi128;
+
+                #[test]
+                fn big_endian() {
+                    #[allow(unused_unsafe)]
+                    fn prop(numbers: Vec<$ty_int>) -> bool {
+                        let numbers: Vec<_> = numbers
+                            .into_iter()
+                            .map(|x| x.clone())
+                            .collect();
+                        let num_bytes = size_of::<$ty_int>() * numbers.len();
+                        let mut bytes = vec![0; num_bytes];
+
+                        BigEndian::$write(&numbers, &mut bytes);
+
+                        let mut got = vec![$zero; numbers.len()];
+                        unsafe { BigEndian::$read(&bytes, &mut got); }
+
+                        numbers == got
+                    }
+                    qc_unsized(prop as fn(_) -> bool);
+                }
+
+                #[test]
+                fn little_endian() {
+                    #[allow(unused_unsafe)]
+                    fn prop(numbers: Vec<$ty_int>) -> bool {
+                        let numbers: Vec<_> = numbers
+                            .into_iter()
+                            .map(|x| x.clone())
+                            .collect();
+                        let num_bytes = size_of::<$ty_int>() * numbers.len();
+                        let mut bytes = vec![0; num_bytes];
+
+                        LittleEndian::$write(&numbers, &mut bytes);
+
+                        let mut got = vec![$zero; numbers.len()];
+                        unsafe { LittleEndian::$read(&bytes, &mut got); }
+
+                        numbers == got
+                    }
+                    qc_unsized(prop as fn(_) -> bool);
+                }
+
+                #[test]
+                fn native_endian() {
+                    #[allow(unused_unsafe)]
+                    fn prop(numbers: Vec<$ty_int>) -> bool {
+                        let numbers: Vec<_> = numbers
+                            .into_iter()
+                            .map(|x| x.clone())
+                            .collect();
+                        let num_bytes = size_of::<$ty_int>() * numbers.len();
+                        let mut bytes = vec![0; num_bytes];
+
+                        NativeEndian::$write(&numbers, &mut bytes);
+
+                        let mut got = vec![$zero; numbers.len()];
+                        unsafe { NativeEndian::$read(&bytes, &mut got); }
+
+                        numbers == got
+                    }
+                    qc_unsized(prop as fn(_) -> bool);
+                }
+            }
+        }
+    }
+
+    qc_slice!(prop_slice_u16, u16, read_u16_into, write_u16_into, 0);
+    qc_slice!(prop_slice_i16, i16, read_i16_into, write_i16_into, 0);
+    qc_slice!(prop_slice_u32, u32, read_u32_into, write_u32_into, 0);
+    qc_slice!(prop_slice_i32, i32, read_i32_into, write_i32_into, 0);
+    qc_slice!(prop_slice_u64, u64, read_u64_into, write_u64_into, 0);
+    qc_slice!(prop_slice_i64, i64, read_i64_into, write_i64_into, 0);
+    #[cfg(feature = "i128")]
+    qc_slice!(
+        prop_slice_u128, Wi128<u128>, read_u128_into, write_u128_into, 0);
+    #[cfg(feature = "i128")]
+    qc_slice!(
+        prop_slice_i128, Wi128<i128>, read_i128_into, write_i128_into, 0);
+
+    qc_slice!(
+        prop_slice_f32, f32, read_f32_into_unchecked, write_f32_into, 0.0);
+    qc_slice!(
+        prop_slice_f64, f64, read_f64_into_unchecked, write_f64_into, 0.0);
 }


Test patch: