1use std::{borrow::Cow, io::Read, ops::Range};
2
3use byteorder::{BigEndian, ReadBytesExt};
4
5use crate::{
6 error::{Error, Result},
7 Tag,
8};
9
10mod private {
11 pub trait Sealed {}
14}
15
16fn try_size(size: i32, multiplier: usize) -> Result<usize> {
17 let size: usize = size
18 .try_into()
19 .map_err(|_| Error::bespoke("size was negative".to_string()))?;
20
21 size.checked_mul(multiplier)
22 .ok_or_else(|| Error::bespoke("size too large".to_string()))
23}
24pub enum Reference<'b, 'c, T>
25where
26 T: ?Sized + 'static,
27{
28 Borrowed(&'b T),
29 Copied(&'c T),
30}
31
32impl<'b, 'c> AsRef<[u8]> for Reference<'b, 'c, [u8]> {
33 fn as_ref(&self) -> &[u8] {
34 match self {
35 Reference::Borrowed(bs) => bs,
36 Reference::Copied(bs) => bs,
37 }
38 }
39}
40
41pub trait Input<'de>: private::Sealed {
42 #[doc(hidden)]
43 fn consume_byte(&mut self) -> Result<u8>;
44
45 #[doc(hidden)]
49 fn ignore_str(&mut self) -> Result<()>;
50
51 #[doc(hidden)]
52 fn ignore_bytes(&mut self, size: usize) -> Result<()>;
53
54 fn consume_tag(&mut self) -> Result<Tag> {
55 let tag = self.consume_byte()?;
56 Tag::try_from(tag).map_err(|_| Error::invalid_tag(tag))
57 }
58
59 fn consume_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>>;
60
61 fn consume_bytes<'s>(
62 &'s mut self,
63 n: usize,
64 scratch: &'s mut Vec<u8>,
65 ) -> Result<Reference<'de, 's, [u8]>>;
66
67 fn consume_i16(&mut self) -> Result<i16>;
68 fn consume_i32(&mut self) -> Result<i32>;
69 fn consume_i64(&mut self) -> Result<i64>;
70 fn consume_f32(&mut self) -> Result<f32>;
71 fn consume_f64(&mut self) -> Result<f64>;
72
73 fn ignore_value(&mut self, tag: Tag) -> Result<()> {
74 match tag {
75 Tag::Byte => {
76 self.consume_byte()?;
77 }
78 Tag::Short => {
79 self.consume_i16()?;
80 }
81 Tag::Int => {
82 self.consume_i32()?;
83 }
84 Tag::Long => {
85 self.consume_i64()?;
86 }
87 Tag::Float => {
88 self.consume_f32()?;
89 }
90 Tag::Double => {
91 self.consume_f64()?;
92 }
93 Tag::String => {
94 self.ignore_str()?;
95 }
96 Tag::ByteArray => {
97 let size = self.consume_i32()? as usize;
98 self.ignore_bytes(size)?;
99 }
100 Tag::IntArray => {
101 let size = self.consume_i32()?;
102 self.ignore_bytes(try_size(size, std::mem::size_of::<i32>())?)?;
103 }
104 Tag::LongArray => {
105 let size = self.consume_i32()?;
106 self.ignore_bytes(try_size(size, std::mem::size_of::<i64>())?)?;
107 }
108 Tag::Compound => {
109 loop {
113 let tag = self.consume_tag()?;
114 if tag == Tag::End {
115 break;
116 }
117
118 self.ignore_str()?;
120 self.ignore_value(tag)?;
121 }
122 }
123 Tag::List => {
124 let element_tag = self.consume_tag()?;
125 let size = self.consume_i32()?;
126 for _ in 0..size {
127 self.ignore_value(element_tag)?;
128 }
129 }
130 Tag::End => {
131 unreachable!()
139 }
140 }
141
142 Ok(())
143 }
144}
145
146pub struct Slice<'de> {
147 pub(crate) data: &'de [u8],
148}
149
150impl<'de> private::Sealed for Slice<'de> {}
151impl<'de> Slice<'de> {
152 fn consume(&mut self, r: Range<usize>) -> Result<&'de [u8]> {
153 if r.end <= self.data.len() {
154 let ret = &self.data[r.start..r.end];
155 self.data = &self.data[r.end..];
156 Ok(ret)
157 } else {
158 Err(Error::unexpected_eof())
159 }
160 }
161}
162
163impl<'de> Input<'de> for Slice<'de> {
164 fn consume_byte(&mut self) -> Result<u8> {
165 Ok(self.consume(0..1)?[0])
166 }
167
168 fn ignore_str(&mut self) -> Result<()> {
169 let len = self.consume(0..2)?.read_u16::<BigEndian>()? as usize;
170 self.consume(0..len).map(|_| ())
171 }
172
173 fn consume_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>> {
174 let len = self.consume(0..2)?.read_u16::<BigEndian>()? as usize;
175 let str = self.consume(0..len)?;
176 let str = cesu8::from_java_cesu8(str).map_err(|_| Error::nonunicode_string(str))?;
177
178 Ok(match str {
179 Cow::Borrowed(str) => Reference::Borrowed(str),
180 Cow::Owned(str) => {
181 *scratch = str.into_bytes();
182 Reference::Copied(unsafe { std::str::from_utf8_unchecked(scratch) })
185 }
186 })
187 }
188
189 fn consume_bytes<'s>(
190 &'s mut self,
191 n: usize,
192 _scratch: &'s mut Vec<u8>,
193 ) -> Result<Reference<'de, 's, [u8]>> {
194 let bs = self.consume(0..n)?;
195 Ok(Reference::Borrowed(bs))
196 }
197
198 fn consume_i16(&mut self) -> Result<i16> {
199 let mut bs = self.consume(0..std::mem::size_of::<i16>())?;
200 Ok(bs.read_i16::<BigEndian>()?)
201 }
202
203 fn consume_i32(&mut self) -> Result<i32> {
204 let mut bs = self.consume(0..std::mem::size_of::<i32>())?;
205 Ok(bs.read_i32::<BigEndian>()?)
206 }
207
208 fn consume_i64(&mut self) -> Result<i64> {
209 let mut bs = self.consume(0..std::mem::size_of::<i64>())?;
210 Ok(bs.read_i64::<BigEndian>()?)
211 }
212
213 fn consume_f32(&mut self) -> Result<f32> {
214 let mut bs = self.consume(0..std::mem::size_of::<f32>())?;
215 Ok(bs.read_f32::<BigEndian>()?)
216 }
217
218 fn consume_f64(&mut self) -> Result<f64> {
219 let mut bs = self.consume(0..std::mem::size_of::<f64>())?;
220 Ok(bs.read_f64::<BigEndian>()?)
221 }
222
223 fn ignore_bytes(&mut self, size: usize) -> Result<()> {
224 self.consume(0..size)?;
225 Ok(())
226 }
227}
228
229pub struct Reader<R: Read> {
230 pub(crate) reader: R,
231}
232
233impl<R: Read> private::Sealed for Reader<R> {}
234
235impl<'de, R: Read> Input<'de> for Reader<R> {
236 fn consume_byte(&mut self) -> Result<u8> {
237 Ok(self.reader.read_u8()?)
238 }
239
240 fn ignore_str(&mut self) -> Result<()> {
241 let len = self.reader.read_u16::<BigEndian>()? as usize;
242 let mut buf = vec![0; len]; Ok(self.reader.read_exact(&mut buf)?)
244 }
245
246 fn consume_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>> {
247 let len = self.reader.read_u16::<BigEndian>()? as usize;
248 scratch.clear();
249 scratch.resize(len, 0);
250 self.reader.read_exact(scratch)?;
251
252 let str = cesu8::from_java_cesu8(scratch).map_err(|_| Error::nonunicode_string(scratch))?;
253
254 Ok(match str {
255 Cow::Borrowed(_) => {
256 Reference::Copied(unsafe { std::str::from_utf8_unchecked(scratch) })
257 }
258 Cow::Owned(s) => {
259 *scratch = s.into_bytes();
260 Reference::Copied(unsafe { std::str::from_utf8_unchecked(scratch) })
261 }
262 })
263 }
264
265 fn consume_bytes<'s>(
266 &'s mut self,
267 n: usize,
268 scratch: &'s mut Vec<u8>,
269 ) -> Result<Reference<'de, 's, [u8]>> {
270 scratch.clear();
271 scratch.resize(n, 0);
272 self.reader.read_exact(scratch.as_mut_slice())?;
273
274 Ok(Reference::Copied(scratch.as_slice()))
275 }
276
277 fn consume_i16(&mut self) -> Result<i16> {
278 Ok(self.reader.read_i16::<BigEndian>()?)
279 }
280
281 fn consume_i32(&mut self) -> Result<i32> {
282 Ok(self.reader.read_i32::<BigEndian>()?)
283 }
284
285 fn consume_i64(&mut self) -> Result<i64> {
286 Ok(self.reader.read_i64::<BigEndian>()?)
287 }
288
289 fn consume_f32(&mut self) -> Result<f32> {
290 Ok(self.reader.read_f32::<BigEndian>()?)
291 }
292
293 fn consume_f64(&mut self) -> Result<f64> {
294 Ok(self.reader.read_f64::<BigEndian>()?)
295 }
296
297 fn ignore_bytes(&mut self, size: usize) -> Result<()> {
298 let mut buf = vec![0; size]; self.reader.read_exact(&mut buf)?;
300 Ok(())
301 }
302}