Mercurial > touhou
comparison utils/src/bitstream.rs @ 757:21b186be2590
Split the Rust version into multiple crates.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 05 Jan 2021 02:16:32 +0100 |
parents | src/util/bitstream.rs@afa012bb8021 |
children | daa23a4ff24d |
comparison
equal
deleted
inserted
replaced
756:4d91790cf8ab | 757:21b186be2590 |
---|---|
1 //! Bitstream module. | |
2 | |
3 use std::io; | |
4 | |
5 /// Wrapper around any `Read` trait, to allow bit operations. | |
6 pub struct BitStream<R: io::Read + io::Seek> { | |
7 io: R, | |
8 remaining_bits: usize, | |
9 byte: u8, | |
10 } | |
11 | |
12 impl<R: io::Read + io::Seek> BitStream<R> { | |
13 /// Create a new bitstream. | |
14 pub fn new(io: R) -> BitStream<R> { | |
15 BitStream { | |
16 io, | |
17 remaining_bits: 0, | |
18 byte: 0, | |
19 } | |
20 } | |
21 | |
22 /// Seek inside the bitstream, ditching any unused data read. | |
23 pub fn seek(&mut self, seek_from: io::SeekFrom) -> io::Result<u64> { | |
24 self.remaining_bits = 0; | |
25 self.byte = 0; | |
26 self.io.seek(seek_from) | |
27 } | |
28 | |
29 fn fill_byte(&mut self) -> io::Result<()> { | |
30 assert!(self.remaining_bits == 0); | |
31 | |
32 let mut buf = [0u8; 1]; | |
33 self.io.read_exact(&mut buf)?; | |
34 self.byte = buf[0]; | |
35 self.remaining_bits = 8; | |
36 Ok(()) | |
37 } | |
38 | |
39 /// Read only one bit from the stream. | |
40 pub fn read_bit(&mut self) -> io::Result<bool> { | |
41 if self.remaining_bits == 0 { | |
42 self.fill_byte()?; | |
43 } | |
44 self.remaining_bits -= 1; | |
45 Ok((self.byte >> self.remaining_bits) & 0x01 != 0) | |
46 } | |
47 | |
48 /// Read `nb_bits` bits from the stream. | |
49 pub fn read(&mut self, nb_bits: usize) -> io::Result<usize> { | |
50 let mut nb_bits2 = nb_bits; | |
51 let mut value: usize = 0; | |
52 while nb_bits2 > 0 { | |
53 if self.remaining_bits == 0 { | |
54 self.fill_byte()?; | |
55 } | |
56 let read = if nb_bits2 > self.remaining_bits { self.remaining_bits } else { nb_bits2 }; | |
57 nb_bits2 -= read; | |
58 self.remaining_bits -= read; | |
59 value |= (self.byte as usize >> self.remaining_bits) << nb_bits2; | |
60 } | |
61 Ok(value & ((1 << nb_bits) - 1)) | |
62 } | |
63 | |
64 /// Read a given amount of bytes. | |
65 pub fn read_bytes(&mut self, nb_bytes: usize) -> io::Result<Vec<u8>> { | |
66 let mut buf = vec![0u8; nb_bytes]; | |
67 self.io.read_exact(&mut buf)?; | |
68 Ok(buf) | |
69 } | |
70 } | |
71 | |
72 #[cfg(test)] | |
73 mod tests { | |
74 use super::*; | |
75 use crate::util::SeekableSlice; | |
76 | |
77 #[test] | |
78 fn bit_by_bit() { | |
79 let data = SeekableSlice::new(&[1, 2, 3]); | |
80 let mut bitstream = BitStream::new(data); | |
81 | |
82 // 1 | |
83 assert_eq!(bitstream.read_bit().unwrap(), false); | |
84 assert_eq!(bitstream.read_bit().unwrap(), false); | |
85 assert_eq!(bitstream.read_bit().unwrap(), false); | |
86 assert_eq!(bitstream.read_bit().unwrap(), false); | |
87 assert_eq!(bitstream.read_bit().unwrap(), false); | |
88 assert_eq!(bitstream.read_bit().unwrap(), false); | |
89 assert_eq!(bitstream.read_bit().unwrap(), false); | |
90 assert_eq!(bitstream.read_bit().unwrap(), true); | |
91 | |
92 // 2 | |
93 assert_eq!(bitstream.read_bit().unwrap(), false); | |
94 assert_eq!(bitstream.read_bit().unwrap(), false); | |
95 assert_eq!(bitstream.read_bit().unwrap(), false); | |
96 assert_eq!(bitstream.read_bit().unwrap(), false); | |
97 assert_eq!(bitstream.read_bit().unwrap(), false); | |
98 assert_eq!(bitstream.read_bit().unwrap(), false); | |
99 assert_eq!(bitstream.read_bit().unwrap(), true); | |
100 assert_eq!(bitstream.read_bit().unwrap(), false); | |
101 | |
102 // 3 | |
103 assert_eq!(bitstream.read_bit().unwrap(), false); | |
104 assert_eq!(bitstream.read_bit().unwrap(), false); | |
105 assert_eq!(bitstream.read_bit().unwrap(), false); | |
106 assert_eq!(bitstream.read_bit().unwrap(), false); | |
107 assert_eq!(bitstream.read_bit().unwrap(), false); | |
108 assert_eq!(bitstream.read_bit().unwrap(), false); | |
109 assert_eq!(bitstream.read_bit().unwrap(), true); | |
110 assert_eq!(bitstream.read_bit().unwrap(), true); | |
111 | |
112 // Can’t read after the end. | |
113 bitstream.read_bit().unwrap_err(); | |
114 } | |
115 | |
116 #[test] | |
117 fn byte_by_byte() { | |
118 let data = SeekableSlice::new(&[1, 2, 3]); | |
119 let mut bitstream = BitStream::new(data); | |
120 | |
121 assert_eq!(bitstream.read(8).unwrap(), 1); | |
122 assert_eq!(bitstream.read(8).unwrap(), 2); | |
123 assert_eq!(bitstream.read(8).unwrap(), 3); | |
124 | |
125 // Can’t read after the end. | |
126 bitstream.read(1).unwrap_err(); | |
127 } | |
128 | |
129 #[test] | |
130 fn unaligned_bytes() { | |
131 let data = SeekableSlice::new(&[0, 129, 1, 128]); | |
132 let mut bitstream = BitStream::new(data); | |
133 | |
134 assert_eq!(bitstream.read_bit().unwrap(), false); | |
135 assert_eq!(bitstream.read(8).unwrap(), 1); | |
136 assert_eq!(bitstream.read(8).unwrap(), 2); | |
137 assert_eq!(bitstream.read(8).unwrap(), 3); | |
138 assert_eq!(bitstream.read(7).unwrap(), 0); | |
139 | |
140 // Can’t read after the end. | |
141 bitstream.read(1).unwrap_err(); | |
142 } | |
143 } |