use std::sync::Arc;
use zenoh_buffers::ZBuf;
use crate::msg::{ZDeserializer, ZSerializer};
use super::error::DynamicError;
use super::message::DynamicMessage;
use super::schema::MessageSchema;
pub struct DynamicSerdeCdrSerdes;
impl ZSerializer for DynamicSerdeCdrSerdes {
type Input<'a> = &'a DynamicMessage;
fn serialize_to_zbuf(input: &DynamicMessage) -> ZBuf {
input
.to_cdr_zbuf()
.expect("DynamicMessage CDR serialization failed")
}
fn serialize_to_zbuf_with_hint(input: &DynamicMessage, _capacity_hint: usize) -> ZBuf {
Self::serialize_to_zbuf(input)
}
fn serialize_to_shm(
input: &DynamicMessage,
_estimated_size: usize,
provider: &zenoh::shm::ShmProvider<zenoh::shm::PosixShmProviderBackend>,
) -> zenoh::Result<(ZBuf, usize)> {
let data = input.to_cdr().map_err(|e| {
zenoh::Error::from(format!("DynamicMessage serialization failed: {}", e))
})?;
let actual_size = data.len();
use zenoh::Wait;
use zenoh::shm::{BlockOn, GarbageCollect};
let mut shm_buf = provider
.alloc(actual_size)
.with_policy::<BlockOn<GarbageCollect>>()
.wait()
.map_err(|e| zenoh::Error::from(format!("SHM allocation failed: {}", e)))?;
shm_buf[0..actual_size].copy_from_slice(&data);
Ok((ZBuf::from(shm_buf), actual_size))
}
fn serialize(input: &DynamicMessage) -> Vec<u8> {
input
.to_cdr()
.expect("DynamicMessage CDR serialization failed")
}
fn serialize_to_buf(input: &DynamicMessage, buffer: &mut Vec<u8>) {
buffer.clear();
buffer.extend(
input
.to_cdr()
.expect("DynamicMessage CDR serialization failed"),
);
}
}
impl ZDeserializer for DynamicSerdeCdrSerdes {
type Input<'a> = (&'a [u8], &'a Arc<MessageSchema>);
type Output = DynamicMessage;
type Error = DynamicError;
fn deserialize(input: Self::Input<'_>) -> Result<DynamicMessage, DynamicError> {
let (bytes, schema) = input;
DynamicMessage::from_cdr(bytes, schema)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dynamic::schema::{FieldType, MessageSchema};
use zenoh_buffers::buffer::Buffer;
fn create_point_schema() -> Arc<MessageSchema> {
MessageSchema::builder("geometry_msgs/msg/Point")
.field("x", FieldType::Float64)
.field("y", FieldType::Float64)
.field("z", FieldType::Float64)
.build()
.unwrap()
}
#[test]
fn test_serialize_to_zbuf() {
let schema = create_point_schema();
let mut msg = DynamicMessage::new(&schema);
msg.set("x", 1.0f64).unwrap();
msg.set("y", 2.0f64).unwrap();
msg.set("z", 3.0f64).unwrap();
let zbuf = DynamicSerdeCdrSerdes::serialize_to_zbuf(&msg);
assert!(zbuf.len() > 0);
}
#[test]
fn test_serialize_deserialize_roundtrip() {
let schema = create_point_schema();
let mut msg = DynamicMessage::new(&schema);
msg.set("x", 1.5f64).unwrap();
msg.set("y", 2.5f64).unwrap();
msg.set("z", 3.5f64).unwrap();
let bytes = DynamicSerdeCdrSerdes::serialize(&msg);
let deserialized = DynamicSerdeCdrSerdes::deserialize((&bytes, &schema)).unwrap();
assert_eq!(deserialized.get::<f64>("x").unwrap(), 1.5);
assert_eq!(deserialized.get::<f64>("y").unwrap(), 2.5);
assert_eq!(deserialized.get::<f64>("z").unwrap(), 3.5);
}
#[test]
fn test_serialize_to_buf() {
let schema = create_point_schema();
let mut msg = DynamicMessage::new(&schema);
msg.set("x", 1.0f64).unwrap();
msg.set("y", 2.0f64).unwrap();
msg.set("z", 3.0f64).unwrap();
let mut buffer = Vec::new();
DynamicSerdeCdrSerdes::serialize_to_buf(&msg, &mut buffer);
let direct = DynamicSerdeCdrSerdes::serialize(&msg);
assert_eq!(buffer, direct);
}
}