use crate::prelude::IPCResult; use byteorder::{BigEndian, ReadBytesExt}; use std::io::Read; #[cfg(feature = "serialize")] pub use super::payload_serializer::*; /// Trait to convert event data into sending bytes /// It is implemented for all types that implement Serialize pub trait EventSendPayload { fn to_payload_bytes(self) -> IPCResult>; } /// Trait to get the event data from receiving bytes. /// It is implemented for all types that are DeserializeOwned pub trait EventReceivePayload: Sized { fn from_payload_bytes(reader: R) -> IPCResult; } /// A payload wrapper type for sending bytes directly without /// serializing them #[derive(Clone)] pub struct BytePayload { bytes: Vec, } impl BytePayload { pub fn new(bytes: Vec) -> Self { Self { bytes } } /// Returns the bytes of the payload pub fn into_inner(self) -> Vec { self.bytes } } impl EventSendPayload for BytePayload { fn to_payload_bytes(self) -> IPCResult> { Ok(self.bytes) } } impl EventReceivePayload for BytePayload { fn from_payload_bytes(mut reader: R) -> IPCResult { let mut buf = Vec::new(); reader.read_to_end(&mut buf)?; Ok(Self::new(buf)) } } /// A payload wrapper that allows storing two different payloads /// independent from each other. For example one payload can be /// a payload serialized by serde while the other is a raw byte /// payload pub struct TandemPayload { load1: P1, load2: P2, } impl TandemPayload { pub fn new(load1: P1, load2: P2) -> Self { Self { load1, load2 } } /// Returns both payload stored in the tandem payload pub fn into_inner(self) -> (P1, P2) { (self.load1, self.load2) } } impl EventSendPayload for TandemPayload where P1: EventSendPayload, P2: EventSendPayload, { fn to_payload_bytes(self) -> IPCResult> { let mut p1_bytes = self.load1.to_payload_bytes()?; let mut p2_bytes = self.load2.to_payload_bytes()?; let mut p1_length_bytes = (p1_bytes.len() as u64).to_be_bytes().to_vec(); let mut p2_length_bytes = (p2_bytes.len() as u64).to_be_bytes().to_vec(); let mut bytes = Vec::new(); bytes.append(&mut p1_length_bytes); bytes.append(&mut p1_bytes); bytes.append(&mut p2_length_bytes); bytes.append(&mut p2_bytes); Ok(bytes) } } impl EventReceivePayload for TandemPayload where P1: EventReceivePayload, P2: EventReceivePayload, { fn from_payload_bytes(mut reader: R) -> IPCResult { let p1_length = reader.read_u64::()?; let mut load1_bytes = vec![0u8; p1_length as usize]; reader.read_exact(&mut load1_bytes)?; let p2_length = reader.read_u64::()?; let mut load2_bytes = vec![0u8; p2_length as usize]; reader.read_exact(&mut load2_bytes)?; Ok(Self { load1: P1::from_payload_bytes(load1_bytes.as_slice())?, load2: P2::from_payload_bytes(load2_bytes.as_slice())?, }) } } impl EventSendPayload for () { fn to_payload_bytes(self) -> IPCResult> { Ok(vec![]) } } #[cfg(feature = "serialize")] mod serde_payload { use super::DynamicSerializer; use crate::context::Context; use crate::payload::EventReceivePayload; use crate::prelude::{EventSendPayload, IPCResult}; use byteorder::ReadBytesExt; use serde::de::DeserializeOwned; use serde::Serialize; use std::io::Read; /// A payload representing a payload storing serde serialized data pub struct SerdePayload { data: T, serializer: DynamicSerializer, } impl SerdePayload { /// Creates a new serde payload with a specified serializer pub fn new(serializer: DynamicSerializer, data: T) -> Self { Self { serializer, data } } pub fn data(self) -> T { self.data } } impl Clone for SerdePayload where T: Clone, { fn clone(&self) -> Self { Self { serializer: self.serializer.clone(), data: self.data.clone(), } } } impl EventSendPayload for SerdePayload where T: Serialize, { fn to_payload_bytes(self) -> IPCResult> { let mut buf = Vec::new(); let mut data_bytes = self.serializer.serialize(self.data)?; let format_id = self.serializer as u8; buf.push(format_id); buf.append(&mut data_bytes); Ok(buf) } } impl EventReceivePayload for SerdePayload where T: DeserializeOwned, { fn from_payload_bytes(mut reader: R) -> IPCResult { let format_id = reader.read_u8()?; let serializer = DynamicSerializer::from_primitive(format_id as usize)?; let data = serializer.deserialize(reader)?; Ok(Self { serializer, data }) } } pub trait IntoSerdePayload: Sized { fn into_serde_payload(self, ctx: &Context) -> SerdePayload { ctx.create_serde_payload(self) } } impl IntoSerdePayload for T where T: Serialize {} } #[cfg(feature = "serialize")] pub use serde_payload::*;