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}
527
528#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
568pub struct Position {
569 pub x: i32,
571 pub y: i16,
573 pub z: i32,
575}
576
577impl TypeCodec for Position {
578 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
579 let value = ((self.x as i64 & 0x3ff_ffff) << 38)
580 | ((self.z as i64 & 0x3ff_ffff) << 12)
581 | (self.y as i64 & 0xfff);
582 write_all_counted(writer, &value.to_be_bytes(), CodecKind::Position, 0)
583 }
584
585 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
586 let mut bytes = [0; 8];
587 read_exact_counted(reader, &mut bytes, CodecKind::Position, 0)?;
588 let value = i64::from_be_bytes(bytes);
589
590 Ok(Self {
591 x: (value >> 38) as i32,
592 y: ((value << 52) >> 52) as i16,
593 z: ((value << 26) >> 38) as i32,
594 })
595 }
596}
597
598#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
622pub struct Angle(
623 pub u8,
625);
626
627impl Angle {
628 pub fn to_degrees(&self) -> f64 {
632 f64::from(self.0) * 360.0 / 256.0
633 }
634
635 pub fn to_radians(&self) -> f64 {
639 f64::from(self.0) * std::f64::consts::TAU / 256.0
640 }
641}
642
643impl TypeCodec for Angle {
644 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
645 write_all_counted(writer, &[self.0], CodecKind::Angle, 0)
646 }
647
648 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
649 let mut bytes = [0; 1];
650 read_exact_counted(reader, &mut bytes, CodecKind::Angle, 0)?;
651 Ok(Self(bytes[0]))
652 }
653}
654
655#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
688pub struct Uuid(
689 pub uuid::Uuid,
691);
692
693impl Uuid {
694 pub fn from_bytes(bytes: [u8; 16]) -> Self {
696 Self(uuid::Uuid::from_bytes(bytes))
697 }
698
699 pub fn into_bytes(self) -> [u8; 16] {
701 self.0.into_bytes()
702 }
703}
704
705impl TypeCodec for Uuid {
706 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
707 write_all_counted(writer, &self.0.into_bytes(), CodecKind::Uuid, 0)
708 }
709
710 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
711 let mut bytes = [0; 16];
712 read_exact_counted(reader, &mut bytes, CodecKind::Uuid, 0)?;
713 Ok(Self::from_bytes(bytes))
714 }
715}
716
717#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
750pub struct BitSet(
751 pub Vec<u64>,
753);
754
755impl BitSet {
756 pub fn contains(&self, index: usize) -> bool {
758 match self.0.get(index / 64) {
759 Some(word) => (word & (1 << (index % 64))) != 0,
760 None => false,
761 }
762 }
763}
764
765impl TypeCodec for BitSet {
766 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
767 let prefix_size = writer
768 .write_varint_with_size(self.0.len() as i32)
769 .map_err(|error| error.with_context(CodecKind::BitSet))?;
770
771 let mut bytes_processed = prefix_size;
772 for word in &self.0 {
773 write_all_counted(
774 writer,
775 &word.to_be_bytes(),
776 CodecKind::BitSet,
777 bytes_processed,
778 )?;
779 bytes_processed += 8;
780 }
781
782 Ok(())
783 }
784
785 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
786 let (length, prefix_size) = reader
787 .read_varint_with_size()
788 .map_err(|error| error.with_context(CodecKind::BitSet))?;
789 let length = usize::try_from(length).map_err(|_| {
790 CodecError::invalid_encoding(
791 CodecKind::BitSet,
792 prefix_size,
793 InvalidEncodingReason::NegativeLength { value: length },
794 )
795 })?;
796
797 let mut words = Vec::with_capacity(length);
798 let mut bytes_processed = prefix_size;
799 for _ in 0..length {
800 let mut bytes = [0; 8];
801 read_exact_counted(reader, &mut bytes, CodecKind::BitSet, bytes_processed)?;
802 words.push(u64::from_be_bytes(bytes));
803 bytes_processed += 8;
804 }
805
806 Ok(Self(words))
807 }
808}
809
810#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
845pub struct FixedBitSet<const N: usize>(
846 pub Vec<u8>,
848);
849
850impl<const N: usize> FixedBitSet<N> {
851 pub const BYTE_LEN: usize = N.div_ceil(8);
853
854 pub fn contains(&self, index: usize) -> bool {
858 index < N
859 && self
860 .0
861 .get(index / 8)
862 .is_some_and(|byte| (byte & (1 << (index % 8))) != 0)
863 }
864
865 fn validate(
866 &self,
867 operation: CodecOperation,
868 bytes_processed: usize,
869 ) -> Result<(), CodecError> {
870 if self.0.len() != Self::BYTE_LEN {
871 return Err(CodecError::invalid_encoding_for_operation(
872 CodecKind::FixedBitSet,
873 operation,
874 bytes_processed,
875 InvalidEncodingReason::InvalidFixedBitSetLength {
876 expected: Self::BYTE_LEN,
877 actual: self.0.len(),
878 },
879 ));
880 }
881
882 if let Some(last_byte) = self.0.last()
883 && N % 8 != 0
884 {
885 let allowed_mask = (1u8 << (N % 8)) - 1;
886 if last_byte & !allowed_mask != 0 {
887 return Err(CodecError::invalid_encoding_for_operation(
888 CodecKind::FixedBitSet,
889 operation,
890 bytes_processed,
891 InvalidEncodingReason::ValueOutOfRange {
892 terminal_byte: *last_byte,
893 allowed_mask,
894 },
895 ));
896 }
897 }
898
899 Ok(())
900 }
901}
902
903impl<const N: usize> TypeCodec for FixedBitSet<N> {
904 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
905 self.validate(CodecOperation::Write, 0)?;
906 write_all_counted(writer, &self.0, CodecKind::FixedBitSet, 0)
907 }
908
909 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
910 let mut bytes = vec![0; Self::BYTE_LEN];
911 read_exact_counted(reader, &mut bytes, CodecKind::FixedBitSet, 0)?;
912
913 let value = Self(bytes);
914 value.validate(CodecOperation::Read, Self::BYTE_LEN)?;
915 Ok(value)
916 }
917}