1use std::{
2 io::{self, Seek},
3 rc::Rc,
4};
5
6use sit_algos::huffman::HuffmanReader;
7use sit_algos::huffman_fixed::HuffmanReader as HuffmanFixedReader;
8use sit_algos::lmzw::LmzwReader;
9use sit_algos::lz_huffman::LzHuffmanReader;
10use sit_algos::lzah::LzahReader;
11use sit_algos::lzw::LzwReader;
12use sit_algos::none::NoneReader;
13use sit_algos::rle90::Rle90Reader;
14use sit_algos::{arsenic::ArsenicReader, installer::InstallerReader};
15
16use crate::{Error, VerifyingEntryReader, structs::Algorithm};
17
18pub(crate) enum EntryReader<'a, R: io::Read + io::Seek> {
19 None {
20 reader: NoneReader<&'a mut R>,
21 },
22 Rle {
23 reader: Rle90Reader<NoneReader<&'a mut R>>,
24 },
25 Lzw {
26 reader: Box<LzwReader<NoneReader<&'a mut R>>>,
27 },
28 Huffman {
29 reader: HuffmanReader<NoneReader<&'a mut R>>,
30 },
31 Lzah {
32 reader: Box<LzahReader<NoneReader<&'a mut R>>>,
33 },
34 HuffmanFixed {
35 reader: Box<HuffmanFixedReader<NoneReader<&'a mut R>>>,
36 },
37 Lmzw {
38 reader: Box<LmzwReader<NoneReader<&'a mut R>>>,
39 },
40 LzHuffman {
41 reader: Box<LzHuffmanReader<NoneReader<&'a mut R>>>,
42 },
43 Installer {
44 reader: Box<InstallerReader<NoneReader<&'a mut R>>>,
45 },
46 Arsenic {
47 reader: Box<ArsenicReader<'a, NoneReader<&'a mut R>>>,
48 },
49}
50
51impl<'a, R: io::Read + io::Seek> EntryReader<'a, R> {
52 pub(crate) fn try_from(
53 reader: &'a mut Rc<R>,
54 algo: Algorithm,
55 uncompressed_size: u64,
56 compressed_size: usize,
57 offset: u64,
58 ) -> Result<Self, Error> {
59 unsafe { Rc::get_mut_unchecked(reader).seek(io::SeekFrom::Start(offset))? };
60
61 unsafe {
62 Ok(match algo {
63 Algorithm::None => EntryReader::None {
64 reader: NoneReader::with_length(
65 Rc::get_mut_unchecked(reader),
66 offset,
67 compressed_size as u64,
68 ),
69 },
70 Algorithm::RLE => EntryReader::Rle {
71 reader: Rle90Reader::new(
72 NoneReader::with_length(
73 Rc::get_mut_unchecked(reader),
74 offset,
75 compressed_size as u64,
76 ),
77 uncompressed_size,
78 ),
79 },
80 Algorithm::LZW => EntryReader::Lzw {
81 reader: Box::new(LzwReader::new(
82 NoneReader::with_length(
83 Rc::get_mut_unchecked(reader),
84 offset,
85 compressed_size as u64,
86 ),
87 uncompressed_size,
88 )),
89 },
90 Algorithm::Huffman => EntryReader::Huffman {
91 reader: HuffmanReader::try_from(
92 NoneReader::with_length(
93 Rc::get_mut_unchecked(reader),
94 offset,
95 compressed_size as u64,
96 ),
97 uncompressed_size,
98 )?,
99 },
100 Algorithm::LZAH => EntryReader::Lzah {
101 reader: Box::new(LzahReader::new(
102 NoneReader::with_length(
103 Rc::get_mut_unchecked(reader),
104 offset,
105 compressed_size as u64,
106 ),
107 uncompressed_size,
108 )),
109 },
110 Algorithm::HuffmanFixed => EntryReader::HuffmanFixed {
111 reader: Box::new(HuffmanFixedReader::try_from(
112 NoneReader::with_length(
113 Rc::get_mut_unchecked(reader),
114 offset,
115 compressed_size as u64,
116 ),
117 uncompressed_size,
118 )?),
119 },
120 Algorithm::LZMW => EntryReader::Lmzw {
121 reader: Box::new(LmzwReader::new(
122 NoneReader::with_length(
123 Rc::get_mut_unchecked(reader),
124 offset,
125 compressed_size as u64,
126 ),
127 uncompressed_size,
128 )),
129 },
130 Algorithm::LzHuffman => EntryReader::LzHuffman {
131 reader: Box::new(LzHuffmanReader::new(
132 NoneReader::with_length(
133 Rc::get_mut_unchecked(reader),
134 offset,
135 compressed_size as u64,
136 ),
137 uncompressed_size,
138 )),
139 },
140 Algorithm::Installer => EntryReader::Installer {
141 reader: Box::new(InstallerReader::try_new(NoneReader::with_length(
142 Rc::get_mut_unchecked(reader),
143 offset,
144 compressed_size as u64,
145 ))?),
146 },
147 Algorithm::Arsenic => EntryReader::Arsenic {
148 reader: Box::new(ArsenicReader::try_from(
149 NoneReader::with_length(
150 Rc::get_mut_unchecked(reader),
151 offset,
152 compressed_size as u64,
153 ),
154 uncompressed_size,
155 )?),
156 },
157 Algorithm::Unknown(id) => {
158 return Err(Error::UnsupportedFeature(
159 crate::error::UnsupportedFeature::Algorithm(Algorithm::Unknown(id)),
160 ));
161 }
162 })
163 }
164 }
165
166 pub fn verifying(self, checksum: u16) -> VerifyingEntryReader<'a, R> {
167 let is_arsenic = matches!(self, EntryReader::Arsenic { .. });
170
171 VerifyingEntryReader::new(self, checksum, is_arsenic)
172 }
173
174 pub(crate) fn ended(&mut self) -> Result<bool, io::Error> {
175 Ok(self.stream_position()? >= self.stream_len()?)
176 }
177}
178
179impl<'a, R: io::Read + io::Seek> io::Read for EntryReader<'a, R> {
180 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
181 match self {
182 EntryReader::None { reader, .. } => reader.read(buf),
183 EntryReader::Rle { reader, .. } => reader.read(buf),
184 EntryReader::Lzw { reader, .. } => reader.read(buf),
185 EntryReader::Huffman { reader, .. } => reader.read(buf),
186 EntryReader::Lzah { reader, .. } => reader.read(buf),
187 EntryReader::HuffmanFixed { reader, .. } => reader.read(buf),
188 EntryReader::Lmzw { reader, .. } => reader.read(buf),
189 EntryReader::LzHuffman { reader, .. } => reader.read(buf),
190 EntryReader::Installer { reader } => reader.read(buf),
191 EntryReader::Arsenic { reader, .. } => reader.read(buf),
192 }
193 }
194}
195
196impl<'a, R: io::Read + io::Seek> io::Seek for EntryReader<'a, R> {
197 #[inline]
198 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
199 match self {
200 EntryReader::None { reader, .. } => reader.seek(pos),
201 EntryReader::Rle { reader, .. } => reader.seek(pos),
202 EntryReader::Lzw { reader, .. } => reader.seek(pos),
203 EntryReader::Huffman { reader, .. } => reader.seek(pos),
204 EntryReader::Lzah { reader, .. } => reader.seek(pos),
205 EntryReader::HuffmanFixed { reader, .. } => reader.seek(pos),
206 EntryReader::Lmzw { reader, .. } => reader.seek(pos),
207 EntryReader::LzHuffman { reader, .. } => reader.seek(pos),
208 EntryReader::Installer { reader } => reader.seek(pos),
209 EntryReader::Arsenic { reader, .. } => reader.seek(pos),
210 }
211 }
212
213 #[inline]
214 fn stream_position(&mut self) -> io::Result<u64> {
215 match self {
216 EntryReader::None { reader, .. } => reader.stream_position(),
217 EntryReader::Rle { reader, .. } => reader.stream_position(),
218 EntryReader::Lzw { reader, .. } => reader.stream_position(),
219 EntryReader::Huffman { reader, .. } => reader.stream_position(),
220 EntryReader::Lzah { reader, .. } => reader.stream_position(),
221 EntryReader::HuffmanFixed { reader, .. } => reader.stream_position(),
222 EntryReader::Lmzw { reader, .. } => reader.stream_position(),
223 EntryReader::LzHuffman { reader, .. } => reader.stream_position(),
224 EntryReader::Installer { reader, .. } => reader.stream_position(),
225 EntryReader::Arsenic { reader, .. } => reader.stream_position(),
226 }
227 }
228
229 #[inline]
230 fn stream_len(&mut self) -> io::Result<u64> {
231 match self {
232 EntryReader::None { reader, .. } => reader.stream_len(),
233 EntryReader::Rle { reader, .. } => reader.stream_len(),
234 EntryReader::Lzw { reader, .. } => reader.stream_len(),
235 EntryReader::Huffman { reader, .. } => reader.stream_len(),
236 EntryReader::Lzah { reader, .. } => reader.stream_len(),
237 EntryReader::HuffmanFixed { reader, .. } => reader.stream_len(),
238 EntryReader::Lmzw { reader, .. } => reader.stream_len(),
239 EntryReader::LzHuffman { reader, .. } => reader.stream_len(),
240 EntryReader::Installer { reader, .. } => reader.stream_len(),
241 EntryReader::Arsenic { reader, .. } => reader.stream_len(),
242 }
243 }
244}