scuffle_amf0/de/
mod.rs

1//! Deserialize AMF0 data to a Rust data structure.
2
3use std::io;
4
5use scuffle_bytes_util::zero_copy::ZeroCopyReader;
6use serde::de::{EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess};
7
8use crate::decoder::{Amf0Decoder, ObjectHeader};
9use crate::{Amf0Error, Amf0Marker};
10
11mod stream;
12
13pub use stream::*;
14
15/// Deserialize a value from a given [`bytes::Buf`].
16pub fn from_buf<'de, T>(buf: impl bytes::Buf) -> crate::Result<T>
17where
18    T: serde::de::Deserialize<'de>,
19{
20    let mut de = Amf0Decoder::from_buf(buf);
21    let value = T::deserialize(&mut de)?;
22    Ok(value)
23}
24
25/// Deserialize a value from a given [`io::Read`].
26pub fn from_reader<'de, T>(reader: impl io::Read) -> crate::Result<T>
27where
28    T: serde::de::Deserialize<'de>,
29{
30    let mut de = Amf0Decoder::from_reader(reader);
31    let value = T::deserialize(&mut de)?;
32    Ok(value)
33}
34
35/// Deserialize a value from a given byte slice.
36pub fn from_slice<'de, T>(bytes: &'de [u8]) -> crate::Result<T>
37where
38    T: serde::de::Deserialize<'de>,
39{
40    let mut de = Amf0Decoder::from_slice(bytes);
41    let value = T::deserialize(&mut de)?;
42    Ok(value)
43}
44
45impl<'de, R> serde::de::Deserializer<'de> for &mut Amf0Decoder<R>
46where
47    R: ZeroCopyReader<'de>,
48{
49    type Error = Amf0Error;
50
51    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
52    where
53        V: serde::de::Visitor<'de>,
54    {
55        let marker = self.peek_marker()?;
56
57        match marker {
58            Amf0Marker::Boolean => self.deserialize_bool(visitor),
59            Amf0Marker::Number | Amf0Marker::Date => self.deserialize_f64(visitor),
60            Amf0Marker::String | Amf0Marker::LongString | Amf0Marker::XmlDocument => self.deserialize_str(visitor),
61            Amf0Marker::Null | Amf0Marker::Undefined => self.deserialize_unit(visitor),
62            Amf0Marker::Object | Amf0Marker::TypedObject | Amf0Marker::EcmaArray => self.deserialize_map(visitor),
63            Amf0Marker::StrictArray => self.deserialize_seq(visitor),
64            _ => Err(Amf0Error::UnsupportedMarker(marker)),
65        }
66    }
67
68    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
69    where
70        V: serde::de::Visitor<'de>,
71    {
72        let value = self.decode_boolean()?;
73        visitor.visit_bool(value)
74    }
75
76    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
77    where
78        V: serde::de::Visitor<'de>,
79    {
80        self.deserialize_i64(visitor)
81    }
82
83    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
84    where
85        V: serde::de::Visitor<'de>,
86    {
87        self.deserialize_i64(visitor)
88    }
89
90    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
91    where
92        V: serde::de::Visitor<'de>,
93    {
94        self.deserialize_i64(visitor)
95    }
96
97    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
98    where
99        V: serde::de::Visitor<'de>,
100    {
101        let value = self.decode_number()?;
102        visitor.visit_i64(value as i64)
103    }
104
105    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
106    where
107        V: serde::de::Visitor<'de>,
108    {
109        self.deserialize_u64(visitor)
110    }
111
112    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
113    where
114        V: serde::de::Visitor<'de>,
115    {
116        self.deserialize_u64(visitor)
117    }
118
119    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
120    where
121        V: serde::de::Visitor<'de>,
122    {
123        self.deserialize_u64(visitor)
124    }
125
126    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
127    where
128        V: serde::de::Visitor<'de>,
129    {
130        let value = self.decode_number()?;
131        visitor.visit_u64(value as u64)
132    }
133
134    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
135    where
136        V: serde::de::Visitor<'de>,
137    {
138        self.deserialize_f64(visitor)
139    }
140
141    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
142    where
143        V: serde::de::Visitor<'de>,
144    {
145        let value = self.decode_number()?;
146        visitor.visit_f64(value)
147    }
148
149    fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
150    where
151        V: serde::de::Visitor<'de>,
152    {
153        Err(Amf0Error::CharNotSupported)
154    }
155
156    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
157    where
158        V: serde::de::Visitor<'de>,
159    {
160        let value = self.decode_string()?;
161        value.into_deserializer().deserialize_string(visitor)
162    }
163
164    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
165    where
166        V: serde::de::Visitor<'de>,
167    {
168        let value = self.decode_string()?;
169        value.into_deserializer().deserialize_str(visitor)
170    }
171
172    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
173    where
174        V: serde::de::Visitor<'de>,
175    {
176        self.deserialize_seq(visitor)
177    }
178
179    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
180    where
181        V: serde::de::Visitor<'de>,
182    {
183        self.deserialize_seq(visitor)
184    }
185
186    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
187    where
188        V: serde::de::Visitor<'de>,
189    {
190        let marker = self.peek_marker()?;
191
192        if marker == Amf0Marker::Null || marker == Amf0Marker::Undefined {
193            self.next_marker = None; // clear the marker buffer
194
195            visitor.visit_none()
196        } else {
197            visitor.visit_some(self)
198        }
199    }
200
201    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
202    where
203        V: serde::de::Visitor<'de>,
204    {
205        self.decode_null()?;
206        visitor.visit_unit()
207    }
208
209    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
210    where
211        V: serde::de::Visitor<'de>,
212    {
213        self.deserialize_unit(visitor)
214    }
215
216    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
217    where
218        V: serde::de::Visitor<'de>,
219    {
220        if name == stream::MULTI_VALUE_NEW_TYPE {
221            visitor.visit_seq(MultiValueDe { de: self })
222        } else {
223            visitor.visit_newtype_struct(self)
224        }
225    }
226
227    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
228    where
229        V: serde::de::Visitor<'de>,
230    {
231        let size = self.decode_strict_array_header()? as usize;
232
233        visitor.visit_seq(StrictArray {
234            de: self,
235            remaining: size,
236        })
237    }
238
239    fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
240    where
241        V: serde::de::Visitor<'de>,
242    {
243        let size = self.decode_strict_array_header()? as usize;
244
245        if len != size {
246            return Err(Amf0Error::WrongArrayLength {
247                expected: len,
248                got: size,
249            });
250        }
251
252        visitor.visit_seq(StrictArray {
253            de: self,
254            remaining: size,
255        })
256    }
257
258    fn deserialize_tuple_struct<V>(self, _name: &'static str, len: usize, visitor: V) -> Result<V::Value, Self::Error>
259    where
260        V: serde::de::Visitor<'de>,
261    {
262        self.deserialize_tuple(len, visitor)
263    }
264
265    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
266    where
267        V: serde::de::Visitor<'de>,
268    {
269        let header = self.decode_object_header()?;
270
271        match header {
272            ObjectHeader::Object | ObjectHeader::TypedObject { .. } => visitor.visit_map(Object { de: self }),
273            ObjectHeader::EcmaArray { size } => visitor.visit_map(EcmaArray {
274                de: self,
275                remaining: size as usize,
276            }),
277        }
278    }
279
280    fn deserialize_struct<V>(
281        self,
282        _name: &'static str,
283        _fields: &'static [&'static str],
284        visitor: V,
285    ) -> Result<V::Value, Self::Error>
286    where
287        V: serde::de::Visitor<'de>,
288    {
289        self.deserialize_map(visitor)
290    }
291
292    fn deserialize_enum<V>(
293        self,
294        _name: &'static str,
295        _variants: &'static [&'static str],
296        visitor: V,
297    ) -> Result<V::Value, Self::Error>
298    where
299        V: serde::de::Visitor<'de>,
300    {
301        visitor.visit_enum(Enum { de: self })
302    }
303
304    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
305    where
306        V: serde::de::Visitor<'de>,
307    {
308        let s = self.decode_string()?;
309        s.into_deserializer().deserialize_identifier(visitor)
310    }
311
312    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
313    where
314        V: serde::de::Visitor<'de>,
315    {
316        self.deserialize_any(visitor)
317    }
318}
319
320struct StrictArray<'a, R> {
321    de: &'a mut Amf0Decoder<R>,
322    remaining: usize,
323}
324
325impl<'de, R> SeqAccess<'de> for StrictArray<'_, R>
326where
327    R: ZeroCopyReader<'de>,
328{
329    type Error = Amf0Error;
330
331    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
332    where
333        T: serde::de::DeserializeSeed<'de>,
334    {
335        if self.remaining == 0 {
336            return Ok(None);
337        }
338
339        self.remaining -= 1;
340        seed.deserialize(&mut *self.de).map(Some)
341    }
342
343    fn size_hint(&self) -> Option<usize> {
344        Some(self.remaining)
345    }
346}
347
348struct Object<'a, R> {
349    de: &'a mut Amf0Decoder<R>,
350}
351
352impl<'de, R> MapAccess<'de> for Object<'_, R>
353where
354    R: ZeroCopyReader<'de>,
355{
356    type Error = Amf0Error;
357
358    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
359    where
360        K: serde::de::DeserializeSeed<'de>,
361    {
362        let Some(key) = self.de.decode_object_key()? else {
363            // Reached ObjectEnd marker
364            return Ok(None);
365        };
366
367        let string_de = key.into_deserializer();
368        seed.deserialize(string_de).map(Some)
369    }
370
371    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
372    where
373        V: serde::de::DeserializeSeed<'de>,
374    {
375        seed.deserialize(&mut *self.de)
376    }
377}
378
379struct EcmaArray<'a, R> {
380    de: &'a mut Amf0Decoder<R>,
381    remaining: usize,
382}
383
384impl<'de, R> MapAccess<'de> for EcmaArray<'_, R>
385where
386    R: ZeroCopyReader<'de>,
387{
388    type Error = Amf0Error;
389
390    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
391    where
392        K: serde::de::DeserializeSeed<'de>,
393    {
394        if self.remaining == 0 {
395            // There might be an object end marker after the last key
396            if self.de.has_remaining()? && self.de.peek_marker()? == Amf0Marker::ObjectEnd {
397                self.de.next_marker = None; // clear the marker buffer
398            }
399
400            return Ok(None);
401        }
402
403        self.remaining -= 1;
404
405        // Object keys are not preceeded with a marker and are always normal strings
406        let s = self.de.decode_normal_string()?;
407        let string_de = s.into_deserializer();
408        seed.deserialize(string_de).map(Some)
409    }
410
411    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
412    where
413        V: serde::de::DeserializeSeed<'de>,
414    {
415        seed.deserialize(&mut *self.de)
416    }
417
418    fn size_hint(&self) -> Option<usize> {
419        Some(self.remaining)
420    }
421}
422
423struct Enum<'a, R> {
424    de: &'a mut Amf0Decoder<R>,
425}
426
427impl<'de, R> EnumAccess<'de> for Enum<'_, R>
428where
429    R: ZeroCopyReader<'de>,
430{
431    type Error = Amf0Error;
432    type Variant = Self;
433
434    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
435    where
436        V: serde::de::DeserializeSeed<'de>,
437    {
438        let variant = self.de.decode_string()?;
439        let string_de = IntoDeserializer::<Self::Error>::into_deserializer(variant);
440        let value = seed.deserialize(string_de)?;
441
442        Ok((value, self))
443    }
444}
445
446impl<'de, R> VariantAccess<'de> for Enum<'_, R>
447where
448    R: ZeroCopyReader<'de>,
449{
450    type Error = Amf0Error;
451
452    fn unit_variant(self) -> Result<(), Self::Error> {
453        Ok(())
454    }
455
456    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
457    where
458        T: serde::de::DeserializeSeed<'de>,
459    {
460        seed.deserialize(&mut *self.de)
461    }
462
463    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
464    where
465        V: serde::de::Visitor<'de>,
466    {
467        serde::de::Deserializer::deserialize_seq(self.de, visitor)
468    }
469
470    fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
471    where
472        V: serde::de::Visitor<'de>,
473    {
474        serde::de::Deserializer::deserialize_map(self.de, visitor)
475    }
476}
477
478#[cfg(test)]
479#[cfg_attr(all(test, coverage_nightly), coverage(off))]
480mod tests {
481    use core::f64;
482    use std::collections::HashMap;
483    use std::fmt::Debug;
484
485    use bytes::Bytes;
486    use scuffle_bytes_util::StringCow;
487
488    use crate::de::MultiValue;
489    use crate::decoder::Amf0Decoder;
490    use crate::{Amf0Error, Amf0Marker, Amf0Object, Amf0Value, from_buf};
491
492    #[test]
493    fn string() {
494        #[rustfmt::skip]
495        let bytes = [
496            Amf0Marker::String as u8,
497            0, 5, // length
498            b'h', b'e', b'l', b'l', b'o',
499        ];
500
501        let value: String = from_buf(Bytes::from_owner(bytes)).unwrap();
502        assert_eq!(value, "hello");
503
504        #[rustfmt::skip]
505        let bytes = [
506            Amf0Marker::LongString as u8,
507            0, 0, 0, 5, // length
508            b'h', b'e', b'l', b'l', b'o',
509        ];
510
511        let value: String = from_buf(Bytes::from_owner(bytes)).unwrap();
512        assert_eq!(value, "hello");
513
514        let bytes = [Amf0Marker::Boolean as u8];
515        let err = from_buf::<String>(Bytes::from_owner(bytes)).unwrap_err();
516        assert!(matches!(
517            err,
518            Amf0Error::UnexpectedType {
519                expected: [Amf0Marker::String, Amf0Marker::LongString, Amf0Marker::XmlDocument],
520                got: Amf0Marker::Boolean
521            }
522        ));
523    }
524
525    #[test]
526    fn bool() {
527        let bytes = [Amf0Marker::Boolean as u8, 1];
528        let value: bool = from_buf(Bytes::from_owner(bytes)).unwrap();
529        assert!(value);
530
531        let bytes = [Amf0Marker::String as u8];
532        let err = from_buf::<bool>(Bytes::from_owner(bytes)).unwrap_err();
533        assert!(matches!(
534            err,
535            Amf0Error::UnexpectedType {
536                expected: [Amf0Marker::Boolean],
537                got: Amf0Marker::String
538            }
539        ));
540    }
541
542    fn number_test<'de, T>(one: T)
543    where
544        T: serde::Deserialize<'de> + PartialEq + Debug,
545    {
546        const NUMBER_ONE: [u8; 9] = const {
547            let one = 1.0f64.to_be_bytes();
548            [
549                Amf0Marker::Number as u8,
550                one[0],
551                one[1],
552                one[2],
553                one[3],
554                one[4],
555                one[5],
556                one[6],
557                one[7],
558            ]
559        };
560
561        let value: T = from_buf(Bytes::from_static(&NUMBER_ONE)).unwrap();
562        assert_eq!(value, one);
563    }
564
565    #[test]
566    fn numbers() {
567        number_test(1u8);
568        number_test(1u16);
569        number_test(1u32);
570        number_test(1u64);
571        number_test(1i8);
572        number_test(1i16);
573        number_test(1i32);
574        number_test(1i64);
575        number_test(1f32);
576        number_test(1f64);
577
578        let mut bytes = vec![Amf0Marker::Date as u8];
579        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
580        bytes.extend_from_slice(&0u16.to_be_bytes()); // timezone
581        let value: f64 = from_buf(Bytes::from_owner(bytes)).unwrap();
582        assert_eq!(value, f64::consts::PI);
583
584        let bytes = [Amf0Marker::Boolean as u8];
585        let err = from_buf::<f64>(Bytes::from_owner(bytes)).unwrap_err();
586        assert!(matches!(
587            err,
588            Amf0Error::UnexpectedType {
589                expected: [Amf0Marker::Number, Amf0Marker::Date],
590                got: Amf0Marker::Boolean
591            }
592        ));
593    }
594
595    #[test]
596    fn char() {
597        let err = from_buf::<char>(Bytes::from_owner([])).unwrap_err();
598        assert!(matches!(err, Amf0Error::CharNotSupported));
599    }
600
601    #[test]
602    fn optional() {
603        let bytes = [Amf0Marker::Null as u8];
604        let value: Option<bool> = from_buf(Bytes::from_owner(bytes)).unwrap();
605        assert_eq!(value, None);
606
607        let bytes = [Amf0Marker::Null as u8];
608        from_buf::<()>(Bytes::from_owner(bytes)).unwrap();
609
610        let bytes = [Amf0Marker::String as u8];
611        let err = from_buf::<()>(Bytes::from_owner(bytes)).unwrap_err();
612        assert!(matches!(
613            err,
614            Amf0Error::UnexpectedType {
615                expected: [Amf0Marker::Null, Amf0Marker::Undefined],
616                got: Amf0Marker::String
617            }
618        ));
619
620        let bytes = [Amf0Marker::Undefined as u8];
621        let value: Option<bool> = from_buf(Bytes::from_owner(bytes)).unwrap();
622        assert_eq!(value, None);
623
624        let bytes = [Amf0Marker::Boolean as u8, 0];
625        let value: Option<bool> = from_buf(Bytes::from_owner(bytes)).unwrap();
626        assert_eq!(value, Some(false));
627
628        #[derive(serde::Deserialize, PartialEq, Debug)]
629        struct Unit;
630
631        let bytes = [Amf0Marker::Null as u8];
632        let value: Unit = from_buf(Bytes::from_owner(bytes)).unwrap();
633        assert_eq!(value, Unit);
634    }
635
636    #[test]
637    fn newtype_struct() {
638        #[derive(serde::Deserialize, Debug, PartialEq)]
639        struct Test(String);
640
641        #[rustfmt::skip]
642        let bytes = [
643            Amf0Marker::String as u8,
644            0, 5, // length
645            b'h', b'e', b'l', b'l', b'o',
646        ];
647        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
648        assert_eq!(value, Test("hello".to_string()));
649    }
650
651    #[test]
652    fn tuple_struct() {
653        #[derive(serde::Deserialize, Debug, PartialEq)]
654        struct Test(bool, String);
655
656        #[rustfmt::skip]
657        let bytes = [
658            Amf0Marker::StrictArray as u8,
659            0, 0, 0, 2, // length
660            Amf0Marker::Boolean as u8,
661            1,
662            Amf0Marker::String as u8,
663            0, 5, // length
664            b'h', b'e', b'l', b'l', b'o',
665        ];
666        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
667        assert_eq!(value, Test(true, "hello".to_string()));
668
669        #[rustfmt::skip]
670        let bytes = [
671            Amf0Marker::StrictArray as u8,
672            0, 0, 0, 1, // length
673            Amf0Marker::Boolean as u8,
674            1,
675        ];
676        let err = from_buf::<Test>(Bytes::from_owner(bytes)).unwrap_err();
677        assert!(matches!(err, Amf0Error::WrongArrayLength { expected: 2, got: 1 }));
678    }
679
680    #[test]
681    fn typed_object() {
682        #[derive(serde::Deserialize, Debug, PartialEq)]
683        struct Test {
684            a: bool,
685            b: String,
686        }
687
688        #[rustfmt::skip]
689        let bytes = [
690            Amf0Marker::TypedObject as u8,
691            0, 1, // name length
692            b'a', // name
693            0, 1, // length
694            b'a', // key
695            Amf0Marker::Boolean as u8,
696            1,
697            0, 1, // length
698            b'b', // key
699            Amf0Marker::String as u8,
700            0, 5, // length
701            b'h', b'e', b'l', b'l', b'o',
702            0, 0, Amf0Marker::ObjectEnd as u8,
703        ];
704        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
705        assert_eq!(
706            value,
707            Test {
708                a: true,
709                b: "hello".to_string()
710            }
711        );
712    }
713
714    #[test]
715    fn simple_struct() {
716        #[derive(serde::Deserialize, Debug, PartialEq)]
717        struct Test {
718            a: bool,
719            b: String,
720            c: f64,
721        }
722
723        #[rustfmt::skip]
724        let mut bytes = vec![
725            Amf0Marker::Object as u8,
726            0, 1, // length
727            b'a', // key
728            Amf0Marker::Boolean as u8, // value
729            1,
730            0, 1, // length
731            b'b', // key
732            Amf0Marker::String as u8, // value
733            0, 1, // length
734            b'b', // value
735            0, 1, // length
736            b'c', // key
737            Amf0Marker::Number as u8, // value
738        ];
739        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
740        bytes.extend_from_slice(&[0, 0, Amf0Marker::ObjectEnd as u8]);
741        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
742
743        assert_eq!(
744            value,
745            Test {
746                a: true,
747                b: "b".to_string(),
748                c: f64::consts::PI,
749            }
750        );
751
752        #[rustfmt::skip]
753        let mut bytes = vec![
754            Amf0Marker::EcmaArray as u8,
755            0, 0, 0, 3, // length
756            0, 1, // length
757            b'a', // key
758            Amf0Marker::Boolean as u8, // value
759            1,
760            0, 1, // length
761            b'b', // key
762            Amf0Marker::String as u8, // value
763            0, 1, // length
764            b'b', // value
765            0, 1, // length
766            b'c', // key
767            Amf0Marker::Number as u8, // value
768        ];
769        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
770        bytes.extend_from_slice(&[0, 0, 0]); // not object end marker
771        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
772
773        assert_eq!(
774            value,
775            Test {
776                a: true,
777                b: "b".to_string(),
778                c: f64::consts::PI,
779            }
780        );
781
782        let err = from_buf::<Test>(Bytes::from_owner([Amf0Marker::String as u8])).unwrap_err();
783        assert!(matches!(
784            err,
785            Amf0Error::UnexpectedType {
786                expected: [Amf0Marker::Object, Amf0Marker::TypedObject, Amf0Marker::EcmaArray],
787                got: Amf0Marker::String
788            }
789        ));
790    }
791
792    #[test]
793    fn simple_enum() {
794        #[derive(serde::Deserialize, Debug, PartialEq)]
795        enum Test {
796            A,
797            B,
798        }
799
800        #[rustfmt::skip]
801        let bytes = vec![
802            Amf0Marker::String as u8,
803            0, 1, // length
804            b'A',
805        ];
806        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
807        assert_eq!(value, Test::A);
808
809        #[rustfmt::skip]
810        let bytes = vec![
811            Amf0Marker::String as u8,
812            0, 1, // length
813            b'B',
814        ];
815        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
816        assert_eq!(value, Test::B);
817    }
818
819    #[test]
820    fn complex_enum() {
821        #[derive(serde::Deserialize, Debug, PartialEq)]
822        enum Test {
823            A(bool),
824            B { a: String, b: String },
825            C(bool, String),
826        }
827
828        #[rustfmt::skip]
829        let bytes = [
830            Amf0Marker::String as u8,
831            0, 1, // length
832            b'A',
833            Amf0Marker::Boolean as u8,
834            1,
835        ];
836        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
837        assert_eq!(value, Test::A(true));
838
839        #[rustfmt::skip]
840        let bytes = [
841            Amf0Marker::String as u8,
842            0, 1, // length
843            b'B',
844            Amf0Marker::Object as u8,
845            0, 1, // length
846            b'a',
847            Amf0Marker::String as u8,
848            0, 5, // length
849            b'h', b'e', b'l', b'l', b'o',
850            0, 1, // length
851            b'b',
852            Amf0Marker::String as u8,
853            0, 5, // length
854            b'w', b'o', b'r', b'l', b'd',
855            0, 0, Amf0Marker::ObjectEnd as u8,
856        ];
857        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
858        assert_eq!(
859            value,
860            Test::B {
861                a: "hello".to_string(),
862                b: "world".to_string()
863            }
864        );
865
866        #[rustfmt::skip]
867        let bytes = [
868            Amf0Marker::String as u8,
869            0, 1, // length
870            b'C',
871            Amf0Marker::StrictArray as u8,
872            0, 0, 0, 2, // array length
873            Amf0Marker::Boolean as u8,
874            1,
875            Amf0Marker::String as u8,
876            0, 5, // length
877            b'h', b'e', b'l', b'l', b'o',
878        ];
879        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
880        assert_eq!(value, Test::C(true, "hello".to_string()));
881    }
882
883    #[test]
884    fn series() {
885        #[rustfmt::skip]
886        let mut bytes = vec![
887            Amf0Marker::String as u8,
888            0, 5, // length
889            b'h', b'e', b'l', b'l', b'o',
890            Amf0Marker::Boolean as u8,
891            1,
892            Amf0Marker::Number as u8,
893        ];
894        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
895
896        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
897        let value: String = serde::de::Deserialize::deserialize(&mut de).unwrap();
898        assert_eq!(value, "hello");
899        let value: bool = serde::de::Deserialize::deserialize(&mut de).unwrap();
900        assert!(value);
901        let value: f64 = serde::de::Deserialize::deserialize(&mut de).unwrap();
902        assert_eq!(value, f64::consts::PI);
903    }
904
905    #[test]
906    fn flatten() {
907        #[rustfmt::skip]
908        let bytes = [
909            Amf0Marker::Object as u8,
910            0, 1, // length
911            b'a',
912            Amf0Marker::Boolean as u8,
913            1,
914            0, 1, // length
915            b'b',
916            Amf0Marker::String as u8,
917            0, 1, // length
918            b'b',
919            0, 1, // length
920            b'c',
921            Amf0Marker::String as u8,
922            0, 1, // length
923            b'c',
924            0, 0, Amf0Marker::ObjectEnd as u8,
925        ];
926
927        #[derive(serde::Deserialize, Debug, PartialEq)]
928        struct Test<'a> {
929            b: String,
930            #[serde(flatten, borrow)]
931            other: HashMap<StringCow<'a>, Amf0Value<'a>>,
932        }
933
934        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
935        assert_eq!(
936            value,
937            Test {
938                b: "b".to_string(),
939                other: vec![
940                    ("a".into(), Amf0Value::from(true)),
941                    ("c".into(), StringCow::from_static("c").into())
942                ]
943                .into_iter()
944                .collect(),
945            }
946        );
947    }
948
949    #[test]
950    fn all() {
951        let bytes = [
952            Amf0Marker::String as u8,
953            0,
954            5, // length
955            b'h',
956            b'e',
957            b'l',
958            b'l',
959            b'o',
960            Amf0Marker::Boolean as u8,
961            1,
962            Amf0Marker::Object as u8,
963            0,
964            1, // length
965            b'a',
966            Amf0Marker::Boolean as u8,
967            1,
968            0,
969            0,
970            Amf0Marker::ObjectEnd as u8,
971        ];
972
973        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
974        let values = de.decode_all().unwrap();
975        assert_eq!(
976            values,
977            vec![
978                Amf0Value::String("hello".into()),
979                Amf0Value::Boolean(true),
980                Amf0Value::Object([("a".into(), Amf0Value::Boolean(true))].into_iter().collect())
981            ]
982        );
983    }
984
985    #[test]
986    fn multi_value() {
987        #[rustfmt::skip]
988        let bytes = [
989            Amf0Marker::String as u8,
990            0, 5, // length
991            b'h', b'e', b'l', b'l', b'o',
992            Amf0Marker::Boolean as u8,
993            1,
994            Amf0Marker::Object as u8,
995            0, 1, // length
996            b'a',
997            Amf0Marker::Boolean as u8,
998            1,
999            0, 0, Amf0Marker::ObjectEnd as u8,
1000        ];
1001
1002        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
1003        let values: MultiValue<(String, bool, Amf0Object)> = de.deserialize().unwrap();
1004        assert_eq!(values.0.0, "hello");
1005        assert!(values.0.1);
1006        assert_eq!(
1007            values.0.2,
1008            [("a".into(), Amf0Value::Boolean(true))].into_iter().collect::<Amf0Object>()
1009        );
1010    }
1011
1012    #[test]
1013    fn deserializer_stream() {
1014        #[rustfmt::skip]
1015        let bytes = [
1016            Amf0Marker::String as u8,
1017            0, 5, // length
1018            b'h', b'e', b'l', b'l', b'o',
1019            Amf0Marker::String as u8,
1020            0, 5, // length
1021            b'w', b'o', b'r', b'l', b'd',
1022            Amf0Marker::String as u8,
1023            0, 1, // length
1024            b'a',
1025        ];
1026
1027        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
1028        let mut stream = de.deserialize_stream::<String>();
1029        assert_eq!(stream.next().unwrap().unwrap(), "hello");
1030        assert_eq!(stream.next().unwrap().unwrap(), "world");
1031        assert_eq!(stream.next().unwrap().unwrap(), "a");
1032        assert_eq!(stream.next().transpose().unwrap(), None);
1033    }
1034}