|  | // Copyright 2015 Ilkka Rauta | 
|  | // | 
|  | // 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. | 
|  |  | 
|  | use super::*; | 
|  |  | 
|  | #[test] | 
|  | fn read_buffer() { | 
|  | let bytes = &[ | 
|  | 0b1011_0101, 0b0110_1010, 0b1010_1100, 0b1001_1001, | 
|  | 0b1001_1001, 0b1001_1001, 0b1001_1001, 0b1110_0111, | 
|  | ]; | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  |  | 
|  | assert_eq!(reader.read_u8(1).unwrap(), 0b1); | 
|  | assert_eq!(reader.peek_u8(3).unwrap(), 0b011); | 
|  | assert_eq!(reader.read_u8(1).unwrap(), 0b0); | 
|  | assert_eq!(reader.read_u8(2).unwrap(), 0b11); | 
|  |  | 
|  | assert!(!reader.is_aligned(1)); | 
|  | assert!(!reader.is_aligned(2)); | 
|  | assert!(!reader.is_aligned(4)); | 
|  |  | 
|  | assert_eq!(reader.position(), 4); | 
|  | assert_eq!(reader.remaining(), 60); | 
|  |  | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0101); | 
|  |  | 
|  | assert!(reader.is_aligned(1)); | 
|  | assert!(!reader.is_aligned(2)); | 
|  | assert!(!reader.is_aligned(4)); | 
|  |  | 
|  | assert_eq!(reader.align(1), Ok(())); // shouldn't do anything if already aligned | 
|  |  | 
|  | assert_eq!(reader.peek_u64(16).unwrap(), 0b110_1010_1010_1100); | 
|  | assert_eq!(reader.read_u8(3).unwrap(), 0b11); | 
|  | assert_eq!(reader.peek_u16(13).unwrap(), 0b1010_1010_1100); | 
|  | assert_eq!(reader.peek_u32(13).unwrap(), 0b1010_1010_1100); | 
|  | assert_eq!(reader.peek_u64(13).unwrap(), 0b1010_1010_1100); | 
|  | assert_eq!(reader.peek_u16(10).unwrap(), 0b01_0101_0101); | 
|  | assert_eq!(reader.peek_u8(8).unwrap(), 0b0101_0101); | 
|  | assert_eq!(reader.read_u16(10).unwrap(), 0b01_0101_0101); | 
|  | assert_eq!(reader.read_u8(3).unwrap(), 0b100); | 
|  |  | 
|  | assert_eq!(reader.position(), 24); | 
|  | assert_eq!(reader.remaining(), 40); | 
|  |  | 
|  | assert!(reader.is_aligned(1)); | 
|  |  | 
|  | assert_eq!(reader.read_u32(32).unwrap(), 0b1001_1001_1001_1001_1001_1001_1001_1001); | 
|  |  | 
|  | assert_eq!(reader.peek_bool().unwrap(), true); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b1110); | 
|  | assert_eq!(reader.peek_bool().unwrap(), false); | 
|  | assert_eq!(reader.read_u8(3).unwrap(), 0b011); | 
|  | assert_eq!(reader.peek_bool().unwrap(), true); | 
|  | assert_eq!(reader.read_bool().unwrap(), true); | 
|  |  | 
|  | // Could also be 8 at this point! | 
|  | assert!(reader.is_aligned(4)); | 
|  |  | 
|  | // shouldn't do anything if already aligned | 
|  | assert_eq!(reader.align(1), Ok(())); | 
|  | assert_eq!(reader.align(2), Ok(())); | 
|  | assert_eq!(reader.align(4), Ok(())); | 
|  | assert_eq!(reader.align(8), Ok(())); | 
|  |  | 
|  | // Start over to test align() | 
|  | let mut reader = BitReader::new(bytes); | 
|  |  | 
|  | // shouldn't do anything if already aligned | 
|  | assert_eq!(reader.align(1), Ok(())); | 
|  | assert_eq!(reader.align(2), Ok(())); | 
|  | assert_eq!(reader.align(4), Ok(())); | 
|  | assert_eq!(reader.align(8), Ok(())); | 
|  | assert_eq!(reader.position(), 0); | 
|  |  | 
|  | assert_eq!(reader.read_u8(1).unwrap(), 0b1); | 
|  |  | 
|  | assert_eq!(reader.align(1), Ok(())); | 
|  | assert_eq!(reader.position(), 8); | 
|  |  | 
|  | assert!(reader.is_aligned(1)); | 
|  | assert!(!reader.is_aligned(2)); | 
|  | assert!(!reader.is_aligned(4)); | 
|  |  | 
|  | assert_eq!(reader.align(2), Ok(())); | 
|  | assert_eq!(reader.position(), 16); | 
|  | assert!(reader.is_aligned(1)); | 
|  | assert!(reader.is_aligned(2)); | 
|  | assert!(!reader.is_aligned(4)); | 
|  |  | 
|  | assert_eq!(reader.read_u8(7).unwrap(), 0b0101_0110); | 
|  | assert_eq!(reader.align(4), Ok(())); | 
|  | assert_eq!(reader.position(), 32); | 
|  | assert!(reader.is_aligned(1)); | 
|  | assert!(reader.is_aligned(2)); | 
|  | assert!(reader.is_aligned(4)); | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.position(), 0); | 
|  | assert_eq!(reader.skip(1), Ok(())); | 
|  | assert_eq!(reader.align(4), Ok(())); | 
|  | assert_eq!(reader.position(), 32); | 
|  | assert_eq!(reader.skip(7), Ok(())); | 
|  | assert_eq!(reader.align(1), Ok(())); | 
|  | assert_eq!(reader.position(), 40); | 
|  | assert_eq!(reader.align(2), Ok(())); | 
|  | assert_eq!(reader.position(), 48); | 
|  | assert_eq!(reader.skip(5), Ok(())); | 
|  | assert_eq!(reader.align(2), Ok(())); | 
|  | assert_eq!(reader.position(), 64); | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.skip(1), Ok(())); | 
|  | assert_eq!(reader.align(3), Ok(())); | 
|  | assert_eq!(reader.position(), 24); | 
|  |  | 
|  | assert!(!reader.align(128).is_ok()); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn try_all_sizes() { | 
|  | let bytes = &[ | 
|  | 0x4a, 0x1e, 0x39, 0xbb, 0xd0, 0x07, 0xca, 0x9a, | 
|  | 0xa6, 0xba, 0x25, 0x52, 0x6f, 0x0a, 0x6a, 0xba, | 
|  | ]; | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u64(64).unwrap(), 0x4a1e39bbd007ca9a); | 
|  | assert_eq!(reader.read_u64(64).unwrap(), 0xa6ba25526f0a6aba); | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u32(32).unwrap(), 0x4a1e39bb); | 
|  | assert_eq!(reader.read_u32(32).unwrap(), 0xd007ca9a); | 
|  | assert_eq!(reader.read_u32(32).unwrap(), 0xa6ba2552); | 
|  | assert_eq!(reader.read_u32(32).unwrap(), 0x6f0a6aba); | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0x4a1e); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0x39bb); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0xd007); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0xca9a); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0xa6ba); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0x2552); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0x6f0a); | 
|  | assert_eq!(reader.read_u16(16).unwrap(), 0x6aba); | 
|  |  | 
|  | let mut reader = BitReader::new(&bytes[..]); | 
|  | for byte in bytes { | 
|  | assert_eq!(reader.read_u8(8).unwrap(), *byte); | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn skipping_and_zero_reads() { | 
|  | let bytes = &[ | 
|  | 0b1011_0101, 0b1110_1010, 0b1010_1100, 0b0011_0101, | 
|  | ]; | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  |  | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b1011); | 
|  | // Reading zero bits should be a no-op | 
|  | assert_eq!(reader.read_u8(0).unwrap(), 0b0); | 
|  | assert_eq!(reader.read_i8(0).unwrap(), 0b0); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0101); | 
|  | reader.skip(3).unwrap(); // 0b111 | 
|  | assert_eq!(reader.read_u16(10).unwrap(), 0b0101010101); | 
|  | assert_eq!(reader.read_u8(3).unwrap(), 0b100); | 
|  | reader.skip(4).unwrap(); // 0b0011 | 
|  | assert_eq!(reader.read_u32(2).unwrap(), 0b01); | 
|  | assert_eq!(reader.read_bool().unwrap(), false); | 
|  | assert_eq!(reader.read_bool().unwrap(), true); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn errors() { | 
|  | let bytes = &[ | 
|  | 0b1011_0101, 0b1110_1010, 0b1010_1100, | 
|  | ]; | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b1011); | 
|  | assert_eq!(reader.read_u8(9).unwrap_err(), BitReaderError::TooManyBitsForType { | 
|  | position: 4, | 
|  | requested: 9, | 
|  | allowed: 8 | 
|  | }); | 
|  | // If an error happens, it should be possible to resume as if nothing had happened | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0101); | 
|  |  | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b1011); | 
|  | // Same with this error | 
|  | assert_eq!(reader.read_u32(21).unwrap_err(), BitReaderError::NotEnoughData { | 
|  | position: 4, | 
|  | length: (bytes.len() * 8) as u64, | 
|  | requested: 21 | 
|  | }); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0101); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn signed_values() { | 
|  | let from = -2048; | 
|  | let to = 2048; | 
|  | for x in from..to { | 
|  | let bytes = &[ | 
|  | (x >> 8) as u8, | 
|  | x as u8, | 
|  | ]; | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), if x < 0 { 0b1111 } else { 0 }); | 
|  | assert_eq!(reader.read_i16(12).unwrap(), x); | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(feature = "std")] | 
|  | #[test] | 
|  | fn boolean_values() { | 
|  | let bytes: Vec<u8> = (0..16).collect(); | 
|  | let mut reader = BitReader::new(&bytes); | 
|  | for v in &bytes { | 
|  | assert_eq!(reader.read_bool().unwrap(), false); | 
|  | reader.skip(3).unwrap(); | 
|  | assert_eq!(reader.read_bool().unwrap(), v & 0x08 == 8); | 
|  | assert_eq!(reader.read_bool().unwrap(), v & 0x04 == 4); | 
|  | assert_eq!(reader.read_bool().unwrap(), v & 0x02 == 2); | 
|  | assert_eq!(reader.read_bool().unwrap(), v & 0x01 == 1); | 
|  | } | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn read_slice() { | 
|  | let bytes = &[ | 
|  | 0b1111_0000, 0b0000_1111, 0b1111_0000, | 
|  | 0b0000_1000, 0b0000_0100, 0b0000_0011, | 
|  | 0b1111_1100, 0b0000_0011, 0b1101_1000, | 
|  | ]; | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b1111); | 
|  | // Just some pattern that's definitely not in the bytes array | 
|  | let mut output = [0b1010_1101; 3]; | 
|  | reader.read_u8_slice(&mut output).unwrap(); | 
|  | assert_eq!(&output, &[0u8, 255u8, 0u8]); | 
|  |  | 
|  | assert_eq!(reader.read_u8(1).unwrap(), 1); | 
|  |  | 
|  | reader.read_u8_slice(&mut output[1..2]).unwrap(); | 
|  | assert_eq!(&output, &[0u8, 0u8, 0u8]); | 
|  |  | 
|  | assert_eq!(reader.read_u8(1).unwrap(), 1); | 
|  |  | 
|  | output = [0b1010_1101; 3]; | 
|  | reader.read_u8_slice(&mut output).unwrap(); | 
|  | assert_eq!(&output, &[0u8, 255u8, 0u8]); | 
|  |  | 
|  | reader.read_u8_slice(&mut output[0..1]).unwrap(); | 
|  | assert_eq!(output[0], 0b1111_0110); | 
|  |  | 
|  | assert_eq!(reader.read_u8(2).unwrap(), 0); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn read_slice_too_much() { | 
|  | let bytes = &[ | 
|  | 0b1111_1111, 0b1111_1111, 0b1111_1111, 0b1111_1111, | 
|  | ]; | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u8(1).unwrap(), 1); | 
|  |  | 
|  | let mut output = [0u8; 4]; | 
|  | let should_be_error = reader.read_u8_slice(&mut output); | 
|  | assert_eq!(should_be_error.unwrap_err(), BitReaderError::NotEnoughData { | 
|  | position: 1, | 
|  | length: (bytes.len() * 8) as u64, | 
|  | requested: (&output.len() * 8) as u64 | 
|  | }); | 
|  | assert_eq!(&output, &[0u8; 4]); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn relative_reader() { | 
|  | let bytes = &[ | 
|  | 0b0001_0010, 0b0011_0100, | 
|  | ]; | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0001); | 
|  |  | 
|  | let mut relative_reader = reader.relative_reader(); | 
|  |  | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0010); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0011); | 
|  | assert_eq!(reader.read_u8(4).unwrap(), 0b0100); | 
|  |  | 
|  | assert_eq!(reader.read_u8(1).unwrap_err(), BitReaderError::NotEnoughData { | 
|  | position: 16, | 
|  | length: 16, | 
|  | requested: 1 | 
|  | }); | 
|  |  | 
|  | assert_eq!(relative_reader.read_u8(4).unwrap(), 0b0010); | 
|  | assert_eq!(relative_reader.read_u8(4).unwrap(), 0b0011); | 
|  | assert_eq!(relative_reader.read_u8(4).unwrap(), 0b0100); | 
|  |  | 
|  | assert_eq!(relative_reader.read_u8(1).unwrap_err(), BitReaderError::NotEnoughData { | 
|  | position: 12, | 
|  | length: 12, | 
|  | requested: 1 | 
|  | }); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_read_u64_max() { | 
|  | let bytes = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_u64(64).unwrap(), u64::MAX); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_read_i64_max() { | 
|  | let bytes = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; | 
|  | let mut reader = BitReader::new(bytes); | 
|  | assert_eq!(reader.read_i64(64).unwrap(), -1); | 
|  | } |