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    use serde_derive::Deserialize;
488
489    use crate::de::MultiValue;
490    use crate::decoder::Amf0Decoder;
491    use crate::{Amf0Error, Amf0Marker, Amf0Object, Amf0Value, from_buf};
492
493    #[test]
494    fn string() {
495        #[rustfmt::skip]
496        let bytes = [
497            Amf0Marker::String as u8,
498            0, 5, // length
499            b'h', b'e', b'l', b'l', b'o',
500        ];
501
502        let value: String = from_buf(Bytes::from_owner(bytes)).unwrap();
503        assert_eq!(value, "hello");
504
505        #[rustfmt::skip]
506        let bytes = [
507            Amf0Marker::LongString as u8,
508            0, 0, 0, 5, // length
509            b'h', b'e', b'l', b'l', b'o',
510        ];
511
512        let value: String = from_buf(Bytes::from_owner(bytes)).unwrap();
513        assert_eq!(value, "hello");
514
515        let bytes = [Amf0Marker::Boolean as u8];
516        let err = from_buf::<String>(Bytes::from_owner(bytes)).unwrap_err();
517        assert!(matches!(
518            err,
519            Amf0Error::UnexpectedType {
520                expected: [Amf0Marker::String, Amf0Marker::LongString, Amf0Marker::XmlDocument],
521                got: Amf0Marker::Boolean
522            }
523        ));
524    }
525
526    #[test]
527    fn bool() {
528        let bytes = [Amf0Marker::Boolean as u8, 1];
529        let value: bool = from_buf(Bytes::from_owner(bytes)).unwrap();
530        assert!(value);
531
532        let bytes = [Amf0Marker::String as u8];
533        let err = from_buf::<bool>(Bytes::from_owner(bytes)).unwrap_err();
534        assert!(matches!(
535            err,
536            Amf0Error::UnexpectedType {
537                expected: [Amf0Marker::Boolean],
538                got: Amf0Marker::String
539            }
540        ));
541    }
542
543    fn number_test<'de, T>(one: T)
544    where
545        T: serde::Deserialize<'de> + PartialEq + Debug,
546    {
547        const NUMBER_ONE: [u8; 9] = const {
548            let one = 1.0f64.to_be_bytes();
549            [
550                Amf0Marker::Number as u8,
551                one[0],
552                one[1],
553                one[2],
554                one[3],
555                one[4],
556                one[5],
557                one[6],
558                one[7],
559            ]
560        };
561
562        let value: T = from_buf(Bytes::from_static(&NUMBER_ONE)).unwrap();
563        assert_eq!(value, one);
564    }
565
566    #[test]
567    fn numbers() {
568        number_test(1u8);
569        number_test(1u16);
570        number_test(1u32);
571        number_test(1u64);
572        number_test(1i8);
573        number_test(1i16);
574        number_test(1i32);
575        number_test(1i64);
576        number_test(1f32);
577        number_test(1f64);
578
579        let mut bytes = vec![Amf0Marker::Date as u8];
580        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
581        bytes.extend_from_slice(&0u16.to_be_bytes()); // timezone
582        let value: f64 = from_buf(Bytes::from_owner(bytes)).unwrap();
583        assert_eq!(value, f64::consts::PI);
584
585        let bytes = [Amf0Marker::Boolean as u8];
586        let err = from_buf::<f64>(Bytes::from_owner(bytes)).unwrap_err();
587        assert!(matches!(
588            err,
589            Amf0Error::UnexpectedType {
590                expected: [Amf0Marker::Number, Amf0Marker::Date],
591                got: Amf0Marker::Boolean
592            }
593        ));
594    }
595
596    #[test]
597    fn char() {
598        let err = from_buf::<char>(Bytes::from_owner([])).unwrap_err();
599        assert!(matches!(err, Amf0Error::CharNotSupported));
600    }
601
602    #[test]
603    fn optional() {
604        let bytes = [Amf0Marker::Null as u8];
605        let value: Option<bool> = from_buf(Bytes::from_owner(bytes)).unwrap();
606        assert_eq!(value, None);
607
608        let bytes = [Amf0Marker::Null as u8];
609        from_buf::<()>(Bytes::from_owner(bytes)).unwrap();
610
611        let bytes = [Amf0Marker::String as u8];
612        let err = from_buf::<()>(Bytes::from_owner(bytes)).unwrap_err();
613        assert!(matches!(
614            err,
615            Amf0Error::UnexpectedType {
616                expected: [Amf0Marker::Null, Amf0Marker::Undefined],
617                got: Amf0Marker::String
618            }
619        ));
620
621        let bytes = [Amf0Marker::Undefined as u8];
622        let value: Option<bool> = from_buf(Bytes::from_owner(bytes)).unwrap();
623        assert_eq!(value, None);
624
625        let bytes = [Amf0Marker::Boolean as u8, 0];
626        let value: Option<bool> = from_buf(Bytes::from_owner(bytes)).unwrap();
627        assert_eq!(value, Some(false));
628
629        #[derive(Deserialize, PartialEq, Debug)]
630        struct Unit;
631
632        let bytes = [Amf0Marker::Null as u8];
633        let value: Unit = from_buf(Bytes::from_owner(bytes)).unwrap();
634        assert_eq!(value, Unit);
635    }
636
637    #[test]
638    fn newtype_struct() {
639        #[derive(Deserialize, Debug, PartialEq)]
640        struct Test(String);
641
642        #[rustfmt::skip]
643        let bytes = [
644            Amf0Marker::String as u8,
645            0, 5, // length
646            b'h', b'e', b'l', b'l', b'o',
647        ];
648        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
649        assert_eq!(value, Test("hello".to_string()));
650    }
651
652    #[test]
653    fn tuple_struct() {
654        #[derive(Deserialize, Debug, PartialEq)]
655        struct Test(bool, String);
656
657        #[rustfmt::skip]
658        let bytes = [
659            Amf0Marker::StrictArray as u8,
660            0, 0, 0, 2, // length
661            Amf0Marker::Boolean as u8,
662            1,
663            Amf0Marker::String as u8,
664            0, 5, // length
665            b'h', b'e', b'l', b'l', b'o',
666        ];
667        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
668        assert_eq!(value, Test(true, "hello".to_string()));
669
670        #[rustfmt::skip]
671        let bytes = [
672            Amf0Marker::StrictArray as u8,
673            0, 0, 0, 1, // length
674            Amf0Marker::Boolean as u8,
675            1,
676        ];
677        let err = from_buf::<Test>(Bytes::from_owner(bytes)).unwrap_err();
678        assert!(matches!(err, Amf0Error::WrongArrayLength { expected: 2, got: 1 }));
679    }
680
681    #[test]
682    fn typed_object() {
683        #[derive(Deserialize, Debug, PartialEq)]
684        struct Test {
685            a: bool,
686            b: String,
687        }
688
689        #[rustfmt::skip]
690        let bytes = [
691            Amf0Marker::TypedObject as u8,
692            0, 1, // name length
693            b'a', // name
694            0, 1, // length
695            b'a', // key
696            Amf0Marker::Boolean as u8,
697            1,
698            0, 1, // length
699            b'b', // key
700            Amf0Marker::String as u8,
701            0, 5, // length
702            b'h', b'e', b'l', b'l', b'o',
703            0, 0, Amf0Marker::ObjectEnd as u8,
704        ];
705        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
706        assert_eq!(
707            value,
708            Test {
709                a: true,
710                b: "hello".to_string()
711            }
712        );
713    }
714
715    #[test]
716    fn simple_struct() {
717        #[derive(Deserialize, Debug, PartialEq)]
718        struct Test {
719            a: bool,
720            b: String,
721            c: f64,
722        }
723
724        #[rustfmt::skip]
725        let mut bytes = vec![
726            Amf0Marker::Object as u8,
727            0, 1, // length
728            b'a', // key
729            Amf0Marker::Boolean as u8, // value
730            1,
731            0, 1, // length
732            b'b', // key
733            Amf0Marker::String as u8, // value
734            0, 1, // length
735            b'b', // value
736            0, 1, // length
737            b'c', // key
738            Amf0Marker::Number as u8, // value
739        ];
740        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
741        bytes.extend_from_slice(&[0, 0, Amf0Marker::ObjectEnd as u8]);
742        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
743
744        assert_eq!(
745            value,
746            Test {
747                a: true,
748                b: "b".to_string(),
749                c: f64::consts::PI,
750            }
751        );
752
753        #[rustfmt::skip]
754        let mut bytes = vec![
755            Amf0Marker::EcmaArray as u8,
756            0, 0, 0, 3, // length
757            0, 1, // length
758            b'a', // key
759            Amf0Marker::Boolean as u8, // value
760            1,
761            0, 1, // length
762            b'b', // key
763            Amf0Marker::String as u8, // value
764            0, 1, // length
765            b'b', // value
766            0, 1, // length
767            b'c', // key
768            Amf0Marker::Number as u8, // value
769        ];
770        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
771        bytes.extend_from_slice(&[0, 0, 0]); // not object end marker
772        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
773
774        assert_eq!(
775            value,
776            Test {
777                a: true,
778                b: "b".to_string(),
779                c: f64::consts::PI,
780            }
781        );
782
783        let err = from_buf::<Test>(Bytes::from_owner([Amf0Marker::String as u8])).unwrap_err();
784        assert!(matches!(
785            err,
786            Amf0Error::UnexpectedType {
787                expected: [Amf0Marker::Object, Amf0Marker::TypedObject, Amf0Marker::EcmaArray],
788                got: Amf0Marker::String
789            }
790        ));
791    }
792
793    #[test]
794    fn simple_enum() {
795        #[derive(Deserialize, Debug, PartialEq)]
796        enum Test {
797            A,
798            B,
799        }
800
801        #[rustfmt::skip]
802        let bytes = vec![
803            Amf0Marker::String as u8,
804            0, 1, // length
805            b'A',
806        ];
807        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
808        assert_eq!(value, Test::A);
809
810        #[rustfmt::skip]
811        let bytes = vec![
812            Amf0Marker::String as u8,
813            0, 1, // length
814            b'B',
815        ];
816        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
817        assert_eq!(value, Test::B);
818    }
819
820    #[test]
821    fn complex_enum() {
822        #[derive(Deserialize, Debug, PartialEq)]
823        enum Test {
824            A(bool),
825            B { a: String, b: String },
826            C(bool, String),
827        }
828
829        #[rustfmt::skip]
830        let bytes = [
831            Amf0Marker::String as u8,
832            0, 1, // length
833            b'A',
834            Amf0Marker::Boolean as u8,
835            1,
836        ];
837        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
838        assert_eq!(value, Test::A(true));
839
840        #[rustfmt::skip]
841        let bytes = [
842            Amf0Marker::String as u8,
843            0, 1, // length
844            b'B',
845            Amf0Marker::Object as u8,
846            0, 1, // length
847            b'a',
848            Amf0Marker::String as u8,
849            0, 5, // length
850            b'h', b'e', b'l', b'l', b'o',
851            0, 1, // length
852            b'b',
853            Amf0Marker::String as u8,
854            0, 5, // length
855            b'w', b'o', b'r', b'l', b'd',
856            0, 0, Amf0Marker::ObjectEnd as u8,
857        ];
858        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
859        assert_eq!(
860            value,
861            Test::B {
862                a: "hello".to_string(),
863                b: "world".to_string()
864            }
865        );
866
867        #[rustfmt::skip]
868        let bytes = [
869            Amf0Marker::String as u8,
870            0, 1, // length
871            b'C',
872            Amf0Marker::StrictArray as u8,
873            0, 0, 0, 2, // array length
874            Amf0Marker::Boolean as u8,
875            1,
876            Amf0Marker::String as u8,
877            0, 5, // length
878            b'h', b'e', b'l', b'l', b'o',
879        ];
880        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
881        assert_eq!(value, Test::C(true, "hello".to_string()));
882    }
883
884    #[test]
885    fn series() {
886        #[rustfmt::skip]
887        let mut bytes = vec![
888            Amf0Marker::String as u8,
889            0, 5, // length
890            b'h', b'e', b'l', b'l', b'o',
891            Amf0Marker::Boolean as u8,
892            1,
893            Amf0Marker::Number as u8,
894        ];
895        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
896
897        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
898        let value: String = serde::de::Deserialize::deserialize(&mut de).unwrap();
899        assert_eq!(value, "hello");
900        let value: bool = serde::de::Deserialize::deserialize(&mut de).unwrap();
901        assert!(value);
902        let value: f64 = serde::de::Deserialize::deserialize(&mut de).unwrap();
903        assert_eq!(value, f64::consts::PI);
904    }
905
906    #[test]
907    fn flatten() {
908        #[rustfmt::skip]
909        let bytes = [
910            Amf0Marker::Object as u8,
911            0, 1, // length
912            b'a',
913            Amf0Marker::Boolean as u8,
914            1,
915            0, 1, // length
916            b'b',
917            Amf0Marker::String as u8,
918            0, 1, // length
919            b'b',
920            0, 1, // length
921            b'c',
922            Amf0Marker::String as u8,
923            0, 1, // length
924            b'c',
925            0, 0, Amf0Marker::ObjectEnd as u8,
926        ];
927
928        #[derive(Deserialize, Debug, PartialEq)]
929        struct Test<'a> {
930            b: String,
931            #[serde(flatten, borrow)]
932            other: HashMap<StringCow<'a>, Amf0Value<'a>>,
933        }
934
935        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
936        assert_eq!(
937            value,
938            Test {
939                b: "b".to_string(),
940                other: vec![
941                    ("a".into(), Amf0Value::from(true)),
942                    ("c".into(), StringCow::from_static("c").into())
943                ]
944                .into_iter()
945                .collect(),
946            }
947        );
948    }
949
950    #[test]
951    fn all() {
952        let bytes = [
953            Amf0Marker::String as u8,
954            0,
955            5, // length
956            b'h',
957            b'e',
958            b'l',
959            b'l',
960            b'o',
961            Amf0Marker::Boolean as u8,
962            1,
963            Amf0Marker::Object as u8,
964            0,
965            1, // length
966            b'a',
967            Amf0Marker::Boolean as u8,
968            1,
969            0,
970            0,
971            Amf0Marker::ObjectEnd as u8,
972        ];
973
974        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
975        let values = de.decode_all().unwrap();
976        assert_eq!(
977            values,
978            vec![
979                Amf0Value::String("hello".into()),
980                Amf0Value::Boolean(true),
981                Amf0Value::Object([("a".into(), Amf0Value::Boolean(true))].into_iter().collect())
982            ]
983        );
984    }
985
986    #[test]
987    fn multi_value() {
988        #[rustfmt::skip]
989        let bytes = [
990            Amf0Marker::String as u8,
991            0, 5, // length
992            b'h', b'e', b'l', b'l', b'o',
993            Amf0Marker::Boolean as u8,
994            1,
995            Amf0Marker::Object as u8,
996            0, 1, // length
997            b'a',
998            Amf0Marker::Boolean as u8,
999            1,
1000            0, 0, Amf0Marker::ObjectEnd as u8,
1001        ];
1002
1003        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
1004        let values: MultiValue<(String, bool, Amf0Object)> = de.deserialize().unwrap();
1005        assert_eq!(values.0.0, "hello");
1006        assert!(values.0.1);
1007        assert_eq!(
1008            values.0.2,
1009            [("a".into(), Amf0Value::Boolean(true))].into_iter().collect::<Amf0Object>()
1010        );
1011    }
1012
1013    #[test]
1014    fn deserializer_stream() {
1015        #[rustfmt::skip]
1016        let bytes = [
1017            Amf0Marker::String as u8,
1018            0, 5, // length
1019            b'h', b'e', b'l', b'l', b'o',
1020            Amf0Marker::String as u8,
1021            0, 5, // length
1022            b'w', b'o', b'r', b'l', b'd',
1023            Amf0Marker::String as u8,
1024            0, 1, // length
1025            b'a',
1026        ];
1027
1028        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
1029        let mut stream = de.deserialize_stream::<String>();
1030        assert_eq!(stream.next().unwrap().unwrap(), "hello");
1031        assert_eq!(stream.next().unwrap().unwrap(), "world");
1032        assert_eq!(stream.next().unwrap().unwrap(), "a");
1033        assert_eq!(stream.next().transpose().unwrap(), None);
1034    }
1035}