use std::collections::BTreeMap;
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use speedy::{Context, Readable, Reader, Writable, Writer};
use crate::{
messages::submessages::elements::parameter::Parameter,
serialization::pl_cdr_adapters::{PlCdrDeserializeError, PlCdrSerializeError},
structure::parameter_id::ParameterId,
RepresentationIdentifier,
};
pub fn pl_cdr_rep_id_to_speedy(
encoding: RepresentationIdentifier,
) -> Result<speedy::Endianness, PlCdrSerializeError> {
match encoding {
RepresentationIdentifier::PL_CDR_LE => Ok(speedy::Endianness::LittleEndian),
RepresentationIdentifier::PL_CDR_BE => Ok(speedy::Endianness::BigEndian),
RepresentationIdentifier::CDR_LE => Ok(speedy::Endianness::LittleEndian),
RepresentationIdentifier::CDR_BE => Ok(speedy::Endianness::BigEndian),
rep_id => Err(PlCdrSerializeError::NotSupported(format!(
"Unknown {rep_id:?}"
))),
}
}
pub fn pl_cdr_rep_id_to_speedy_d(
encoding: RepresentationIdentifier,
) -> Result<speedy::Endianness, PlCdrDeserializeError> {
match encoding {
RepresentationIdentifier::PL_CDR_LE => Ok(speedy::Endianness::LittleEndian),
RepresentationIdentifier::PL_CDR_BE => Ok(speedy::Endianness::BigEndian),
RepresentationIdentifier::CDR_LE => Ok(speedy::Endianness::LittleEndian),
RepresentationIdentifier::CDR_BE => Ok(speedy::Endianness::BigEndian),
rep_id => Err(PlCdrDeserializeError::NotSupported(format!(
"Unknown {rep_id:?}"
))),
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StringWithNul {
string: String,
}
impl StringWithNul {
pub fn len(&self) -> usize {
self.string.len() + 1
}
}
impl From<String> for StringWithNul {
fn from(string: String) -> Self {
StringWithNul { string }
}
}
impl From<&String> for StringWithNul {
fn from(string: &String) -> Self {
StringWithNul {
string: string.clone(),
}
}
}
impl From<StringWithNul> for String {
fn from(value: StringWithNul) -> String {
value.string
}
}
impl<C: Context> Writable<C> for StringWithNul {
#[inline]
fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> std::result::Result<(), C::Error> {
writer.write_u32((self.string.len() + 1).try_into().unwrap())?; writer.write_slice(self.string.as_bytes())?;
writer.write_u8(0)?; Ok(())
}
}
impl<'a, C: Context> Readable<'a, C> for StringWithNul {
#[inline]
fn read_from<R: speedy::Reader<'a, C>>(reader: &mut R) -> std::result::Result<Self, C::Error> {
let mut raw_str: String = reader.read_value()?;
let assumed_nul = raw_str.pop(); match assumed_nul {
Some('\0') => { }
Some(other) => error!("StringWithNul deserialize: Expected NUL character, decoded {other:?}"),
None => {
error!("StringWithNul deserialize: Expected NUL character, but end of input reached.");
}
}
Ok(StringWithNul { string: raw_str })
}
}
pub(crate) fn read_pad<'a, C: Context, R: Reader<'a, C>>(
reader: &mut R,
read_length: usize,
align: usize,
) -> std::result::Result<(), C::Error> {
let m = read_length % align;
if m > 0 {
reader.skip_bytes(align - m)?;
}
Ok(())
}
pub(crate) fn write_pad<C: Context, T: ?Sized + Writer<C>>(
writer: &mut T,
previous_length: usize,
align: usize,
) -> std::result::Result<(), C::Error> {
let m = previous_length % align;
if m > 0 {
for _ in 0..(align - m) {
writer.write_u8(0)?;
}
}
Ok(())
}
pub(crate) fn get_first_from_pl_map<'a, C, D>(
pl_map: &'a BTreeMap<ParameterId, Vec<&Parameter>>,
ctx: C,
pid: ParameterId,
name: &str,
) -> Result<D, PlCdrDeserializeError>
where
C: speedy::Context,
D: Readable<'a, C>,
PlCdrDeserializeError: From<<C as speedy::Context>::Error>,
{
pl_map
.get(&pid)
.and_then(|v| v.first())
.ok_or(PlCdrDeserializeError::MissingField(pid, name.to_string()))
.and_then(|p| {
D::read_from_buffer_with_ctx(ctx, &p.value).map_err(|e| {
error!("PL_CDR Deserializing {name}");
e.into()
})
})
}
pub(crate) fn get_all_from_pl_map<'a, C, D>(
pl_map: &'a BTreeMap<ParameterId, Vec<&Parameter>>,
ctx: &C,
pid: ParameterId,
name: &str,
) -> Result<Vec<D>, PlCdrDeserializeError>
where
C: speedy::Context + Clone,
D: Readable<'a, C>,
PlCdrDeserializeError: From<<C as speedy::Context>::Error>,
{
pl_map
.get(&pid)
.unwrap_or(&Vec::new())
.iter()
.map(|p| {
D::read_from_buffer_with_ctx(ctx.clone(), &p.value).map_err(|e| {
error!("PL_CDR Deserializing {name}");
e.into()
})
})
.collect()
}
pub(crate) fn get_option_from_pl_map<'a, C, D>(
pl_map: &'a BTreeMap<ParameterId, Vec<&Parameter>>,
ctx: C,
pid: ParameterId,
name: &str,
) -> Result<Option<D>, PlCdrDeserializeError>
where
C: speedy::Context + Clone,
D: Readable<'a, C>,
PlCdrDeserializeError: From<<C as speedy::Context>::Error>,
{
pl_map
.get(&pid)
.and_then(|v| v.first()) .map(|p| {
D::read_from_buffer_with_ctx(ctx, &p.value).map_err(|e| {
error!("PL_CDR Deserializing {name}");
info!("Parameter payload was {:x?}", p.value);
e.into()
})
})
.transpose()
}