minetest_protocol/wire/
ser.rs1use 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 fn direction(&self) -> CommandDirection;
33
34 fn write<F>(&mut self, length: usize, f: F) -> SerializeResult
38 where
39 F: FnOnce(&mut [u8]);
40
41 fn write_bytes(&mut self, fragment: &[u8]) -> SerializeResult;
43
44 fn write_marker(&mut self, length: usize) -> Result<Self::Marker, SerializeError>;
46
47 fn set_marker(&mut self, marker: Self::Marker, fragment: &[u8]) -> SerializeResult;
49
50 fn marker_distance(&self, marker: &Self::Marker) -> usize;
52}
53
54pub 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 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
216pub 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 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}