1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use serde::{Deserialize, Serialize};

pub trait AsIpcPacket {
    fn timestamp(&self) -> &std::time::SystemTime;
    fn data(&self) -> &[u8];
}

#[derive(Debug, Deserialize, Serialize)]
pub struct IpcPacket<'a> {
    timestamp: std::time::SystemTime,
    #[serde(with = "serde_bytes")]
    data: &'a [u8],
}

impl<'a, T: AsIpcPacket> From<&'a T> for IpcPacket<'a> {
    fn from(v: &'a T) -> Self {
        IpcPacket {
            timestamp: v.timestamp().clone(),
            data: v.data(),
        }
    }
}

impl<'a> From<IpcPacket<'a>> for Packet {
    fn from(v: IpcPacket<'a>) -> Self {
        Packet {
            ts: v.timestamp.clone(),
            data: v.data.to_vec(),
        }
    }
}

#[derive(Debug)]
pub struct Packet {
    ts: std::time::SystemTime,
    data: Vec<u8>,
}

impl Packet {
    pub fn new(ts: std::time::SystemTime, data: Vec<u8>) -> Packet {
        Packet { ts, data }
    }

    pub fn into_data(self) -> Vec<u8> {
        self.data
    }
}

impl AsIpcPacket for Packet {
    fn timestamp(&self) -> &std::time::SystemTime {
        &self.ts
    }
    fn data(&self) -> &[u8] {
        self.data.as_ref()
    }
}

#[macro_export]
macro_rules! impl_ipc_serialize(
    (
        $t:ident
    ) => {
        impl serde::Serialize for $t {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                let packet = IpcPacket::from(self);
                packet.serialize(serializer)
            }
        }
    }
);

impl_ipc_serialize!(Packet);

impl<'de> Deserialize<'de> for Packet {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let ipc_packet = IpcPacket::deserialize(deserializer)?;
        Ok(ipc_packet.into())
    }
}