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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
use super::*;

use std::convert::TryInto;

/// Contains constants with internal serialisation ids.
///
/// Currently ids between 0 and 20 are in internal use in Kompact.
pub mod serialisation_ids {
    use super::SerId;

    /// Id for a trivial deserialiser.
    pub const UNKNOWN: SerId = 0; // this is used for trivial deserialisers

    /// Id for a `DispatchEnvelope`.
    pub const DISPATCH_ENVELOPE: SerId = 1;

    /// Id for a `UniquePath`
    pub const UNIQUE_PATH: SerId = 2;

    /// Id for a `NamedPath`.
    pub const NAMED_PATH: SerId = 3;
    //pub const SYSTEM_PATH_HEADER: SerId = 4; // this one is freed now...reuse in th future!

    /// Id for a `SystemPath`.
    pub const SYSTEM_PATH: SerId = 5;

    /// Id for an [ActorPath](crate::prelude::ActorPath).
    pub const ACTOR_PATH: SerId = 6;

    /// Id for a `String` serialiser.
    pub const STR: SerId = 6;

    /// Id for a `u64` serialiser.
    pub const U64: SerId = 7;

    /// Id for a `()` (unit type) serialiser.
    pub const UNIT: SerId = 8;

    /// Id for the Serde serialiser
    pub const SERDE: SerId = 19;

    /// Id for the protobuf serialiser
    pub const PBUF: SerId = 20;
}

impl Deserialiser<Never> for Never {
    const SER_ID: SerId = serialisation_ids::UNKNOWN;

    fn deserialise(_buf: &mut dyn Buf) -> Result<Never, SerError> {
        unreachable!("Can't instantiate Never type, so can't deserialise it either");
    }
}

impl Serialisable for String {
    fn ser_id(&self) -> SerId {
        serialisation_ids::STR
    }

    fn size_hint(&self) -> Option<usize> {
        Some(self.as_bytes().len() + 8)
    }

    fn serialise(&self, buf: &mut dyn BufMut) -> Result<(), SerError> {
        let slice = self.as_bytes();
        let len_u64 = slice.len() as u64;
        buf.put_u64(len_u64);
        buf.put_slice(slice);
        Ok(())
    }

    fn local(self: Box<Self>) -> Result<Box<dyn Any + Send>, Box<dyn Serialisable>> {
        Ok(self)
    }
}
impl Deserialiser<String> for String {
    const SER_ID: SerId = serialisation_ids::STR;

    fn deserialise(buf: &mut dyn Buf) -> Result<String, SerError> {
        let len_u64 = buf.get_u64();
        let len: usize = len_u64.try_into().map_err(SerError::from_debug)?;
        // This approach is memory safe, but not overly efficient and also an attack vector for OOM attacks.
        // If you need different guarantees, write a different String serde implementation, that fulfills them
        let mut data: Vec<u8> = vec![0; len];
        buf.copy_to_slice(data.as_mut_slice());
        let s = String::from_utf8(data).map_err(SerError::from_debug)?;
        Ok(s)
    }
}

impl Serialisable for u64 {
    fn ser_id(&self) -> SerId {
        serialisation_ids::U64
    }

    fn size_hint(&self) -> Option<usize> {
        Some(8)
    }

    fn serialise(&self, buf: &mut dyn BufMut) -> Result<(), SerError> {
        buf.put_u64(*self);
        Ok(())
    }

    fn local(self: Box<Self>) -> Result<Box<dyn Any + Send>, Box<dyn Serialisable>> {
        Ok(self)
    }
}
impl Deserialiser<u64> for u64 {
    const SER_ID: SerId = serialisation_ids::U64;

    fn deserialise(buf: &mut dyn Buf) -> Result<u64, SerError> {
        let num = buf.get_u64();
        Ok(num)
    }
}

impl Serialisable for () {
    fn ser_id(&self) -> SerId {
        serialisation_ids::UNIT
    }

    fn size_hint(&self) -> Option<usize> {
        Some(0)
    }

    fn serialise(&self, _buf: &mut dyn BufMut) -> Result<(), SerError> {
        Ok(())
    }

    fn local(self: Box<Self>) -> Result<Box<dyn Any + Send>, Box<dyn Serialisable>> {
        Ok(self)
    }
}
impl Deserialiser<()> for () {
    const SER_ID: SerId = serialisation_ids::UNIT;

    fn deserialise(_buf: &mut dyn Buf) -> Result<(), SerError> {
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use bytes::BytesMut;

    #[test]
    fn test_string_serialisation() {
        let test_str: String = "Test string with more than 16 characters".into();
        let mut mbuf = if let Some(size_hint) = test_str.size_hint() {
            BytesMut::with_capacity(size_hint)
        } else {
            BytesMut::with_capacity(16)
        };
        test_str.serialise(&mut mbuf).expect("serialise");
        let mut buf = mbuf.freeze();
        let res = String::deserialise(&mut buf);
        match res {
            Ok(test_str_res) => assert_eq!(test_str, test_str_res),
            Err(e) => panic!("{}", e),
        }
    }

    #[test]
    fn test_u64_serialisation() {
        let test_num: u64 = 123456789u64;
        let mut mbuf = if let Some(size_hint) = test_num.size_hint() {
            BytesMut::with_capacity(size_hint)
        } else {
            BytesMut::with_capacity(4)
        };
        test_num.serialise(&mut mbuf).expect("serialise");
        let mut buf = mbuf.freeze();
        let res = u64::deserialise(&mut buf);
        match res {
            Ok(test_num_res) => assert_eq!(test_num, test_num_res),
            Err(e) => panic!("{}", e),
        }
    }

    #[test]
    #[allow(clippy::unit_arg)]
    fn test_unit_serialisation() {
        let mut mbuf = if let Some(size_hint) = ().size_hint() {
            BytesMut::with_capacity(size_hint)
        } else {
            panic!("Unit serialiser should have produced a size hint");
        };
        ().serialise(&mut mbuf).expect("serialise");
        let mut buf = mbuf.freeze();
        let res = <()>::deserialise(&mut buf);
        res.expect("Should have produced a unit value")
    }
}