1use crate::{
4 block::Block,
5 ext::WriteBlock,
6 headers::{ChunkHeader, ChunkType, FileHeader},
7 result::{Error, Result},
8};
9use byteorder::{LittleEndian, ReadBytesExt};
10use crc::crc32::{self, Hasher32};
11use std::{
12 io::{prelude::*, BufReader, ErrorKind},
13 mem, slice,
14};
15
16const BLOCK_SIZE: usize = Block::SIZE as usize;
17const U32_BLOCK_SIZE: usize = BLOCK_SIZE / mem::size_of::<u32>();
18
19pub struct Reader<R: Read> {
24 src: BufReader<R>,
25 current_chunk: Option<ChunkHeader>,
26 current_fill: Option<[u8; 4]>,
27 remaining_chunks: u32,
28 crc: Option<crc32::Digest>,
29 finished: bool,
30}
31
32impl<R: Read> Reader<R> {
33 pub fn new(r: R) -> Result<Self> {
39 let mut src = BufReader::new(r);
40 let header = FileHeader::read_from(&mut src)?;
41 Ok(Self {
42 src,
43 current_chunk: None,
44 current_fill: None,
45 remaining_chunks: header.total_chunks,
46 crc: None,
47 finished: false,
48 })
49 }
50
51 pub fn with_crc(r: R) -> Result<Self> {
54 let mut reader = Self::new(r)?;
55 reader.crc = Some(crc32::Digest::new(crc32::IEEE));
56 Ok(reader)
57 }
58
59 fn next_block(&mut self) -> Result<Block> {
60 let mut chunk = match self.current_chunk.take() {
61 Some(c) => c,
62 None => ChunkHeader::read_from(&mut self.src)?,
63 };
64
65 let block = self.read_block(&mut chunk)?;
66 if let Some(digest) = self.crc.as_mut() {
67 digest.write_block(&block);
68 }
69
70 if chunk.chunk_size <= 1 {
71 self.remaining_chunks -= 1;
72 self.current_chunk = None;
73 self.current_fill = None;
74 } else {
75 chunk.chunk_size -= 1;
76 self.current_chunk = Some(chunk);
77 }
78
79 Ok(block)
80 }
81
82 fn read_block(&mut self, chunk: &mut ChunkHeader) -> Result<Block> {
83 match chunk.chunk_type {
84 ChunkType::Raw => {
85 let mut buf = [0; BLOCK_SIZE];
86 self.src.read_exact(&mut buf)?;
87 Ok(Block::Raw(Box::new(buf)))
88 }
89 ChunkType::Fill => {
90 let value = match self.current_fill {
91 Some(v) => v,
92 None => {
93 self.current_fill = Some(read4(&mut self.src)?);
94 self.current_fill.unwrap()
95 }
96 };
97 Ok(Block::Fill(value))
98 }
99 ChunkType::DontCare => Ok(Block::Skip),
100 ChunkType::Crc32 => {
101 let checksum = self.src.read_u32::<LittleEndian>()?;
102 self.verify_checksum(checksum)?;
103 Ok(Block::Crc32(checksum))
104 }
105 }
106 }
107
108 fn verify_checksum(&self, checksum: u32) -> Result<()> {
109 if let Some(digest) = self.crc.as_ref() {
110 if digest.sum32() != checksum {
111 return Err(Error::Parse("Checksum does not match".into()));
112 }
113 }
114
115 Ok(())
116 }
117}
118
119impl<R: Read> Iterator for Reader<R> {
120 type Item = Result<Block>;
121
122 fn next(&mut self) -> Option<Self::Item> {
123 if self.finished {
124 return None;
125 }
126
127 let result = self.next_block();
128 self.finished = result.is_err() || self.remaining_chunks == 0;
129 Some(result)
130 }
131}
132
133fn read4<R: Read>(mut r: R) -> Result<[u8; 4]> {
134 let mut buf = [0; 4];
135 r.read_exact(&mut buf)?;
136 Ok(buf)
137}
138
139struct AlignedBuf([u32; U32_BLOCK_SIZE]);
146
147impl AlignedBuf {
148 fn new() -> Self {
149 AlignedBuf([0; U32_BLOCK_SIZE])
150 }
151
152 fn as_ref(&self) -> &[u8] {
153 let ptr = self.0.as_ptr().cast();
154 let len = self.0.len() * mem::size_of::<u32>();
155 unsafe { slice::from_raw_parts(ptr, len) }
156 }
157
158 fn as_mut(&mut self) -> &mut [u8] {
159 let ptr = self.0.as_mut_ptr().cast();
160 let len = self.0.len() * mem::size_of::<u32>();
161 unsafe { slice::from_raw_parts_mut(ptr, len) }
162 }
163
164 fn as_u32(&self) -> &[u32] {
165 &self.0
166 }
167
168 fn into_inner(self) -> [u8; BLOCK_SIZE] {
169 unsafe { mem::transmute::<[u32; U32_BLOCK_SIZE], [u8; BLOCK_SIZE]>(self.0) }
170 }
171}
172
173pub struct Encoder<R: Read> {
178 src: R,
179 finished: bool,
180}
181
182impl<R: Read> Encoder<R> {
183 pub fn new(r: R) -> Result<Self> {
185 Ok(Self {
186 src: r,
187 finished: false,
188 })
189 }
190
191 fn read_block(&mut self) -> Result<Option<Block>> {
192 let mut buf = AlignedBuf::new();
193 let bytes_read = read_all(&mut self.src, buf.as_mut())?;
194
195 let block = match bytes_read {
196 0 => None,
197 _ => Some(Self::encode_block(buf)),
198 };
199 Ok(block)
200 }
201
202 fn encode_block(buf: AlignedBuf) -> Block {
203 if is_sparse(buf.as_u32()) {
204 let value = read4(buf.as_ref()).unwrap();
205 if value == [0; 4] {
206 Block::Skip
207 } else {
208 Block::Fill(value)
209 }
210 } else {
211 Block::Raw(Box::new(buf.into_inner()))
212 }
213 }
214}
215
216impl<R: Read> Iterator for Encoder<R> {
217 type Item = Result<Block>;
218
219 fn next(&mut self) -> Option<Self::Item> {
220 if self.finished {
221 return None;
222 }
223
224 match self.read_block() {
225 Ok(Some(c)) => Some(Ok(c)),
226 Ok(None) => {
227 self.finished = true;
228 None
229 }
230 Err(e) => {
231 self.finished = true;
232 Some(Err(e))
233 }
234 }
235 }
236}
237
238fn read_all<R: Read>(mut r: R, mut buf: &mut [u8]) -> Result<usize> {
239 let buf_size = buf.len();
240
241 while !buf.is_empty() {
242 match r.read(buf) {
243 Ok(0) => break,
244 Ok(n) => {
245 let tmp = buf;
246 buf = &mut tmp[n..];
247 }
248 Err(ref e) if e.kind() == ErrorKind::Interrupted => (),
249 Err(e) => return Err(e.into()),
250 };
251 }
252
253 Ok(buf_size - buf.len())
254}
255
256fn is_sparse(buf: &[u32]) -> bool {
257 let mut parts = buf.iter();
258 let first = parts.next().unwrap();
259 parts.all(|p| p == first)
260}
261
262#[cfg(test)]
263mod test {
264 use super::*;
265
266 const U8_BUF: &[u8] = &[0xaa; BLOCK_SIZE];
267 const U32_BUF: &[u32] = &[0xaaaaaaaa; U32_BLOCK_SIZE];
268 const HALF_BLOCK_SIZE: usize = BLOCK_SIZE / 2;
269
270 #[test]
271 fn aligned_buf() {
272 let mut buf = AlignedBuf::new();
273 buf.as_mut().write_all(U8_BUF).unwrap();
274
275 assert_eq!(buf.as_ref(), U8_BUF);
276 assert_eq!(buf.as_u32(), U32_BUF);
277
278 let content = buf.into_inner();
279 assert_eq!(&content[..], U8_BUF);
280 }
281
282 #[test]
283 fn read4() {
284 assert_eq!(super::read4(U8_BUF).unwrap(), [0xaa; 4]);
285 }
286
287 #[test]
288 fn read_all() {
289 let mut buf = [0; BLOCK_SIZE];
290
291 assert_eq!(
292 super::read_all(&U8_BUF[..HALF_BLOCK_SIZE], &mut buf).unwrap(),
293 HALF_BLOCK_SIZE
294 );
295 assert_eq!(&buf[..HALF_BLOCK_SIZE], &U8_BUF[..HALF_BLOCK_SIZE]);
296 assert_eq!(&buf[HALF_BLOCK_SIZE..], &[0; HALF_BLOCK_SIZE][..]);
297
298 assert_eq!(super::read_all(U8_BUF, &mut buf).unwrap(), BLOCK_SIZE);
299 assert_eq!(&buf[..], U8_BUF);
300 }
301
302 #[test]
303 fn is_sparse() {
304 assert!(super::is_sparse(U32_BUF));
305
306 let buf: Vec<_> = (0..U32_BLOCK_SIZE as u32).collect();
307 assert!(!super::is_sparse(&buf));
308 }
309}