6919cf5fe1
The trait will keep the `Iterator` naming, but a more concise module name makes using the free functions less verbose. The module will define iterables in addition to iterators, as it deals with iteration in general.
991 lines
26 KiB
Rust
991 lines
26 KiB
Rust
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
//! Utility mixins that apply to all Readers and Writers
|
|
|
|
// XXX: Not sure how this should be structured
|
|
// XXX: Iteration should probably be considered separately
|
|
|
|
use uint;
|
|
use int;
|
|
use iter::Iterator;
|
|
use vec;
|
|
use rt::io::{Reader, Writer, Decorator};
|
|
use rt::io::{read_error, standard_error, EndOfFile, DEFAULT_BUF_SIZE};
|
|
use option::{Option, Some, None};
|
|
use unstable::finally::Finally;
|
|
use util;
|
|
use cast;
|
|
use io::{u64_to_le_bytes, u64_to_be_bytes};
|
|
|
|
pub trait ReaderUtil {
|
|
|
|
/// Reads a single byte. Returns `None` on EOF.
|
|
///
|
|
/// # Failure
|
|
///
|
|
/// Raises the same conditions as the `read` method. Returns
|
|
/// `None` if the condition is handled.
|
|
fn read_byte(&mut self) -> Option<u8>;
|
|
|
|
/// Reads `len` bytes and appends them to a vector.
|
|
///
|
|
/// May push fewer than the requested number of bytes on error
|
|
/// or EOF. Returns true on success, false on EOF or error.
|
|
///
|
|
/// # Failure
|
|
///
|
|
/// Raises the same conditions as `read`. Additionally raises `read_error`
|
|
/// on EOF. If `read_error` is handled then `push_bytes` may push less
|
|
/// than the requested number of bytes.
|
|
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint);
|
|
|
|
/// Reads `len` bytes and gives you back a new vector of length `len`
|
|
///
|
|
/// # Failure
|
|
///
|
|
/// Raises the same conditions as `read`. Additionally raises `read_error`
|
|
/// on EOF. If `read_error` is handled then the returned vector may
|
|
/// contain less than the requested number of bytes.
|
|
fn read_bytes(&mut self, len: uint) -> ~[u8];
|
|
|
|
/// Reads all remaining bytes from the stream.
|
|
///
|
|
/// # Failure
|
|
///
|
|
/// Raises the same conditions as the `read` method.
|
|
fn read_to_end(&mut self) -> ~[u8];
|
|
|
|
/// Create an iterator that reads a single byte on
|
|
/// each iteration, until EOF.
|
|
///
|
|
/// # Failure
|
|
///
|
|
/// Raises the same conditions as the `read` method, for
|
|
/// each call to its `.next()` method.
|
|
/// Ends the iteration if the condition is handled.
|
|
fn bytes(self) -> ByteIterator<Self>;
|
|
|
|
}
|
|
|
|
pub trait ReaderByteConversions {
|
|
/// Reads `n` little-endian unsigned integer bytes.
|
|
///
|
|
/// `n` must be between 1 and 8, inclusive.
|
|
fn read_le_uint_n_(&mut self, nbytes: uint) -> u64;
|
|
|
|
/// Reads `n` little-endian signed integer bytes.
|
|
///
|
|
/// `n` must be between 1 and 8, inclusive.
|
|
fn read_le_int_n_(&mut self, nbytes: uint) -> i64;
|
|
|
|
/// Reads `n` big-endian unsigned integer bytes.
|
|
///
|
|
/// `n` must be between 1 and 8, inclusive.
|
|
fn read_be_uint_n_(&mut self, nbytes: uint) -> u64;
|
|
|
|
/// Reads `n` big-endian signed integer bytes.
|
|
///
|
|
/// `n` must be between 1 and 8, inclusive.
|
|
fn read_be_int_n_(&mut self, nbytes: uint) -> i64;
|
|
|
|
/// Reads a little-endian unsigned integer.
|
|
///
|
|
/// The number of bytes returned is system-dependant.
|
|
fn read_le_uint_(&mut self) -> uint;
|
|
|
|
/// Reads a little-endian integer.
|
|
///
|
|
/// The number of bytes returned is system-dependant.
|
|
fn read_le_int_(&mut self) -> int;
|
|
|
|
/// Reads a big-endian unsigned integer.
|
|
///
|
|
/// The number of bytes returned is system-dependant.
|
|
fn read_be_uint_(&mut self) -> uint;
|
|
|
|
/// Reads a big-endian integer.
|
|
///
|
|
/// The number of bytes returned is system-dependant.
|
|
fn read_be_int_(&mut self) -> int;
|
|
|
|
/// Reads a big-endian `u64`.
|
|
///
|
|
/// `u64`s are 8 bytes long.
|
|
fn read_be_u64_(&mut self) -> u64;
|
|
|
|
/// Reads a big-endian `u32`.
|
|
///
|
|
/// `u32`s are 4 bytes long.
|
|
fn read_be_u32_(&mut self) -> u32;
|
|
|
|
/// Reads a big-endian `u16`.
|
|
///
|
|
/// `u16`s are 2 bytes long.
|
|
fn read_be_u16_(&mut self) -> u16;
|
|
|
|
/// Reads a big-endian `i64`.
|
|
///
|
|
/// `i64`s are 8 bytes long.
|
|
fn read_be_i64_(&mut self) -> i64;
|
|
|
|
/// Reads a big-endian `i32`.
|
|
///
|
|
/// `i32`s are 4 bytes long.
|
|
fn read_be_i32_(&mut self) -> i32;
|
|
|
|
/// Reads a big-endian `i16`.
|
|
///
|
|
/// `i16`s are 2 bytes long.
|
|
fn read_be_i16_(&mut self) -> i16;
|
|
|
|
/// Reads a big-endian `f64`.
|
|
///
|
|
/// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
|
|
fn read_be_f64_(&mut self) -> f64;
|
|
|
|
/// Reads a big-endian `f32`.
|
|
///
|
|
/// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
|
|
fn read_be_f32_(&mut self) -> f32;
|
|
|
|
/// Reads a little-endian `u64`.
|
|
///
|
|
/// `u64`s are 8 bytes long.
|
|
fn read_le_u64_(&mut self) -> u64;
|
|
|
|
/// Reads a little-endian `u32`.
|
|
///
|
|
/// `u32`s are 4 bytes long.
|
|
fn read_le_u32_(&mut self) -> u32;
|
|
|
|
/// Reads a little-endian `u16`.
|
|
///
|
|
/// `u16`s are 2 bytes long.
|
|
fn read_le_u16_(&mut self) -> u16;
|
|
|
|
/// Reads a little-endian `i64`.
|
|
///
|
|
/// `i64`s are 8 bytes long.
|
|
fn read_le_i64_(&mut self) -> i64;
|
|
|
|
/// Reads a little-endian `i32`.
|
|
///
|
|
/// `i32`s are 4 bytes long.
|
|
fn read_le_i32_(&mut self) -> i32;
|
|
|
|
/// Reads a little-endian `i16`.
|
|
///
|
|
/// `i16`s are 2 bytes long.
|
|
fn read_le_i16_(&mut self) -> i16;
|
|
|
|
/// Reads a little-endian `f64`.
|
|
///
|
|
/// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
|
|
fn read_le_f64_(&mut self) -> f64;
|
|
|
|
/// Reads a little-endian `f32`.
|
|
///
|
|
/// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
|
|
fn read_le_f32_(&mut self) -> f32;
|
|
|
|
/// Read a u8.
|
|
///
|
|
/// `u8`s are 1 byte.
|
|
fn read_u8_(&mut self) -> u8;
|
|
|
|
/// Read an i8.
|
|
///
|
|
/// `i8`s are 1 byte.
|
|
fn read_i8_(&mut self) -> i8;
|
|
|
|
}
|
|
|
|
pub trait WriterByteConversions {
|
|
/// Write the result of passing n through `int::to_str_bytes`.
|
|
fn write_int_(&mut self, n: int);
|
|
|
|
/// Write the result of passing n through `uint::to_str_bytes`.
|
|
fn write_uint_(&mut self, n: uint);
|
|
|
|
/// Write a little-endian uint (number of bytes depends on system).
|
|
fn write_le_uint_(&mut self, n: uint);
|
|
|
|
/// Write a little-endian int (number of bytes depends on system).
|
|
fn write_le_int_(&mut self, n: int);
|
|
|
|
/// Write a big-endian uint (number of bytes depends on system).
|
|
fn write_be_uint_(&mut self, n: uint);
|
|
|
|
/// Write a big-endian int (number of bytes depends on system).
|
|
fn write_be_int_(&mut self, n: int);
|
|
|
|
/// Write a big-endian u64 (8 bytes).
|
|
fn write_be_u64_(&mut self, n: u64);
|
|
|
|
/// Write a big-endian u32 (4 bytes).
|
|
fn write_be_u32_(&mut self, n: u32);
|
|
|
|
/// Write a big-endian u16 (2 bytes).
|
|
fn write_be_u16_(&mut self, n: u16);
|
|
|
|
/// Write a big-endian i64 (8 bytes).
|
|
fn write_be_i64_(&mut self, n: i64);
|
|
|
|
/// Write a big-endian i32 (4 bytes).
|
|
fn write_be_i32_(&mut self, n: i32);
|
|
|
|
/// Write a big-endian i16 (2 bytes).
|
|
fn write_be_i16_(&mut self, n: i16);
|
|
|
|
/// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
|
|
fn write_be_f64_(&mut self, f: f64);
|
|
|
|
/// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
|
|
fn write_be_f32_(&mut self, f: f32);
|
|
|
|
/// Write a little-endian u64 (8 bytes).
|
|
fn write_le_u64_(&mut self, n: u64);
|
|
|
|
/// Write a little-endian u32 (4 bytes).
|
|
fn write_le_u32_(&mut self, n: u32);
|
|
|
|
/// Write a little-endian u16 (2 bytes).
|
|
fn write_le_u16_(&mut self, n: u16);
|
|
|
|
/// Write a little-endian i64 (8 bytes).
|
|
fn write_le_i64_(&mut self, n: i64);
|
|
|
|
/// Write a little-endian i32 (4 bytes).
|
|
fn write_le_i32_(&mut self, n: i32);
|
|
|
|
/// Write a little-endian i16 (2 bytes).
|
|
fn write_le_i16_(&mut self, n: i16);
|
|
|
|
/// Write a little-endian IEEE754 double-precision floating-point
|
|
/// (8 bytes).
|
|
fn write_le_f64_(&mut self, f: f64);
|
|
|
|
/// Write a little-endian IEEE754 single-precision floating-point
|
|
/// (4 bytes).
|
|
fn write_le_f32_(&mut self, f: f32);
|
|
|
|
/// Write a u8 (1 byte).
|
|
fn write_u8_(&mut self, n: u8);
|
|
|
|
/// Write a i8 (1 byte).
|
|
fn write_i8_(&mut self, n: i8);
|
|
}
|
|
|
|
impl<T: Reader> ReaderUtil for T {
|
|
fn read_byte(&mut self) -> Option<u8> {
|
|
let mut buf = [0];
|
|
match self.read(buf) {
|
|
Some(0) => {
|
|
debug!("read 0 bytes. trying again");
|
|
self.read_byte()
|
|
}
|
|
Some(1) => Some(buf[0]),
|
|
Some(_) => util::unreachable(),
|
|
None => None
|
|
}
|
|
}
|
|
|
|
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) {
|
|
unsafe {
|
|
let start_len = buf.len();
|
|
let mut total_read = 0;
|
|
|
|
buf.reserve_at_least(start_len + len);
|
|
vec::raw::set_len(buf, start_len + len);
|
|
|
|
do (|| {
|
|
while total_read < len {
|
|
let len = buf.len();
|
|
let slice = buf.mut_slice(start_len + total_read, len);
|
|
match self.read(slice) {
|
|
Some(nread) => {
|
|
total_read += nread;
|
|
}
|
|
None => {
|
|
read_error::cond.raise(standard_error(EndOfFile));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}).finally {
|
|
vec::raw::set_len(buf, start_len + total_read);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn read_bytes(&mut self, len: uint) -> ~[u8] {
|
|
let mut buf = vec::with_capacity(len);
|
|
self.push_bytes(&mut buf, len);
|
|
return buf;
|
|
}
|
|
|
|
fn read_to_end(&mut self) -> ~[u8] {
|
|
let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE);
|
|
let mut keep_reading = true;
|
|
do read_error::cond.trap(|e| {
|
|
if e.kind == EndOfFile {
|
|
keep_reading = false;
|
|
} else {
|
|
read_error::cond.raise(e)
|
|
}
|
|
}).inside {
|
|
while keep_reading {
|
|
self.push_bytes(&mut buf, DEFAULT_BUF_SIZE)
|
|
}
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
fn bytes(self) -> ByteIterator<T> {
|
|
ByteIterator{reader: self}
|
|
}
|
|
}
|
|
|
|
/// An iterator that reads a single byte on each iteration,
|
|
/// until `.read_byte()` returns `None`.
|
|
///
|
|
/// # Notes about the Iteration Protocol
|
|
///
|
|
/// The `ByteIterator` may yield `None` and thus terminate
|
|
/// an iteration, but continue to yield elements if iteration
|
|
/// is attempted again.
|
|
///
|
|
/// # Failure
|
|
///
|
|
/// Raises the same conditions as the `read` method, for
|
|
/// each call to its `.next()` method.
|
|
/// Yields `None` if the condition is handled.
|
|
pub struct ByteIterator<T> {
|
|
priv reader: T,
|
|
}
|
|
|
|
impl<R> Decorator<R> for ByteIterator<R> {
|
|
fn inner(self) -> R { self.reader }
|
|
fn inner_ref<'a>(&'a self) -> &'a R { &self.reader }
|
|
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { &mut self.reader }
|
|
}
|
|
|
|
impl<'self, R: Reader> Iterator<u8> for ByteIterator<R> {
|
|
#[inline]
|
|
fn next(&mut self) -> Option<u8> {
|
|
self.reader.read_byte()
|
|
}
|
|
}
|
|
|
|
impl<T: Reader> ReaderByteConversions for T {
|
|
fn read_le_uint_n_(&mut self, nbytes: uint) -> u64 {
|
|
assert!(nbytes > 0 && nbytes <= 8);
|
|
|
|
let mut val = 0u64;
|
|
let mut pos = 0;
|
|
let mut i = nbytes;
|
|
while i > 0 {
|
|
val += (self.read_u8_() as u64) << pos;
|
|
pos += 8;
|
|
i -= 1;
|
|
}
|
|
val
|
|
}
|
|
|
|
fn read_le_int_n_(&mut self, nbytes: uint) -> i64 {
|
|
extend_sign(self.read_le_uint_n_(nbytes), nbytes)
|
|
}
|
|
|
|
fn read_be_uint_n_(&mut self, nbytes: uint) -> u64 {
|
|
assert!(nbytes > 0 && nbytes <= 8);
|
|
|
|
let mut val = 0u64;
|
|
let mut i = nbytes;
|
|
while i > 0 {
|
|
i -= 1;
|
|
val += (self.read_u8_() as u64) << i * 8;
|
|
}
|
|
val
|
|
}
|
|
|
|
fn read_be_int_n_(&mut self, nbytes: uint) -> i64 {
|
|
extend_sign(self.read_be_uint_n_(nbytes), nbytes)
|
|
}
|
|
|
|
fn read_le_uint_(&mut self) -> uint {
|
|
self.read_le_uint_n_(uint::bytes) as uint
|
|
}
|
|
|
|
fn read_le_int_(&mut self) -> int {
|
|
self.read_le_int_n_(int::bytes) as int
|
|
}
|
|
|
|
fn read_be_uint_(&mut self) -> uint {
|
|
self.read_be_uint_n_(uint::bytes) as uint
|
|
}
|
|
|
|
fn read_be_int_(&mut self) -> int {
|
|
self.read_be_int_n_(int::bytes) as int
|
|
}
|
|
|
|
fn read_be_u64_(&mut self) -> u64 {
|
|
self.read_be_uint_n_(8) as u64
|
|
}
|
|
|
|
fn read_be_u32_(&mut self) -> u32 {
|
|
self.read_be_uint_n_(4) as u32
|
|
}
|
|
|
|
fn read_be_u16_(&mut self) -> u16 {
|
|
self.read_be_uint_n_(2) as u16
|
|
}
|
|
|
|
fn read_be_i64_(&mut self) -> i64 {
|
|
self.read_be_int_n_(8) as i64
|
|
}
|
|
|
|
fn read_be_i32_(&mut self) -> i32 {
|
|
self.read_be_int_n_(4) as i32
|
|
}
|
|
|
|
fn read_be_i16_(&mut self) -> i16 {
|
|
self.read_be_int_n_(2) as i16
|
|
}
|
|
|
|
fn read_be_f64_(&mut self) -> f64 {
|
|
unsafe {
|
|
cast::transmute::<u64, f64>(self.read_be_u64_())
|
|
}
|
|
}
|
|
|
|
fn read_be_f32_(&mut self) -> f32 {
|
|
unsafe {
|
|
cast::transmute::<u32, f32>(self.read_be_u32_())
|
|
}
|
|
}
|
|
|
|
fn read_le_u64_(&mut self) -> u64 {
|
|
self.read_le_uint_n_(8) as u64
|
|
}
|
|
|
|
fn read_le_u32_(&mut self) -> u32 {
|
|
self.read_le_uint_n_(4) as u32
|
|
}
|
|
|
|
fn read_le_u16_(&mut self) -> u16 {
|
|
self.read_le_uint_n_(2) as u16
|
|
}
|
|
|
|
fn read_le_i64_(&mut self) -> i64 {
|
|
self.read_le_int_n_(8) as i64
|
|
}
|
|
|
|
fn read_le_i32_(&mut self) -> i32 {
|
|
self.read_le_int_n_(4) as i32
|
|
}
|
|
|
|
fn read_le_i16_(&mut self) -> i16 {
|
|
self.read_le_int_n_(2) as i16
|
|
}
|
|
|
|
fn read_le_f64_(&mut self) -> f64 {
|
|
unsafe {
|
|
cast::transmute::<u64, f64>(self.read_le_u64_())
|
|
}
|
|
}
|
|
|
|
fn read_le_f32_(&mut self) -> f32 {
|
|
unsafe {
|
|
cast::transmute::<u32, f32>(self.read_le_u32_())
|
|
}
|
|
}
|
|
|
|
fn read_u8_(&mut self) -> u8 {
|
|
match self.read_byte() {
|
|
Some(b) => b as u8,
|
|
None => 0
|
|
}
|
|
}
|
|
|
|
fn read_i8_(&mut self) -> i8 {
|
|
match self.read_byte() {
|
|
Some(b) => b as i8,
|
|
None => 0
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
impl<T: Writer> WriterByteConversions for T {
|
|
fn write_int_(&mut self, n: int) {
|
|
int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
|
|
}
|
|
|
|
fn write_uint_(&mut self, n: uint) {
|
|
uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
|
|
}
|
|
|
|
fn write_le_uint_(&mut self, n: uint) {
|
|
u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_int_(&mut self, n: int) {
|
|
u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_uint_(&mut self, n: uint) {
|
|
u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_int_(&mut self, n: int) {
|
|
u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_u64_(&mut self, n: u64) {
|
|
u64_to_be_bytes(n, 8u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_u32_(&mut self, n: u32) {
|
|
u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_u16_(&mut self, n: u16) {
|
|
u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_i64_(&mut self, n: i64) {
|
|
u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_i32_(&mut self, n: i32) {
|
|
u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_i16_(&mut self, n: i16) {
|
|
u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_be_f64_(&mut self, f: f64) {
|
|
unsafe {
|
|
self.write_be_u64_(cast::transmute(f))
|
|
}
|
|
}
|
|
|
|
fn write_be_f32_(&mut self, f: f32) {
|
|
unsafe {
|
|
self.write_be_u32_(cast::transmute(f))
|
|
}
|
|
}
|
|
|
|
fn write_le_u64_(&mut self, n: u64) {
|
|
u64_to_le_bytes(n, 8u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_u32_(&mut self, n: u32) {
|
|
u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_u16_(&mut self, n: u16) {
|
|
u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_i64_(&mut self, n: i64) {
|
|
u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_i32_(&mut self, n: i32) {
|
|
u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_i16_(&mut self, n: i16) {
|
|
u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
|
}
|
|
|
|
fn write_le_f64_(&mut self, f: f64) {
|
|
unsafe {
|
|
self.write_le_u64_(cast::transmute(f))
|
|
}
|
|
}
|
|
|
|
fn write_le_f32_(&mut self, f: f32) {
|
|
unsafe {
|
|
self.write_le_u32_(cast::transmute(f))
|
|
}
|
|
}
|
|
|
|
fn write_u8_(&mut self, n: u8) {
|
|
self.write([n])
|
|
}
|
|
|
|
fn write_i8_(&mut self, n: i8) {
|
|
self.write([n as u8])
|
|
}
|
|
}
|
|
|
|
fn extend_sign(val: u64, nbytes: uint) -> i64 {
|
|
let shift = (8 - nbytes) * 8;
|
|
(val << shift) as i64 >> shift
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::ReaderUtil;
|
|
use option::{Some, None};
|
|
use cell::Cell;
|
|
use rt::io::mem::{MemReader, MemWriter};
|
|
use rt::io::mock::MockReader;
|
|
use rt::io::{read_error, placeholder_error};
|
|
|
|
#[test]
|
|
fn read_byte() {
|
|
let mut reader = MemReader::new(~[10]);
|
|
let byte = reader.read_byte();
|
|
assert!(byte == Some(10));
|
|
}
|
|
|
|
#[test]
|
|
fn read_byte_0_bytes() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
Some(0)
|
|
} else {
|
|
buf[0] = 10;
|
|
Some(1)
|
|
}
|
|
}
|
|
};
|
|
let byte = reader.read_byte();
|
|
assert!(byte == Some(10));
|
|
}
|
|
|
|
#[test]
|
|
fn read_byte_eof() {
|
|
let mut reader = MockReader::new();
|
|
reader.read = |_| None;
|
|
let byte = reader.read_byte();
|
|
assert!(byte == None);
|
|
}
|
|
|
|
#[test]
|
|
fn read_byte_error() {
|
|
let mut reader = MockReader::new();
|
|
reader.read = |_| {
|
|
read_error::cond.raise(placeholder_error());
|
|
None
|
|
};
|
|
do read_error::cond.trap(|_| {
|
|
}).inside {
|
|
let byte = reader.read_byte();
|
|
assert!(byte == None);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn bytes_0_bytes() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
Some(0)
|
|
} else {
|
|
buf[0] = 10;
|
|
Some(1)
|
|
}
|
|
}
|
|
};
|
|
let byte = reader.bytes().next();
|
|
assert!(byte == Some(10));
|
|
}
|
|
|
|
#[test]
|
|
fn bytes_eof() {
|
|
let mut reader = MockReader::new();
|
|
reader.read = |_| None;
|
|
let byte = reader.bytes().next();
|
|
assert!(byte == None);
|
|
}
|
|
|
|
#[test]
|
|
fn bytes_error() {
|
|
let mut reader = MockReader::new();
|
|
reader.read = |_| {
|
|
read_error::cond.raise(placeholder_error());
|
|
None
|
|
};
|
|
let mut it = reader.bytes();
|
|
do read_error::cond.trap(|_| ()).inside {
|
|
let byte = it.next();
|
|
assert!(byte == None);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn read_bytes() {
|
|
let mut reader = MemReader::new(~[10, 11, 12, 13]);
|
|
let bytes = reader.read_bytes(4);
|
|
assert!(bytes == ~[10, 11, 12, 13]);
|
|
}
|
|
|
|
#[test]
|
|
fn read_bytes_partial() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
buf[0] = 10;
|
|
buf[1] = 11;
|
|
Some(2)
|
|
} else {
|
|
buf[0] = 12;
|
|
buf[1] = 13;
|
|
Some(2)
|
|
}
|
|
}
|
|
};
|
|
let bytes = reader.read_bytes(4);
|
|
assert!(bytes == ~[10, 11, 12, 13]);
|
|
}
|
|
|
|
#[test]
|
|
fn read_bytes_eof() {
|
|
let mut reader = MemReader::new(~[10, 11]);
|
|
do read_error::cond.trap(|_| {
|
|
}).inside {
|
|
assert!(reader.read_bytes(4) == ~[10, 11]);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn push_bytes() {
|
|
let mut reader = MemReader::new(~[10, 11, 12, 13]);
|
|
let mut buf = ~[8, 9];
|
|
reader.push_bytes(&mut buf, 4);
|
|
assert!(buf == ~[8, 9, 10, 11, 12, 13]);
|
|
}
|
|
|
|
#[test]
|
|
fn push_bytes_partial() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
buf[0] = 10;
|
|
buf[1] = 11;
|
|
Some(2)
|
|
} else {
|
|
buf[0] = 12;
|
|
buf[1] = 13;
|
|
Some(2)
|
|
}
|
|
}
|
|
};
|
|
let mut buf = ~[8, 9];
|
|
reader.push_bytes(&mut buf, 4);
|
|
assert!(buf == ~[8, 9, 10, 11, 12, 13]);
|
|
}
|
|
|
|
#[test]
|
|
fn push_bytes_eof() {
|
|
let mut reader = MemReader::new(~[10, 11]);
|
|
let mut buf = ~[8, 9];
|
|
do read_error::cond.trap(|_| {
|
|
}).inside {
|
|
reader.push_bytes(&mut buf, 4);
|
|
assert!(buf == ~[8, 9, 10, 11]);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn push_bytes_error() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
buf[0] = 10;
|
|
Some(1)
|
|
} else {
|
|
read_error::cond.raise(placeholder_error());
|
|
None
|
|
}
|
|
}
|
|
};
|
|
let mut buf = ~[8, 9];
|
|
do read_error::cond.trap(|_| { } ).inside {
|
|
reader.push_bytes(&mut buf, 4);
|
|
}
|
|
assert!(buf == ~[8, 9, 10]);
|
|
}
|
|
|
|
#[test]
|
|
#[should_fail]
|
|
fn push_bytes_fail_reset_len() {
|
|
// push_bytes unsafely sets the vector length. This is testing that
|
|
// upon failure the length is reset correctly.
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
buf[0] = 10;
|
|
Some(1)
|
|
} else {
|
|
read_error::cond.raise(placeholder_error());
|
|
None
|
|
}
|
|
}
|
|
};
|
|
let buf = @mut ~[8, 9];
|
|
do (|| {
|
|
reader.push_bytes(&mut *buf, 4);
|
|
}).finally {
|
|
// NB: Using rtassert here to trigger abort on failure since this is a should_fail test
|
|
// FIXME: #7049 This fails because buf is still borrowed
|
|
//rtassert!(*buf == ~[8, 9, 10]);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn read_to_end() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
buf[0] = 10;
|
|
buf[1] = 11;
|
|
Some(2)
|
|
} else if *count == 1 {
|
|
*count = 2;
|
|
buf[0] = 12;
|
|
buf[1] = 13;
|
|
Some(2)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
};
|
|
let buf = reader.read_to_end();
|
|
assert!(buf == ~[10, 11, 12, 13]);
|
|
}
|
|
|
|
#[test]
|
|
#[should_fail]
|
|
fn read_to_end_error() {
|
|
let mut reader = MockReader::new();
|
|
let count = Cell::new(0);
|
|
reader.read = |buf| {
|
|
do count.with_mut_ref |count| {
|
|
if *count == 0 {
|
|
*count = 1;
|
|
buf[0] = 10;
|
|
buf[1] = 11;
|
|
Some(2)
|
|
} else {
|
|
read_error::cond.raise(placeholder_error());
|
|
None
|
|
}
|
|
}
|
|
};
|
|
let buf = reader.read_to_end();
|
|
assert!(buf == ~[10, 11]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_read_write_le_mem() {
|
|
let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
|
|
|
|
let mut writer = MemWriter::new();
|
|
for i in uints.iter() {
|
|
writer.write_le_u64_(*i);
|
|
}
|
|
|
|
let mut reader = MemReader::new(writer.inner());
|
|
for i in uints.iter() {
|
|
assert!(reader.read_le_u64_() == *i);
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn test_read_write_be() {
|
|
let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
|
|
|
|
let mut writer = MemWriter::new();
|
|
for i in uints.iter() {
|
|
writer.write_be_u64_(*i);
|
|
}
|
|
|
|
let mut reader = MemReader::new(writer.inner());
|
|
for i in uints.iter() {
|
|
assert!(reader.read_be_u64_() == *i);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_read_be_int_n() {
|
|
let ints = [::i32::min_value, -123456, -42, -5, 0, 1, ::i32::max_value];
|
|
|
|
let mut writer = MemWriter::new();
|
|
for i in ints.iter() {
|
|
writer.write_be_i32_(*i);
|
|
}
|
|
|
|
let mut reader = MemReader::new(writer.inner());
|
|
for i in ints.iter() {
|
|
// this tests that the sign extension is working
|
|
// (comparing the values as i32 would not test this)
|
|
assert!(reader.read_be_int_n_(4) == *i as i64);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_read_f32() {
|
|
//big-endian floating-point 8.1250
|
|
let buf = ~[0x41, 0x02, 0x00, 0x00];
|
|
|
|
let mut writer = MemWriter::new();
|
|
writer.write(buf);
|
|
|
|
let mut reader = MemReader::new(writer.inner());
|
|
let f = reader.read_be_f32_();
|
|
assert!(f == 8.1250);
|
|
}
|
|
|
|
#[test]
|
|
fn test_read_write_f32() {
|
|
let f:f32 = 8.1250;
|
|
|
|
let mut writer = MemWriter::new();
|
|
writer.write_be_f32_(f);
|
|
writer.write_le_f32_(f);
|
|
|
|
let mut reader = MemReader::new(writer.inner());
|
|
assert!(reader.read_be_f32_() == 8.1250);
|
|
assert!(reader.read_le_f32_() == 8.1250);
|
|
}
|
|
|
|
}
|