use heapless::String as HString;
use crate::protocol::dds::byte_cursor::{ByteCursor, ByteWriter, Endianness};
use crate::protocol::dds::ros2::log::LogSeverity;
use super::dds_type::DdsType;
use super::error::DdsApiError;
const CDR_LE_HEADER: [u8; 4] = [0x00, 0x01, 0x00, 0x00];
fn make_writer(buf: &mut [u8]) -> Result<ByteWriter<'_>, DdsApiError> {
if buf.len() < 4 {
return Err(DdsApiError::PayloadBufferTooSmall);
}
buf[..4].copy_from_slice(&CDR_LE_HEADER);
Ok(ByteWriter::new(&mut buf[4..], Endianness::Little))
}
fn make_cursor(payload: &[u8]) -> Result<ByteCursor<'_>, DdsApiError> {
if payload.len() < 4 {
return Err(DdsApiError::Serialization(
"payload shorter than CDR header",
));
}
let endianness = if payload[1] & 0x01 != 0 {
Endianness::Little
} else {
Endianness::Big
};
Ok(ByteCursor::new(&payload[4..], endianness))
}
impl DdsType for HString<256> {
const TYPE_NAME: &'static str = "std_msgs::msg::dds_::String_";
fn serialize(&self, buf: &mut [u8]) -> Result<usize, DdsApiError> {
let mut w = make_writer(buf)?;
w.write_cdr_string(self.as_str())
.map_err(DdsApiError::from)?;
Ok(4 + w.position())
}
fn deserialize(payload: &[u8]) -> Result<Self, DdsApiError> {
let mut cur = make_cursor(payload)?;
let s = cur.read_cdr_string().map_err(DdsApiError::from)?;
let mut result = HString::<256>::new();
result
.push_str(s)
.map_err(|_| DdsApiError::Serialization("string exceeds 256-byte capacity"))?;
Ok(result)
}
}
#[derive(Debug, Clone)]
pub struct LogOwned {
pub severity: LogSeverity,
pub name: HString<256>,
pub msg: HString<256>,
pub file: HString<256>,
pub function: HString<256>,
pub line: u32,
pub stamp_sec: i32,
pub stamp_nsec: u32,
}
impl Default for LogOwned {
fn default() -> Self {
Self {
severity: LogSeverity::Info,
name: HString::new(),
msg: HString::new(),
file: HString::new(),
function: HString::new(),
line: 0,
stamp_sec: 0,
stamp_nsec: 0,
}
}
}
impl DdsType for LogOwned {
const TYPE_NAME: &'static str = "rcl_interfaces::msg::dds_::Log_";
fn serialize(&self, buf: &mut [u8]) -> Result<usize, DdsApiError> {
let mut w = make_writer(buf)?;
w.write_i32(self.stamp_sec).map_err(DdsApiError::from)?;
w.write_u32(self.stamp_nsec).map_err(DdsApiError::from)?;
w.write_u8(self.severity as u8).map_err(DdsApiError::from)?;
w.align_to(4).map_err(DdsApiError::from)?;
w.write_cdr_string(self.name.as_str())
.map_err(DdsApiError::from)?;
w.write_cdr_string(self.msg.as_str())
.map_err(DdsApiError::from)?;
w.write_cdr_string(self.file.as_str())
.map_err(DdsApiError::from)?;
w.write_cdr_string(self.function.as_str())
.map_err(DdsApiError::from)?;
w.write_u32(self.line).map_err(DdsApiError::from)?;
Ok(4 + w.position())
}
fn deserialize(payload: &[u8]) -> Result<Self, DdsApiError> {
let mut cur = make_cursor(payload)?;
let stamp_sec = cur.read_i32().map_err(DdsApiError::from)?;
let stamp_nsec = cur.read_u32().map_err(DdsApiError::from)?;
let level_raw = cur.read_u8().map_err(DdsApiError::from)?;
cur.align_to(4).map_err(DdsApiError::from)?;
let severity = log_severity_from_u8(level_raw);
let name_s = cur.read_cdr_string().map_err(DdsApiError::from)?;
let msg_s = cur.read_cdr_string().map_err(DdsApiError::from)?;
let file_s = cur.read_cdr_string().map_err(DdsApiError::from)?;
let function_s = cur.read_cdr_string().map_err(DdsApiError::from)?;
let line = cur.read_u32().map_err(DdsApiError::from)?;
let mut name = HString::<256>::new();
name.push_str(name_s)
.map_err(|_| DdsApiError::Serialization("log name too long"))?;
let mut msg = HString::<256>::new();
msg.push_str(msg_s)
.map_err(|_| DdsApiError::Serialization("log msg too long"))?;
let mut file = HString::<256>::new();
file.push_str(file_s)
.map_err(|_| DdsApiError::Serialization("log file too long"))?;
let mut function = HString::<256>::new();
function
.push_str(function_s)
.map_err(|_| DdsApiError::Serialization("log function too long"))?;
Ok(Self {
severity,
name,
msg,
file,
function,
line,
stamp_sec,
stamp_nsec,
})
}
}
fn log_severity_from_u8(v: u8) -> LogSeverity {
match v {
10 => LogSeverity::Debug,
20 => LogSeverity::Info,
30 => LogSeverity::Warn,
40 => LogSeverity::Error,
50 => LogSeverity::Fatal,
_ => LogSeverity::Info,
}
}
#[derive(Debug, Clone, Default)]
pub struct ParameterEventOwned {
pub stamp_sec: i32,
pub stamp_nsec: u32,
pub node: HString<256>,
pub new_parameters_count: u32,
pub changed_parameters_count: u32,
pub deleted_parameters_count: u32,
}
impl DdsType for ParameterEventOwned {
const TYPE_NAME: &'static str = "rcl_interfaces::msg::dds_::ParameterEvent_";
fn serialize(&self, buf: &mut [u8]) -> Result<usize, DdsApiError> {
let mut w = make_writer(buf)?;
w.write_i32(self.stamp_sec).map_err(DdsApiError::from)?;
w.write_u32(self.stamp_nsec).map_err(DdsApiError::from)?;
w.write_cdr_string(self.node.as_str())
.map_err(DdsApiError::from)?;
w.write_u32(self.new_parameters_count)
.map_err(DdsApiError::from)?;
w.write_u32(self.changed_parameters_count)
.map_err(DdsApiError::from)?;
w.write_u32(self.deleted_parameters_count)
.map_err(DdsApiError::from)?;
Ok(4 + w.position())
}
fn deserialize(payload: &[u8]) -> Result<Self, DdsApiError> {
let mut cur = make_cursor(payload)?;
let stamp_sec = cur.read_i32().map_err(DdsApiError::from)?;
let stamp_nsec = cur.read_u32().map_err(DdsApiError::from)?;
let node_s = cur.read_cdr_string().map_err(DdsApiError::from)?;
let new_count = cur.read_u32().map_err(DdsApiError::from)?;
let changed_count = cur.read_u32().map_err(DdsApiError::from)?;
let deleted_count = cur.read_u32().map_err(DdsApiError::from)?;
let mut node = HString::<256>::new();
node.push_str(node_s)
.map_err(|_| DdsApiError::Serialization("parameter event node name too long"))?;
Ok(Self {
stamp_sec,
stamp_nsec,
node,
new_parameters_count: new_count,
changed_parameters_count: changed_count,
deleted_parameters_count: deleted_count,
})
}
}