Skip to main content

nbt_rs/types/
array.rs

1use std::{fmt, ops::Deref};
2
3use bytemuck::cast_slice;
4
5use crate::{error::ValidationError, traits::NbtSerialize};
6
7/// A wrapper around a `Vec<T>`, limiting its length to the maximum allowed in nbt.
8#[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    /// Attempts to create an `NbtArray`.
45    ///
46    /// # Errors
47    /// Will fail if the source vec has more than `i32::MAX` items.
48    ///
49    /// # Examples
50    /// ```
51    /// let nbt_array: nbt_rs::types::NbtArray<i8> = vec![0i8, 1i8, 2i8].try_into().unwrap();
52    /// ```
53    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);