1use compact_str::CompactString;
2use enum_as_inner::EnumAsInner;
3#[cfg(feature = "serde")]
4use serde::{ser::SerializeMap, Deserialize, Serialize};
5
6pub type NbtByte = i8;
7pub type NbtShort = i16;
8pub type NbtInt = i32;
9pub type NbtLong = i64;
10pub type NbtFloat = f32;
11pub type NbtDouble = f64;
12pub type NbtByteArray = Vec<u8>;
13pub type NbtString = CompactString;
14pub type NbtIntArray = Vec<i32>;
15pub type NbtLongArray = Vec<i64>;
16
17pub const END_ID: u8 = 0;
18pub const BYTE_ID: u8 = 1;
19pub const SHORT_ID: u8 = 2;
20pub const INT_ID: u8 = 3;
21pub const LONG_ID: u8 = 4;
22pub const FLOAT_ID: u8 = 5;
23pub const DOUBLE_ID: u8 = 6;
24pub const BYTE_ARRAY_ID: u8 = 7;
25pub const STRING_ID: u8 = 8;
26pub const LIST_ID: u8 = 9;
27pub const COMPOUND_ID: u8 = 10;
28pub const INT_ARRAY_ID: u8 = 11;
29pub const LONG_ARRAY_ID: u8 = 12;
30
31#[derive(Clone, Debug, PartialEq, Default, EnumAsInner)]
33#[repr(u8)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(untagged))]
35pub enum Nbt {
36 #[default]
37 End = END_ID,
38 Byte(NbtByte) = BYTE_ID,
39 Short(NbtShort) = SHORT_ID,
40 Int(NbtInt) = INT_ID,
41 Long(NbtLong) = LONG_ID,
42 Float(NbtFloat) = FLOAT_ID,
43 Double(NbtDouble) = DOUBLE_ID,
44 ByteArray(NbtByteArray) = BYTE_ARRAY_ID,
45 String(NbtString) = STRING_ID,
46 List(NbtList) = LIST_ID,
47 Compound(NbtCompound) = COMPOUND_ID,
48 IntArray(NbtIntArray) = INT_ARRAY_ID,
49 LongArray(NbtLongArray) = LONG_ARRAY_ID,
50}
51impl Nbt {
52 #[inline]
54 pub fn id(&self) -> u8 {
55 unsafe { *<*const _>::from(self).cast::<u8>() }
60 }
61}
62
63#[derive(Clone, Debug, PartialEq)]
65#[repr(u8)]
66#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(untagged))]
67pub enum NbtList {
68 Empty = END_ID,
69 Byte(Vec<NbtByte>) = BYTE_ID,
70 Short(Vec<NbtShort>) = SHORT_ID,
71 Int(Vec<NbtInt>) = INT_ID,
72 Long(Vec<NbtLong>) = LONG_ID,
73 Float(Vec<NbtFloat>) = FLOAT_ID,
74 Double(Vec<NbtDouble>) = DOUBLE_ID,
75 ByteArray(Vec<NbtByteArray>) = BYTE_ARRAY_ID,
76 String(Vec<NbtString>) = STRING_ID,
77 List(Vec<NbtList>) = LIST_ID,
78 Compound(Vec<NbtCompound>) = COMPOUND_ID,
79 IntArray(Vec<NbtIntArray>) = INT_ARRAY_ID,
80 LongArray(Vec<NbtLongArray>) = LONG_ARRAY_ID,
81}
82
83impl NbtList {
84 #[inline]
86 pub fn id(&self) -> u8 {
87 unsafe { *<*const _>::from(self).cast::<u8>() }
92 }
93}
94impl From<Vec<NbtByte>> for NbtList {
95 fn from(v: Vec<NbtByte>) -> Self {
96 Self::Byte(v)
97 }
98}
99impl From<Vec<NbtShort>> for NbtList {
100 fn from(v: Vec<NbtShort>) -> Self {
101 Self::Short(v)
102 }
103}
104impl From<Vec<NbtInt>> for NbtList {
105 fn from(v: Vec<NbtInt>) -> Self {
106 Self::Int(v)
107 }
108}
109impl From<Vec<NbtLong>> for NbtList {
110 fn from(v: Vec<NbtLong>) -> Self {
111 Self::Long(v)
112 }
113}
114impl From<Vec<NbtFloat>> for NbtList {
115 fn from(v: Vec<NbtFloat>) -> Self {
116 Self::Float(v)
117 }
118}
119impl From<Vec<NbtDouble>> for NbtList {
120 fn from(v: Vec<NbtDouble>) -> Self {
121 Self::Double(v)
122 }
123}
124impl From<Vec<NbtByteArray>> for NbtList {
125 fn from(v: Vec<NbtByteArray>) -> Self {
126 Self::ByteArray(v)
127 }
128}
129impl From<Vec<NbtString>> for NbtList {
130 fn from(v: Vec<NbtString>) -> Self {
131 Self::String(v)
132 }
133}
134impl From<Vec<NbtList>> for NbtList {
135 fn from(v: Vec<NbtList>) -> Self {
136 Self::List(v)
137 }
138}
139impl From<Vec<NbtCompound>> for NbtList {
140 fn from(v: Vec<NbtCompound>) -> Self {
141 Self::Compound(v)
142 }
143}
144impl From<Vec<NbtIntArray>> for NbtList {
145 fn from(v: Vec<NbtIntArray>) -> Self {
146 Self::IntArray(v)
147 }
148}
149impl From<Vec<NbtLongArray>> for NbtList {
150 fn from(v: Vec<NbtLongArray>) -> Self {
151 Self::LongArray(v)
152 }
153}
154
155#[derive(Debug, Clone, Default, PartialEq)]
157pub struct NbtCompound {
158 inner: Vec<(NbtString, Nbt)>,
159}
160impl NbtCompound {
161 #[inline]
162 pub fn with_capacity(capacity: usize) -> Self {
163 Self {
164 inner: Vec::with_capacity(capacity),
165 }
166 }
167
168 #[inline]
169 fn binary_search(&self, key: &NbtString) -> Result<usize, usize> {
170 self.inner.binary_search_by(|(k, _)| k.cmp(key))
171 }
172
173 #[inline]
178 pub fn get(&self, key: &str) -> Option<&Nbt> {
179 if self.is_worth_sorting() {
180 let key = NbtString::from(key);
181 self.binary_search(&key).ok().map(|i| &self.inner[i].1)
182 } else {
183 for (k, v) in &self.inner {
184 if &key == k {
185 return Some(v);
186 }
187 }
188 None
189 }
190 }
191
192 #[inline]
193 pub fn insert_unsorted(&mut self, key: NbtString, value: Nbt) {
194 self.inner.push((key, value));
195 }
196
197 #[inline]
204 pub fn insert(&mut self, key: NbtString, value: Nbt) {
205 self.inner.push((key, value));
206 self.sort()
207 }
208
209 #[inline]
210 pub fn sort(&mut self) {
211 if !self.is_worth_sorting() {
212 return;
213 }
214 self.inner.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
215 }
216
217 #[inline]
218 pub fn iter(&self) -> std::slice::Iter<'_, (CompactString, Nbt)> {
219 self.inner.iter()
220 }
221
222 #[inline]
223 fn is_worth_sorting(&self) -> bool {
224 self.inner.len() >= 32
227 }
228}
229#[cfg(feature = "serde")]
230impl Serialize for NbtCompound {
231 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
232 let mut map = serializer.serialize_map(Some(self.inner.len()))?;
233 for (key, value) in &self.inner {
234 map.serialize_entry(key, value)?;
235 }
236 map.end()
237 }
238}
239#[cfg(feature = "serde")]
240impl<'de> Deserialize<'de> for NbtCompound {
241 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
242 use std::collections::BTreeMap;
243 let map = <BTreeMap<NbtString, Nbt> as Deserialize>::deserialize(deserializer)?;
244 Ok(Self {
245 inner: map.into_iter().collect(),
246 })
247 }
248}
249
250impl FromIterator<(NbtString, Nbt)> for NbtCompound {
251 fn from_iter<T: IntoIterator<Item = (NbtString, Nbt)>>(iter: T) -> Self {
252 let inner = iter.into_iter().collect::<Vec<_>>();
253 Self { inner }
254 }
255}
256
257impl From<Vec<(NbtString, Nbt)>> for NbtCompound {
258 fn from(inner: Vec<(NbtString, Nbt)>) -> Self {
259 Self { inner }
260 }
261}