1use std::io;
4
5use byteorder::{BigEndian, ReadBytesExt};
6use num_traits::FromPrimitive;
7use scuffle_bytes_util::StringCow;
8use scuffle_bytes_util::zero_copy::ZeroCopyReader;
9
10use crate::{Amf0Array, Amf0Error, Amf0Marker, Amf0Object, Amf0Value};
11
12#[derive(Debug, Clone)]
16pub struct Amf0Decoder<R> {
17 pub(crate) reader: R,
18 pub(crate) next_marker: Option<Amf0Marker>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub(crate) enum ObjectHeader<'a> {
23 Object,
24 TypedObject {
25 name: StringCow<'a>,
26 },
27 EcmaArray {
28 size: u32,
29 },
30}
31
32impl<B> Amf0Decoder<scuffle_bytes_util::zero_copy::BytesBuf<B>>
33where
34 B: bytes::Buf,
35{
36 pub fn from_buf(buf: B) -> Self {
38 Self {
39 reader: buf.into(),
40 next_marker: None,
41 }
42 }
43}
44
45impl<R> Amf0Decoder<scuffle_bytes_util::zero_copy::IoRead<R>>
46where
47 R: std::io::Read,
48{
49 pub fn from_reader(reader: R) -> Self {
51 Self {
52 reader: reader.into(),
53 next_marker: None,
54 }
55 }
56}
57
58impl<'a> Amf0Decoder<scuffle_bytes_util::zero_copy::Slice<'a>> {
59 pub fn from_slice(slice: &'a [u8]) -> Amf0Decoder<scuffle_bytes_util::zero_copy::Slice<'a>> {
61 Self {
62 reader: slice.into(),
63 next_marker: None,
64 }
65 }
66}
67
68impl<'a, R> Amf0Decoder<R>
69where
70 R: ZeroCopyReader<'a>,
71{
72 pub fn decode_value(&mut self) -> Result<Amf0Value<'a>, Amf0Error> {
74 let marker = self.peek_marker()?;
75
76 match marker {
77 Amf0Marker::Boolean => self.decode_boolean().map(Into::into),
78 Amf0Marker::Number | Amf0Marker::Date => self.decode_number().map(Into::into),
79 Amf0Marker::String | Amf0Marker::LongString | Amf0Marker::XmlDocument => self.decode_string().map(Into::into),
80 Amf0Marker::Null | Amf0Marker::Undefined => self.decode_null().map(|_| Amf0Value::Null),
81 Amf0Marker::Object | Amf0Marker::TypedObject | Amf0Marker::EcmaArray => self.decode_object().map(Into::into),
82 Amf0Marker::StrictArray => self.decode_strict_array().map(Into::into),
83 _ => Err(Amf0Error::UnsupportedMarker(marker)),
84 }
85 }
86
87 pub fn decode_all(&mut self) -> Result<Vec<Amf0Value<'a>>, Amf0Error> {
89 let mut values = Vec::new();
90
91 while self.has_remaining()? {
92 values.push(self.decode_value()?);
93 }
94
95 Ok(values)
96 }
97
98 pub fn stream(&mut self) -> Amf0DecoderStream<'_, 'a, R> {
100 Amf0DecoderStream {
101 decoder: self,
102 _marker: std::marker::PhantomData,
103 }
104 }
105
106 pub fn has_remaining(&mut self) -> Result<bool, Amf0Error> {
108 match self.peek_marker() {
109 Ok(_) => Ok(true),
110 Err(Amf0Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => Ok(false),
111 Err(err) => Err(err),
112 }
113 }
114
115 pub fn peek_marker(&mut self) -> Result<Amf0Marker, Amf0Error> {
117 let marker = self.read_marker()?;
118 self.next_marker = Some(marker);
120
121 Ok(marker)
122 }
123
124 fn read_marker(&mut self) -> Result<Amf0Marker, Amf0Error> {
125 if let Some(marker) = self.next_marker.take() {
126 return Ok(marker);
127 }
128
129 let marker = self.reader.as_std().read_u8()?;
130 let marker = Amf0Marker::from_u8(marker).ok_or(Amf0Error::UnknownMarker(marker))?;
131 Ok(marker)
132 }
133
134 fn expect_marker(&mut self, expect: &'static [Amf0Marker]) -> Result<Amf0Marker, Amf0Error> {
135 let marker = self.read_marker()?;
136
137 if !expect.contains(&marker) {
138 Err(Amf0Error::UnexpectedType {
139 expected: expect,
140 got: marker,
141 })
142 } else {
143 Ok(marker)
144 }
145 }
146
147 pub fn decode_number(&mut self) -> Result<f64, Amf0Error> {
149 let marker = self.expect_marker(&[Amf0Marker::Number, Amf0Marker::Date])?;
150
151 let number = self.reader.as_std().read_f64::<BigEndian>()?;
152
153 if marker == Amf0Marker::Date {
154 self.reader.as_std().read_i16::<BigEndian>()?;
156 }
157
158 Ok(number)
159 }
160
161 pub fn decode_boolean(&mut self) -> Result<bool, Amf0Error> {
163 self.expect_marker(&[Amf0Marker::Boolean])?;
164 let value = self.reader.as_std().read_u8()?;
165 Ok(value != 0)
166 }
167
168 pub(crate) fn decode_normal_string(&mut self) -> Result<StringCow<'a>, Amf0Error> {
169 let len = self.reader.as_std().read_u16::<BigEndian>()? as usize;
170
171 let bytes = self.reader.try_read(len)?;
172 Ok(StringCow::from_bytes(bytes.into_bytes().try_into()?))
173 }
174
175 pub fn decode_string(&mut self) -> Result<StringCow<'a>, Amf0Error> {
179 let marker = self.expect_marker(&[Amf0Marker::String, Amf0Marker::LongString, Amf0Marker::XmlDocument])?;
180
181 let len = if marker == Amf0Marker::String {
182 self.reader.as_std().read_u16::<BigEndian>()? as usize
183 } else {
184 self.reader.as_std().read_u32::<BigEndian>()? as usize
186 };
187
188 let bytes = self.reader.try_read(len)?;
189 Ok(StringCow::from_bytes(bytes.into_bytes().try_into()?))
190 }
191
192 pub fn decode_null(&mut self) -> Result<(), Amf0Error> {
196 self.expect_marker(&[Amf0Marker::Null, Amf0Marker::Undefined])?;
197 Ok(())
198 }
199
200 #[cfg(feature = "serde")]
202 pub fn deserialize<T>(&mut self) -> Result<T, Amf0Error>
203 where
204 T: serde::de::Deserialize<'a>,
205 {
206 T::deserialize(self)
207 }
208
209 #[cfg(feature = "serde")]
211 pub fn deserialize_stream<T>(&mut self) -> crate::de::Amf0DeserializerStream<'_, R, T>
212 where
213 T: serde::de::Deserialize<'a>,
214 {
215 crate::de::Amf0DeserializerStream::new(self)
216 }
217
218 pub(crate) fn decode_object_header(&mut self) -> Result<ObjectHeader<'a>, Amf0Error> {
221 let marker = self.expect_marker(&[Amf0Marker::Object, Amf0Marker::TypedObject, Amf0Marker::EcmaArray])?;
222
223 if marker == Amf0Marker::Object {
224 Ok(ObjectHeader::Object)
225 } else if marker == Amf0Marker::TypedObject {
226 let name = self.decode_normal_string()?;
227 Ok(ObjectHeader::TypedObject { name })
228 } else {
229 let size = self.reader.as_std().read_u32::<BigEndian>()?;
231 Ok(ObjectHeader::EcmaArray { size })
232 }
233 }
234
235 pub(crate) fn decode_object_key(&mut self) -> Result<Option<StringCow<'a>>, Amf0Error> {
236 let key = self.decode_normal_string()?;
238
239 if key.as_str().is_empty() {
241 if self.peek_marker()? == Amf0Marker::ObjectEnd {
243 self.next_marker = None;
245
246 return Ok(None);
247 }
248 }
249
250 Ok(Some(key))
251 }
252
253 pub fn decode_object(&mut self) -> Result<Amf0Object<'a>, Amf0Error> {
257 let header = self.decode_object_header()?;
258
259 match header {
260 ObjectHeader::Object | ObjectHeader::TypedObject { .. } => {
261 let mut object = Amf0Object::new();
262
263 while let Some(key) = self.decode_object_key()? {
264 let value = self.decode_value()?;
265 object.insert(key, value);
266 }
267
268 Ok(object)
269 }
270 ObjectHeader::EcmaArray { size } => {
271 let mut object = Amf0Object::with_capacity(size as usize);
272
273 for _ in 0..size {
274 let key = self.decode_normal_string()?;
276 let value = self.decode_value()?;
277 object.insert(key, value);
278 }
279
280 if self.has_remaining()? && self.peek_marker()? == Amf0Marker::ObjectEnd {
282 self.next_marker = None;
284 }
285
286 Ok(object)
287 }
288 }
289 }
290
291 pub(crate) fn decode_strict_array_header(&mut self) -> Result<u32, Amf0Error> {
294 self.expect_marker(&[Amf0Marker::StrictArray])?;
295 let size = self.reader.as_std().read_u32::<BigEndian>()?;
296
297 Ok(size)
298 }
299
300 pub fn decode_strict_array(&mut self) -> Result<Amf0Array<'a>, Amf0Error> {
302 let size = self.decode_strict_array_header()? as usize;
303
304 let mut array = Vec::with_capacity(size);
305
306 for _ in 0..size {
307 let value = self.decode_value()?;
308 array.push(value);
309 }
310
311 Ok(Amf0Array::from(array))
312 }
313}
314
315#[must_use = "Iterators are lazy and do nothing unless consumed"]
319pub struct Amf0DecoderStream<'a, 'de, R> {
320 decoder: &'a mut Amf0Decoder<R>,
321 _marker: std::marker::PhantomData<&'de ()>,
322}
323
324impl<'de, R: ZeroCopyReader<'de>> Iterator for Amf0DecoderStream<'_, 'de, R> {
325 type Item = Result<Amf0Value<'de>, Amf0Error>;
326
327 fn next(&mut self) -> Option<Self::Item> {
328 match self.decoder.has_remaining() {
329 Ok(true) => Some(self.decoder.decode_value()),
330 Ok(false) => None,
331 Err(err) => Some(Err(err)),
332 }
333 }
334}
335
336impl<'de, R> std::iter::FusedIterator for Amf0DecoderStream<'_, 'de, R> where R: ZeroCopyReader<'de> {}
337
338#[cfg(test)]
339#[cfg_attr(all(test, coverage_nightly), coverage(off))]
340mod tests {
341 use super::Amf0Decoder;
342 use crate::{Amf0Marker, Amf0Value};
343
344 #[test]
345 fn strict_array() {
346 #[rustfmt::skip]
347 let bytes = [
348 Amf0Marker::StrictArray as u8,
349 0, 0, 0, 2, Amf0Marker::String as u8,
351 0, 3, b'v', b'a', b'l', Amf0Marker::Boolean as u8,
353 1, ];
355
356 let mut decoder = Amf0Decoder::from_slice(&bytes);
357 let array = decoder.decode_strict_array().unwrap();
358 assert_eq!(array.len(), 2);
359 assert_eq!(array[0], Amf0Value::String("val".into()));
360 assert_eq!(array[1], Amf0Value::Boolean(true));
361 }
362
363 #[test]
364 fn ecma_array() {
365 #[rustfmt::skip]
366 let bytes = [
367 Amf0Marker::EcmaArray as u8,
368 0, 0, 0, 2, 0, 3, b'a', b'b', b'c', Amf0Marker::String as u8,
371 0, 3, b'v', b'a', b'l', 0, 4, b'd', b'e', b'f', b'g', Amf0Marker::Boolean as u8,
374 1, ];
376
377 let mut decoder = Amf0Decoder::from_slice(&bytes);
378 let object = decoder.decode_object().unwrap();
379 assert_eq!(object.len(), 2);
380 assert_eq!(*object.get(&"abc".into()).unwrap(), Amf0Value::String("val".into()));
381 assert_eq!(*object.get(&"defg".into()).unwrap(), Amf0Value::Boolean(true));
382 }
383
384 #[test]
385 fn decoder_stream() {
386 #[rustfmt::skip]
387 let bytes = [
388 Amf0Marker::Boolean as u8,
389 1, Amf0Marker::String as u8,
391 0, 3, b'a', b'b', b'c', Amf0Marker::Null as u8,
393 ];
394
395 let mut decoder = Amf0Decoder::from_slice(&bytes);
396 let mut stream = decoder.stream();
397 assert_eq!(stream.next().unwrap().unwrap(), Amf0Value::Boolean(true));
398 assert_eq!(stream.next().unwrap().unwrap(), Amf0Value::String("abc".into()));
399 assert_eq!(stream.next().unwrap().unwrap(), Amf0Value::Null);
400 assert!(stream.next().is_none());
401 }
402}