1use crate::Variant;
4
5use std::collections::VecDeque;
6use std::io::{self, Cursor, Read, Write};
7
8pub struct PrsDecoder<R: Read, V: Variant> {
10 inner: R,
11 cmds: u8,
12 rem: u8,
13 copy_buf: VecDeque<u8>,
14 eof: bool,
15 pd: std::marker::PhantomData<V>,
16}
17
18#[derive(Debug)]
20enum Cmd {
21 Literal(u8),
22 Pointer(usize, usize),
23}
24
25impl<R: Read, V: Variant> PrsDecoder<R, V> {
26 pub fn new(inner: R) -> PrsDecoder<R, V> {
27 PrsDecoder {
28 inner,
29 cmds: 0,
30 rem: 0,
31 copy_buf: VecDeque::with_capacity(8191),
32 eof: false,
33 pd: std::marker::PhantomData,
34 }
35 }
36
37 fn read_bit(&mut self) -> io::Result<bool> {
38 if self.rem == 0 {
39 let mut buf = [0; 1];
40 self.inner.read_exact(&mut buf)?;
41 self.cmds = buf[0];
42 self.rem = 8;
43 }
44
45 let ret = self.cmds & 1;
46 self.cmds >>= 1;
47 self.rem -= 1;
48
49 match ret { 0 => Ok(false), _ => Ok(true) }
50 }
51
52 fn next_cmd(&mut self) -> io::Result<Option<Cmd>> {
53 if self.read_bit()? {
54 let mut buf = [0; 1];
56 self.inner.read_exact(&mut buf)?;
57 return Ok(Some(Cmd::Literal(buf[0])));
58 }
59
60 if self.read_bit()? {
61 let mut buf = [0; 2];
63 self.inner.read_exact(&mut buf)?;
64 let mut offset = i16::from_le_bytes(buf) as i32;
65
66 if offset == 0 {
67 return Ok(None);
68 }
69
70 let mut size = (offset & 0b111) as usize;
71 offset >>= 3;
72
73 if size == 0 {
74 self.inner.read_exact(&mut buf[..1])?;
76 size = buf[0] as usize;
77 size += V::MIN_LONG_COPY_LENGTH as usize;
79 } else {
80 size += 2;
81 }
82 offset |= -8192i32;
83
84 Ok(Some(Cmd::Pointer((-offset) as usize, size)))
85 } else {
86 let mut buf = [0; 1];
88 let flag = if self.read_bit()? { 1 } else { 0 };
89 let bit = if self.read_bit()? { 1 } else { 0 };
90 let size = (bit | (flag << 1)) + 2;
91 self.inner.read_exact(&mut buf)?;
92 let offset = buf[0] as i32;
93 let offset = offset | -256i32;
94
95 Ok(Some(Cmd::Pointer((-offset) as usize, size)))
96 }
97 }
98}
99
100impl<R: Read, V: Variant> Read for PrsDecoder<R, V> {
101 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
102 while self.copy_buf.len() < 8191 + buf.len() && !self.eof {
104 match self.next_cmd()? {
105 None => {
106 self.eof = true;
107 break;
108 },
109 Some(Cmd::Literal(b)) => {
110 self.copy_buf.push_back(b);
111 },
112 Some(Cmd::Pointer(offset, size)) => {
113 for _ in 0..size {
114 if offset == 0 || self.copy_buf.len() < offset {
115 return Err(io::Error::new(
116 io::ErrorKind::InvalidData,
117 "bad pointer copy in stream"
118 ));
119 }
120 self.copy_buf.push_back(self.copy_buf[self.copy_buf.len() - offset]);
121 }
122 },
123 }
124 }
125
126 let bytes_read = std::cmp::min(buf.len(), self.copy_buf.len());
128 let mut cursor = Cursor::new(buf);
129 self.copy_buf.drain(..bytes_read).for_each(|b| { cursor.write_all(&[b]).unwrap(); });
130
131 Ok(bytes_read)
132 }
133}