use crate::{write_arena::WriteArena, DdsResult, DdsType};
use std::ffi::c_void;
pub trait SerdeTypeName {
const TYPE_NAME: &'static str;
}
#[macro_export]
macro_rules! serde_type_name {
($t:ty, $name:expr) => {
impl $crate::SerdeTypeName for $t {
const TYPE_NAME: &'static str = $name;
}
};
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SerdeSample<T> {
payload: Vec<u8>,
_marker: std::marker::PhantomData<T>,
}
impl<T> SerdeSample<T> {
pub fn new(value: &T) -> DdsResult<Self>
where
T: serde::Serialize,
{
let payload = postcard::to_vec::<T, 4096>(value).map_err(|e| {
crate::DdsError::BadParameter(format!("serde serialization failed: {}", e))
})?;
Ok(SerdeSample {
payload: payload.to_vec(),
_marker: std::marker::PhantomData,
})
}
pub fn deserialize(&self) -> DdsResult<T>
where
T: for<'de> serde::Deserialize<'de>,
{
postcard::from_bytes(&self.payload).map_err(|e| {
crate::DdsError::BadParameter(format!("serde deserialization failed: {}", e))
})
}
pub fn as_bytes(&self) -> &[u8] {
&self.payload
}
}
#[repr(C)]
pub struct SerdeSampleNative {
payload: crate::DdsSequence<u8>,
}
unsafe impl<T> DdsType for SerdeSample<T>
where
T: serde::Serialize + for<'de> serde::Deserialize<'de> + SerdeTypeName + Send + 'static,
{
type Native = SerdeSampleNative;
fn type_name() -> &'static str {
T::TYPE_NAME
}
fn ops() -> Vec<u32> {
use crate::topic::{OP_ADR, OP_RTS, SUBTYPE_1BY, TYPE_SEQ};
vec![
OP_ADR | TYPE_SEQ | SUBTYPE_1BY,
std::mem::offset_of!(SerdeSampleNative, payload) as u32,
OP_RTS,
]
}
unsafe fn clone_out(ptr: *const Self) -> DdsResult<Self> {
let native_ptr = ptr as *const SerdeSampleNative;
if native_ptr.is_null() {
return Err(crate::DdsError::BadParameter(format!(
"SerdeSample clone_out: null pointer for {}",
Self::type_name()
)));
}
if (native_ptr as usize) % std::mem::align_of::<SerdeSampleNative>() != 0 {
return Err(crate::DdsError::BadParameter(format!(
"SerdeSample clone_out: unaligned pointer for {}",
Self::type_name()
)));
}
let native = &*native_ptr;
Ok(SerdeSample {
payload: native.payload.to_vec(),
_marker: std::marker::PhantomData,
})
}
fn write_to_native<'a>(&'a self, arena: &'a mut WriteArena) -> DdsResult<*const c_void> {
let native = SerdeSampleNative {
payload: crate::DdsSequence::from_slice(&self.payload)?,
};
Ok(arena.hold(native).cast())
}
}