1use std::{fmt, ops::Deref};
2
3use bytemuck::cast_slice;
4
5use crate::{error::ValidationError, traits::NbtSerialize};
6
7#[derive(Debug, PartialEq, Clone, Hash)]
9pub struct NbtArray<T> {
10 pub(crate) items: Vec<T>,
11}
12
13impl<T: Eq> Eq for NbtArray<T> {}
14
15impl<T: PartialOrd> PartialOrd for NbtArray<T> {
16 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
17 self.items.partial_cmp(&other.items)
18 }
19}
20
21impl<T: Ord> Ord for NbtArray<T> {
22 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
23 self.items.cmp(&other.items)
24 }
25}
26
27impl<T: fmt::Display> fmt::Display for NbtArray<T> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(
30 f,
31 "[{}]",
32 self.items
33 .iter()
34 .map(|e| e.to_string())
35 .collect::<Vec<_>>()
36 .join(", ")
37 )
38 }
39}
40
41impl<T> TryFrom<Vec<T>> for NbtArray<T> {
42 type Error = (ValidationError, Vec<T>);
43
44 fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
54 if vec.len() > i32::MAX as usize {
55 Err((ValidationError::ArrayTooLong(vec.len()), vec))
56 } else {
57 Ok(Self { items: vec })
58 }
59 }
60}
61
62impl<T> From<NbtArray<T>> for Vec<T> {
63 fn from(array: NbtArray<T>) -> Self {
64 array.items
65 }
66}
67
68impl<T> Deref for NbtArray<T> {
69 type Target = [T];
70
71 fn deref(&self) -> &Self::Target {
72 &self.items
73 }
74}
75
76impl NbtSerialize for NbtArray<i8> {
77 fn serialize_nbt_payload(&self, buf: &mut Vec<u8>) {
78 (self.len() as i32).serialize_nbt_payload(buf);
79 buf.extend_from_slice(cast_slice(&self.items));
80 }
81}
82
83macro_rules! impl_nbt_serialize_array {
84 ($ty:ty) => {
85 impl NbtSerialize for NbtArray<$ty> {
86 fn serialize_nbt_payload(&self, buf: &mut Vec<u8>) {
87 (self.len() as i32).serialize_nbt_payload(buf);
88 for v in self.iter() {
89 buf.extend_from_slice(&v.to_be_bytes());
90 }
91 }
92 }
93 };
94}
95
96impl_nbt_serialize_array!(i32);
97impl_nbt_serialize_array!(u32);
98impl_nbt_serialize_array!(i64);
99impl_nbt_serialize_array!(u64);