use crate::messages::fragment_number::FragmentNumber;
use crate::messages::submessages::submessage_elements::parameter_list::ParameterList;
use crate::messages::submessages::submessage_elements::serialized_payload::SerializedPayload;
use crate::structure::guid::EntityId;
use crate::structure::sequence_number::SequenceNumber;
use crate::messages::submessages::submessages::*;
use log::debug;
use speedy::{Context, Writer, Readable, Writable, Error};
use enumflags2::BitFlags;
use std::io;
#[derive(Debug, PartialEq)]
pub struct DataFrag {
pub reader_id: EntityId,
pub writer_id: EntityId,
pub writer_sn: SequenceNumber,
pub fragment_starting_num: FragmentNumber,
pub fragments_in_submessage: u16,
pub data_size: u32,
pub fragment_size: u16,
pub inline_qos: Option<ParameterList>,
pub serialized_payload: SerializedPayload,
}
impl<'a> DataFrag {
pub fn deserialize(buffer: &'a [u8], flags: BitFlags<DATAFRAG_Flags>) -> io::Result<DataFrag> {
let mut cursor = io::Cursor::new(buffer);
let endianness = endianness_flag(flags.bits());
let map_speedy_err = |p: Error| io::Error::new(io::ErrorKind::Other, p);
let _extra_flags =
u16::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let octets_to_inline_qos =
u16::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let reader_id =
EntityId::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let writer_id =
EntityId::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let writer_sn =
SequenceNumber::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let fragment_starting_num =
FragmentNumber::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let fragments_in_submessage =
u16::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let fragment_size =
u16::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let data_size =
u32::read_from_stream_with_ctx(endianness, &mut cursor).map_err(map_speedy_err)?;
let expect_qos = flags.contains(DATAFRAG_Flags::InlineQos);
let rtps_v23_header_size: u16 = 7 * 4;
let extra_octets = octets_to_inline_qos - rtps_v23_header_size;
if octets_to_inline_qos < rtps_v23_header_size {
return Err(io::Error::new(
io::ErrorKind::Other,
"DataFrag has too low octetsToInlineQos",
));
}
cursor.set_position(cursor.position() + extra_octets as u64);
let inline_qos = if expect_qos {
Some(
ParameterList::read_from_stream_with_ctx(endianness, &mut cursor)
.map_err(map_speedy_err)?,
)
} else {
None
};
let serialized_payload = SerializedPayload::from_bytes(&buffer[cursor.position() as usize..])?;
Ok(DataFrag {
reader_id,
writer_id,
writer_sn,
fragment_starting_num,
fragments_in_submessage,
data_size,
fragment_size,
inline_qos,
serialized_payload,
})
}
}
#[cfg(test)]
impl Default for DataFrag {
fn default() -> Self {
DataFrag {
reader_id: EntityId::default(),
writer_id: EntityId::default(),
writer_sn: SequenceNumber::default(),
fragment_starting_num: FragmentNumber::default(),
fragments_in_submessage: 0,
data_size: 0,
fragment_size: 0,
inline_qos: None,
serialized_payload: SerializedPayload::default(),
}
}
}
impl<C: Context> Writable<C> for DataFrag {
fn write_to<'a, T: ?Sized + Writer<C>>(&'a self, writer: &mut T) -> Result<(), C::Error> {
writer.write_u16(0)?;
if self.inline_qos.is_some() && self.inline_qos.as_ref().unwrap().parameters.len() > 0 {
debug!("self.inline_qos {:?}", self.inline_qos);
todo!()
} else if self.inline_qos.is_some() && self.inline_qos.as_ref().unwrap().parameters.len() == 0 {
writer.write_u16(24)?;
} else if self.inline_qos.is_none() {
writer.write_u16(24)?;
}
writer.write_value(&self.reader_id)?;
writer.write_value(&self.writer_id)?;
writer.write_value(&self.writer_sn)?;
writer.write_value(&self.fragment_starting_num)?;
writer.write_value(&self.fragments_in_submessage)?;
writer.write_value(&self.fragment_size)?;
writer.write_value(&self.data_size)?;
if self.inline_qos.is_some() && self.inline_qos.as_ref().unwrap().parameters.len() > 0 {
writer.write_value(&self.inline_qos)?;
}
writer.write_value(&self.serialized_payload)?;
Ok(())
}
}