1use crate::TypeCodec;
7use mcproto_codec::{
8 error::{CodecError, CodecKind, CodecOperation, InvalidEncodingReason},
9 io::{read_exact_counted, write_all_counted},
10 varint::{VarIntRead, VarIntWrite},
11 varlong::{VarLongRead, VarLongWrite},
12};
13use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _};
14use std::{
15 fmt,
16 io::{Read, Write},
17};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
21pub struct Boolean(
22 pub bool,
24);
25
26impl TypeCodec for Boolean {
27 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
28 let byte = if self.0 { 1u8 } else { 0u8 };
29 write_all_counted(writer, &[byte], CodecKind::Boolean, 0)
30 }
31
32 fn decode(reader: &mut impl Read) -> Result<Self, CodecError>
33 where
34 Self: Sized,
35 {
36 let mut buf = [0u8; 1];
37 read_exact_counted(reader, &mut buf, CodecKind::Boolean, 0)?;
38 match buf[0] {
39 0 => Ok(Boolean(false)),
40 1 => Ok(Boolean(true)),
41 _ => Err(CodecError::invalid_encoding(
42 CodecKind::Boolean,
43 1,
44 InvalidEncodingReason::InvalidBooleanValue { value: buf[0] },
45 )),
46 }
47 }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
52pub struct Byte(
53 pub i8,
55);
56
57impl TypeCodec for Byte {
58 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
59 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::Byte, 0)
60 }
61
62 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
63 let mut bytes = [0; 1];
64 read_exact_counted(reader, &mut bytes, CodecKind::Byte, 0)?;
65 Ok(Self(i8::from_be_bytes(bytes)))
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
71pub struct UnsignedByte(
72 pub u8,
74);
75
76impl TypeCodec for UnsignedByte {
77 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
78 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::UnsignedByte, 0)
79 }
80
81 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
82 let mut bytes = [0; 1];
83 read_exact_counted(reader, &mut bytes, CodecKind::UnsignedByte, 0)?;
84 Ok(Self(u8::from_be_bytes(bytes)))
85 }
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
90pub struct Short(
91 pub i16,
93);
94
95impl TypeCodec for Short {
96 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
97 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::Short, 0)
98 }
99
100 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
101 let mut bytes = [0; 2];
102 read_exact_counted(reader, &mut bytes, CodecKind::Short, 0)?;
103 Ok(Self(i16::from_be_bytes(bytes)))
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
109pub struct UnsignedShort(
110 pub u16,
112);
113
114impl TypeCodec for UnsignedShort {
115 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
116 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::UnsignedShort, 0)
117 }
118
119 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
120 let mut bytes = [0; 2];
121 read_exact_counted(reader, &mut bytes, CodecKind::UnsignedShort, 0)?;
122 Ok(Self(u16::from_be_bytes(bytes)))
123 }
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
129pub struct Int(
130 pub i32,
132);
133
134impl TypeCodec for Int {
135 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
136 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::Int, 0)
137 }
138
139 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
140 let mut bytes = [0; 4];
141 read_exact_counted(reader, &mut bytes, CodecKind::Int, 0)?;
142 Ok(Self(i32::from_be_bytes(bytes)))
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
149pub struct Long(
150 pub i64,
152);
153
154impl TypeCodec for Long {
155 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
156 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::Long, 0)
157 }
158
159 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
160 let mut bytes = [0; 8];
161 read_exact_counted(reader, &mut bytes, CodecKind::Long, 0)?;
162 Ok(Self(i64::from_be_bytes(bytes)))
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
176pub struct PrefixedString(
177 pub String,
179);
180
181impl PrefixedString {
182 pub const MAX_UTF16_CODE_UNITS: usize = 0x7fff;
184 pub const MAX_BYTES: usize = Self::MAX_UTF16_CODE_UNITS * 3;
186
187 fn encode_value(value: &str, writer: &mut impl Write) -> Result<(), CodecError> {
188 encode_prefixed_string(
189 value,
190 writer,
191 CodecKind::String,
192 Self::MAX_BYTES,
193 Self::MAX_UTF16_CODE_UNITS,
194 )
195 }
196
197 fn decode_value(reader: &mut impl Read) -> Result<(String, usize), CodecError> {
198 decode_prefixed_string(
199 reader,
200 CodecKind::String,
201 Self::MAX_BYTES,
202 Self::MAX_UTF16_CODE_UNITS,
203 )
204 }
205}
206
207pub(crate) fn encode_prefixed_string(
219 value: &str,
220 writer: &mut impl Write,
221 codec: CodecKind,
222 max_bytes: usize,
223 max_code_units: usize,
224) -> Result<(), CodecError> {
225 if value.len() > max_bytes {
226 return Err(CodecError::invalid_encoding_for_operation(
227 codec,
228 CodecOperation::Write,
229 0,
230 InvalidEncodingReason::StringTooLong { max_bytes },
231 ));
232 }
233 if value.encode_utf16().count() > max_code_units {
234 return Err(CodecError::invalid_encoding_for_operation(
235 codec,
236 CodecOperation::Write,
237 0,
238 InvalidEncodingReason::TooManyUtf16CodeUnits { max_code_units },
239 ));
240 }
241
242 let bytes = value.as_bytes();
243 let prefix_size = writer
244 .write_varint_with_size(bytes.len() as i32)
245 .map_err(|error| error.with_context(codec))?;
246 write_all_counted(writer, bytes, codec, prefix_size)
247}
248
249pub(crate) fn decode_prefixed_string(
262 reader: &mut impl Read,
263 codec: CodecKind,
264 max_bytes: usize,
265 max_code_units: usize,
266) -> Result<(String, usize), CodecError> {
267 let (byte_length, prefix_size) = reader
268 .read_varint_with_size()
269 .map_err(|error| error.with_context(codec))?;
270 let byte_length = usize::try_from(byte_length).map_err(|_| {
271 CodecError::invalid_encoding(
272 codec,
273 prefix_size,
274 InvalidEncodingReason::NegativeLength { value: byte_length },
275 )
276 })?;
277
278 if byte_length > max_bytes {
279 return Err(CodecError::invalid_encoding(
280 codec,
281 prefix_size,
282 InvalidEncodingReason::StringTooLong { max_bytes },
283 ));
284 }
285
286 let mut bytes = vec![0; byte_length];
287 read_exact_counted(reader, &mut bytes, codec, prefix_size)?;
288 let bytes_processed = prefix_size + byte_length;
289 let value = String::from_utf8(bytes).map_err(|error| {
290 let utf8_error = error.utf8_error();
291 CodecError::invalid_encoding(
292 codec,
293 bytes_processed,
294 InvalidEncodingReason::InvalidUtf8 {
295 valid_up_to: utf8_error.valid_up_to(),
296 error_len: utf8_error.error_len(),
297 },
298 )
299 })?;
300 if value.len() > max_bytes {
301 return Err(CodecError::invalid_encoding(
302 codec,
303 bytes_processed,
304 InvalidEncodingReason::StringTooLong { max_bytes },
305 ));
306 }
307 if value.encode_utf16().count() > max_code_units {
308 return Err(CodecError::invalid_encoding(
309 codec,
310 bytes_processed,
311 InvalidEncodingReason::TooManyUtf16CodeUnits { max_code_units },
312 ));
313 }
314 Ok((value, bytes_processed))
315}
316
317impl TypeCodec for PrefixedString {
318 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
319 Self::encode_value(&self.0, writer)
320 }
321
322 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
323 Self::decode_value(reader).map(|(value, _)| Self(value))
324 }
325}
326
327#[derive(Debug, Clone, PartialEq, Eq, Hash)]
334pub struct Identifier(String);
335
336impl Identifier {
337 pub const MAX_UTF16_CODE_UNITS: usize = PrefixedString::MAX_UTF16_CODE_UNITS;
339 pub const MAX_BYTES: usize = PrefixedString::MAX_BYTES;
341 pub const MAX_ENCODED_BYTES: usize = Self::MAX_BYTES + 3;
343
344 pub fn new(value: impl Into<String>) -> Result<Self, InvalidIdentifier> {
354 let value = value.into();
355 validate_identifier(&value)?;
356 Ok(Self(value))
357 }
358
359 pub fn as_str(&self) -> &str {
361 &self.0
362 }
363
364 pub fn into_inner(self) -> String {
366 self.0
367 }
368}
369
370impl fmt::Display for Identifier {
371 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
372 formatter.write_str(&self.0)
373 }
374}
375
376impl Serialize for Identifier {
377 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
378 where
379 S: Serializer,
380 {
381 serializer.serialize_str(&self.0)
382 }
383}
384
385impl<'de> Deserialize<'de> for Identifier {
386 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387 where
388 D: Deserializer<'de>,
389 {
390 Self::new(String::deserialize(deserializer)?).map_err(D::Error::custom)
391 }
392}
393
394impl TypeCodec for Identifier {
395 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
396 PrefixedString::encode_value(&self.0, writer)
397 .map_err(|error| error.with_context(CodecKind::Identifier))
398 }
399
400 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
401 let (value, bytes_processed) = PrefixedString::decode_value(reader)
402 .map_err(|error| error.with_context(CodecKind::Identifier))?;
403 Self::new(value).map_err(|_| {
404 CodecError::invalid_encoding(
405 CodecKind::Identifier,
406 bytes_processed,
407 InvalidEncodingReason::InvalidIdentifier,
408 )
409 })
410 }
411}
412
413pub(crate) fn is_valid_identifier(value: &str) -> bool {
421 let (namespace, path) = match value.split_once(':') {
422 Some((namespace, path)) => (namespace, path),
423 None => ("minecraft", value),
424 };
425 let namespace_is_valid = !namespace.is_empty()
426 && namespace.bytes().all(|byte| {
427 byte.is_ascii_lowercase() || byte.is_ascii_digit() || b"_.-".contains(&byte)
428 });
429 let path_is_valid = !path.is_empty()
430 && path.bytes().all(|byte| {
431 byte.is_ascii_lowercase() || byte.is_ascii_digit() || b"/._-".contains(&byte)
432 });
433 namespace_is_valid && path_is_valid && !path.contains(':')
434}
435
436fn validate_identifier(value: &str) -> Result<(), InvalidIdentifier> {
437 if is_valid_identifier(value) {
438 Ok(())
439 } else {
440 Err(InvalidIdentifier)
441 }
442}
443
444#[derive(Debug, Clone, Copy, PartialEq, Eq)]
446pub struct InvalidIdentifier;
447
448impl fmt::Display for InvalidIdentifier {
449 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
450 formatter.write_str("invalid Minecraft identifier")
451 }
452}
453
454impl std::error::Error for InvalidIdentifier {}
455
456#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
476pub struct VarInt(
477 pub i32,
479);
480
481impl TypeCodec for VarInt {
482 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
483 writer.write_varint(self.0)
484 }
485
486 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
487 reader.read_varint().map(Self)
488 }
489}
490
491#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
513pub struct VarLong(
514 pub i64,
516);
517
518impl TypeCodec for VarLong {
519 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
520 writer.write_varlong(self.0)
521 }
522
523 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
524 reader.read_varlong().map(Self)
525 }
526}