use super::{chunk_header::*, chunk_type::*, *};
use crate::param::{param_header::*, *};
use crate::util::get_padding_size;
use bytes::{Bytes, BytesMut};
use std::fmt;
#[derive(Default, Debug)]
pub(crate) struct ChunkReconfig {
pub(crate) param_a: Option<Box<dyn Param + Send + Sync>>,
pub(crate) param_b: Option<Box<dyn Param + Send + Sync>>,
}
impl Clone for ChunkReconfig {
fn clone(&self) -> Self {
ChunkReconfig {
param_a: self.param_a.as_ref().cloned(),
param_b: self.param_b.as_ref().cloned(),
}
}
}
impl fmt::Display for ChunkReconfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut res = String::new();
if let Some(param_a) = &self.param_a {
res += format!("Param A:\n {}", param_a).as_str();
}
if let Some(param_b) = &self.param_b {
res += format!("Param B:\n {}", param_b).as_str()
}
write!(f, "{}", res)
}
}
impl Chunk for ChunkReconfig {
fn header(&self) -> ChunkHeader {
ChunkHeader {
typ: CT_RECONFIG,
flags: 0,
value_length: self.value_length() as u16,
}
}
fn unmarshal(raw: &Bytes) -> Result<Self> {
let header = ChunkHeader::unmarshal(raw)?;
if header.typ != CT_RECONFIG {
return Err(Error::ErrChunkTypeNotReconfig);
}
let param_a =
build_param(&raw.slice(CHUNK_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length()))?;
let padding = get_padding_size(PARAM_HEADER_LENGTH + param_a.value_length());
let offset = CHUNK_HEADER_SIZE + PARAM_HEADER_LENGTH + param_a.value_length() + padding;
let param_b = if CHUNK_HEADER_SIZE + header.value_length() > offset {
Some(build_param(
&raw.slice(offset..CHUNK_HEADER_SIZE + header.value_length()),
)?)
} else {
None
};
Ok(ChunkReconfig {
param_a: Some(param_a),
param_b,
})
}
fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
self.header().marshal_to(writer)?;
let param_a_value_length = if let Some(param_a) = &self.param_a {
writer.extend(param_a.marshal()?);
param_a.value_length()
} else {
return Err(Error::ErrChunkReconfigInvalidParamA);
};
if let Some(param_b) = &self.param_b {
let padding = get_padding_size(PARAM_HEADER_LENGTH + param_a_value_length);
writer.extend(vec![0u8; padding]);
writer.extend(param_b.marshal()?);
}
Ok(writer.len())
}
fn check(&self) -> Result<()> {
Ok(())
}
fn value_length(&self) -> usize {
let mut l = PARAM_HEADER_LENGTH;
let param_a_value_length = if let Some(param_a) = &self.param_a {
l += param_a.value_length();
param_a.value_length()
} else {
0
};
if let Some(param_b) = &self.param_b {
let padding = get_padding_size(PARAM_HEADER_LENGTH + param_a_value_length);
l += PARAM_HEADER_LENGTH + param_b.value_length() + padding;
}
l
}
fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}
}