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