use crate::amf0;
use crate::errors::Error;
use crate::packet::{Header, Message, Packet};
use crate::types::AMFVersion;
fn write_header(
header: &Header,
out: &mut Vec<u8>,
exact_lengths: bool,
) -> Result<(), Error<'static>> {
let name_length = u16::try_from(header.name.len()).map_err(|_| Error::PacketTooLarge)?;
out.extend(name_length.to_be_bytes());
out.extend(header.name.as_bytes());
if header.must_understand {
out.push(1);
} else {
out.push(0);
}
let mut value = Vec::new();
amf0::write::write_value(&mut value, &header.value)
.map_err(|e| Error::IoError(e.to_string(), e.kind()))?;
if exact_lengths {
let value_length = u32::try_from(value.len()).map_err(|_| Error::PacketTooLarge)?;
out.extend(value_length.to_be_bytes());
} else {
out.extend(u32::MAX.to_be_bytes());
}
out.append(&mut value);
Ok(())
}
fn write_message(
message: &Message,
out: &mut Vec<u8>,
exact_lengths: bool,
) -> Result<(), Error<'static>> {
let target_length =
u16::try_from(message.target_uri.len()).map_err(|_| Error::PacketTooLarge)?;
out.extend(target_length.to_be_bytes());
out.extend(message.target_uri.as_bytes());
let response_length =
u16::try_from(message.response_uri.len()).map_err(|_| Error::PacketTooLarge)?;
out.extend(response_length.to_be_bytes());
out.extend(message.response_uri.as_bytes());
let mut contents = Vec::new();
amf0::write::write_value(&mut contents, &message.contents)
.map_err(|e| Error::IoError(e.to_string(), e.kind()))?;
if exact_lengths {
let contents_length = u32::try_from(contents.len()).map_err(|_| Error::PacketTooLarge)?;
out.extend(contents_length.to_be_bytes());
} else {
out.extend(u32::MAX.to_be_bytes());
}
out.append(&mut contents);
Ok(())
}
pub fn write_to_bytes(packet: &Packet, exact_lengths: bool) -> Result<Vec<u8>, Error<'static>> {
let mut buffer = Vec::new();
buffer.push(0);
match packet.version {
AMFVersion::AMF0 => buffer.push(0),
#[cfg(feature = "amf3")]
AMFVersion::AMF3 => buffer.push(3),
}
let header_count = u16::try_from(packet.headers.len()).map_err(|_| Error::PacketTooLarge)?;
buffer.extend(header_count.to_be_bytes());
for header in &packet.headers {
write_header(header, &mut buffer, exact_lengths)?;
}
let message_count = u16::try_from(packet.messages.len()).map_err(|_| Error::PacketTooLarge)?;
buffer.extend(message_count.to_be_bytes());
for message in &packet.messages {
write_message(message, &mut buffer, exact_lengths)?;
}
Ok(buffer)
}