use enumflags2::{bitflags, BitFlags};
#[cfg(test)]
use byteorder::ByteOrder;
use speedy::{Context, Endianness, Readable, Writable, Writer};
use serde::{Deserialize, Serialize};
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use crate::{
dds::key::KeyHash,
messages::submessages::elements::{parameter_list::ParameterList, RepresentationIdentifier},
serialization::{pl_cdr_adapters::PlCdrDeserializeError, speedy_pl_cdr_helpers::*},
structure::{cache_change::ChangeKind, parameter_id::ParameterId, rpc::SampleIdentity},
};
#[cfg(test)]
use crate::{
dds::adapters::no_key::*, serialization, serialization::to_vec,
serialization::CDRDeserializerAdapter,
};
pub(crate) struct InlineQos {}
impl InlineQos {
pub fn status_info(
params: &ParameterList,
rep_id: RepresentationIdentifier,
) -> std::result::Result<StatusInfo, PlCdrDeserializeError> {
let status_info = params
.parameters
.iter()
.find(|p| p.parameter_id == ParameterId::PID_STATUS_INFO);
let ctx = pl_cdr_rep_id_to_speedy_d(rep_id)?;
let status_info = match status_info {
Some(p) => StatusInfo::read_from_buffer_with_ctx(ctx, &p.value)?,
None => StatusInfo::empty(),
};
Ok(status_info)
}
pub fn key_hash(params: &ParameterList) -> Result<Option<KeyHash>, PlCdrDeserializeError> {
let key_hash = params
.parameters
.iter()
.find(|p| p.parameter_id == ParameterId::PID_KEY_HASH);
Ok(match key_hash {
Some(p) => Some(KeyHash::from_pl_cdr_bytes(p.value.clone())?),
None => None,
})
}
pub fn related_sample_identity(
params: &ParameterList,
representation_id: RepresentationIdentifier,
) -> Result<Option<SampleIdentity>, PlCdrDeserializeError> {
let rsi = params
.parameters
.iter()
.find(|p| {
p.parameter_id == ParameterId::PID_RELATED_SAMPLE_IDENTITY
|| p.parameter_id == ParameterId::PID_RELATED_SAMPLE_IDENTITY_CUSTOM
});
let endianness = match representation_id {
RepresentationIdentifier::PL_CDR_LE => Endianness::LittleEndian,
RepresentationIdentifier::CDR_LE => Endianness::LittleEndian,
RepresentationIdentifier::PL_CDR_BE => Endianness::BigEndian,
RepresentationIdentifier::CDR_BE => Endianness::BigEndian,
_ => Err(PlCdrDeserializeError::NotSupported(
"Unknown encoding, expected PL_CDR".to_string(),
))?,
};
Ok(match rsi {
Some(p) => Some(
SampleIdentity::read_from_buffer_with_ctx(endianness, &p.value)?,
),
None => None,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
#[bitflags]
pub enum StatusInfoEnum {
Disposed = 0b0001,
Unregistered = 0b0010,
Filtered = 0b0100,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct StatusInfo {
em: [u8; 3],
si: BitFlags<StatusInfoEnum>,
}
impl<C: Context> Writable<C> for StatusInfo {
#[inline]
fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> std::result::Result<(), C::Error> {
writer.write_u8(0x00)?;
writer.write_u8(0x00)?;
writer.write_u8(0x00)?;
writer.write_u8(self.si.bits())?;
Ok(())
}
}
impl<'a, C: Context> Readable<'a, C> for StatusInfo {
#[inline]
fn read_from<R: speedy::Reader<'a, C>>(reader: &mut R) -> std::result::Result<Self, C::Error> {
reader.read_u8()?;
reader.read_u8()?;
reader.read_u8()?;
let si = BitFlags::<StatusInfoEnum>::from_bits_truncate(reader.read_u8()?);
Ok(Self { em: [0; 3], si })
}
}
impl StatusInfo {
pub fn empty() -> Self {
Self {
em: [0; 3],
si: BitFlags::empty(),
}
}
pub fn contains(&self, sie: StatusInfoEnum) -> bool {
self.si.contains(sie)
}
pub fn change_kind(&self) -> ChangeKind {
if self.contains(StatusInfoEnum::Disposed) {
ChangeKind::NotAliveDisposed
} else if self.contains(StatusInfoEnum::Unregistered) {
ChangeKind::NotAliveUnregistered
} else {
ChangeKind::Alive
}
}
#[cfg(test)]
pub fn into_cdr_bytes<BO: ByteOrder>(self) -> Result<Vec<u8>, serialization::Error> {
to_vec::<Self, BO>(&self)
}
#[cfg(test)]
pub fn from_cdr_bytes(
bytes: &[u8],
representation_id: RepresentationIdentifier,
) -> Result<Self, serialization::Error> {
CDRDeserializerAdapter::from_bytes(bytes, representation_id)
}
}
#[cfg(test)]
mod tests {
use byteorder::{BigEndian, LittleEndian};
use super::*;
#[test]
fn inline_qos_status_info() {
let si_bytes = StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered,
}
.into_cdr_bytes::<LittleEndian>()
.unwrap();
let bytes: Vec<u8> = vec![0x00, 0x00, 0x00, 0x03];
assert_eq!(si_bytes, bytes);
let status_info = StatusInfo::from_cdr_bytes(&bytes, RepresentationIdentifier::CDR_LE).unwrap();
assert_eq!(
status_info,
StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered
}
);
let si_bytes = StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered,
}
.into_cdr_bytes::<BigEndian>()
.unwrap();
let bytes: Vec<u8> = vec![0x00, 0x00, 0x00, 0x03];
assert_eq!(si_bytes, bytes);
let status_info = StatusInfo::from_cdr_bytes(&bytes, RepresentationIdentifier::CDR_BE).unwrap();
assert_eq!(
status_info,
StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered
}
);
}
}