1use crate::{EnumRepr, 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, Copy, PartialEq, Default)]
184pub struct Float(
185 pub f32,
187);
188
189impl TypeCodec for Float {
190 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
191 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::Float, 0)
192 }
193
194 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
195 let mut bytes = [0; 4];
196 read_exact_counted(reader, &mut bytes, CodecKind::Float, 0)?;
197 Ok(Self(f32::from_be_bytes(bytes)))
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Default)]
203pub struct Double(
204 pub f64,
206);
207
208impl TypeCodec for Double {
209 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
210 write_all_counted(writer, &self.0.to_be_bytes(), CodecKind::Double, 0)
211 }
212
213 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
214 let mut bytes = [0; 8];
215 read_exact_counted(reader, &mut bytes, CodecKind::Double, 0)?;
216 Ok(Self(f64::from_be_bytes(bytes)))
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
230pub struct PrefixedString(
231 pub String,
233);
234
235impl PrefixedString {
236 pub const MAX_UTF16_CODE_UNITS: usize = 0x7fff;
238 pub const MAX_BYTES: usize = Self::MAX_UTF16_CODE_UNITS * 3;
240
241 fn encode_value(value: &str, writer: &mut impl Write) -> Result<(), CodecError> {
242 encode_prefixed_string(
243 value,
244 writer,
245 CodecKind::String,
246 Self::MAX_BYTES,
247 Self::MAX_UTF16_CODE_UNITS,
248 )
249 }
250
251 fn decode_value(reader: &mut impl Read) -> Result<(String, usize), CodecError> {
252 decode_prefixed_string(
253 reader,
254 CodecKind::String,
255 Self::MAX_BYTES,
256 Self::MAX_UTF16_CODE_UNITS,
257 )
258 }
259}
260
261pub(crate) fn encode_prefixed_string(
273 value: &str,
274 writer: &mut impl Write,
275 codec: CodecKind,
276 max_bytes: usize,
277 max_code_units: usize,
278) -> Result<(), CodecError> {
279 if value.len() > max_bytes {
280 return Err(CodecError::invalid_encoding_for_operation(
281 codec,
282 CodecOperation::Write,
283 0,
284 InvalidEncodingReason::StringTooLong { max_bytes },
285 ));
286 }
287 if value.encode_utf16().count() > max_code_units {
288 return Err(CodecError::invalid_encoding_for_operation(
289 codec,
290 CodecOperation::Write,
291 0,
292 InvalidEncodingReason::TooManyUtf16CodeUnits { max_code_units },
293 ));
294 }
295
296 let bytes = value.as_bytes();
297 let prefix_size = writer
298 .write_varint_with_size(bytes.len() as i32)
299 .map_err(|error| error.with_context(codec))?;
300 write_all_counted(writer, bytes, codec, prefix_size)
301}
302
303pub(crate) fn decode_prefixed_string(
316 reader: &mut impl Read,
317 codec: CodecKind,
318 max_bytes: usize,
319 max_code_units: usize,
320) -> Result<(String, usize), CodecError> {
321 let (byte_length, prefix_size) = reader
322 .read_varint_with_size()
323 .map_err(|error| error.with_context(codec))?;
324 let byte_length = usize::try_from(byte_length).map_err(|_| {
325 CodecError::invalid_encoding(
326 codec,
327 prefix_size,
328 InvalidEncodingReason::NegativeLength { value: byte_length },
329 )
330 })?;
331
332 if byte_length > max_bytes {
333 return Err(CodecError::invalid_encoding(
334 codec,
335 prefix_size,
336 InvalidEncodingReason::StringTooLong { max_bytes },
337 ));
338 }
339
340 let mut bytes = vec![0; byte_length];
341 read_exact_counted(reader, &mut bytes, codec, prefix_size)?;
342 let bytes_processed = prefix_size + byte_length;
343 let value = String::from_utf8(bytes).map_err(|error| {
344 let utf8_error = error.utf8_error();
345 CodecError::invalid_encoding(
346 codec,
347 bytes_processed,
348 InvalidEncodingReason::InvalidUtf8 {
349 valid_up_to: utf8_error.valid_up_to(),
350 error_len: utf8_error.error_len(),
351 },
352 )
353 })?;
354 if value.len() > max_bytes {
355 return Err(CodecError::invalid_encoding(
356 codec,
357 bytes_processed,
358 InvalidEncodingReason::StringTooLong { max_bytes },
359 ));
360 }
361 if value.encode_utf16().count() > max_code_units {
362 return Err(CodecError::invalid_encoding(
363 codec,
364 bytes_processed,
365 InvalidEncodingReason::TooManyUtf16CodeUnits { max_code_units },
366 ));
367 }
368 Ok((value, bytes_processed))
369}
370
371impl TypeCodec for PrefixedString {
372 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
373 Self::encode_value(&self.0, writer)
374 }
375
376 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
377 Self::decode_value(reader).map(|(value, _)| Self(value))
378 }
379}
380
381#[derive(Debug, Clone, PartialEq, Eq, Hash)]
388pub struct Identifier(String);
389
390impl Identifier {
391 pub const MAX_UTF16_CODE_UNITS: usize = PrefixedString::MAX_UTF16_CODE_UNITS;
393 pub const MAX_BYTES: usize = PrefixedString::MAX_BYTES;
395 pub const MAX_ENCODED_BYTES: usize = Self::MAX_BYTES + 3;
397
398 pub fn new(value: impl Into<String>) -> Result<Self, InvalidIdentifier> {
408 let value = value.into();
409 validate_identifier(&value)?;
410 Ok(Self(value))
411 }
412
413 pub fn as_str(&self) -> &str {
415 &self.0
416 }
417
418 pub fn into_inner(self) -> String {
420 self.0
421 }
422}
423
424impl fmt::Display for Identifier {
425 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
426 formatter.write_str(&self.0)
427 }
428}
429
430impl Serialize for Identifier {
431 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
432 where
433 S: Serializer,
434 {
435 serializer.serialize_str(&self.0)
436 }
437}
438
439impl<'de> Deserialize<'de> for Identifier {
440 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
441 where
442 D: Deserializer<'de>,
443 {
444 Self::new(String::deserialize(deserializer)?).map_err(D::Error::custom)
445 }
446}
447
448impl TypeCodec for Identifier {
449 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
450 PrefixedString::encode_value(&self.0, writer)
451 .map_err(|error| error.with_context(CodecKind::Identifier))
452 }
453
454 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
455 let (value, bytes_processed) = PrefixedString::decode_value(reader)
456 .map_err(|error| error.with_context(CodecKind::Identifier))?;
457 Self::new(value).map_err(|_| {
458 CodecError::invalid_encoding(
459 CodecKind::Identifier,
460 bytes_processed,
461 InvalidEncodingReason::InvalidIdentifier,
462 )
463 })
464 }
465}
466
467pub(crate) fn is_valid_identifier(value: &str) -> bool {
475 let (namespace, path) = match value.split_once(':') {
476 Some((namespace, path)) => (namespace, path),
477 None => ("minecraft", value),
478 };
479 let namespace_is_valid = !namespace.is_empty()
480 && namespace.bytes().all(|byte| {
481 byte.is_ascii_lowercase() || byte.is_ascii_digit() || b"_.-".contains(&byte)
482 });
483 let path_is_valid = !path.is_empty()
484 && path.bytes().all(|byte| {
485 byte.is_ascii_lowercase() || byte.is_ascii_digit() || b"/._-".contains(&byte)
486 });
487 namespace_is_valid && path_is_valid && !path.contains(':')
488}
489
490fn validate_identifier(value: &str) -> Result<(), InvalidIdentifier> {
491 if is_valid_identifier(value) {
492 Ok(())
493 } else {
494 Err(InvalidIdentifier)
495 }
496}
497
498#[derive(Debug, Clone, Copy, PartialEq, Eq)]
500pub struct InvalidIdentifier;
501
502impl fmt::Display for InvalidIdentifier {
503 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
504 formatter.write_str("invalid Minecraft identifier")
505 }
506}
507
508impl std::error::Error for InvalidIdentifier {}
509
510#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
530pub struct VarInt(
531 pub i32,
533);
534
535impl TypeCodec for VarInt {
536 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
537 writer.write_varint(self.0)
538 }
539
540 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
541 reader.read_varint().map(Self)
542 }
543}
544
545#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
567pub struct VarLong(
568 pub i64,
570);
571
572impl TypeCodec for VarLong {
573 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
574 writer.write_varlong(self.0)
575 }
576
577 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
578 reader.read_varlong().map(Self)
579 }
580}
581
582#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
622pub struct Position {
623 pub x: i32,
625 pub y: i16,
627 pub z: i32,
629}
630
631impl TypeCodec for Position {
632 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
633 let value = ((self.x as i64 & 0x3ff_ffff) << 38)
634 | ((self.z as i64 & 0x3ff_ffff) << 12)
635 | (self.y as i64 & 0xfff);
636 write_all_counted(writer, &value.to_be_bytes(), CodecKind::Position, 0)
637 }
638
639 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
640 let mut bytes = [0; 8];
641 read_exact_counted(reader, &mut bytes, CodecKind::Position, 0)?;
642 let value = i64::from_be_bytes(bytes);
643
644 Ok(Self {
645 x: (value >> 38) as i32,
646 y: ((value << 52) >> 52) as i16,
647 z: ((value << 26) >> 38) as i32,
648 })
649 }
650}
651
652#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
676pub struct Angle(
677 pub u8,
679);
680
681impl Angle {
682 pub fn to_degrees(&self) -> f64 {
686 f64::from(self.0) * 360.0 / 256.0
687 }
688
689 pub fn to_radians(&self) -> f64 {
693 f64::from(self.0) * std::f64::consts::TAU / 256.0
694 }
695}
696
697impl TypeCodec for Angle {
698 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
699 write_all_counted(writer, &[self.0], CodecKind::Angle, 0)
700 }
701
702 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
703 let mut bytes = [0; 1];
704 read_exact_counted(reader, &mut bytes, CodecKind::Angle, 0)?;
705 Ok(Self(bytes[0]))
706 }
707}
708
709#[derive(Debug, Clone, Copy, PartialEq, Default)]
747pub struct LpVec3 {
748 pub x: f64,
750 pub y: f64,
752 pub z: f64,
754}
755
756impl LpVec3 {
757 pub const MAX_QUANTIZED_VALUE: f64 = 32766.0;
759 pub const ZERO_THRESHOLD: f64 = 1.0 / Self::MAX_QUANTIZED_VALUE;
761 pub const MAX_SCALE_FACTOR: u64 = (u32::MAX as u64) << 2 | 0x03;
764
765 const CONTINUATION_FLAG: u64 = 0x04;
766 const SCALE_BITS: u64 = 0x03;
767
768 #[must_use]
770 pub const fn new(x: f64, y: f64, z: f64) -> Self {
771 Self { x, y, z }
772 }
773
774 fn pack(value: f64) -> u64 {
775 ((value * 0.5 + 0.5) * Self::MAX_QUANTIZED_VALUE).round() as u64
776 }
777
778 fn unpack(value: u64) -> f64 {
779 ((value & 32767) as f64).min(Self::MAX_QUANTIZED_VALUE) * 2.0 / Self::MAX_QUANTIZED_VALUE
780 - 1.0
781 }
782}
783
784impl TypeCodec for LpVec3 {
785 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
786 let contains_nan = self.x.is_nan() || self.y.is_nan() || self.z.is_nan();
787 let max_coordinate = self.x.abs().max(self.y.abs()).max(self.z.abs());
788 if contains_nan || max_coordinate < Self::ZERO_THRESHOLD {
789 return write_all_counted(writer, &[0], CodecKind::LpVec3, 0);
790 }
791
792 let scale_factor = max_coordinate.ceil() as u64;
793 if scale_factor > Self::MAX_SCALE_FACTOR {
794 return Err(CodecError::invalid_encoding_for_operation(
795 CodecKind::LpVec3,
796 CodecOperation::Write,
797 0,
798 InvalidEncodingReason::LpVec3ScaleOutOfRange {
799 scale_factor,
800 max: Self::MAX_SCALE_FACTOR,
801 },
802 ));
803 }
804
805 let need_continuation = scale_factor & Self::SCALE_BITS != scale_factor;
806 let packed_scale = if need_continuation {
807 scale_factor & Self::SCALE_BITS | Self::CONTINUATION_FLAG
808 } else {
809 scale_factor
810 };
811 let scale = scale_factor as f64;
812 let packed = Self::pack(self.x / scale) << 3
813 | Self::pack(self.y / scale) << 18
814 | Self::pack(self.z / scale) << 33
815 | packed_scale;
816 let upper = ((packed >> 16) as u32).to_be_bytes();
817 let bytes = [
818 packed as u8,
819 (packed >> 8) as u8,
820 upper[0],
821 upper[1],
822 upper[2],
823 upper[3],
824 ];
825 write_all_counted(writer, &bytes, CodecKind::LpVec3, 0)?;
826
827 if need_continuation {
828 writer
829 .write_varint((scale_factor >> 2) as u32 as i32)
830 .map_err(|error| error.with_context(CodecKind::LpVec3))?;
831 }
832 Ok(())
833 }
834
835 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
836 let mut first = [0; 1];
837 read_exact_counted(reader, &mut first, CodecKind::LpVec3, 0)?;
838 if first[0] == 0 {
839 return Ok(Self::default());
840 }
841
842 let mut remaining = [0; 5];
843 read_exact_counted(reader, &mut remaining, CodecKind::LpVec3, 1)?;
844 let upper = u32::from_be_bytes([remaining[1], remaining[2], remaining[3], remaining[4]]);
845 let packed = u64::from(upper) << 16 | u64::from(remaining[0]) << 8 | u64::from(first[0]);
846 let mut scale_factor = u64::from(first[0]) & Self::SCALE_BITS;
847 if first[0] & Self::CONTINUATION_FLAG as u8 != 0 {
848 let continuation = reader
849 .read_varint()
850 .map_err(|error| error.with_context(CodecKind::LpVec3))?;
851 scale_factor |= u64::from(continuation as u32) << 2;
852 }
853
854 let scale = scale_factor as f64;
855 Ok(Self {
856 x: Self::unpack(packed >> 3) * scale,
857 y: Self::unpack(packed >> 18) * scale,
858 z: Self::unpack(packed >> 33) * scale,
859 })
860 }
861}
862
863#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
896pub struct Uuid(
897 pub uuid::Uuid,
899);
900
901impl Uuid {
902 pub fn from_bytes(bytes: [u8; 16]) -> Self {
904 Self(uuid::Uuid::from_bytes(bytes))
905 }
906
907 pub fn into_bytes(self) -> [u8; 16] {
909 self.0.into_bytes()
910 }
911}
912
913impl TypeCodec for Uuid {
914 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
915 write_all_counted(writer, &self.0.into_bytes(), CodecKind::Uuid, 0)
916 }
917
918 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
919 let mut bytes = [0; 16];
920 read_exact_counted(reader, &mut bytes, CodecKind::Uuid, 0)?;
921 Ok(Self::from_bytes(bytes))
922 }
923}
924
925#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
958pub struct BitSet(
959 pub Vec<u64>,
961);
962
963impl BitSet {
964 pub fn contains(&self, index: usize) -> bool {
966 match self.0.get(index / 64) {
967 Some(word) => (word & (1 << (index % 64))) != 0,
968 None => false,
969 }
970 }
971}
972
973impl TypeCodec for BitSet {
974 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
975 let prefix_size = writer
976 .write_varint_with_size(self.0.len() as i32)
977 .map_err(|error| error.with_context(CodecKind::BitSet))?;
978
979 let mut bytes_processed = prefix_size;
980 for word in &self.0 {
981 write_all_counted(
982 writer,
983 &word.to_be_bytes(),
984 CodecKind::BitSet,
985 bytes_processed,
986 )?;
987 bytes_processed += 8;
988 }
989
990 Ok(())
991 }
992
993 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
994 let (length, prefix_size) = reader
995 .read_varint_with_size()
996 .map_err(|error| error.with_context(CodecKind::BitSet))?;
997 let length = usize::try_from(length).map_err(|_| {
998 CodecError::invalid_encoding(
999 CodecKind::BitSet,
1000 prefix_size,
1001 InvalidEncodingReason::NegativeLength { value: length },
1002 )
1003 })?;
1004
1005 let mut words = Vec::with_capacity(length);
1006 let mut bytes_processed = prefix_size;
1007 for _ in 0..length {
1008 let mut bytes = [0; 8];
1009 read_exact_counted(reader, &mut bytes, CodecKind::BitSet, bytes_processed)?;
1010 words.push(u64::from_be_bytes(bytes));
1011 bytes_processed += 8;
1012 }
1013
1014 Ok(Self(words))
1015 }
1016}
1017
1018#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
1053pub struct FixedBitSet<const N: usize>(
1054 pub Vec<u8>,
1056);
1057
1058impl<const N: usize> FixedBitSet<N> {
1059 pub const BYTE_LEN: usize = N.div_ceil(8);
1061
1062 pub fn contains(&self, index: usize) -> bool {
1066 index < N
1067 && self
1068 .0
1069 .get(index / 8)
1070 .is_some_and(|byte| (byte & (1 << (index % 8))) != 0)
1071 }
1072
1073 fn validate(
1074 &self,
1075 operation: CodecOperation,
1076 bytes_processed: usize,
1077 ) -> Result<(), CodecError> {
1078 if self.0.len() != Self::BYTE_LEN {
1079 return Err(CodecError::invalid_encoding_for_operation(
1080 CodecKind::FixedBitSet,
1081 operation,
1082 bytes_processed,
1083 InvalidEncodingReason::InvalidFixedBitSetLength {
1084 expected: Self::BYTE_LEN,
1085 actual: self.0.len(),
1086 },
1087 ));
1088 }
1089
1090 if let Some(last_byte) = self.0.last()
1091 && N % 8 != 0
1092 {
1093 let allowed_mask = (1u8 << (N % 8)) - 1;
1094 if last_byte & !allowed_mask != 0 {
1095 return Err(CodecError::invalid_encoding_for_operation(
1096 CodecKind::FixedBitSet,
1097 operation,
1098 bytes_processed,
1099 InvalidEncodingReason::ValueOutOfRange {
1100 terminal_byte: *last_byte,
1101 allowed_mask,
1102 },
1103 ));
1104 }
1105 }
1106
1107 Ok(())
1108 }
1109}
1110
1111impl<const N: usize> TypeCodec for FixedBitSet<N> {
1112 fn encode(&self, writer: &mut impl Write) -> Result<(), CodecError> {
1113 self.validate(CodecOperation::Write, 0)?;
1114 write_all_counted(writer, &self.0, CodecKind::FixedBitSet, 0)
1115 }
1116
1117 fn decode(reader: &mut impl Read) -> Result<Self, CodecError> {
1118 let mut bytes = vec![0; Self::BYTE_LEN];
1119 read_exact_counted(reader, &mut bytes, CodecKind::FixedBitSet, 0)?;
1120
1121 let value = Self(bytes);
1122 value.validate(CodecOperation::Read, Self::BYTE_LEN)?;
1123 Ok(value)
1124 }
1125}
1126
1127macro_rules! impl_enum_repr {
1128 ($type:ident, $primitive:ty) => {
1129 impl EnumRepr for $type {
1130 fn from_discriminant(value: i128) -> Option<Self> {
1131 <$primitive>::try_from(value).ok().map(Self)
1132 }
1133
1134 fn discriminant(&self) -> i128 {
1135 self.0 as i128
1136 }
1137 }
1138 };
1139}
1140
1141impl EnumRepr for Boolean {
1142 fn from_discriminant(value: i128) -> Option<Self> {
1143 match value {
1144 0 => Some(Self(false)),
1145 1 => Some(Self(true)),
1146 _ => None,
1147 }
1148 }
1149
1150 fn discriminant(&self) -> i128 {
1151 if self.0 { 1 } else { 0 }
1152 }
1153}
1154
1155impl_enum_repr!(Byte, i8);
1156impl_enum_repr!(UnsignedByte, u8);
1157impl_enum_repr!(Short, i16);
1158impl_enum_repr!(UnsignedShort, u16);
1159impl_enum_repr!(Int, i32);
1160impl_enum_repr!(Long, i64);
1161impl_enum_repr!(VarInt, i32);
1162impl_enum_repr!(VarLong, i64);
1163impl_enum_repr!(Angle, u8);