minetest_protocol/wire/
ser.rs

1use anyhow::bail;
2use anyhow::Result;
3use std::num::TryFromIntError;
4
5use super::types::CommandDirection;
6use super::types::ProtocolContext;
7
8#[derive(Debug, Clone, thiserror::Error)]
9pub enum SerializeError {
10    #[error("Ran out of space while serializing: {0}")]
11    BufferLimit(String),
12    #[error("Invalid value: {0}")]
13    InvalidValue(String),
14    #[error("CompressionFailed: {0}")]
15    CompressionFailed(String),
16}
17
18impl From<TryFromIntError> for SerializeError {
19    fn from(other: TryFromIntError) -> SerializeError {
20        SerializeError::InvalidValue(format!("{:?}", other))
21    }
22}
23
24pub type SerializeResult = Result<()>;
25
26pub trait Serializer {
27    type Marker;
28
29    fn context(&self) -> ProtocolContext;
30
31    // Serializing a ToServer or ToClient command
32    fn direction(&self) -> CommandDirection;
33
34    // Request writing directly to a slice
35    // Needed for random access writes
36    // It is not guaranteed the 'f' is called.
37    fn write<F>(&mut self, length: usize, f: F) -> SerializeResult
38    where
39        F: FnOnce(&mut [u8]);
40
41    // Write bytes
42    fn write_bytes(&mut self, fragment: &[u8]) -> SerializeResult;
43
44    // Reserve some bytes for writing later.
45    fn write_marker(&mut self, length: usize) -> Result<Self::Marker, SerializeError>;
46
47    // Write to the marker
48    fn set_marker(&mut self, marker: Self::Marker, fragment: &[u8]) -> SerializeResult;
49
50    // Number of bytes written to the stream after the marker (not including the marker itself)
51    fn marker_distance(&self, marker: &Self::Marker) -> usize;
52}
53
54/// Serialize a Packet to a mutable slice
55pub struct SliceSerializer<'a> {
56    context: ProtocolContext,
57    offset: usize,
58    data: &'a mut [u8],
59    overflow: bool,
60}
61
62impl<'a> SliceSerializer<'a> {
63    pub fn new(context: ProtocolContext, data: &'a mut [u8]) -> Self {
64        Self {
65            context,
66            offset: 0,
67            data: data,
68            overflow: false,
69        }
70    }
71
72    /// Returns the finished serialized packet
73    /// This is a subslice of the original data slice provided
74    /// If the serializer ran out of space, returns None.
75    pub fn take(&self) -> Result<&[u8]> {
76        if self.overflow {
77            bail!(SerializeError::BufferLimit(
78                "SliceSerializer overflow".to_string()
79            ));
80        }
81        Ok(&self.data[..self.offset])
82    }
83}
84
85impl<'a> Serializer for SliceSerializer<'a> {
86    type Marker = (usize, usize);
87
88    fn context(&self) -> ProtocolContext {
89        self.context
90    }
91
92    fn direction(&self) -> CommandDirection {
93        self.context.dir
94    }
95
96    fn write_bytes(&mut self, fragment: &[u8]) -> SerializeResult {
97        if self.offset + fragment.len() > self.data.len() {
98            self.overflow = true;
99            bail!(SerializeError::BufferLimit(
100                "SliceSerializer out of space ".to_string(),
101            ));
102        }
103        self.data[self.offset..self.offset + fragment.len()].copy_from_slice(fragment);
104        self.offset += fragment.len();
105        Ok(())
106    }
107
108    fn write_marker(&mut self, length: usize) -> Result<Self::Marker, SerializeError> {
109        if self.offset + length > self.data.len() {
110            self.overflow = true;
111            Err(SerializeError::BufferLimit(
112                "SliceSerializer out of space ".to_string(),
113            ))
114        } else {
115            let marker = (self.offset, length);
116            self.offset += length;
117            Ok(marker)
118        }
119    }
120
121    fn set_marker(&mut self, marker: Self::Marker, fragment: &[u8]) -> SerializeResult {
122        let (offset, length) = marker;
123        if fragment.len() != length {
124            self.overflow = true;
125            bail!(SerializeError::InvalidValue(
126                "Marker has wrong size".to_string(),
127            ));
128        }
129        self.data[offset..offset + length].copy_from_slice(fragment);
130        Ok(())
131    }
132
133    fn marker_distance(&self, marker: &Self::Marker) -> usize {
134        let (offset, length) = marker;
135        self.offset - (offset + length)
136    }
137
138    fn write<F>(&mut self, length: usize, f: F) -> SerializeResult
139    where
140        F: FnOnce(&mut [u8]),
141    {
142        if self.offset + length > self.data.len() {
143            self.overflow = true;
144            bail!(SerializeError::BufferLimit(
145                "SliceSerializer out of space ".to_string(),
146            ))
147        }
148        f(&mut self.data[self.offset..self.offset + length]);
149        self.offset += length;
150        Ok(())
151    }
152}
153
154pub struct VecSerializer {
155    context: ProtocolContext,
156    data: Vec<u8>,
157}
158
159impl VecSerializer {
160    pub fn new(context: ProtocolContext, initial_capacity: usize) -> Self {
161        Self {
162            context,
163            data: Vec::with_capacity(initial_capacity),
164        }
165    }
166
167    pub fn take(self) -> Vec<u8> {
168        self.data
169    }
170}
171
172impl Serializer for VecSerializer {
173    type Marker = (usize, usize);
174
175    fn context(&self) -> ProtocolContext {
176        self.context
177    }
178
179    fn direction(&self) -> CommandDirection {
180        self.context.dir
181    }
182
183    fn write_bytes(&mut self, fragment: &[u8]) -> SerializeResult {
184        self.data.extend_from_slice(fragment);
185        Ok(())
186    }
187
188    fn write_marker(&mut self, length: usize) -> Result<Self::Marker, SerializeError> {
189        let marker = (self.data.len(), length);
190        self.data.resize(self.data.len() + length, 0u8);
191        Ok(marker)
192    }
193
194    fn set_marker(&mut self, marker: Self::Marker, fragment: &[u8]) -> SerializeResult {
195        let (offset, length) = marker;
196        self.data[offset..offset + length].copy_from_slice(fragment);
197        Ok(())
198    }
199
200    fn marker_distance(&self, marker: &Self::Marker) -> usize {
201        let (offset, length) = marker;
202        self.data.len() - (offset + length)
203    }
204
205    fn write<F>(&mut self, length: usize, f: F) -> SerializeResult
206    where
207        F: FnOnce(&mut [u8]),
208    {
209        let offset = self.data.len();
210        self.data.resize(offset + length, 0u8);
211        f(&mut self.data.as_mut_slice()[offset..offset + length]);
212        Ok(())
213    }
214}
215
216/// MockSerializer
217/// Computes the size of the serialized output without storing it
218pub struct MockSerializer {
219    context: ProtocolContext,
220    count: usize,
221}
222
223impl MockSerializer {
224    pub fn new(context: ProtocolContext) -> Self {
225        Self { context, count: 0 }
226    }
227
228    /// How many bytes have been written so far
229    pub fn len(&self) -> usize {
230        self.count
231    }
232}
233
234impl Serializer for MockSerializer {
235    type Marker = (usize, usize);
236
237    fn context(&self) -> ProtocolContext {
238        self.context
239    }
240
241    fn direction(&self) -> CommandDirection {
242        self.context.dir
243    }
244
245    fn write_bytes(&mut self, fragment: &[u8]) -> SerializeResult {
246        self.count += fragment.len();
247        Ok(())
248    }
249
250    fn write_marker(&mut self, length: usize) -> Result<Self::Marker, SerializeError> {
251        let marker = (self.count, length);
252        self.count += length;
253        Ok(marker)
254    }
255
256    fn set_marker(&mut self, _marker: Self::Marker, _fragment: &[u8]) -> SerializeResult {
257        Ok(())
258    }
259
260    fn marker_distance(&self, marker: &Self::Marker) -> usize {
261        let (offset, length) = marker;
262        self.count - (offset + length)
263    }
264
265    fn write<F>(&mut self, length: usize, _f: F) -> SerializeResult
266    where
267        F: FnOnce(&mut [u8]),
268    {
269        self.count += length;
270        Ok(())
271    }
272}
273
274pub trait Serialize {
275    type Input: ?Sized;
276    fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult;
277}