use crate::prelude::IPCResult; use byteorder::{BigEndian, ReadBytesExt}; use std::io::Read; #[cfg(feature = "serialize")] pub use super::payload_serializer::*; /// Trait that serializes a type into bytes and can fail pub trait TryIntoBytes { fn try_into_bytes(self) -> IPCResult>; } /// Trait that serializes a type into bytes and never fails pub trait IntoBytes { fn into_bytes(self) -> Vec; } /// Trait to convert event data into sending bytes /// It is implemented for all types that implement Serialize pub trait IntoPayload { fn into_payload(self, ctx: &Context) -> IPCResult>; } /// Trait to get the event data from receiving bytes. /// It is implemented for all types that are DeserializeOwned pub trait FromPayload: Sized { fn from_payload(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 IntoPayload for BytePayload { fn into_payload(self, _: &Context) -> IPCResult> { Ok(self.bytes) } } impl FromPayload for BytePayload { fn from_payload(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 IntoPayload for TandemPayload { fn into_payload(self, ctx: &Context) -> IPCResult> { let mut p1_bytes = self.load1.into_payload(&ctx)?; let mut p2_bytes = self.load2.into_payload(&ctx)?; 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 FromPayload for TandemPayload { fn from_payload(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(load1_bytes.as_slice())?, load2: P2::from_payload(load2_bytes.as_slice())?, }) } } #[cfg(not(feature = "serialize"))] impl IntoPayload for () { fn into_payload(self, _: &Context) -> IPCResult> { Ok(vec![]) } } #[cfg(feature = "serialize")] mod serde_payload { use super::DynamicSerializer; use crate::context::Context; use crate::payload::{FromPayload, TryIntoBytes}; use crate::prelude::{IPCResult, IntoPayload}; 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 { fn clone(&self) -> Self { Self { serializer: self.serializer.clone(), data: self.data.clone(), } } } impl TryIntoBytes for SerdePayload { fn try_into_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 IntoPayload for SerdePayload { fn into_payload(self, _: &Context) -> IPCResult> { self.try_into_bytes() } } impl FromPayload for SerdePayload { fn from_payload(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 }) } } impl IntoPayload for T { fn into_payload(self, ctx: &Context) -> IPCResult> { ctx.create_serde_payload(self).into_payload(&ctx) } } } use crate::context::Context; #[cfg(feature = "serialize")] pub use serde_payload::*;