diff options
author | quininer kel <quininer@live.com> | 2017-01-03 12:55:58 +0800 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2017-03-29 07:47:05 -0400 |
commit | cac7fc4798425acf63131897eeb04e73a48de91c (patch) | |
tree | d1374b8e523b1b4ce6a49a09464402e25a882094 /src | |
parent | 6dd2f2dee72c3c26ecf8edecd7971a1c38ad0039 (diff) | |
download | byteorder-cac7fc4798425acf63131897eeb04e73a48de91c.tar.gz |
Add i128 support
Adds the following methods to the `ByteOrder` trait:
* `read_{i128, u128}`
* `write_{i128, u128}`
* `{read_uint,read_int,write_uint,write_int}128`
Adds the following methods to the `ReadBytesExt` trait:
* `read_{i128, u128}`
* `{read_uint, read_int}128`
Adds the following methods to the `WriteBytesExt` trait:
* `write_{i128, u128}`
* `{write_uint, write_int}128`
And finally, add tests and benchmarks for i128 support.
Fixes #65
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 732 | ||||
-rw-r--r-- | src/new.rs | 126 |
2 files changed, 774 insertions, 84 deletions
@@ -38,6 +38,8 @@ assert_eq!(wtr, vec![5, 2, 0, 3]); #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "i128", feature(i128_type))] +#![cfg_attr(all(feature = "i128", test), feature(i128))] #![doc(html_root_url = "https://docs.rs/byteorder/1.0.0")] #[cfg(feature = "std")] @@ -60,12 +62,26 @@ fn extend_sign(val: u64, nbytes: usize) -> i64 { (val << shift) as i64 >> shift } +#[cfg(feature = "i128")] +#[inline] +fn extend_sign128(val: u128, nbytes: usize) -> i128 { + let shift = (16 - nbytes) * 8; + (val << shift) as i128 >> shift +} + #[inline] fn unextend_sign(val: i64, nbytes: usize) -> u64 { let shift = (8 - nbytes) * 8; (val << shift) as u64 >> shift } +#[cfg(feature = "i128")] +#[inline] +fn unextend_sign128(val: i128, nbytes: usize) -> u128 { + let shift = (16 - nbytes) * 8; + (val << shift) as u128 >> shift +} + #[inline] fn pack_size(n: u64) -> usize { if n < 1 << 8 { @@ -87,6 +103,44 @@ fn pack_size(n: u64) -> usize { } } +#[cfg(feature = "i128")] +#[inline] +fn pack_size128(n: u128) -> usize { + if n < 1 << 8 { + 1 + } else if n < 1 << 16 { + 2 + } else if n < 1 << 24 { + 3 + } else if n < 1 << 32 { + 4 + } else if n < 1 << 40 { + 5 + } else if n < 1 << 48 { + 6 + } else if n < 1 << 56 { + 7 + } else if n < 1 << 64 { + 8 + } else if n < 1 << 72 { + 9 + } else if n < 1 << 80 { + 10 + } else if n < 1 << 88 { + 11 + } else if n < 1 << 96 { + 12 + } else if n < 1 << 104 { + 13 + } else if n < 1 << 112 { + 14 + } else if n < 1 << 120 { + 15 + } else { + 16 + } +} + mod private { /// Sealed stops crates other than byteorder from implementing any traits that use it. pub trait Sealed{} @@ -173,6 +227,14 @@ pub trait ByteOrder /// ``` fn read_u64(buf: &[u8]) -> u64; + /// Reads an unsigned 128 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + #[cfg(feature = "i128")] + fn read_u128(buf: &[u8]) -> u128; + /// Reads an unsigned n-bytes integer from `buf`. /// /// # Panics @@ -193,6 +255,15 @@ pub trait ByteOrder /// ``` fn read_uint(buf: &[u8], nbytes: usize) -> u64; + /// Reads an unsigned n-bytes integer from `buf`. + /// + /// # Panics + /// + /// Panics when `nbytes < 1` or `nbytes > 16` or + /// `buf.len() < nbytes` + #[cfg(feature = "i128")] + fn read_uint128(buf: &[u8], nbytes: usize) -> u128; + /// Writes an unsigned 16 bit integer `n` to `buf`. /// /// # Panics @@ -250,6 +321,14 @@ pub trait ByteOrder /// ``` fn write_u64(buf: &mut [u8], n: u64); + /// Writes an unsigned 128 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + #[cfg(feature = "i128")] + fn write_u128(buf: &mut [u8], n: u128); + /// Writes an unsigned integer `n` to `buf` using only `nbytes`. /// /// # Panics @@ -270,6 +349,15 @@ pub trait ByteOrder /// ``` fn write_uint(buf: &mut [u8], n: u64, nbytes: usize); + /// Writes an unsigned integer `n` to `buf` using only `nbytes`. + /// + /// # Panics + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 16`, then + /// this method panics. + #[cfg(feature = "i128")] + fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize); + /// Reads a signed 16 bit integer from `buf`. /// /// # Panics @@ -336,6 +424,17 @@ pub trait ByteOrder Self::read_u64(buf) as i64 } + /// Reads a signed 128 bit integer from `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + #[cfg(feature = "i128")] + #[inline] + fn read_i128(buf: &[u8]) -> i128 { + Self::read_u128(buf) as i128 + } + /// Reads a signed n-bytes integer from `buf`. /// /// # Panics @@ -359,6 +458,18 @@ pub trait ByteOrder extend_sign(Self::read_uint(buf, nbytes), nbytes) } + /// Reads a signed n-bytes integer from `buf`. + /// + /// # Panics + /// + /// Panics when `nbytes < 1` or `nbytes > 16` or + /// `buf.len() < nbytes` + #[cfg(feature = "i128")] + #[inline] + fn read_int128(buf: &[u8], nbytes: usize) -> i128 { + extend_sign128(Self::read_uint128(buf, nbytes), nbytes) + } + /// Reads a IEEE754 single-precision (4 bytes) floating point number. /// /// # Panics @@ -471,6 +582,17 @@ pub trait ByteOrder Self::write_u64(buf, n as u64) } + /// Writes a signed 128 bit integer `n` to `buf`. + /// + /// # Panics + /// + /// Panics when `buf.len() < 16`. + #[cfg(feature = "i128")] + #[inline] + fn write_i128(buf: &mut [u8], n: i128) { + Self::write_u128(buf, n as u128) + } + /// Writes a signed integer `n` to `buf` using only `nbytes`. /// /// # Panics @@ -494,6 +616,18 @@ pub trait ByteOrder Self::write_uint(buf, unextend_sign(n, nbytes), nbytes) } + /// Writes a signed integer `n` to `buf` using only `nbytes`. + /// + /// # Panics + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 16`, then + /// this method panics. + #[cfg(feature = "i128")] + #[inline] + fn write_int128(buf: &mut [u8], n: i128, nbytes: usize) { + Self::write_uint128(buf, unextend_sign128(n, nbytes), nbytes) + } + /// Writes a IEEE754 single-precision (4 bytes) floating point number. /// /// # Panics @@ -671,6 +805,12 @@ impl ByteOrder for BigEndian { read_num_bytes!(u64, 8, buf, to_be) } + #[cfg(feature = "i128")] + #[inline] + fn read_u128(buf: &[u8]) -> u128 { + read_num_bytes!(u128, 16, buf, to_be) + } + #[inline] fn read_uint(buf: &[u8], nbytes: usize) -> u64 { assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len()); @@ -683,6 +823,19 @@ impl ByteOrder for BigEndian { } } + #[cfg(feature = "i128")] + #[inline] + fn read_uint128(buf: &[u8], nbytes: usize) -> u128 { + assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len()); + let mut out = [0u8; 16]; + let ptr_out = out.as_mut_ptr(); + unsafe { + copy_nonoverlapping( + buf.as_ptr(), ptr_out.offset((16 - nbytes) as isize), nbytes); + (*(ptr_out as *const u128)).to_be() + } + } + #[inline] fn write_u16(buf: &mut [u8], n: u16) { write_num_bytes!(u16, 2, n, buf, to_be); @@ -698,6 +851,12 @@ impl ByteOrder for BigEndian { write_num_bytes!(u64, 8, n, buf, to_be); } + #[cfg(feature = "i128")] + #[inline] + fn write_u128(buf: &mut [u8], n: u128) { + write_num_bytes!(u128, 16, n, buf, to_be); + } + #[inline] fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { assert!(pack_size(n) <= nbytes && nbytes <= 8); @@ -710,6 +869,20 @@ impl ByteOrder for BigEndian { nbytes); } } + + #[cfg(feature = "i128")] + #[inline] + fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) { + assert!(pack_size128(n) <= nbytes && nbytes <= 16); + assert!(nbytes <= buf.len()); + unsafe { + let bytes: [u8; 16] = transmute(n.to_be()); + copy_nonoverlapping( + bytes.as_ptr().offset((16 - nbytes) as isize), + buf.as_mut_ptr(), + nbytes); + } + } } impl ByteOrder for LittleEndian { @@ -728,6 +901,12 @@ impl ByteOrder for LittleEndian { read_num_bytes!(u64, 8, buf, to_le) } + #[cfg(feature = "i128")] + #[inline] + fn read_u128(buf: &[u8]) -> u128 { + read_num_bytes!(u128, 16, buf, to_le) + } + #[inline] fn read_uint(buf: &[u8], nbytes: usize) -> u64 { assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len()); @@ -739,6 +918,18 @@ impl ByteOrder for LittleEndian { } } + #[cfg(feature = "i128")] + #[inline] + fn read_uint128(buf: &[u8], nbytes: usize) -> u128 { + assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len()); + let mut out = [0u8; 16]; + let ptr_out = out.as_mut_ptr(); + unsafe { + copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes); + (*(ptr_out as *const u128)).to_le() + } + } + #[inline] fn write_u16(buf: &mut [u8], n: u16) { write_num_bytes!(u16, 2, n, buf, to_le); @@ -754,6 +945,12 @@ impl ByteOrder for LittleEndian { write_num_bytes!(u64, 8, n, buf, to_le); } + #[cfg(feature = "i128")] + #[inline] + fn write_u128(buf: &mut [u8], n: u128) { + write_num_bytes!(u128, 16, n, buf, to_le); + } + #[inline] fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { assert!(pack_size(n as u64) <= nbytes && nbytes <= 8); @@ -763,6 +960,17 @@ impl ByteOrder for LittleEndian { copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes); } } + + #[cfg(feature = "i128")] + #[inline] + fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) { + assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16); + assert!(nbytes <= buf.len()); + unsafe { + let bytes: [u8; 16] = transmute(n.to_le()); + copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes); + } + } } #[cfg(test)] @@ -772,10 +980,56 @@ mod test { use self::rand::thread_rng; use self::quickcheck::{QuickCheck, StdGen, Testable}; + #[cfg(feature = "i128")] use self::quickcheck::{ Arbitrary, Gen }; pub const U64_MAX: u64 = ::core::u64::MAX; pub const I64_MAX: u64 = ::core::i64::MAX as u64; + macro_rules! calc_max { + ($max:expr, $bytes:expr) => { calc_max!($max, $bytes, 8) }; + ($max:expr, $bytes:expr, $maxbytes:expr) => { + ($max - 1) >> (8 * ($maxbytes - $bytes)) + }; + } + + #[derive(Clone, Debug)] + pub struct Wi128<T>(pub T); + + #[cfg(feature = "i128")] + impl<T: Clone> Wi128<T> { + pub fn clone(&self) -> T { + self.0.clone() + } + } + + impl<T: PartialEq> PartialEq<T> for Wi128<T> { + fn eq(&self, other: &T) -> bool { + self.0.eq(other) + } + } + + #[cfg(feature = "i128")] + impl Arbitrary for Wi128<u128> { + fn arbitrary<G: Gen>(gen: &mut G) -> Wi128<u128> { + let max = calc_max!(::core::u128::MAX, gen.size(), 16); + let output = + (gen.gen::<u64>() as u128) | + ((gen.gen::<u64>() as u128) << 64); + Wi128(output & (max - 1)) + } + } + + #[cfg(feature = "i128")] + impl Arbitrary for Wi128<i128> { + fn arbitrary<G: Gen>(gen: &mut G) -> Wi128<i128> { + let max = calc_max!(::core::i128::MAX, gen.size(), 16); + let output = + (gen.gen::<i64>() as i128) | + ((gen.gen::<i64>() as i128) << 64); + Wi128(output & (max - 1)) + } + } + pub fn qc_sized<A: Testable>(f: A, size: u64) { QuickCheck::new() .gen(StdGen::new(thread_rng(), size as usize)) @@ -785,60 +1039,57 @@ mod test { } macro_rules! qc_byte_order { - ($name:ident, $ty_int:ident, $max:expr, + ($name:ident, $ty_int:ty, $max:expr, $bytes:expr, $read:ident, $write:ident) => ( mod $name { use {BigEndian, ByteOrder, NativeEndian, LittleEndian}; - use super::qc_sized; + #[allow(unused_imports)] use super::{ qc_sized, Wi128 }; #[test] fn big_endian() { - let max = ($max - 1) >> (8 * (8 - $bytes)); fn prop(n: $ty_int) -> bool { - let mut buf = [0; 8]; - BigEndian::$write(&mut buf, n, $bytes); + let mut buf = [0; 16]; + BigEndian::$write(&mut buf, n.clone(), $bytes); n == BigEndian::$read(&mut buf[..$bytes], $bytes) } - qc_sized(prop as fn($ty_int) -> bool, max); + qc_sized(prop as fn($ty_int) -> bool, $max); } #[test] fn little_endian() { - let max = ($max - 1) >> (8 * (8 - $bytes)); fn prop(n: $ty_int) -> bool { - let mut buf = [0; 8]; - LittleEndian::$write(&mut buf, n, $bytes); + let mut buf = [0; 16]; + LittleEndian::$write(&mut buf, n.clone(), $bytes); n == LittleEndian::$read(&mut buf[..$bytes], $bytes) } - qc_sized(prop as fn($ty_int) -> bool, max); + qc_sized(prop as fn($ty_int) -> bool, $max); } #[test] fn native_endian() { - let max = ($max - 1) >> (8 * (8 - $bytes)); fn prop(n: $ty_int) -> bool { - let mut buf = [0; 8]; - NativeEndian::$write(&mut buf, n, $bytes); + let mut buf = [0; 16]; + NativeEndian::$write(&mut buf, n.clone(), $bytes); n == NativeEndian::$read(&mut buf[..$bytes], $bytes) } - qc_sized(prop as fn($ty_int) -> bool, max); + qc_sized(prop as fn($ty_int) -> bool, $max); } } ); - ($name:ident, $ty_int:ident, $max:expr, + ($name:ident, $ty_int:ty, $max:expr, $read:ident, $write:ident) => ( mod $name { use core::mem::size_of; use {BigEndian, ByteOrder, NativeEndian, LittleEndian}; - use super::qc_sized; + #[allow(unused_imports)] use super::{ qc_sized, Wi128 }; #[test] fn big_endian() { fn prop(n: $ty_int) -> bool { let bytes = size_of::<$ty_int>(); - let mut buf = [0; 8]; - BigEndian::$write(&mut buf[8 - bytes..], n); - n == BigEndian::$read(&mut buf[8 - bytes..]) + let mut buf = [0; 16]; + BigEndian::$write(&mut buf[16 - bytes..], n.clone()); + n == BigEndian::$read(&mut buf[16 - bytes..]) } qc_sized(prop as fn($ty_int) -> bool, $max - 1); } @@ -847,8 +1098,8 @@ mod test { fn little_endian() { fn prop(n: $ty_int) -> bool { let bytes = size_of::<$ty_int>(); - let mut buf = [0; 8]; - LittleEndian::$write(&mut buf[..bytes], n); + let mut buf = [0; 16]; + LittleEndian::$write(&mut buf[..bytes], n.clone()); n == LittleEndian::$read(&mut buf[..bytes]) } qc_sized(prop as fn($ty_int) -> bool, $max - 1); @@ -858,8 +1109,8 @@ mod test { fn native_endian() { fn prop(n: $ty_int) -> bool { let bytes = size_of::<$ty_int>(); - let mut buf = [0; 8]; - NativeEndian::$write(&mut buf[..bytes], n); + let mut buf = [0; 16]; + NativeEndian::$write(&mut buf[..bytes], n.clone()); n == NativeEndian::$read(&mut buf[..bytes]) } qc_sized(prop as fn($ty_int) -> bool, $max - 1); @@ -877,23 +1128,143 @@ mod test { qc_byte_order!(prop_f32, f32, ::core::u64::MAX as u64, read_f32, write_f32); qc_byte_order!(prop_f64, f64, ::core::i64::MAX as u64, read_f64, write_f64); - qc_byte_order!(prop_uint_1, u64, super::U64_MAX, 1, read_uint, write_uint); - qc_byte_order!(prop_uint_2, u64, super::U64_MAX, 2, read_uint, write_uint); - qc_byte_order!(prop_uint_3, u64, super::U64_MAX, 3, read_uint, write_uint); - qc_byte_order!(prop_uint_4, u64, super::U64_MAX, 4, read_uint, write_uint); - qc_byte_order!(prop_uint_5, u64, super::U64_MAX, 5, read_uint, write_uint); - qc_byte_order!(prop_uint_6, u64, super::U64_MAX, 6, read_uint, write_uint); - qc_byte_order!(prop_uint_7, u64, super::U64_MAX, 7, read_uint, write_uint); - qc_byte_order!(prop_uint_8, u64, super::U64_MAX, 8, read_uint, write_uint); - - qc_byte_order!(prop_int_1, i64, super::I64_MAX, 1, read_int, write_int); - qc_byte_order!(prop_int_2, i64, super::I64_MAX, 2, read_int, write_int); - qc_byte_order!(prop_int_3, i64, super::I64_MAX, 3, read_int, write_int); - qc_byte_order!(prop_int_4, i64, super::I64_MAX, 4, read_int, write_int); - qc_byte_order!(prop_int_5, i64, super::I64_MAX, 5, read_int, write_int); - qc_byte_order!(prop_int_6, i64, super::I64_MAX, 6, read_int, write_int); - qc_byte_order!(prop_int_7, i64, super::I64_MAX, 7, read_int, write_int); - qc_byte_order!(prop_int_8, i64, super::I64_MAX, 8, read_int, write_int); + #[cfg(feature = "i128")] + qc_byte_order!(prop_u128, Wi128<u128>, 16 + 1, read_u128, write_u128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_i128, Wi128<i128>, 16 + 1, read_i128, write_i128); + + qc_byte_order!(prop_uint_1, + u64, calc_max!(super::U64_MAX, 1), 1, read_uint, write_uint); + qc_byte_order!(prop_uint_2, + u64, calc_max!(super::U64_MAX, 2), 2, read_uint, write_uint); + qc_byte_order!(prop_uint_3, + u64, calc_max!(super::U64_MAX, 3), 3, read_uint, write_uint); + qc_byte_order!(prop_uint_4, + u64, calc_max!(super::U64_MAX, 4), 4, read_uint, write_uint); + qc_byte_order!(prop_uint_5, + u64, calc_max!(super::U64_MAX, 5), 5, read_uint, write_uint); + qc_byte_order!(prop_uint_6, + u64, calc_max!(super::U64_MAX, 6), 6, read_uint, write_uint); + qc_byte_order!(prop_uint_7, + u64, calc_max!(super::U64_MAX, 7), 7, read_uint, write_uint); + qc_byte_order!(prop_uint_8, + u64, calc_max!(super::U64_MAX, 8), 8, read_uint, write_uint); + + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_1, + Wi128<u128>, 1, 1, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_2, + Wi128<u128>, 2, 2, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_3, + Wi128<u128>, 3, 3, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_4, + Wi128<u128>, 4, 4, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_5, + Wi128<u128>, 5, 5, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_6, + Wi128<u128>, 6, 6, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_7, + Wi128<u128>, 7, 7, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_8, + Wi128<u128>, 8, 8, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_9, + Wi128<u128>, 9, 9, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_10, + Wi128<u128>, 10, 10, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_11, + Wi128<u128>, 11, 11, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_12, + Wi128<u128>, 12, 12, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_13, + Wi128<u128>, 13, 13, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_14, + Wi128<u128>, 14, 14, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_15, + Wi128<u128>, 15, 15, read_uint128, write_uint128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_uint128_16, + Wi128<u128>, 16, 16, read_uint128, write_uint128); + + qc_byte_order!(prop_int_1, + i64, calc_max!(super::I64_MAX, 1), 1, read_int, write_int); + qc_byte_order!(prop_int_2, + i64, calc_max!(super::I64_MAX, 2), 2, read_int, write_int); + qc_byte_order!(prop_int_3, + i64, calc_max!(super::I64_MAX, 3), 3, read_int, write_int); + qc_byte_order!(prop_int_4, + i64, calc_max!(super::I64_MAX, 4), 4, read_int, write_int); + qc_byte_order!(prop_int_5, + i64, calc_max!(super::I64_MAX, 5), 5, read_int, write_int); + qc_byte_order!(prop_int_6, + i64, calc_max!(super::I64_MAX, 6), 6, read_int, write_int); + qc_byte_order!(prop_int_7, + i64, calc_max!(super::I64_MAX, 7), 7, read_int, write_int); + qc_byte_order!(prop_int_8, + i64, calc_max!(super::I64_MAX, 8), 8, read_int, write_int); + + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_1, + Wi128<i128>, 1, 1, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_2, + Wi128<i128>, 2, 2, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_3, + Wi128<i128>, 3, 3, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_4, + Wi128<i128>, 4, 4, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_5, + Wi128<i128>, 5, 5, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_6, + Wi128<i128>, 6, 6, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_7, + Wi128<i128>, 7, 7, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_8, + Wi128<i128>, 8, 8, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_9, + Wi128<i128>, 9, 9, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_10, + Wi128<i128>, 10, 10, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_11, + Wi128<i128>, 11, 11, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_12, + Wi128<i128>, 12, 12, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_13, + Wi128<i128>, 13, 13, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_14, + Wi128<i128>, 14, 14, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_15, + Wi128<i128>, 15, 15, read_int128, write_int128); + #[cfg(feature = "i128")] + qc_byte_order!(prop_int128_16, + Wi128<i128>, 16, 16, read_int128, write_int128); + // Test that all of the byte conversion functions panic when given a // buffer that is too small. @@ -985,6 +1356,10 @@ mod test { too_small!(small_i64, 7, 0, read_i64, write_i64); too_small!(small_f32, 3, 0.0, read_f32, write_f32); too_small!(small_f64, 7, 0.0, read_f64, write_f64); + #[cfg(feature = "i128")] + too_small!(small_u128, 15, 0, read_u128, write_u128); + #[cfg(feature = "i128")] + too_small!(small_i128, 15, 0, read_i128, write_i128); too_small!(small_uint_1, 1, read_uint); too_small!(small_uint_2, 2, read_uint); @@ -994,6 +1369,37 @@ mod test { too_small!(small_uint_6, 6, read_uint); too_small!(small_uint_7, 7, read_uint); + #[cfg(feature = "i128")] + too_small!(small_uint128_1, 1, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_2, 2, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_3, 3, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_4, 4, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_5, 5, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_6, 6, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_7, 7, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_8, 8, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_9, 9, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_10, 10, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_11, 11, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_12, 12, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_13, 13, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_14, 14, read_uint128); + #[cfg(feature = "i128")] + too_small!(small_uint128_15, 15, read_uint128); + too_small!(small_int_1, 1, read_int); too_small!(small_int_2, 2, read_int); too_small!(small_int_3, 3, read_int); @@ -1002,6 +1408,37 @@ mod test { too_small!(small_int_6, 6, read_int); too_small!(small_int_7, 7, read_int); + #[cfg(feature = "i128")] + too_small!(small_int128_1, 1, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_2, 2, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_3, 3, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_4, 4, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_5, 5, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_6, 6, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_7, 7, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_8, 8, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_9, 9, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_10, 10, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_11, 11, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_12, 12, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_13, 13, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_14, 14, read_int128); + #[cfg(feature = "i128")] + too_small!(small_int128_15, 15, read_int128); + #[test] fn uint_bigger_buffer() { use {ByteOrder, LittleEndian}; @@ -1013,8 +1450,12 @@ mod test { #[cfg(test)] #[cfg(feature = "std")] mod stdtests { + macro_rules! calc_max { + ($max:expr, $bytes:expr) => { ($max - 1) >> (8 * (8 - $bytes)) }; + } + macro_rules! qc_bytes_ext { - ($name:ident, $ty_int:ident, $max:expr, + ($name:ident, $ty_int:ty, $max:expr, $bytes:expr, $read:ident, $write:ident) => ( mod $name { use std::io::Cursor; @@ -1022,61 +1463,58 @@ mod stdtests { ReadBytesExt, WriteBytesExt, BigEndian, NativeEndian, LittleEndian, }; - use test::qc_sized; + #[allow(unused_imports)] use test::{ qc_sized, Wi128 }; #[test] fn big_endian() { - let max = ($max - 1) >> (8 * (8 - $bytes)); fn prop(n: $ty_int) -> bool { let mut wtr = vec![]; - wtr.$write::<BigEndian>(n).unwrap(); + wtr.$write::<BigEndian>(n.clone()).unwrap(); let mut rdr = Vec::new(); - rdr.extend(wtr[8 - $bytes..].iter().map(|&x|x)); + rdr.extend(wtr[wtr.len()-$bytes..].iter().map(|&x| x)); let mut rdr = Cursor::new(rdr); n == rdr.$read::<BigEndian>($bytes).unwrap() } - qc_sized(prop as fn($ty_int) -> bool, max); + qc_sized(prop as fn($ty_int) -> bool, $max); } #[test] fn little_endian() { - let max = ($max - 1) >> (8 * (8 - $bytes)); fn prop(n: $ty_int) -> bool { let mut wtr = vec![]; - wtr.$write::<LittleEndian>(n).unwrap(); + wtr.$write::<LittleEndian>(n.clone()).unwrap(); let mut rdr = Cursor::new(wtr); n == rdr.$read::<LittleEndian>($bytes).unwrap() } - qc_sized(prop as fn($ty_int) -> bool, max); + qc_sized(prop as fn($ty_int) -> bool, $max); } #[test] fn native_endian() { - let max = ($max - 1) >> (8 * (8 - $bytes)); fn prop(n: $ty_int) -> bool { let mut wtr = vec![]; - wtr.$write::<NativeEndian>(n).unwrap(); + wtr.$write::<NativeEndian>(n.clone()).unwrap(); let mut rdr = Cursor::new(wtr); n == rdr.$read::<NativeEndian>($bytes).unwrap() } - qc_sized(prop as fn($ty_int) -> bool, max); + qc_sized(prop as fn($ty_int) -> bool, $max); } } ); - ($name:ident, $ty_int:ident, $max:expr, $read:ident, $write:ident) => ( + ($name:ident, $ty_int:ty, $max:expr, $read:ident, $write:ident) => ( mod $name { use std::io::Cursor; use { ReadBytesExt, WriteBytesExt, BigEndian, NativeEndian, LittleEndian, }; - use test::qc_sized; + #[allow(unused_imports)] use test::{ qc_sized, Wi128 }; #[test] fn big_endian() { fn prop(n: $ty_int) -> bool { let mut wtr = vec![]; - wtr.$write::<BigEndian>(n).unwrap(); + wtr.$write::<BigEndian>(n.clone()).unwrap(); let mut rdr = Cursor::new(wtr); n == rdr.$read::<BigEndian>().unwrap() } @@ -1087,7 +1525,7 @@ mod stdtests { fn little_endian() { fn prop(n: $ty_int) -> bool { let mut wtr = vec![]; - wtr.$write::<LittleEndian>(n).unwrap(); + wtr.$write::<LittleEndian>(n.clone()).unwrap(); let mut rdr = Cursor::new(wtr); n == rdr.$read::<LittleEndian>().unwrap() } @@ -1098,7 +1536,7 @@ mod stdtests { fn native_endian() { fn prop(n: $ty_int) -> bool { let mut wtr = vec![]; - wtr.$write::<NativeEndian>(n).unwrap(); + wtr.$write::<NativeEndian>(n.clone()).unwrap(); let mut rdr = Cursor::new(wtr); n == rdr.$read::<NativeEndian>().unwrap() } @@ -1108,31 +1546,157 @@ mod stdtests { ); } - qc_bytes_ext!(prop_ext_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16); - qc_bytes_ext!(prop_ext_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16); - qc_bytes_ext!(prop_ext_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32); - qc_bytes_ext!(prop_ext_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32); - qc_bytes_ext!(prop_ext_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64); - qc_bytes_ext!(prop_ext_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64); - qc_bytes_ext!(prop_ext_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32); - qc_bytes_ext!(prop_ext_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64); - - qc_bytes_ext!(prop_ext_uint_1, u64, ::test::U64_MAX, 1, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_2, u64, ::test::U64_MAX, 2, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_3, u64, ::test::U64_MAX, 3, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_4, u64, ::test::U64_MAX, 4, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_5, u64, ::test::U64_MAX, 5, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_6, u64, ::test::U64_MAX, 6, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_7, u64, ::test::U64_MAX, 7, read_uint, write_u64); - qc_bytes_ext!(prop_ext_uint_8, u64, ::test::U64_MAX, 8, read_uint, write_u64); - - qc_bytes_ext!(prop_ext_int_1, i64, ::test::I64_MAX, 1, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_2, i64, ::test::I64_MAX, 2, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_3, i64, ::test::I64_MAX, 3, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_4, i64, ::test::I64_MAX, 4, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_5, i64, ::test::I64_MAX, 5, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_6, i64, ::test::I64_MAX, 6, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_7, i64, ::test::I64_MAX, 7, read_int, write_i64); - qc_bytes_ext!(prop_ext_int_8, i64, ::test::I64_MAX, 8, read_int, write_i64); + qc_bytes_ext!(prop_ext_u16, + u16, ::std::u16::MAX as u64, read_u16, write_u16); + qc_bytes_ext!(prop_ext_i16, + i16, ::std::i16::MAX as u64, read_i16, write_i16); + qc_bytes_ext!(prop_ext_u32, + u32, ::std::u32::MAX as u64, read_u32, write_u32); + qc_bytes_ext!(prop_ext_i32, + i32, ::std::i32::MAX as u64, read_i32, write_i32); + qc_bytes_ext!(prop_ext_u64, + u64, ::std::u64::MAX as u64, read_u64, write_u64); + qc_bytes_ext!(prop_ext_i64, + i64, ::std::i64::MAX as u64, read_i64, write_i64); + qc_bytes_ext!(prop_ext_f32, + f32, ::std::u64::MAX as u64, read_f32, write_f32); + qc_bytes_ext!(prop_ext_f64, + f64, ::std::i64::MAX as u64, read_f64, write_f64); + + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_u128, Wi128<u128>, 16 + 1, read_u128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_i128, Wi128<i128>, 16 + 1, read_i128, write_i128); + + qc_bytes_ext!(prop_ext_uint_1, + u64, calc_max!(::test::U64_MAX, 1), 1, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_2, + u64, calc_max!(::test::U64_MAX, 2), 2, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_3, + u64, calc_max!(::test::U64_MAX, 3), 3, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_4, + u64, calc_max!(::test::U64_MAX, 4), 4, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_5, + u64, calc_max!(::test::U64_MAX, 5), 5, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_6, + u64, calc_max!(::test::U64_MAX, 6), 6, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_7, + u64, calc_max!(::test::U64_MAX, 7), 7, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_8, + u64, calc_max!(::test::U64_MAX, 8), 8, read_uint, write_u64); + + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_1, + Wi128<u128>, 1, 1, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_2, + Wi128<u128>, 2, 2, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_3, + Wi128<u128>, 3, 3, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_4, + Wi128<u128>, 4, 4, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_5, + Wi128<u128>, 5, 5, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_6, + Wi128<u128>, 6, 6, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_7, + Wi128<u128>, 7, 7, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_8, + Wi128<u128>, 8, 8, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_9, + Wi128<u128>, 9, 9, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_10, + Wi128<u128>, 10, 10, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_11, + Wi128<u128>, 11, 11, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_12, + Wi128<u128>, 12, 12, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_13, + Wi128<u128>, 13, 13, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_14, + Wi128<u128>, 14, 14, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_15, + Wi128<u128>, 15, 15, read_uint128, write_u128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_uint128_16, + Wi128<u128>, 16, 16, read_uint128, write_u128); + + qc_bytes_ext!(prop_ext_int_1, + i64, calc_max!(::test::I64_MAX, 1), 1, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_2, + i64, calc_max!(::test::I64_MAX, 2), 2, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_3, + i64, calc_max!(::test::I64_MAX, 3), 3, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_4, + i64, calc_max!(::test::I64_MAX, 4), 4, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_5, + i64, calc_max!(::test::I64_MAX, 5), 5, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_6, + i64, calc_max!(::test::I64_MAX, 6), 6, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_7, + i64, calc_max!(::test::I64_MAX, 1), 7, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_8, + i64, calc_max!(::test::I64_MAX, 8), 8, read_int, write_i64); + + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_1, + Wi128<i128>, 1, 1, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_2, + Wi128<i128>, 2, 2, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_3, + Wi128<i128>, 3, 3, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_4, + Wi128<i128>, 4, 4, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_5, + Wi128<i128>, 5, 5, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_6, + Wi128<i128>, 6, 6, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_7, + Wi128<i128>, 7, 7, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_8, + Wi128<i128>, 8, 8, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_9, + Wi128<i128>, 9, 9, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_10, + Wi128<i128>, 10, 10, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_11, + Wi128<i128>, 11, 11, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_12, + Wi128<i128>, 12, 12, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_13, + Wi128<i128>, 13, 13, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_14, + Wi128<i128>, 14, 14, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_15, + Wi128<i128>, 15, 15, read_int128, write_i128); + #[cfg(feature = "i128")] + qc_bytes_ext!(prop_ext_int128_16, + Wi128<i128>, 16, 16, read_int128, write_i128); } - @@ -239,6 +239,64 @@ pub trait ReadBytesExt: io::Read { Ok(T::read_i64(&buf)) } + /// Reads an unsigned 128 bit integer from the underlying reader. + /// + /// # 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 an unsigned 128 bit big-endian integer from a `Read`: + /// + /// ```rust + /// use std::io::Cursor; + /// use byteorder::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![ + /// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83, + /// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83 + /// ]); + /// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().unwrap()); + /// ``` + #[cfg(feature = "i128")] + #[inline] + fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> { + let mut buf = [0; 16]; + try!(self.read_exact(&mut buf)); + Ok(T::read_u128(&buf)) + } + + /// Reads a signed 128 bit integer from the underlying reader. + /// + /// # 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 signed 128 bit big-endian integer from a `Read`: + /// + /// ```rust + /// #![feature(i128_type)] + /// use std::io::Cursor; + /// use byteorder::{BigEndian, ReadBytesExt}; + /// + /// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + /// assert_eq!(i128::min_value(), rdr.read_i128::<BigEndian>().unwrap()); + /// ``` + #[cfg(feature = "i128")] + #[inline] + fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> { + let mut buf = [0; 16]; + try!(self.read_exact(&mut buf)); + Ok(T::read_i128(&buf)) + } + /// Reads an unsigned n-bytes integer from the underlying reader. /// /// # Errors @@ -289,6 +347,24 @@ pub trait ReadBytesExt: io::Read { Ok(T::read_int(&buf[..nbytes], nbytes)) } + /// Reads an unsigned n-bytes integer from the underlying reader. + #[cfg(feature = "i128")] + #[inline] + fn read_uint128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u128> { + let mut buf = [0; 16]; + try!(self.read_exact(&mut buf[..nbytes])); + Ok(T::read_uint128(&buf[..nbytes], nbytes)) + } + + /// Reads a signed n-bytes integer from the underlying reader. + #[cfg(feature = "i128")] + #[inline] + fn read_int128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i128> { + let mut buf = [0; 16]; + try!(self.read_exact(&mut buf[..nbytes])); + Ok(T::read_int128(&buf[..nbytes], nbytes)) + } + /// Reads a IEEE754 single-precision (4 bytes) floating point number from /// the underlying reader. /// @@ -481,6 +557,24 @@ pub trait WriteBytesExt: io::Write { self.write_all(&buf) } + /// Writes an unsigned 128 bit integer to the underlying writer. + #[cfg(feature = "i128")] + #[inline] + fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> { + let mut buf = [0; 16]; + T::write_u128(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 128 bit integer to the underlying writer. + #[cfg(feature = "i128")] + #[inline] + fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> { + let mut buf = [0; 16]; + T::write_i128(&mut buf, n); + self.write_all(&buf) + } + /// Writes an unsigned n-bytes integer to the underlying writer. /// /// # Errors @@ -527,6 +621,38 @@ pub trait WriteBytesExt: io::Write { self.write_all(&buf[0..nbytes]) } + /// Writes an unsigned n-bytes integer to the underlying writer. + /// + /// If the given integer is not representable in the given number of bytes, + /// this method panics. If `nbytes > 16`, this method panics. + #[cfg(feature = "i128")] + #[inline] + fn write_uint128<T: ByteOrder>( + &mut self, + n: u128, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 16]; + T::write_uint128(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + + /// Writes a signed n-bytes integer to the underlying writer. + /// + /// If the given integer is not representable in the given number of bytes, + /// this method panics. If `nbytes > 16`, this method panics. + #[cfg(feature = "i128")] + #[inline] + fn write_int128<T: ByteOrder>( + &mut self, + n: i128, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 16]; + T::write_int128(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + /// Writes a IEEE754 single-precision (4 bytes) floating point number to /// the underlying writer. /// |