1use std::io::Write;
3
4#[cfg(feature = "amf3")]
5use crate::FORMAT_VERSION_AMF3;
6#[cfg(feature = "amf3")]
7use crate::amf3::write::AMF3Encoder;
8use crate::errors::Error;
9use crate::nom_utils::write_string;
10use crate::types::{AMFVersion, Header, Lso};
11use crate::{FORMAT_VERSION_AMF0, HEADER_SIGNATURE, HEADER_VERSION, PADDING};
12
13#[derive(Default)]
15pub struct Writer {
16 #[cfg(feature = "amf3")]
18 pub amf3_encoder: AMF3Encoder,
19}
20
21impl Writer {
22 pub fn write_full<'a, 'b: 'a, W: Write + 'a>(
24 &'a mut self,
25 writer: &mut W,
26 lso: &'b mut Lso,
27 ) -> std::io::Result<()> {
28 let mut buffer = Vec::new();
29 if lso.header.format_version == AMFVersion::AMF0 {
30 crate::amf0::write::write_body(&mut buffer, &lso.body)?;
31 } else {
32 #[cfg(feature = "amf3")]
33 self.amf3_encoder.write_body(&mut buffer, &lso.body)?;
34 }
35
36 lso.header.length = buffer.len() as u32 + header_length(&lso.header) as u32;
37
38 write_header(writer, &lso.header)?;
39 writer.write_all(&buffer)?;
40 Ok(())
41 }
42}
43
44fn write_header<'a, 'b: 'a, W: Write + 'a>(
45 writer: &mut W,
46 header: &'b Header,
47) -> std::io::Result<()> {
48 writer.write_all(&HEADER_VERSION)?;
49 writer.write_u32(header.length)?;
50 writer.write_all(&HEADER_SIGNATURE)?;
51 write_string(writer, &header.name)?;
52 writer.write_all(&PADDING)?;
53 writer.write_all(&PADDING)?;
54 writer.write_all(&PADDING)?;
55 match header.format_version {
56 AMFVersion::AMF0 => writer.write_all(&[FORMAT_VERSION_AMF0])?,
57 #[cfg(feature = "amf3")]
58 AMFVersion::AMF3 => writer.write_all(&[FORMAT_VERSION_AMF3])?,
59 };
60 Ok(())
61}
62
63pub fn header_length(header: &Header) -> usize {
65 10 + (2 + header.name.len() + 3 + 1)
67}
68
69pub fn write_to_bytes<'a>(lso: &mut Lso) -> Result<Vec<u8>, Error<'a>> {
71 let mut v = Vec::new();
72
73 let mut s = Writer::default();
74 s.write_full(&mut v, lso)
75 .map_err(|e| Error::IoError(e.to_string(), e.kind()))?;
76 Ok(v)
77}
78
79pub(crate) trait WriteExt {
80 fn write_u8(&mut self, value: u8) -> std::io::Result<()>;
81 fn write_u16(&mut self, value: u16) -> std::io::Result<()>;
82 fn write_u32(&mut self, value: u32) -> std::io::Result<()>;
83 fn write_i32(&mut self, value: i32) -> std::io::Result<()>;
84 fn write_f64(&mut self, value: f64) -> std::io::Result<()>;
85}
86
87impl<T> WriteExt for T
88where
89 T: Write,
90{
91 fn write_u8(&mut self, value: u8) -> std::io::Result<()> {
92 self.write_all(&[value])
93 }
94
95 fn write_u16(&mut self, value: u16) -> std::io::Result<()> {
96 self.write_all(&value.to_be_bytes())
97 }
98
99 fn write_u32(&mut self, value: u32) -> std::io::Result<()> {
100 self.write_all(&value.to_be_bytes())
101 }
102
103 fn write_i32(&mut self, value: i32) -> std::io::Result<()> {
104 self.write_all(&value.to_be_bytes())
105 }
106
107 fn write_f64(&mut self, value: f64) -> std::io::Result<()> {
108 self.write_all(&value.to_be_bytes())
109 }
110}