1use std::borrow::Borrow;
4use std::io;
5
6use byteorder::{BigEndian, WriteBytesExt};
7
8use crate::{Amf0Error, Amf0Marker, Amf0Object, Amf0Value};
9
10#[derive(Debug)]
14pub struct Amf0Encoder<W> {
15 writer: W,
16}
17
18impl<W> Amf0Encoder<W> {
19 pub fn new(writer: W) -> Self {
21 Amf0Encoder { writer }
22 }
23}
24
25impl<W> Amf0Encoder<W>
26where
27 W: io::Write,
28{
29 pub fn encode_boolean(&mut self, value: bool) -> Result<(), Amf0Error> {
31 self.writer.write_u8(Amf0Marker::Boolean as u8)?;
32 self.writer.write_u8(value as u8)?;
33 Ok(())
34 }
35
36 pub fn encode_number(&mut self, value: f64) -> Result<(), Amf0Error> {
38 self.writer.write_u8(Amf0Marker::Number as u8)?;
39 self.writer.write_f64::<BigEndian>(value)?;
40 Ok(())
41 }
42
43 pub fn encode_string(&mut self, value: &str) -> Result<(), Amf0Error> {
47 let len = value.len();
48
49 if len <= (u16::MAX as usize) {
50 self.writer.write_u8(Amf0Marker::String as u8)?;
52 self.writer.write_u16::<BigEndian>(len as u16)?;
53 self.writer.write_all(value.as_bytes())?;
54 } else {
55 let len: u32 = len.try_into()?;
59
60 self.writer.write_u8(Amf0Marker::LongString as u8)?;
61 self.writer.write_u32::<BigEndian>(len)?;
62 self.writer.write_all(value.as_bytes())?;
63 }
64
65 Ok(())
66 }
67
68 pub fn encode_null(&mut self) -> Result<(), Amf0Error> {
70 self.writer.write_u8(Amf0Marker::Null as u8)?;
71 Ok(())
72 }
73
74 pub fn encode_undefined(&mut self) -> Result<(), Amf0Error> {
76 self.writer.write_u8(Amf0Marker::Undefined as u8)?;
77 Ok(())
78 }
79
80 pub(crate) fn encode_array_header(&mut self, len: u32) -> Result<(), Amf0Error> {
81 self.writer.write_u8(Amf0Marker::StrictArray as u8)?;
82 self.writer.write_u32::<BigEndian>(len)?;
83 Ok(())
84 }
85
86 pub fn encode_array<'a, I, B>(&mut self, values: I) -> Result<(), Amf0Error>
88 where
89 B: Borrow<Amf0Value<'a>>,
90 I: IntoIterator<Item = B>,
91 I::IntoIter: ExactSizeIterator,
92 {
93 let iter = values.into_iter();
94 self.encode_array_header(iter.len().try_into()?)?;
95
96 for value in iter {
97 value.borrow().encode(self)?;
98 }
99
100 Ok(())
101 }
102
103 pub(crate) fn encode_object_header(&mut self) -> Result<(), Amf0Error> {
104 self.writer.write_u8(Amf0Marker::Object as u8)?;
105 Ok(())
106 }
107
108 pub(crate) fn encode_object_key(&mut self, key: &str) -> Result<(), Amf0Error> {
109 self.writer.write_u16::<BigEndian>(key.len().try_into()?)?;
110 self.writer.write_all(key.as_bytes())?;
111 Ok(())
112 }
113
114 pub(crate) fn encode_object_trailer(&mut self) -> Result<(), Amf0Error> {
115 self.writer.write_u16::<BigEndian>(0)?;
117 self.writer.write_u8(Amf0Marker::ObjectEnd as u8)?;
119 Ok(())
120 }
121
122 pub fn encode_object(&mut self, values: &Amf0Object) -> Result<(), Amf0Error> {
124 self.encode_object_header()?;
125
126 for (key, value) in values.iter() {
127 self.encode_object_key(key.as_str())?;
128 value.encode(self)?;
129 }
130
131 self.encode_object_trailer()?;
132
133 Ok(())
134 }
135
136 #[cfg(feature = "serde")]
138 pub fn serialize<T>(&mut self, value: T) -> Result<(), Amf0Error>
139 where
140 T: serde::Serialize,
141 {
142 value.serialize(self)?;
143 Ok(())
144 }
145}