1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Utility mixins that apply to all Readers and Writers
13 #![allow(missing_docs)]
15 // FIXME: Not sure how this should be structured
16 // FIXME: Iteration should probably be considered separately
18 use io::{IoError, IoResult, Reader};
24 use option::Option::{Some, None};
26 use result::Result::{Ok, Err};
27 use slice::{SliceExt, AsSlice};
29 /// An iterator that reads a single byte on each iteration,
30 /// until `.read_byte()` returns `EndOfFile`.
32 /// # Notes about the Iteration Protocol
34 /// The `Bytes` may yield `None` and thus terminate
35 /// an iteration, but continue to yield elements if iteration
36 /// is attempted again.
40 /// Any error other than `EndOfFile` that is produced by the underlying Reader
41 /// is returned by the iterator and should be handled by the caller.
42 pub struct Bytes<'r, T:'r> {
46 impl<'r, R: Reader> Bytes<'r, R> {
47 /// Constructs a new byte iterator from the given Reader instance.
48 pub fn new(r: &'r mut R) -> Bytes<'r, R> {
55 impl<'r, R: Reader> Iterator for Bytes<'r, R> {
56 type Item = IoResult<u8>;
59 fn next(&mut self) -> Option<IoResult<u8>> {
60 match self.reader.read_byte() {
62 Err(IoError { kind: io::EndOfFile, .. }) => None,
63 Err(e) => Some(Err(e))
68 /// Converts an 8-bit to 64-bit unsigned value to a little-endian byte
69 /// representation of the given size. If the size is not big enough to
70 /// represent the value, then the high-order bytes are truncated.
74 /// * `n`: The value to convert.
75 /// * `size`: The size of the value, in bytes. This must be 8 or less, or task
76 /// panic occurs. If this is less than 8, then a value of that
77 /// many bytes is produced. For example, if `size` is 4, then a
78 /// 32-bit byte representation is produced.
79 /// * `f`: A callback that receives the value.
81 /// This function returns the value returned by the callback, for convenience.
82 pub fn u64_to_le_bytes<T, F>(n: u64, size: uint, f: F) -> T where
83 F: FnOnce(&[u8]) -> T,
87 // LLVM fails to properly optimize this when using shifts instead of the to_le* intrinsics
91 2u => f(unsafe { & transmute::<_, [u8; 2]>((n as u16).to_le()) }),
92 4u => f(unsafe { & transmute::<_, [u8; 4]>((n as u32).to_le()) }),
93 8u => f(unsafe { & transmute::<_, [u8; 8]>(n.to_le()) }),
96 let mut bytes = vec!();
100 bytes.push((n & 255_u64) as u8);
109 /// Converts an 8-bit to 64-bit unsigned value to a big-endian byte
110 /// representation of the given size. If the size is not big enough to
111 /// represent the value, then the high-order bytes are truncated.
115 /// * `n`: The value to convert.
116 /// * `size`: The size of the value, in bytes. This must be 8 or less, or task
117 /// panic occurs. If this is less than 8, then a value of that
118 /// many bytes is produced. For example, if `size` is 4, then a
119 /// 32-bit byte representation is produced.
120 /// * `f`: A callback that receives the value.
122 /// This function returns the value returned by the callback, for convenience.
123 pub fn u64_to_be_bytes<T, F>(n: u64, size: uint, f: F) -> T where
124 F: FnOnce(&[u8]) -> T,
128 // LLVM fails to properly optimize this when using shifts instead of the to_be* intrinsics
132 2u => f(unsafe { & transmute::<_, [u8; 2]>((n as u16).to_be()) }),
133 4u => f(unsafe { & transmute::<_, [u8; 4]>((n as u32).to_be()) }),
134 8u => f(unsafe { & transmute::<_, [u8; 8]>(n.to_be()) }),
136 let mut bytes = vec!();
139 let shift = (i - 1u) * 8u;
140 bytes.push((n >> shift) as u8);
148 /// Extracts an 8-bit to 64-bit unsigned big-endian value from the given byte
149 /// buffer and returns it as a 64-bit value.
153 /// * `data`: The buffer in which to extract the value.
154 /// * `start`: The offset at which to extract the value.
155 /// * `size`: The size of the value in bytes to extract. This must be 8 or
156 /// less, or task panic occurs. If this is less than 8, then only
157 /// that many bytes are parsed. For example, if `size` is 4, then a
158 /// 32-bit value is parsed.
159 pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
160 use ptr::{copy_nonoverlapping_memory};
165 if data.len() - start < size {
166 panic!("index out of bounds");
169 let mut buf = [0u8; 8];
171 let ptr = data.as_ptr().offset(start as int);
172 let out = buf.as_mut_ptr();
173 copy_nonoverlapping_memory(out.offset((8 - size) as int), ptr, size);
174 (*(out as *const u64)).to_be()
182 use io::{MemReader, BytesReader};
184 struct InitialZeroByteReader {
188 impl Reader for InitialZeroByteReader {
189 fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
202 impl Reader for EofReader {
203 fn read(&mut self, _: &mut [u8]) -> io::IoResult<uint> {
204 Err(io::standard_error(io::EndOfFile))
208 struct ErroringReader;
210 impl Reader for ErroringReader {
211 fn read(&mut self, _: &mut [u8]) -> io::IoResult<uint> {
212 Err(io::standard_error(io::InvalidInput))
216 struct PartialReader {
220 impl Reader for PartialReader {
221 fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
235 struct ErroringLaterReader {
239 impl Reader for ErroringLaterReader {
240 fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
246 Err(io::standard_error(io::InvalidInput))
251 struct ThreeChunkReader {
255 impl Reader for ThreeChunkReader {
256 fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
262 } else if self.count == 1 {
268 Err(io::standard_error(io::EndOfFile))
275 let mut reader = MemReader::new(vec!(10));
276 let byte = reader.read_byte();
277 assert!(byte == Ok(10));
281 fn read_byte_0_bytes() {
282 let mut reader = InitialZeroByteReader {
285 let byte = reader.read_byte();
286 assert!(byte == Ok(10));
291 let mut reader = EofReader;
292 let byte = reader.read_byte();
293 assert!(byte.is_err());
297 fn read_byte_error() {
298 let mut reader = ErroringReader;
299 let byte = reader.read_byte();
300 assert!(byte.is_err());
305 let mut reader = InitialZeroByteReader {
308 let byte = reader.bytes().next();
309 assert!(byte == Some(Ok(10)));
314 let mut reader = EofReader;
315 let byte = reader.bytes().next();
316 assert!(byte.is_none());
321 let mut reader = ErroringReader;
322 let mut it = reader.bytes();
323 let byte = it.next();
324 assert!(byte.unwrap().is_err());
329 let mut reader = MemReader::new(vec!(10, 11, 12, 13));
330 let bytes = reader.read_exact(4).unwrap();
331 assert!(bytes == vec!(10, 11, 12, 13));
335 fn read_bytes_partial() {
336 let mut reader = PartialReader {
339 let bytes = reader.read_exact(4).unwrap();
340 assert!(bytes == vec!(10, 11, 12, 13));
344 fn read_bytes_eof() {
345 let mut reader = MemReader::new(vec!(10, 11));
346 assert!(reader.read_exact(4).is_err());
351 let mut reader = MemReader::new(vec![10, 11, 12, 13]);
352 let mut buf = vec![8, 9];
353 assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
354 assert!(buf == vec![8, 9, 10, 11, 12, 13]);
358 fn push_at_least_partial() {
359 let mut reader = PartialReader {
362 let mut buf = vec![8, 9];
363 assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
364 assert!(buf == vec![8, 9, 10, 11, 12, 13]);
368 fn push_at_least_eof() {
369 let mut reader = MemReader::new(vec![10, 11]);
370 let mut buf = vec![8, 9];
371 assert!(reader.push_at_least(4, 4, &mut buf).is_err());
372 assert!(buf == vec![8, 9, 10, 11]);
376 fn push_at_least_error() {
377 let mut reader = ErroringLaterReader {
380 let mut buf = vec![8, 9];
381 assert!(reader.push_at_least(4, 4, &mut buf).is_err());
382 assert!(buf == vec![8, 9, 10]);
387 let mut reader = ThreeChunkReader {
390 let buf = reader.read_to_end().unwrap();
391 assert!(buf == vec!(10, 11, 12, 13));
396 fn read_to_end_error() {
397 let mut reader = ThreeChunkReader {
400 let buf = reader.read_to_end().unwrap();
401 assert!(buf == vec!(10, 11));
405 fn test_read_write_le_mem() {
406 let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::MAX];
408 let mut writer = Vec::new();
409 for i in uints.iter() {
410 writer.write_le_u64(*i).unwrap();
413 let mut reader = MemReader::new(writer);
414 for i in uints.iter() {
415 assert!(reader.read_le_u64().unwrap() == *i);
421 fn test_read_write_be() {
422 let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::MAX];
424 let mut writer = Vec::new();
425 for i in uints.iter() {
426 writer.write_be_u64(*i).unwrap();
429 let mut reader = MemReader::new(writer);
430 for i in uints.iter() {
431 assert!(reader.read_be_u64().unwrap() == *i);
436 fn test_read_be_int_n() {
437 let ints = [::i32::MIN, -123456, -42, -5, 0, 1, ::i32::MAX];
439 let mut writer = Vec::new();
440 for i in ints.iter() {
441 writer.write_be_i32(*i).unwrap();
444 let mut reader = MemReader::new(writer);
445 for i in ints.iter() {
446 // this tests that the sign extension is working
447 // (comparing the values as i32 would not test this)
448 assert!(reader.read_be_int_n(4).unwrap() == *i as i64);
454 //big-endian floating-point 8.1250
455 let buf = vec![0x41, 0x02, 0x00, 0x00];
457 let mut writer = Vec::new();
458 writer.write(buf.as_slice()).unwrap();
460 let mut reader = MemReader::new(writer);
461 let f = reader.read_be_f32().unwrap();
462 assert!(f == 8.1250);
466 fn test_read_write_f32() {
469 let mut writer = Vec::new();
470 writer.write_be_f32(f).unwrap();
471 writer.write_le_f32(f).unwrap();
473 let mut reader = MemReader::new(writer);
474 assert!(reader.read_be_f32().unwrap() == 8.1250);
475 assert!(reader.read_le_f32().unwrap() == 8.1250);
479 fn test_u64_from_be_bytes() {
480 use super::u64_from_be_bytes;
482 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
485 assert_eq!(u64_from_be_bytes(&buf, 0, 0), 0);
486 assert_eq!(u64_from_be_bytes(&buf, 0, 1), 0x01);
487 assert_eq!(u64_from_be_bytes(&buf, 0, 2), 0x0102);
488 assert_eq!(u64_from_be_bytes(&buf, 0, 3), 0x010203);
489 assert_eq!(u64_from_be_bytes(&buf, 0, 4), 0x01020304);
490 assert_eq!(u64_from_be_bytes(&buf, 0, 5), 0x0102030405);
491 assert_eq!(u64_from_be_bytes(&buf, 0, 6), 0x010203040506);
492 assert_eq!(u64_from_be_bytes(&buf, 0, 7), 0x01020304050607);
493 assert_eq!(u64_from_be_bytes(&buf, 0, 8), 0x0102030405060708);
496 assert_eq!(u64_from_be_bytes(&buf, 1, 0), 0);
497 assert_eq!(u64_from_be_bytes(&buf, 1, 1), 0x02);
498 assert_eq!(u64_from_be_bytes(&buf, 1, 2), 0x0203);
499 assert_eq!(u64_from_be_bytes(&buf, 1, 3), 0x020304);
500 assert_eq!(u64_from_be_bytes(&buf, 1, 4), 0x02030405);
501 assert_eq!(u64_from_be_bytes(&buf, 1, 5), 0x0203040506);
502 assert_eq!(u64_from_be_bytes(&buf, 1, 6), 0x020304050607);
503 assert_eq!(u64_from_be_bytes(&buf, 1, 7), 0x02030405060708);
504 assert_eq!(u64_from_be_bytes(&buf, 1, 8), 0x0203040506070809);
513 use self::test::Bencher;
515 // why is this a macro? wouldn't an inlined function work just as well?
516 macro_rules! u64_from_be_bytes_bench_impl {
517 ($b:expr, $size:expr, $stride:expr, $start_index:expr) =>
519 use super::u64_from_be_bytes;
521 let data = Vec::from_fn($stride*100+$start_index, |i| i as u8);
524 let mut i = $start_index;
525 while i < data.len() {
526 sum += u64_from_be_bytes(data.as_slice(), i, $size);
534 fn u64_from_be_bytes_4_aligned(b: &mut Bencher) {
535 u64_from_be_bytes_bench_impl!(b, 4, 4, 0);
539 fn u64_from_be_bytes_4_unaligned(b: &mut Bencher) {
540 u64_from_be_bytes_bench_impl!(b, 4, 4, 1);
544 fn u64_from_be_bytes_7_aligned(b: &mut Bencher) {
545 u64_from_be_bytes_bench_impl!(b, 7, 8, 0);
549 fn u64_from_be_bytes_7_unaligned(b: &mut Bencher) {
550 u64_from_be_bytes_bench_impl!(b, 7, 8, 1);
554 fn u64_from_be_bytes_8_aligned(b: &mut Bencher) {
555 u64_from_be_bytes_bench_impl!(b, 8, 8, 0);
559 fn u64_from_be_bytes_8_unaligned(b: &mut Bencher) {
560 u64_from_be_bytes_bench_impl!(b, 8, 8, 1);