luanti_protocol/wire/
ser.rs1use anyhow::Result;
2use anyhow::bail;
3use std::num::TryFromIntError;
4
5use crate::types::CommandDirection;
6use crate::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<'data> {
56 context: ProtocolContext,
57 offset: usize,
58 data: &'data mut [u8],
59 overflow: bool,
60}
61
62impl<'data> SliceSerializer<'data> {
63 pub fn new(context: ProtocolContext, data: &'data mut [u8]) -> Self {
64 Self {
65 context,
66 offset: 0,
67 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".into()
79 ));
80 }
81 Ok(&self.data[..self.offset])
82 }
83}
84
85impl Serializer for SliceSerializer<'_> {
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 ".into(),
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 ".into(),
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("Marker has wrong size".into(),));
126 }
127 self.data[offset..offset + length].copy_from_slice(fragment);
128 Ok(())
129 }
130
131 fn marker_distance(&self, marker: &Self::Marker) -> usize {
132 let (offset, length) = marker;
133 self.offset - (offset + length)
134 }
135
136 fn write<F>(&mut self, length: usize, write_slice_fn: F) -> SerializeResult
137 where
138 F: FnOnce(&mut [u8]),
139 {
140 if self.offset + length > self.data.len() {
141 self.overflow = true;
142 bail!(SerializeError::BufferLimit(
143 "SliceSerializer out of space ".into(),
144 ))
145 }
146 write_slice_fn(&mut self.data[self.offset..self.offset + length]);
147 self.offset += length;
148 Ok(())
149 }
150}
151
152pub struct VecSerializer {
153 context: ProtocolContext,
154 data: Vec<u8>,
155}
156
157impl VecSerializer {
158 #[must_use]
159 pub fn new(context: ProtocolContext, initial_capacity: usize) -> Self {
160 Self {
161 context,
162 data: Vec::with_capacity(initial_capacity),
163 }
164 }
165
166 #[must_use]
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, 0_u8);
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, write_slice_fn: F) -> SerializeResult
206 where
207 F: FnOnce(&mut [u8]),
208 {
209 let offset = self.data.len();
210 self.data.resize(offset + length, 0_u8);
211 write_slice_fn(&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 #[must_use]
225 pub fn new(context: ProtocolContext) -> Self {
226 Self { context, count: 0 }
227 }
228
229 #[must_use]
231 #[expect(
232 clippy::len_without_is_empty,
233 reason = "seems to be unneeded in this context"
234 )]
235 pub fn len(&self) -> usize {
236 self.count
237 }
238}
239
240impl Serializer for MockSerializer {
241 type Marker = (usize, usize);
242
243 fn context(&self) -> ProtocolContext {
244 self.context
245 }
246
247 fn direction(&self) -> CommandDirection {
248 self.context.dir
249 }
250
251 fn write_bytes(&mut self, fragment: &[u8]) -> SerializeResult {
252 self.count += fragment.len();
253 Ok(())
254 }
255
256 fn write_marker(&mut self, length: usize) -> Result<Self::Marker, SerializeError> {
257 let marker = (self.count, length);
258 self.count += length;
259 Ok(marker)
260 }
261
262 fn set_marker(&mut self, _marker: Self::Marker, _fragment: &[u8]) -> SerializeResult {
263 Ok(())
264 }
265
266 fn marker_distance(&self, marker: &Self::Marker) -> usize {
267 let (offset, length) = marker;
268 self.count - (offset + length)
269 }
270
271 fn write<F>(&mut self, length: usize, _f: F) -> SerializeResult
272 where
273 F: FnOnce(&mut [u8]),
274 {
275 self.count += length;
276 Ok(())
277 }
278}
279
280pub trait Serialize {
281 type Input: ?Sized;
282 fn serialize<S: Serializer>(value: &Self::Input, serializer: &mut S) -> SerializeResult;
283}