use {
super::{amf0_markers, errors::Amf0WriteErrorValue, Amf0ValueType, Amf0WriteError},
byteorder::BigEndian,
bytes::BytesMut,
bytesio::bytes_writer::BytesWriter,
indexmap::IndexMap,
};
#[derive(Default)]
pub struct Amf0Writer {
writer: BytesWriter,
}
impl Amf0Writer {
pub fn new() -> Self {
Self {
writer: BytesWriter::new(),
}
}
pub fn write_anys(&mut self, values: &Vec<Amf0ValueType>) -> Result<(), Amf0WriteError> {
for val in values {
self.write_any(val)?;
}
Ok(())
}
pub fn write_any(&mut self, value: &Amf0ValueType) -> Result<(), Amf0WriteError> {
match *value {
Amf0ValueType::Boolean(ref val) => self.write_bool(val),
Amf0ValueType::Null => self.write_null(),
Amf0ValueType::Number(ref val) => self.write_number(val),
Amf0ValueType::UTF8String(ref val) => self.write_string(val),
Amf0ValueType::Object(ref val) => self.write_object(val),
Amf0ValueType::EcmaArray(ref val) => self.write_eacm_array(val),
_ => Ok(()),
}
}
pub fn write_number(&mut self, value: &f64) -> Result<(), Amf0WriteError> {
self.writer.write_u8(amf0_markers::NUMBER)?;
self.writer.write_f64::<BigEndian>(*value)?;
Ok(())
}
pub fn write_bool(&mut self, value: &bool) -> Result<(), Amf0WriteError> {
self.writer.write_u8(amf0_markers::BOOLEAN)?;
self.writer.write_u8(*value as u8)?;
Ok(())
}
pub fn write_string(&mut self, value: &String) -> Result<(), Amf0WriteError> {
if value.len() > (u16::max_value() as usize) {
return Err(Amf0WriteError {
value: Amf0WriteErrorValue::NormalStringTooLong,
});
}
self.writer.write_u8(amf0_markers::STRING)?;
self.writer.write_u16::<BigEndian>(value.len() as u16)?;
self.writer.write(value.as_bytes())?;
Ok(())
}
pub fn write_null(&mut self) -> Result<(), Amf0WriteError> {
self.writer.write_u8(amf0_markers::NULL)?;
Ok(())
}
pub fn write_object_eof(&mut self) -> Result<(), Amf0WriteError> {
self.writer
.write_u24::<BigEndian>(amf0_markers::OBJECT_END as u32)?;
Ok(())
}
pub fn write_object(
&mut self,
properties: &IndexMap<String, Amf0ValueType>,
) -> Result<(), Amf0WriteError> {
self.writer.write_u8(amf0_markers::OBJECT)?;
for (key, value) in properties {
self.writer.write_u16::<BigEndian>(key.len() as u16)?;
self.writer.write(key.as_bytes())?;
self.write_any(value)?;
}
self.write_object_eof()?;
Ok(())
}
pub fn write_eacm_array(
&mut self,
properties: &IndexMap<String, Amf0ValueType>,
) -> Result<(), Amf0WriteError> {
self.writer.write_u8(amf0_markers::ECMA_ARRAY)?;
self.writer
.write_u32::<BigEndian>(properties.len() as u32)?;
for (key, value) in properties {
self.writer.write_u16::<BigEndian>(key.len() as u16)?;
self.writer.write(key.as_bytes())?;
self.write_any(value)?;
}
self.write_object_eof()?;
Ok(())
}
pub fn extract_current_bytes(&mut self) -> BytesMut {
self.writer.extract_current_bytes()
}
pub fn get_current_bytes(&mut self) -> BytesMut {
self.writer.get_current_bytes()
}
pub fn len(&self) -> usize {
self.writer.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}