diff options
Diffstat (limited to 'third_party/rust/byteorder')
-rw-r--r-- | third_party/rust/byteorder/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/byteorder/.cargo-ok | 0 | ||||
-rw-r--r-- | third_party/rust/byteorder/.gitignore | 6 | ||||
-rw-r--r-- | third_party/rust/byteorder/.travis.yml | 15 | ||||
-rw-r--r-- | third_party/rust/byteorder/COPYING | 3 | ||||
-rw-r--r-- | third_party/rust/byteorder/Cargo.toml | 25 | ||||
-rw-r--r-- | third_party/rust/byteorder/LICENSE-MIT | 21 | ||||
-rw-r--r-- | third_party/rust/byteorder/Makefile | 14 | ||||
-rw-r--r-- | third_party/rust/byteorder/README.md | 59 | ||||
-rw-r--r-- | third_party/rust/byteorder/UNLICENSE | 24 | ||||
-rw-r--r-- | third_party/rust/byteorder/benches/bench.rs | 148 | ||||
-rw-r--r-- | third_party/rust/byteorder/session.vim | 1 | ||||
-rw-r--r-- | third_party/rust/byteorder/src/lib.rs | 802 | ||||
-rw-r--r-- | third_party/rust/byteorder/src/new.rs | 269 |
14 files changed, 1388 insertions, 0 deletions
diff --git a/third_party/rust/byteorder/.cargo-checksum.json b/third_party/rust/byteorder/.cargo-checksum.json new file mode 100644 index 000000000..88feac215 --- /dev/null +++ b/third_party/rust/byteorder/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"2879af3c0512f976015d532e2d768f04ff22fdcf8745b69b955b78fda321c3fb",".travis.yml":"81545ce3c6c72111a68434464c3f9fa8df9cbe39759a081fac527628ab21ae0c","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"a7282931b50dff2e463f82baaed95a9d76636bc0fef3e921acd8ca69eab32b83","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"fbcc46b6d0a585096737f50922818b59016b69d959b05f1b29863b2af8e4da43","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"f583692d829c8dfe19b1d5b9e968ccf5c74d6733367ca183edff74041a6afedd","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/lib.rs":"ef9e7a218fa3a4912c47f6840d32b975940d98277b6c9be85e8d7d045552eb87","src/new.rs":"161c21b7ebb5668c7cc70b46b0eb37709e06bb9c854f2fdfc6ce3d3babcbf3de"},"package":"0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"}
\ No newline at end of file diff --git a/third_party/rust/byteorder/.cargo-ok b/third_party/rust/byteorder/.cargo-ok new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/third_party/rust/byteorder/.cargo-ok diff --git a/third_party/rust/byteorder/.gitignore b/third_party/rust/byteorder/.gitignore new file mode 100644 index 000000000..1fec0efb8 --- /dev/null +++ b/third_party/rust/byteorder/.gitignore @@ -0,0 +1,6 @@ +.*.swp +doc +tags +build +target +Cargo.lock diff --git a/third_party/rust/byteorder/.travis.yml b/third_party/rust/byteorder/.travis.yml new file mode 100644 index 000000000..d6a279372 --- /dev/null +++ b/third_party/rust/byteorder/.travis.yml @@ -0,0 +1,15 @@ +language: rust +matrix: + include: + - rust: "nightly" + env: TEST_SUITE=suite_nightly + - rust: "beta" + env: TEST_SUITE=suite_beta + - rust: "stable" + env: TEST_SUITE=suite_stable +script: + - cargo build --verbose + - cargo test --verbose + - if [ "$TEST_SUITE" = "suite_nightly" ]; then + cargo bench --verbose; + fi diff --git a/third_party/rust/byteorder/COPYING b/third_party/rust/byteorder/COPYING new file mode 100644 index 000000000..bb9c20a09 --- /dev/null +++ b/third_party/rust/byteorder/COPYING @@ -0,0 +1,3 @@ +This project is dual-licensed under the Unlicense and MIT licenses. + +You may use this code under the terms of either license. diff --git a/third_party/rust/byteorder/Cargo.toml b/third_party/rust/byteorder/Cargo.toml new file mode 100644 index 000000000..32894e646 --- /dev/null +++ b/third_party/rust/byteorder/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "byteorder" +version = "0.5.3" #:version +authors = ["Andrew Gallant <jamslam@gmail.com>"] +description = "Library for reading/writing numbers in big-endian and little-endian." +documentation = "http://burntsushi.net/rustdoc/byteorder/" +homepage = "https://github.com/BurntSushi/byteorder" +repository = "https://github.com/BurntSushi/byteorder" +readme = "README.md" +keywords = ["byte", "endian", "big-endian", "little-endian", "binary"] +license = "Unlicense/MIT" + +[lib] +name = "byteorder" + +[dev-dependencies] +quickcheck = "0.2" +rand = "0.3" + +[features] +default = ["std"] +std = [] + +[profile.bench] +opt-level = 3 diff --git a/third_party/rust/byteorder/LICENSE-MIT b/third_party/rust/byteorder/LICENSE-MIT new file mode 100644 index 000000000..3b0a5dc09 --- /dev/null +++ b/third_party/rust/byteorder/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/third_party/rust/byteorder/Makefile b/third_party/rust/byteorder/Makefile new file mode 100644 index 000000000..9f956f4c4 --- /dev/null +++ b/third_party/rust/byteorder/Makefile @@ -0,0 +1,14 @@ +all: + echo Nothing to do... + +ctags: + ctags --recurse --options=ctags.rust --languages=Rust + +docs: + cargo doc + in-dir ./target/doc fix-perms + rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/ + +push: + git push origin master + git push github master diff --git a/third_party/rust/byteorder/README.md b/third_party/rust/byteorder/README.md new file mode 100644 index 000000000..5640f3e66 --- /dev/null +++ b/third_party/rust/byteorder/README.md @@ -0,0 +1,59 @@ +This crate provides convenience methods for encoding and decoding numbers in +either big-endian or little-endian order. This is meant to replace the old +methods defined on the standard library `Reader` and `Writer` traits. + +[![Build status](https://api.travis-ci.org/BurntSushi/byteorder.png)](https://travis-ci.org/BurntSushi/byteorder) +[![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder) + +Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). + + +### Documentation + +[http://burntsushi.net/rustdoc/byteorder/](http://burntsushi.net/rustdoc/byteorder/). + +The documentation includes examples. + + +### Installation + +This crate works with Cargo and is on +[crates.io](https://crates.io/crates/byteorder). The package is regularly +updated. Add it to your `Cargo.toml` like so: + +```toml +[dependencies] +byteorder = "0.5" +``` + +If you want to augment existing `Read` and `Write` traits, then import the +extension methods like so: + +```rust +extern crate byteorder; + +use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian}; +``` + +For example: + +```rust +use std::io::Cursor; +use byteorder::{BigEndian, ReadBytesExt}; + +let mut rdr = Cursor::new(vec![2, 5, 3, 0]); +// Note that we use type parameters to indicate which kind of byte order +// we want! +assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap()); +assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap()); +``` + +### `no_std` crates + +This crate has a feature, `std`, that is enabled by default. To use this crate +in a `no_std` context, add the following to your `Cargo.toml`: + +```toml +[dependencies] +byteorder = { version = "0.5", default-features = false } +``` diff --git a/third_party/rust/byteorder/UNLICENSE b/third_party/rust/byteorder/UNLICENSE new file mode 100644 index 000000000..68a49daad --- /dev/null +++ b/third_party/rust/byteorder/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org/> diff --git a/third_party/rust/byteorder/benches/bench.rs b/third_party/rust/byteorder/benches/bench.rs new file mode 100644 index 000000000..51d57b3da --- /dev/null +++ b/third_party/rust/byteorder/benches/bench.rs @@ -0,0 +1,148 @@ +#![feature(test)] + +extern crate byteorder; +extern crate test; + +macro_rules! bench_num { + ($name:ident, $read:ident, $bytes:expr, $data:expr) => ( + mod $name { + use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian}; + use super::test::Bencher; + use super::test::black_box as bb; + + const NITER: usize = 100_000; + + #[bench] + fn read_big_endian(b: &mut Bencher) { + let buf = $data; + b.iter(|| { + for _ in 0..NITER { + bb(BigEndian::$read(&buf, $bytes)); + } + }); + } + + #[bench] + fn read_little_endian(b: &mut Bencher) { + let buf = $data; + b.iter(|| { + for _ in 0..NITER { + bb(LittleEndian::$read(&buf, $bytes)); + } + }); + } + + #[bench] + fn read_native_endian(b: &mut Bencher) { + let buf = $data; + b.iter(|| { + for _ in 0..NITER { + bb(NativeEndian::$read(&buf, $bytes)); + } + }); + } + } + ); + ($ty:ident, $max:ident, + $read:ident, $write:ident, $size:expr, $data:expr) => ( + mod $ty { + use std::$ty; + use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian}; + use super::test::Bencher; + use super::test::black_box as bb; + + const NITER: usize = 100_000; + + #[bench] + fn read_big_endian(b: &mut Bencher) { + let buf = $data; + b.iter(|| { + for _ in 0..NITER { + bb(BigEndian::$read(&buf)); + } + }); + } + + #[bench] + fn read_little_endian(b: &mut Bencher) { + let buf = $data; + b.iter(|| { + for _ in 0..NITER { + bb(LittleEndian::$read(&buf)); + } + }); + } + + #[bench] + fn read_native_endian(b: &mut Bencher) { + let buf = $data; + b.iter(|| { + for _ in 0..NITER { + bb(NativeEndian::$read(&buf)); + } + }); + } + + #[bench] + fn write_big_endian(b: &mut Bencher) { + let mut buf = $data; + let n = $ty::$max; + b.iter(|| { + for _ in 0..NITER { + bb(BigEndian::$write(&mut buf, n)); + } + }); + } + + #[bench] + fn write_little_endian(b: &mut Bencher) { + let mut buf = $data; + let n = $ty::$max; + b.iter(|| { + for _ in 0..NITER { + bb(LittleEndian::$write(&mut buf, n)); + } + }); + } + + #[bench] + fn write_native_endian(b: &mut Bencher) { + let mut buf = $data; + let n = $ty::$max; + b.iter(|| { + for _ in 0..NITER { + bb(NativeEndian::$write(&mut buf, n)); + } + }); + } + } + ); +} + +bench_num!(u16, MAX, read_u16, write_u16, 2, [1, 2]); +bench_num!(i16, MAX, read_i16, write_i16, 2, [1, 2]); +bench_num!(u32, MAX, read_u32, write_u32, 4, [1, 2, 3, 4]); +bench_num!(i32, MAX, read_i32, write_i32, 4, [1, 2, 3, 4]); +bench_num!(u64, MAX, read_u64, write_u64, 8, [1, 2, 3, 4, 5, 6, 7, 8]); +bench_num!(i64, MAX, read_i64, write_i64, 8, [1, 2, 3, 4, 5, 6, 7, 8]); +bench_num!(f32, MAX, read_f32, write_f32, 4, [1, 2, 3, 4]); +bench_num!(f64, MAX, read_f64, write_f64, 8, + [1, 2, 3, 4, 5, 6, 7, 8]); + +bench_num!(uint_1, read_uint, 1, [1]); +bench_num!(uint_2, read_uint, 2, [1, 2]); +bench_num!(uint_3, read_uint, 3, [1, 2, 3]); +bench_num!(uint_4, read_uint, 4, [1, 2, 3, 4]); +bench_num!(uint_5, read_uint, 5, [1, 2, 3, 4, 5]); +bench_num!(uint_6, read_uint, 6, [1, 2, 3, 4, 5, 6]); +bench_num!(uint_7, read_uint, 7, [1, 2, 3, 4, 5, 6, 7]); +bench_num!(uint_8, read_uint, 8, [1, 2, 3, 4, 5, 6, 7, 8]); + +bench_num!(int_1, read_int, 1, [1]); +bench_num!(int_2, read_int, 2, [1, 2]); +bench_num!(int_3, read_int, 3, [1, 2, 3]); +bench_num!(int_4, read_int, 4, [1, 2, 3, 4]); +bench_num!(int_5, read_int, 5, [1, 2, 3, 4, 5]); +bench_num!(int_6, read_int, 6, [1, 2, 3, 4, 5, 6]); +bench_num!(int_7, read_int, 7, [1, 2, 3, 4, 5, 6, 7]); +bench_num!(int_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]); diff --git a/third_party/rust/byteorder/session.vim b/third_party/rust/byteorder/session.vim new file mode 100644 index 000000000..213c95660 --- /dev/null +++ b/third_party/rust/byteorder/session.vim @@ -0,0 +1 @@ +au BufWritePost *.rs silent!make ctags > /dev/null 2>&1 diff --git a/third_party/rust/byteorder/src/lib.rs b/third_party/rust/byteorder/src/lib.rs new file mode 100644 index 000000000..a25bab6e0 --- /dev/null +++ b/third_party/rust/byteorder/src/lib.rs @@ -0,0 +1,802 @@ +/*! +This crate provides convenience methods for encoding and decoding numbers +in either big-endian or little-endian order. + +The organization of the crate is pretty simple. A trait, `ByteOrder`, specifies +byte conversion methods for each type of number in Rust (sans numbers that have +a platform dependent size like `usize` and `isize`). Two types, `BigEndian` +and `LittleEndian` implement these methods. Finally, `ReadBytesExt` and +`WriteBytesExt` provide convenience methods available to all types that +implement `Read` and `Write`. + +# Examples + +Read unsigned 16 bit big-endian integers from a `Read` type: + +```rust +use std::io::Cursor; +use byteorder::{BigEndian, ReadBytesExt}; + +let mut rdr = Cursor::new(vec![2, 5, 3, 0]); +// Note that we use type parameters to indicate which kind of byte order +// we want! +assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap()); +assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap()); +``` + +Write unsigned 16 bit little-endian integers to a `Write` type: + +```rust +use byteorder::{LittleEndian, WriteBytesExt}; + +let mut wtr = vec![]; +wtr.write_u16::<LittleEndian>(517).unwrap(); +wtr.write_u16::<LittleEndian>(768).unwrap(); +assert_eq!(wtr, vec![5, 2, 0, 3]); +``` +*/ + +#![crate_name = "byteorder"] +#![doc(html_root_url = "http://burntsushi.net/rustdoc/byteorder")] + +#![cfg_attr(not(feature = "std"), no_std)] + +#![deny(missing_docs)] + +#[cfg(feature = "std")] +extern crate core; + +use core::mem::transmute; +use core::ptr::copy_nonoverlapping; + +#[cfg(feature = "std")] +pub use new::{ReadBytesExt, WriteBytesExt}; + +#[cfg(feature = "std")] +mod new; + +#[inline] +fn extend_sign(val: u64, nbytes: usize) -> i64 { + let shift = (8 - nbytes) * 8; + (val << shift) as i64 >> shift +} + +#[inline] +fn unextend_sign(val: i64, nbytes: usize) -> u64 { + let shift = (8 - nbytes) * 8; + (val << shift) as u64 >> shift +} + +#[inline] +fn pack_size(n: u64) -> 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 { + 8 + } +} + +/// ByteOrder describes types that can serialize integers as bytes. +/// +/// Note that `Self` does not appear anywhere in this trait's definition! +/// Therefore, in order to use it, you'll need to use syntax like +/// `T::read_u16(&[0, 1])` where `T` implements `ByteOrder`. +/// +/// This crate provides two types that implement `ByteOrder`: `BigEndian` +/// and `LittleEndian`. +/// +/// # Examples +/// +/// Write and read `u32` numbers in little endian order: +/// +/// ```rust +/// use byteorder::{ByteOrder, LittleEndian}; +/// +/// let mut buf = [0; 4]; +/// LittleEndian::write_u32(&mut buf, 1_000_000); +/// assert_eq!(1_000_000, LittleEndian::read_u32(&buf)); +/// ``` +/// +/// Write and read `i16` numbers in big endian order: +/// +/// ```rust +/// use byteorder::{ByteOrder, BigEndian}; +/// +/// let mut buf = [0; 2]; +/// BigEndian::write_i16(&mut buf, -50_000); +/// assert_eq!(-50_000, BigEndian::read_i16(&buf)); +/// ``` +pub trait ByteOrder { + /// Reads an unsigned 16 bit integer from `buf`. + /// + /// Panics when `buf.len() < 2`. + fn read_u16(buf: &[u8]) -> u16; + + /// Reads an unsigned 32 bit integer from `buf`. + /// + /// Panics when `buf.len() < 4`. + fn read_u32(buf: &[u8]) -> u32; + + /// Reads an unsigned 64 bit integer from `buf`. + /// + /// Panics when `buf.len() < 8`. + fn read_u64(buf: &[u8]) -> u64; + + /// Reads an unsigned n-bytes integer from `buf`. + /// + /// Panics when `nbytes < 1` or `nbytes > 8` or + /// `buf.len() < nbytes` + fn read_uint(buf: &[u8], nbytes: usize) -> u64; + + /// Writes an unsigned 16 bit integer `n` to `buf`. + /// + /// Panics when `buf.len() < 2`. + fn write_u16(buf: &mut [u8], n: u16); + + /// Writes an unsigned 32 bit integer `n` to `buf`. + /// + /// Panics when `buf.len() < 4`. + fn write_u32(buf: &mut [u8], n: u32); + + /// Writes an unsigned 64 bit integer `n` to `buf`. + /// + /// Panics when `buf.len() < 8`. + fn write_u64(buf: &mut [u8], n: u64); + + /// Writes an unsigned integer `n` to `buf` using only `nbytes`. + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 8`, then + /// this method panics. + fn write_uint(buf: &mut [u8], n: u64, nbytes: usize); + + /// Reads a signed 16 bit integer from `buf`. + /// + /// Panics when `buf.len() < 2`. + #[inline] + fn read_i16(buf: &[u8]) -> i16 { + Self::read_u16(buf) as i16 + } + + /// Reads a signed 32 bit integer from `buf`. + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn read_i32(buf: &[u8]) -> i32 { + Self::read_u32(buf) as i32 + } + + /// Reads a signed 64 bit integer from `buf`. + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn read_i64(buf: &[u8]) -> i64 { + Self::read_u64(buf) as i64 + } + + /// Reads a signed n-bytes integer from `buf`. + /// + /// Panics when `nbytes < 1` or `nbytes > 8` or + /// `buf.len() < nbytes` + #[inline] + fn read_int(buf: &[u8], nbytes: usize) -> i64 { + extend_sign(Self::read_uint(buf, nbytes), nbytes) + } + + /// Reads a IEEE754 single-precision (4 bytes) floating point number. + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn read_f32(buf: &[u8]) -> f32 { + unsafe { transmute(Self::read_u32(buf)) } + } + + /// Reads a IEEE754 double-precision (8 bytes) floating point number. + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn read_f64(buf: &[u8]) -> f64 { + unsafe { transmute(Self::read_u64(buf)) } + } + + /// Writes a signed 16 bit integer `n` to `buf`. + /// + /// Panics when `buf.len() < 2`. + #[inline] + fn write_i16(buf: &mut [u8], n: i16) { + Self::write_u16(buf, n as u16) + } + + /// Writes a signed 32 bit integer `n` to `buf`. + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn write_i32(buf: &mut [u8], n: i32) { + Self::write_u32(buf, n as u32) + } + + /// Writes a signed 64 bit integer `n` to `buf`. + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn write_i64(buf: &mut [u8], n: i64) { + Self::write_u64(buf, n as u64) + } + + /// Writes a signed integer `n` to `buf` using only `nbytes`. + /// + /// If `n` is not representable in `nbytes`, or if `nbytes` is `> 8`, then + /// this method panics. + #[inline] + fn write_int(buf: &mut [u8], n: i64, nbytes: usize) { + Self::write_uint(buf, unextend_sign(n, nbytes), nbytes) + } + + /// Writes a IEEE754 single-precision (4 bytes) floating point number. + /// + /// Panics when `buf.len() < 4`. + #[inline] + fn write_f32(buf: &mut [u8], n: f32) { + Self::write_u32(buf, unsafe { transmute(n) }) + } + + /// Writes a IEEE754 double-precision (8 bytes) floating point number. + /// + /// Panics when `buf.len() < 8`. + #[inline] + fn write_f64(buf: &mut [u8], n: f64) { + Self::write_u64(buf, unsafe { transmute(n) }) + } +} + +/// Defines big-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +#[allow(missing_copy_implementations)] pub enum BigEndian {} + +/// Defines little-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +#[allow(missing_copy_implementations)] pub enum LittleEndian {} + +/// Defines network byte order serialization. +/// +/// Network byte order is defined by [RFC 1700][1] to be big-endian, and is +/// referred to in several protocol specifications. This type is an alias of +/// BigEndian. +/// +/// [1]: https://tools.ietf.org/html/rfc1700 +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +pub type NetworkEndian = BigEndian; + +/// Defines system native-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +#[cfg(target_endian = "little")] +pub type NativeEndian = LittleEndian; + +/// Defines system native-endian serialization. +/// +/// Note that this type has no value constructor. It is used purely at the +/// type level. +#[cfg(target_endian = "big")] +pub type NativeEndian = BigEndian; + +macro_rules! read_num_bytes { + ($ty:ty, $size:expr, $src:expr, $which:ident) => ({ + assert!($size == ::core::mem::size_of::<$ty>()); + assert!($size <= $src.len()); + let mut data: $ty = 0; + unsafe { + copy_nonoverlapping( + $src.as_ptr(), + &mut data as *mut $ty as *mut u8, + $size); + } + data.$which() + }); +} + +macro_rules! write_num_bytes { + ($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => ({ + assert!($size <= $dst.len()); + unsafe { + // N.B. https://github.com/rust-lang/rust/issues/22776 + let bytes = transmute::<_, [u8; $size]>($n.$which()); + copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size); + } + }); +} + +impl ByteOrder for BigEndian { + #[inline] + fn read_u16(buf: &[u8]) -> u16 { + read_num_bytes!(u16, 2, buf, to_be) + } + + #[inline] + fn read_u32(buf: &[u8]) -> u32 { + read_num_bytes!(u32, 4, buf, to_be) + } + + #[inline] + fn read_u64(buf: &[u8]) -> u64 { + read_num_bytes!(u64, 8, buf, to_be) + } + + #[inline] + fn read_uint(buf: &[u8], nbytes: usize) -> u64 { + assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len()); + let mut out = [0u8; 8]; + let ptr_out = out.as_mut_ptr(); + unsafe { + copy_nonoverlapping( + buf.as_ptr(), ptr_out.offset((8 - nbytes) as isize), nbytes); + (*(ptr_out as *const u64)).to_be() + } + } + + #[inline] + fn write_u16(buf: &mut [u8], n: u16) { + write_num_bytes!(u16, 2, n, buf, to_be); + } + + #[inline] + fn write_u32(buf: &mut [u8], n: u32) { + write_num_bytes!(u32, 4, n, buf, to_be); + } + + #[inline] + fn write_u64(buf: &mut [u8], n: u64) { + write_num_bytes!(u64, 8, n, buf, to_be); + } + + #[inline] + fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { + assert!(pack_size(n) <= nbytes && nbytes <= 8); + assert!(nbytes <= buf.len()); + unsafe { + let bytes: [u8; 8] = transmute(n.to_be()); + copy_nonoverlapping( + bytes.as_ptr().offset((8 - nbytes) as isize), + buf.as_mut_ptr(), + nbytes); + } + } +} + +impl ByteOrder for LittleEndian { + #[inline] + fn read_u16(buf: &[u8]) -> u16 { + read_num_bytes!(u16, 2, buf, to_le) + } + + #[inline] + fn read_u32(buf: &[u8]) -> u32 { + read_num_bytes!(u32, 4, buf, to_le) + } + + #[inline] + fn read_u64(buf: &[u8]) -> u64 { + read_num_bytes!(u64, 8, buf, to_le) + } + + #[inline] + fn read_uint(buf: &[u8], nbytes: usize) -> u64 { + assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len()); + let mut out = [0u8; 8]; + let ptr_out = out.as_mut_ptr(); + unsafe { + copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes); + (*(ptr_out as *const u64)).to_le() + } + } + + #[inline] + fn write_u16(buf: &mut [u8], n: u16) { + write_num_bytes!(u16, 2, n, buf, to_le); + } + + #[inline] + fn write_u32(buf: &mut [u8], n: u32) { + write_num_bytes!(u32, 4, n, buf, to_le); + } + + #[inline] + fn write_u64(buf: &mut [u8], n: u64) { + write_num_bytes!(u64, 8, n, buf, to_le); + } + + #[inline] + fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) { + assert!(pack_size(n as u64) <= nbytes && nbytes <= 8); + assert!(nbytes <= buf.len()); + unsafe { + let bytes: [u8; 8] = transmute(n.to_le()); + copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes); + } + } +} + +#[cfg(test)] +mod test { + extern crate quickcheck; + extern crate rand; + + use test::rand::thread_rng; + use test::quickcheck::{QuickCheck, StdGen, Testable}; + + const U64_MAX: u64 = ::std::u64::MAX; + const I64_MAX: u64 = ::std::i64::MAX as u64; + + fn qc_sized<A: Testable>(f: A, size: u64) { + QuickCheck::new() + .gen(StdGen::new(thread_rng(), size as usize)) + .tests(1_00) + .max_tests(10_000) + .quickcheck(f); + } + + macro_rules! qc_byte_order { + ($name:ident, $ty_int:ident, $max:expr, + $bytes:expr, $read:ident, $write:ident) => ( + mod $name { + use {BigEndian, ByteOrder, NativeEndian, LittleEndian}; + use super::qc_sized; + + #[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); + n == BigEndian::$read(&mut buf[..$bytes], $bytes) + } + 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); + n == LittleEndian::$read(&mut buf[..$bytes], $bytes) + } + 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); + n == NativeEndian::$read(&mut buf[..$bytes], $bytes) + } + qc_sized(prop as fn($ty_int) -> bool, max); + } + } + ); + ($name:ident, $ty_int:ident, $max:expr, + $read:ident, $write:ident) => ( + mod $name { + use std::mem::size_of; + use {BigEndian, ByteOrder, NativeEndian, LittleEndian}; + use super::qc_sized; + + #[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..]) + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[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); + n == LittleEndian::$read(&mut buf[..bytes]) + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[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); + n == NativeEndian::$read(&mut buf[..bytes]) + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + } + ); + } + + qc_byte_order!(prop_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16); + qc_byte_order!(prop_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16); + qc_byte_order!(prop_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32); + qc_byte_order!(prop_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32); + qc_byte_order!(prop_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64); + qc_byte_order!(prop_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64); + qc_byte_order!(prop_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32); + qc_byte_order!(prop_f64, f64, ::std::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); + + macro_rules! qc_bytes_ext { + ($name:ident, $ty_int:ident, $max:expr, + $bytes:expr, $read:ident, $write:ident) => ( + mod $name { + use std::io::Cursor; + use { + ReadBytesExt, WriteBytesExt, + BigEndian, NativeEndian, LittleEndian, + }; + use super::qc_sized; + + #[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(); + let mut rdr = Vec::new(); + rdr.extend(wtr[8 - $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); + } + + #[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(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::<LittleEndian>($bytes).unwrap() + } + 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(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::<NativeEndian>($bytes).unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, max); + } + } + ); + ($name:ident, $ty_int:ident, $max:expr, $read:ident, $write:ident) => ( + mod $name { + use std::io::Cursor; + use { + ReadBytesExt, WriteBytesExt, + BigEndian, NativeEndian, LittleEndian, + }; + use super::qc_sized; + + #[test] + fn big_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::<BigEndian>(n).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::<BigEndian>().unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[test] + fn little_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::<LittleEndian>(n).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::<LittleEndian>().unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + + #[test] + fn native_endian() { + fn prop(n: $ty_int) -> bool { + let mut wtr = vec![]; + wtr.$write::<NativeEndian>(n).unwrap(); + let mut rdr = Cursor::new(wtr); + n == rdr.$read::<NativeEndian>().unwrap() + } + qc_sized(prop as fn($ty_int) -> bool, $max - 1); + } + } + ); + } + + 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, super::U64_MAX, 1, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_2, u64, super::U64_MAX, 2, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_3, u64, super::U64_MAX, 3, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_4, u64, super::U64_MAX, 4, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_5, u64, super::U64_MAX, 5, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_6, u64, super::U64_MAX, 6, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_7, u64, super::U64_MAX, 7, read_uint, write_u64); + qc_bytes_ext!(prop_ext_uint_8, u64, super::U64_MAX, 8, read_uint, write_u64); + + qc_bytes_ext!(prop_ext_int_1, i64, super::I64_MAX, 1, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_2, i64, super::I64_MAX, 2, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_3, i64, super::I64_MAX, 3, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_4, i64, super::I64_MAX, 4, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_5, i64, super::I64_MAX, 5, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_6, i64, super::I64_MAX, 6, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_7, i64, super::I64_MAX, 7, read_int, write_i64); + qc_bytes_ext!(prop_ext_int_8, i64, super::I64_MAX, 8, read_int, write_i64); + + // Test that all of the byte conversion functions panic when given a + // buffer that is too small. + // + // These tests are critical to ensure safety, otherwise we might end up + // with a buffer overflow. + macro_rules! too_small { + ($name:ident, $maximally_small:expr, $zero:expr, + $read:ident, $write:ident) => ( + mod $name { + use {BigEndian, ByteOrder, NativeEndian, LittleEndian}; + + #[test] + #[should_panic] + fn read_big_endian() { + let buf = [0; $maximally_small]; + BigEndian::$read(&buf); + } + + #[test] + #[should_panic] + fn read_little_endian() { + let buf = [0; $maximally_small]; + LittleEndian::$read(&buf); + } + + #[test] + #[should_panic] + fn read_native_endian() { + let buf = [0; $maximally_small]; + NativeEndian::$read(&buf); + } + + #[test] + #[should_panic] + fn write_big_endian() { + let mut buf = [0; $maximally_small]; + BigEndian::$write(&mut buf, $zero); + } + + #[test] + #[should_panic] + fn write_little_endian() { + let mut buf = [0; $maximally_small]; + LittleEndian::$write(&mut buf, $zero); + } + + #[test] + #[should_panic] + fn write_native_endian() { + let mut buf = [0; $maximally_small]; + NativeEndian::$write(&mut buf, $zero); + } + } + ); + ($name:ident, $maximally_small:expr, $read:ident) => ( + mod $name { + use {BigEndian, ByteOrder, NativeEndian, LittleEndian}; + + #[test] + #[should_panic] + fn read_big_endian() { + let buf = [0; $maximally_small]; + BigEndian::$read(&buf, $maximally_small + 1); + } + + #[test] + #[should_panic] + fn read_little_endian() { + let buf = [0; $maximally_small]; + LittleEndian::$read(&buf, $maximally_small + 1); + } + + #[test] + #[should_panic] + fn read_native_endian() { + let buf = [0; $maximally_small]; + NativeEndian::$read(&buf, $maximally_small + 1); + } + } + ); + } + + too_small!(small_u16, 1, 0, read_u16, write_u16); + too_small!(small_i16, 1, 0, read_i16, write_i16); + too_small!(small_u32, 3, 0, read_u32, write_u32); + too_small!(small_i32, 3, 0, read_i32, write_i32); + too_small!(small_u64, 7, 0, read_u64, write_u64); + 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); + + too_small!(small_uint_1, 1, read_uint); + too_small!(small_uint_2, 2, read_uint); + too_small!(small_uint_3, 3, read_uint); + too_small!(small_uint_4, 4, read_uint); + too_small!(small_uint_5, 5, read_uint); + too_small!(small_uint_6, 6, read_uint); + too_small!(small_uint_7, 7, read_uint); + + too_small!(small_int_1, 1, read_int); + too_small!(small_int_2, 2, read_int); + too_small!(small_int_3, 3, read_int); + too_small!(small_int_4, 4, read_int); + too_small!(small_int_5, 5, read_int); + too_small!(small_int_6, 6, read_int); + too_small!(small_int_7, 7, read_int); + + #[test] + fn uint_bigger_buffer() { + use {ByteOrder, LittleEndian}; + let n = LittleEndian::read_uint(&[1, 2, 3, 4, 5, 6, 7, 8], 5); + assert_eq!(n, 0x0504030201); + } +} diff --git a/third_party/rust/byteorder/src/new.rs b/third_party/rust/byteorder/src/new.rs new file mode 100644 index 000000000..b5f37700f --- /dev/null +++ b/third_party/rust/byteorder/src/new.rs @@ -0,0 +1,269 @@ +use std::io::{self, Result}; + +use ByteOrder; + +/// Extends `Read` with methods for reading numbers. (For `std::io`.) +/// +/// Most of the methods defined here have an unconstrained type parameter that +/// must be explicitly instantiated. Typically, it is instantiated with either +/// the `BigEndian` or `LittleEndian` types defined in this crate. +/// +/// # Examples +/// +/// Read 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]); +/// assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap()); +/// assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap()); +/// ``` +pub trait ReadBytesExt: io::Read { + /// Reads an unsigned 8 bit integer from the underlying reader. + /// + /// Note that since this reads a single byte, no byte order conversions + /// are used. It is included for completeness. + #[inline] + fn read_u8(&mut self) -> Result<u8> { + let mut buf = [0; 1]; + try!(self.read_exact(&mut buf)); + Ok(buf[0]) + } + + /// Reads a signed 8 bit integer from the underlying reader. + /// + /// Note that since this reads a single byte, no byte order conversions + /// are used. It is included for completeness. + #[inline] + fn read_i8(&mut self) -> Result<i8> { + let mut buf = [0; 1]; + try!(self.read_exact(&mut buf)); + Ok(buf[0] as i8) + } + + /// Reads an unsigned 16 bit integer from the underlying reader. + #[inline] + fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> { + let mut buf = [0; 2]; + try!(self.read_exact(&mut buf)); + Ok(T::read_u16(&buf)) + } + + /// Reads a signed 16 bit integer from the underlying reader. + #[inline] + fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> { + let mut buf = [0; 2]; + try!(self.read_exact(&mut buf)); + Ok(T::read_i16(&buf)) + } + + /// Reads an unsigned 32 bit integer from the underlying reader. + #[inline] + fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> { + let mut buf = [0; 4]; + try!(self.read_exact(&mut buf)); + Ok(T::read_u32(&buf)) + } + + /// Reads a signed 32 bit integer from the underlying reader. + #[inline] + fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> { + let mut buf = [0; 4]; + try!(self.read_exact(&mut buf)); + Ok(T::read_i32(&buf)) + } + + /// Reads an unsigned 64 bit integer from the underlying reader. + #[inline] + fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> { + let mut buf = [0; 8]; + try!(self.read_exact(&mut buf)); + Ok(T::read_u64(&buf)) + } + + /// Reads a signed 64 bit integer from the underlying reader. + #[inline] + fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> { + let mut buf = [0; 8]; + try!(self.read_exact(&mut buf)); + Ok(T::read_i64(&buf)) + } + + /// Reads an unsigned n-bytes integer from the underlying reader. + #[inline] + fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> { + let mut buf = [0; 8]; + try!(self.read_exact(&mut buf[..nbytes])); + Ok(T::read_uint(&buf[..nbytes], nbytes)) + } + + /// Reads a signed n-bytes integer from the underlying reader. + #[inline] + fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> { + let mut buf = [0; 8]; + try!(self.read_exact(&mut buf[..nbytes])); + Ok(T::read_int(&buf[..nbytes], nbytes)) + } + + /// Reads a IEEE754 single-precision (4 bytes) floating point number from + /// the underlying reader. + #[inline] + fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> { + let mut buf = [0; 4]; + try!(self.read_exact(&mut buf)); + Ok(T::read_f32(&buf)) + } + + /// Reads a IEEE754 double-precision (8 bytes) floating point number from + /// the underlying reader. + #[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)) + } +} + +/// All types that implement `Read` get methods defined in `ReadBytesExt` +/// for free. +impl<R: io::Read + ?Sized> ReadBytesExt for R {} + +/// Extends `Write` with methods for writing numbers. (For `std::io`.) +/// +/// Most of the methods defined here have an unconstrained type parameter that +/// must be explicitly instantiated. Typically, it is instantiated with either +/// the `BigEndian` or `LittleEndian` types defined in this crate. +/// +/// # Examples +/// +/// Write unsigned 16 bit big-endian integers to a `Write`: +/// +/// ```rust +/// use byteorder::{BigEndian, WriteBytesExt}; +/// +/// let mut wtr = vec![]; +/// wtr.write_u16::<BigEndian>(517).unwrap(); +/// wtr.write_u16::<BigEndian>(768).unwrap(); +/// assert_eq!(wtr, vec![2, 5, 3, 0]); +/// ``` +pub trait WriteBytesExt: io::Write { + /// Writes an unsigned 8 bit integer to the underlying writer. + /// + /// Note that since this writes a single byte, no byte order conversions + /// are used. It is included for completeness. + #[inline] + fn write_u8(&mut self, n: u8) -> Result<()> { + self.write_all(&[n]) + } + + /// Writes a signed 8 bit integer to the underlying writer. + /// + /// Note that since this writes a single byte, no byte order conversions + /// are used. It is included for completeness. + #[inline] + fn write_i8(&mut self, n: i8) -> Result<()> { + self.write_all(&[n as u8]) + } + + /// Writes an unsigned 16 bit integer to the underlying writer. + #[inline] + fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> { + let mut buf = [0; 2]; + T::write_u16(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 16 bit integer to the underlying writer. + #[inline] + fn write_i16<T: ByteOrder>(&mut self, n: i16) -> Result<()> { + let mut buf = [0; 2]; + T::write_i16(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 32 bit integer to the underlying writer. + #[inline] + fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> { + let mut buf = [0; 4]; + T::write_u32(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 32 bit integer to the underlying writer. + #[inline] + fn write_i32<T: ByteOrder>(&mut self, n: i32) -> Result<()> { + let mut buf = [0; 4]; + T::write_i32(&mut buf, n); + self.write_all(&buf) + } + + /// Writes an unsigned 64 bit integer to the underlying writer. + #[inline] + fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> { + let mut buf = [0; 8]; + T::write_u64(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a signed 64 bit integer to the underlying writer. + #[inline] + fn write_i64<T: ByteOrder>(&mut self, n: i64) -> Result<()> { + let mut buf = [0; 8]; + T::write_i64(&mut buf, n); + self.write_all(&buf) + } + + /// 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 > 8`, this method panics. + #[inline] + fn write_uint<T: ByteOrder>( + &mut self, + n: u64, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 8]; + T::write_uint(&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 > 8`, this method panics. + #[inline] + fn write_int<T: ByteOrder>( + &mut self, + n: i64, + nbytes: usize, + ) -> Result<()> { + let mut buf = [0; 8]; + T::write_int(&mut buf, n, nbytes); + self.write_all(&buf[0..nbytes]) + } + + /// Writes a IEEE754 single-precision (4 bytes) floating point number to + /// the underlying writer. + #[inline] + fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> { + let mut buf = [0; 4]; + T::write_f32(&mut buf, n); + self.write_all(&buf) + } + + /// Writes a IEEE754 double-precision (8 bytes) floating point number to + /// the underlying writer. + #[inline] + fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> { + let mut buf = [0; 8]; + T::write_f64(&mut buf, n); + self.write_all(&buf) + } +} + +/// All types that implement `Write` get methods defined in `WriteBytesExt` +/// for free. +impl<W: io::Write + ?Sized> WriteBytesExt for W {} |