scuffle_amf0/
encoder.rs

1//! AMF0 encoder
2
3use std::io;
4
5use byteorder::{BigEndian, WriteBytesExt};
6
7use crate::{Amf0Array, Amf0Error, Amf0Marker, Amf0Object};
8
9/// AMF0 encoder.
10///
11/// Provides various functions to encode different types of AMF0 values into a writer.
12#[derive(Debug)]
13pub struct Amf0Encoder<W> {
14    writer: W,
15}
16
17impl<W> Amf0Encoder<W> {
18    /// Create a new encoder from a writer.
19    pub fn new(writer: W) -> Self {
20        Amf0Encoder { writer }
21    }
22}
23
24impl<W> Amf0Encoder<W>
25where
26    W: io::Write,
27{
28    /// Encode a [`bool`] as a AMF0 boolean value.
29    pub fn encode_boolean(&mut self, value: bool) -> Result<(), Amf0Error> {
30        self.writer.write_u8(Amf0Marker::Boolean as u8)?;
31        self.writer.write_u8(value as u8)?;
32        Ok(())
33    }
34
35    /// Encode a [`f64`] as a AMF0 number value.
36    pub fn encode_number(&mut self, value: f64) -> Result<(), Amf0Error> {
37        self.writer.write_u8(Amf0Marker::Number as u8)?;
38        self.writer.write_f64::<BigEndian>(value)?;
39        Ok(())
40    }
41
42    /// Encode a [`&str`](str) as a AMF0 string value.
43    ///
44    /// This function decides based on the length of the given string slice whether to use a normal string or a long string.
45    pub fn encode_string(&mut self, value: &str) -> Result<(), Amf0Error> {
46        let len = value.len();
47
48        if len <= (u16::MAX as usize) {
49            // Normal string
50            self.writer.write_u8(Amf0Marker::String as u8)?;
51            self.writer.write_u16::<BigEndian>(len as u16)?;
52            self.writer.write_all(value.as_bytes())?;
53        } else {
54            // Long string
55
56            // This try_into fails if the length is greater than u32::MAX
57            let len: u32 = len.try_into()?;
58
59            self.writer.write_u8(Amf0Marker::LongString as u8)?;
60            self.writer.write_u32::<BigEndian>(len)?;
61            self.writer.write_all(value.as_bytes())?;
62        }
63
64        Ok(())
65    }
66
67    /// Encode AMF0 Null value.
68    pub fn encode_null(&mut self) -> Result<(), Amf0Error> {
69        self.writer.write_u8(Amf0Marker::Null as u8)?;
70        Ok(())
71    }
72
73    /// Encode AMF0 Undefined value.
74    pub fn encode_undefined(&mut self) -> Result<(), Amf0Error> {
75        self.writer.write_u8(Amf0Marker::Undefined as u8)?;
76        Ok(())
77    }
78
79    pub(crate) fn encode_array_header(&mut self, len: u32) -> Result<(), Amf0Error> {
80        self.writer.write_u8(Amf0Marker::StrictArray as u8)?;
81        self.writer.write_u32::<BigEndian>(len)?;
82        Ok(())
83    }
84
85    /// Encode an [`Amf0Array`] as an AMF0 StrictArray value.
86    pub fn encode_array(&mut self, values: &Amf0Array) -> Result<(), Amf0Error> {
87        self.encode_array_header(values.len().try_into()?)?;
88
89        for value in values.iter() {
90            value.encode(self)?;
91        }
92
93        Ok(())
94    }
95
96    pub(crate) fn encode_object_header(&mut self) -> Result<(), Amf0Error> {
97        self.writer.write_u8(Amf0Marker::Object as u8)?;
98        Ok(())
99    }
100
101    pub(crate) fn encode_object_key(&mut self, key: &str) -> Result<(), Amf0Error> {
102        self.writer.write_u16::<BigEndian>(key.len().try_into()?)?;
103        self.writer.write_all(key.as_bytes())?;
104        Ok(())
105    }
106
107    pub(crate) fn encode_object_trailer(&mut self) -> Result<(), Amf0Error> {
108        self.writer.write_u24::<BigEndian>(Amf0Marker::ObjectEnd as u32)?;
109        Ok(())
110    }
111
112    /// Encode an [`Amf0Object`] as an AMF0 Object value.
113    pub fn encode_object(&mut self, values: &Amf0Object) -> Result<(), Amf0Error> {
114        self.encode_object_header()?;
115
116        for (key, value) in values.iter() {
117            self.encode_object_key(key.as_str())?;
118            value.encode(self)?;
119        }
120
121        self.encode_object_trailer()?;
122
123        Ok(())
124    }
125
126    /// Encode a given value using [serde].
127    #[cfg(feature = "serde")]
128    pub fn serialize<T>(&mut self, value: T) -> Result<(), Amf0Error>
129    where
130        T: serde::Serialize,
131    {
132        value.serialize(self)?;
133        Ok(())
134    }
135}