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 {
826                a: String,
827                b: String,
828            },
829            C(bool, String),
830        }
831
832        #[rustfmt::skip]
833        let bytes = [
834            Amf0Marker::String as u8,
835            0, 1, // length
836            b'A',
837            Amf0Marker::Boolean as u8,
838            1,
839        ];
840        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
841        assert_eq!(value, Test::A(true));
842
843        #[rustfmt::skip]
844        let bytes = [
845            Amf0Marker::String as u8,
846            0, 1, // length
847            b'B',
848            Amf0Marker::Object as u8,
849            0, 1, // length
850            b'a',
851            Amf0Marker::String as u8,
852            0, 5, // length
853            b'h', b'e', b'l', b'l', b'o',
854            0, 1, // length
855            b'b',
856            Amf0Marker::String as u8,
857            0, 5, // length
858            b'w', b'o', b'r', b'l', b'd',
859            0, 0, Amf0Marker::ObjectEnd as u8,
860        ];
861        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
862        assert_eq!(
863            value,
864            Test::B {
865                a: "hello".to_string(),
866                b: "world".to_string()
867            }
868        );
869
870        #[rustfmt::skip]
871        let bytes = [
872            Amf0Marker::String as u8,
873            0, 1, // length
874            b'C',
875            Amf0Marker::StrictArray as u8,
876            0, 0, 0, 2, // array length
877            Amf0Marker::Boolean as u8,
878            1,
879            Amf0Marker::String as u8,
880            0, 5, // length
881            b'h', b'e', b'l', b'l', b'o',
882        ];
883        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
884        assert_eq!(value, Test::C(true, "hello".to_string()));
885    }
886
887    #[test]
888    fn series() {
889        #[rustfmt::skip]
890        let mut bytes = vec![
891            Amf0Marker::String as u8,
892            0, 5, // length
893            b'h', b'e', b'l', b'l', b'o',
894            Amf0Marker::Boolean as u8,
895            1,
896            Amf0Marker::Number as u8,
897        ];
898        bytes.extend_from_slice(&f64::consts::PI.to_be_bytes());
899
900        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
901        let value: String = serde::de::Deserialize::deserialize(&mut de).unwrap();
902        assert_eq!(value, "hello");
903        let value: bool = serde::de::Deserialize::deserialize(&mut de).unwrap();
904        assert!(value);
905        let value: f64 = serde::de::Deserialize::deserialize(&mut de).unwrap();
906        assert_eq!(value, f64::consts::PI);
907    }
908
909    #[test]
910    fn flatten() {
911        #[rustfmt::skip]
912        let bytes = [
913            Amf0Marker::Object as u8,
914            0, 1, // length
915            b'a',
916            Amf0Marker::Boolean as u8,
917            1,
918            0, 1, // length
919            b'b',
920            Amf0Marker::String as u8,
921            0, 1, // length
922            b'b',
923            0, 1, // length
924            b'c',
925            Amf0Marker::String as u8,
926            0, 1, // length
927            b'c',
928            0, 0, Amf0Marker::ObjectEnd as u8,
929        ];
930
931        #[derive(Deserialize, Debug, PartialEq)]
932        struct Test<'a> {
933            b: String,
934            #[serde(flatten, borrow)]
935            other: HashMap<StringCow<'a>, Amf0Value<'a>>,
936        }
937
938        let value: Test = from_buf(Bytes::from_owner(bytes)).unwrap();
939        assert_eq!(
940            value,
941            Test {
942                b: "b".to_string(),
943                other: vec![
944                    ("a".into(), Amf0Value::from(true)),
945                    ("c".into(), StringCow::from_static("c").into())
946                ]
947                .into_iter()
948                .collect(),
949            }
950        );
951    }
952
953    #[test]
954    fn all() {
955        let bytes = [
956            Amf0Marker::String as u8,
957            0,
958            5, // length
959            b'h',
960            b'e',
961            b'l',
962            b'l',
963            b'o',
964            Amf0Marker::Boolean as u8,
965            1,
966            Amf0Marker::Object as u8,
967            0,
968            1, // length
969            b'a',
970            Amf0Marker::Boolean as u8,
971            1,
972            0,
973            0,
974            Amf0Marker::ObjectEnd as u8,
975        ];
976
977        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
978        let values = de.decode_all().unwrap();
979        assert_eq!(
980            values,
981            vec![
982                Amf0Value::String("hello".into()),
983                Amf0Value::Boolean(true),
984                Amf0Value::Object([("a".into(), Amf0Value::Boolean(true))].into_iter().collect())
985            ]
986        );
987    }
988
989    #[test]
990    fn multi_value() {
991        #[rustfmt::skip]
992        let bytes = [
993            Amf0Marker::String as u8,
994            0, 5, // length
995            b'h', b'e', b'l', b'l', b'o',
996            Amf0Marker::Boolean as u8,
997            1,
998            Amf0Marker::Object as u8,
999            0, 1, // length
1000            b'a',
1001            Amf0Marker::Boolean as u8,
1002            1,
1003            0, 0, Amf0Marker::ObjectEnd as u8,
1004        ];
1005
1006        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
1007        let values: MultiValue<(String, bool, Amf0Object)> = de.deserialize().unwrap();
1008        assert_eq!(values.0.0, "hello");
1009        assert!(values.0.1);
1010        assert_eq!(
1011            values.0.2,
1012            [("a".into(), Amf0Value::Boolean(true))].into_iter().collect::<Amf0Object>()
1013        );
1014    }
1015
1016    #[test]
1017    fn deserializer_stream() {
1018        #[rustfmt::skip]
1019        let bytes = [
1020            Amf0Marker::String as u8,
1021            0, 5, // length
1022            b'h', b'e', b'l', b'l', b'o',
1023            Amf0Marker::String as u8,
1024            0, 5, // length
1025            b'w', b'o', b'r', b'l', b'd',
1026            Amf0Marker::String as u8,
1027            0, 1, // length
1028            b'a',
1029        ];
1030
1031        let mut de = Amf0Decoder::from_buf(Bytes::from_owner(bytes));
1032        let mut stream = de.deserialize_stream::<String>();
1033        assert_eq!(stream.next().unwrap().unwrap(), "hello");
1034        assert_eq!(stream.next().unwrap().unwrap(), "world");
1035        assert_eq!(stream.next().unwrap().unwrap(), "a");
1036        assert_eq!(stream.next().transpose().unwrap(), None);
1037    }
1038}