use crate::{
Encodable, impl_number,
options::EncodingOptions,
utils::{EndianSerialize, ParseResult},
};
#[derive(Default)]
pub struct DataEncoder {
pub(crate) buffer: Vec<u8>,
pub(crate) options: EncodingOptions,
}
impl DataEncoder {
pub fn new() -> Self {
Self {
buffer: Vec::new(),
options: EncodingOptions::default(),
}
}
pub fn set_options(&mut self, options: &EncodingOptions) {
self.options = options.clone(); }
pub(crate) fn add_item<T>(&mut self, data: T) -> ParseResult<()>
where
T: AsRef<[u8]>,
{
let data = data.as_ref();
if self.options.prepend_data_size {
let data_len = data.len() as u32;
self.buffer
.extend_from_slice(&data_len.to_endian_bytes(&self.options.endianness));
}
self.buffer.extend_from_slice(data);
Ok(())
}
fn add_num<T: EndianSerialize>(&mut self, n: T) -> ParseResult<()> {
let data = n.to_endian_bytes(&self.options.endianness);
self.add_item(data)
}
pub fn add_slice<T: Encodable>(&mut self, data: &[T]) -> ParseResult<()> {
let data_len = data.len();
self.add_u32(data_len as u32)?;
for item in data {
let mut temp_encoder = DataEncoder::default();
temp_encoder.set_options(&self.options);
item.encode_data(&mut temp_encoder)?;
let built = temp_encoder.get_data()?;
self.add_u32(built.len() as u32)?;
self.add_item(built)?;
}
Ok(())
}
pub fn get_data(&self) -> ParseResult<&Vec<u8>> {
Ok(&self.buffer)
}
impl_number!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
}