use std::io;
use byteorder::{BigEndian, WriteBytesExt};
use crate::{Amf0Array, Amf0Error, Amf0Marker, Amf0Object};
#[derive(Debug)]
pub struct Amf0Encoder<W> {
writer: W,
}
impl<W> Amf0Encoder<W> {
pub fn new(writer: W) -> Self {
Amf0Encoder { writer }
}
}
impl<W> Amf0Encoder<W>
where
W: io::Write,
{
pub fn encode_boolean(&mut self, value: bool) -> Result<(), Amf0Error> {
self.writer.write_u8(Amf0Marker::Boolean as u8)?;
self.writer.write_u8(value as u8)?;
Ok(())
}
pub fn encode_number(&mut self, value: f64) -> Result<(), Amf0Error> {
self.writer.write_u8(Amf0Marker::Number as u8)?;
self.writer.write_f64::<BigEndian>(value)?;
Ok(())
}
pub fn encode_string(&mut self, value: &str) -> Result<(), Amf0Error> {
let len = value.len();
if len <= (u16::MAX as usize) {
self.writer.write_u8(Amf0Marker::String as u8)?;
self.writer.write_u16::<BigEndian>(len as u16)?;
self.writer.write_all(value.as_bytes())?;
} else {
let len: u32 = len.try_into()?;
self.writer.write_u8(Amf0Marker::LongString as u8)?;
self.writer.write_u32::<BigEndian>(len)?;
self.writer.write_all(value.as_bytes())?;
}
Ok(())
}
pub fn encode_null(&mut self) -> Result<(), Amf0Error> {
self.writer.write_u8(Amf0Marker::Null as u8)?;
Ok(())
}
pub fn encode_undefined(&mut self) -> Result<(), Amf0Error> {
self.writer.write_u8(Amf0Marker::Undefined as u8)?;
Ok(())
}
pub(crate) fn encode_array_header(&mut self, len: u32) -> Result<(), Amf0Error> {
self.writer.write_u8(Amf0Marker::StrictArray as u8)?;
self.writer.write_u32::<BigEndian>(len)?;
Ok(())
}
pub fn encode_array(&mut self, values: &Amf0Array) -> Result<(), Amf0Error> {
self.encode_array_header(values.len().try_into()?)?;
for value in values.iter() {
value.encode(self)?;
}
Ok(())
}
pub(crate) fn encode_object_header(&mut self) -> Result<(), Amf0Error> {
self.writer.write_u8(Amf0Marker::Object as u8)?;
Ok(())
}
pub(crate) fn encode_object_key(&mut self, key: &str) -> Result<(), Amf0Error> {
self.writer.write_u16::<BigEndian>(key.len().try_into()?)?;
self.writer.write_all(key.as_bytes())?;
Ok(())
}
pub(crate) fn encode_object_trailer(&mut self) -> Result<(), Amf0Error> {
self.writer.write_u24::<BigEndian>(Amf0Marker::ObjectEnd as u32)?;
Ok(())
}
pub fn encode_object(&mut self, values: &Amf0Object) -> Result<(), Amf0Error> {
self.encode_object_header()?;
for (key, value) in values.iter() {
self.encode_object_key(key.as_str())?;
value.encode(self)?;
}
self.encode_object_trailer()?;
Ok(())
}
#[cfg(feature = "serde")]
pub fn serialize<T>(&mut self, value: T) -> Result<(), Amf0Error>
where
T: serde::Serialize,
{
value.serialize(self)?;
Ok(())
}
}