1use serde::{
2 de::{Error, VariantAccess, Visitor, EnumAccess, IgnoredAny},
3 Deserialize, Deserializer, Serialize, Serializer
4};
5use std::{
6 collections::HashMap,
7 fmt::{self, Display, Formatter},
8 marker::PhantomData
9};
10
11use super::TagType;
12
13pub type Compound = HashMap<String, Tag>;
16
17#[derive(Clone, PartialEq, Debug)]
20pub enum Tag {
21 Byte(i8),
23 Short(i16),
25 Int(i32),
27 Long(i64),
29 Float(f32),
31 Double(f64),
33 ByteArray(Vec<i8>),
35 String(String),
37 List(List),
39 Compound(Compound),
41 IntArray(Vec<i32>),
43 LongArray(Vec<i64>),
45}
46
47impl Serialize for Tag {
48 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
49 match self {
50 Tag::Byte(v) => v.serialize(serializer),
51 Tag::Short(v) => v.serialize(serializer),
52 Tag::Int(v) => v.serialize(serializer),
53 Tag::Long(v) => v.serialize(serializer),
54 Tag::Float(v) => v.serialize(serializer),
55 Tag::Double(v) => v.serialize(serializer),
56 Tag::ByteArray(v) => byte_array::serialize(v, serializer),
57 Tag::String(v) => v.serialize(serializer),
58 Tag::List(v) => v.serialize(serializer),
59 Tag::Compound(v) => v.serialize(serializer),
60 Tag::IntArray(v) => int_array::serialize(v, serializer),
61 Tag::LongArray(v) => long_array::serialize(v, serializer),
62 }
63 }
64}
65
66impl<'de> Deserialize<'de> for Tag {
67 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
68 deserializer.deserialize_any(TagVisitor)
69 }
70}
71
72struct TagVisitor;
73
74impl<'de> Visitor<'de> for TagVisitor {
75 type Value = Tag;
76
77 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
78 write!(formatter, "a NBT value")
79 }
80
81 fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
82 Ok(Tag::Byte(v))
83 }
84
85 fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
86 Ok(Tag::Short(v))
87 }
88
89 fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
90 Ok(Tag::Int(v))
91 }
92
93 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
94 Ok(Tag::Long(v))
95 }
96
97 fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
98 Ok(Tag::Float(v))
99 }
100
101 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
102 Ok(Tag::Double(v))
103 }
104
105 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
106 Ok(Tag::String(v.to_owned()))
107 }
108
109 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
110 Ok(Tag::String(v))
111 }
112
113 fn visit_map<A: serde::de::MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
114 visit_map(map).map(Tag::Compound)
115 }
116
117 fn visit_enum<A: serde::de::EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
118 let (array_type, variant) = data.variant()?;
119 match array_type {
120 ArrayType::Byte => Ok(Tag::ByteArray(variant.newtype_variant()?)),
121 ArrayType::Int => Ok(Tag::IntArray(variant.newtype_variant()?)),
122 ArrayType::Long => Ok(Tag::LongArray(variant.newtype_variant()?)),
123 }
124 }
125
126 fn visit_seq<A: serde::de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
127 ListVisitor.visit_seq(seq).map(Tag::List)
128 }
129}
130
131fn visit_map<'de, A: serde::de::MapAccess<'de>>(mut map: A) -> Result<Compound, A::Error> {
132 let mut compound = Compound::new();
133
134 while let Some((k, v)) = map.next_entry()? {
135 compound.insert(k, v);
136 }
137
138 Ok(compound)
139}
140
141#[derive(Clone, PartialEq, Debug)]
144pub enum List {
145 Empty,
147 Byte(Vec<i8>),
149 Short(Vec<i16>),
151 Int(Vec<i32>),
153 Long(Vec<i64>),
155 Float(Vec<f32>),
157 Double(Vec<f64>),
159 ByteArray(Vec<Vec<i8>>),
161 String(Vec<String>),
163 List(Vec<List>),
165 Compound(Vec<Compound>),
167 IntArray(Vec<Vec<i32>>),
169 LongArray(Vec<Vec<i64>>),
171}
172
173impl Serialize for List {
174 fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
175 match self {
176 List::Empty => [(); 0].serialize(serializer),
177 List::Byte(l) => l.serialize(serializer),
178 List::Short(l) => l.serialize(serializer),
179 List::Int(l) => l.serialize(serializer),
180 List::Long(l) => l.serialize(serializer),
181 List::Float(l) => l.serialize(serializer),
182 List::Double(l) => l.serialize(serializer),
183 List::ByteArray(l) => l.serialize(serializer),
184 List::String(l) => l.serialize(serializer),
185 List::List(l) => l.serialize(serializer),
186 List::Compound(l) => l.serialize(serializer),
187 List::IntArray(l) => l.serialize(serializer),
188 List::LongArray(l) => l.serialize(serializer),
189 }
190 }
191}
192
193struct ListVisitor;
194
195impl<'de> Visitor<'de> for ListVisitor {
196 type Value = List;
197
198 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
199 write!(formatter, "an NBT list")
200 }
201
202 fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
203 let mut list = List::Empty;
204
205 while seq.next_element_seed(ListElement(&mut list))?.is_some() {}
206
207 Ok(list)
208 }
209}
210
211struct ListElement<'a>(&'a mut List);
212
213impl<'de, 'a> serde::de::DeserializeSeed<'de> for ListElement<'a> {
214 type Value = ();
215
216 fn deserialize<D: serde::Deserializer<'de>>(
217 self,
218 deserializer: D,
219 ) -> Result<Self::Value, D::Error> {
220 deserializer.deserialize_any(self)
221 }
222}
223
224macro_rules! visit {
225 ($self:expr, $variant:ident, $value:expr, $error:ty) => {
226 match $self.0 {
227 List::Empty => {
228 *$self.0 = List::$variant(vec![$value]);
229 Ok(())
230 }
231 List::$variant(l) => {
232 l.push($value);
233 Ok(())
234 }
235 _ => Err(<$error>::custom("NBT lists must be homogenous")),
236 }
237 };
238}
239
240impl<'de, 'a> Visitor<'de> for ListElement<'a> {
241 type Value = ();
242
243 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
244 write!(formatter, "a valid NBT list element")
245 }
246
247 fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
248 visit!(self, Byte, v, E)
249 }
250
251 fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
252 visit!(self, Short, v, E)
253 }
254
255 fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
256 visit!(self, Int, v, E)
257 }
258
259 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
260 visit!(self, Long, v, E)
261 }
262
263 fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
264 visit!(self, Float, v, E)
265 }
266
267 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
268 visit!(self, Double, v, E)
269 }
270
271 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
272 visit!(self, String, v.to_owned(), E)
273 }
274
275 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
276 visit!(self, String, v, E)
277 }
278
279 fn visit_seq<A: serde::de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
280 visit!(self, List, ListVisitor.visit_seq(seq)?, A::Error)
281 }
282
283 fn visit_map<A: serde::de::MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
284 visit!(self, Compound, visit_map(map)?, A::Error)
285 }
286
287 fn visit_enum<A: serde::de::EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
288 let (array_type, variant) = data.variant()?;
289 match array_type {
290 ArrayType::Byte => visit!(self, ByteArray, variant.newtype_variant()?, A::Error),
291 ArrayType::Int => visit!(self, IntArray, variant.newtype_variant()?, A::Error),
292 ArrayType::Long => visit!(self, LongArray, variant.newtype_variant()?, A::Error),
293 }
294 }
295}
296
297pub(crate) const BYTE_ARRAY_NAME: &str = "__byte_array__";
300pub(crate) const INT_ARRAY_NAME: &str = "__int_array__";
301pub(crate) const LONG_ARRAY_NAME: &str = "__long_array__";
302
303pub(crate) const ARRAY_ENUM_NAME: &str = "__array__";
304pub(crate) const ARRAY_VARIANTS: &[&str] = &[BYTE_ARRAY_NAME, INT_ARRAY_NAME, LONG_ARRAY_NAME];
305
306macro_rules! array {
307 ($mod:ident, $tag:literal, $index:literal, $variant:tt) => {
308 pub mod $mod {
309 use super::*;
310
311 pub fn serialize<T, S>(array: &T, serializer: S) -> core::result::Result<S::Ok, S::Error>
312 where
313 T: Serialize,
314 S: Serializer,
315 {
316 serializer.serialize_newtype_variant(ARRAY_ENUM_NAME, $index, $variant, array)
317 }
318
319 pub fn deserialize<'de, T, D>(deserializer: D) -> core::result::Result<T, D::Error>
320 where
321 T: Deserialize<'de>,
322 D: Deserializer<'de>,
323 {
324 struct ArrayVisitor<T>(PhantomData<T>);
325
326 impl<'de, T: Deserialize<'de>> Visitor<'de> for ArrayVisitor<T> {
327 type Value = T;
328
329 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
330 write!(formatter, $tag)
331 }
332
333 fn visit_enum<A>(self, data: A) -> core::result::Result<Self::Value, A::Error>
334 where
335 A: EnumAccess<'de>,
336 {
337 let (_, variant) = data.variant::<IgnoredAny>()?;
339
340 variant.newtype_variant()
341 }
342 }
343
344 deserializer.deserialize_enum(
345 ARRAY_ENUM_NAME,
346 ARRAY_VARIANTS,
347 ArrayVisitor(PhantomData),
348 )
349 }
350 }
351 };
352}
353
354array!(byte_array, "Tag_BYTE_ARRAY", 0, BYTE_ARRAY_NAME);
355array!(int_array, "Tag_INT_ARRAY", 1, INT_ARRAY_NAME);
356array!(long_array, "Tag_LONG_ARRAY", 2, LONG_ARRAY_NAME);
357
358enum ArrayType {
359 Byte,
360 Int,
361 Long,
362}
363
364impl<'de> Deserialize<'de> for ArrayType {
365 fn deserialize<D: ::serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
366 struct ArrayVisitor;
367
368 impl<'de> Visitor<'de> for ArrayVisitor {
369 type Value = ArrayType;
370
371 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
372 write!(formatter, "a u8 or string encoding an NBT array type")
373 }
374
375 fn visit_u8<E: Error>(self, v: u8) -> Result<Self::Value, E> {
376 match v {
377 0 => Ok(ArrayType::Byte),
378 1 => Ok(ArrayType::Int),
379 2 => Ok(ArrayType::Long),
380 i => Err(E::custom(format!("invalid array type index `{i}`"))),
381 }
382 }
383
384 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
385 match v {
386 BYTE_ARRAY_NAME => Ok(ArrayType::Byte),
387 INT_ARRAY_NAME => Ok(ArrayType::Int),
388 LONG_ARRAY_NAME => Ok(ArrayType::Long),
389 s => Err(E::custom(format!("invalid array type `{s}`"))),
390 }
391 }
392 }
393
394 deserializer.deserialize_u8(ArrayVisitor)
395 }
396}
397
398
399#[derive(Debug)]
400pub enum TagConversionError<'a> {
401 Tag(TagType, &'a str),
402 List(TagType, &'a str)
403}
404
405impl<'a> std::error::Error for TagConversionError<'a> {
406 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
407 None
408 }
409}
410
411impl<'a> Display for TagConversionError<'a> {
412 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413 match self {
414 TagConversionError::Tag(x, y) => write!(f, "couldn't convert {x:?} to {y}"),
415 TagConversionError::List(x, y) => write!(f, "couldn't convert {x:?} to Vec<{y}>")
416 }
417 }
418}
419
420pub trait CompoundTryGetInto<T> where Self: Sized {
421 type Error;
422 fn try_get_into(self, key: &str) -> Result<Option<T>, Self::Error>;
423}
424
425macro_rules! tag_conversion {
426 ($tag:ident, &$ty:ty, $str:expr) => {
427 impl<'a> TryInto<&'a $ty> for &'a Tag {
428 type Error = TagConversionError<'a>;
429 fn try_into(self) -> Result<&'a $ty, TagConversionError<'a>> {
430 match self {
431 Tag::$tag(x) => Ok(x),
432 _ => Err(TagConversionError::Tag(self.tag_type(), $str))
433 }
434 }
435 }
436
437 impl<'a> TryInto<&'a mut $ty> for &'a mut Tag {
438 type Error = TagConversionError<'a>;
439 fn try_into(self) -> Result<&'a mut $ty, TagConversionError<'a>> {
440 match self {
441 Tag::$tag(x) => Ok(x),
442 _ => Err(TagConversionError::Tag(self.tag_type(), $str))
443 }
444 }
445 }
446
447 impl<'a> CompoundTryGetInto<&'a $ty> for &'a Compound {
448 type Error = TagConversionError<'a>;
449 fn try_get_into(self, key: &str) -> Result<Option<&'a $ty>, TagConversionError<'a>> {
450 match self.get(key) {
451 Some(x) => match x {
452 Tag::$tag(y) => Ok(Some(y)),
453 _ => Err(TagConversionError::Tag(x.tag_type(), $str))
454 },
455 None => Ok(None)
456 }
457 }
458 }
459
460 impl<'a> CompoundTryGetInto<&'a mut $ty> for &'a mut Compound {
461 type Error = TagConversionError<'a>;
462 fn try_get_into(self, key: &str) -> Result<Option<&'a mut $ty>, TagConversionError<'a>> {
463 match self.get_mut(key) {
464 Some(x) => match x {
465 Tag::$tag(y) => Ok(Some(y)),
466 _ => Err(TagConversionError::Tag(x.tag_type(), $str))
467 },
468 None => Ok(None)
469 }
470 }
471 }
472
473 impl<'a> TryInto<&'a [$ty]> for &'a Tag {
474 type Error = TagConversionError<'a>;
475 fn try_into(self) -> Result<&'a [$ty], TagConversionError<'a>> {
476 match self {
477 Tag::List(List::$tag(x)) => Ok(x),
478 _ => Err(TagConversionError::Tag(self.tag_type(), "{&[$str]}"))
479 }
480 }
481 }
482
483 impl<'a> TryInto<&'a mut [$ty]> for &'a mut Tag {
484 type Error = TagConversionError<'a>;
485 fn try_into(self) -> Result<&'a mut [$ty], TagConversionError<'a>> {
486 match self {
487 Tag::List(List::$tag(x)) => Ok(x),
488 _ => Err(TagConversionError::Tag(self.tag_type(), "{&[$str]}"))
489 }
490 }
491 }
492
493 impl<'a> CompoundTryGetInto<&'a [$ty]> for &'a Compound {
494 type Error = TagConversionError<'a>;
495 fn try_get_into(self, key: &str) -> Result<Option<&'a [$ty]>, TagConversionError<'a>> {
496 match self.get(key) {
497 Some(x) => match x {
498 Tag::List(List::$tag(y)) => Ok(Some(y)),
499 _ => Err(TagConversionError::Tag(x.tag_type(), $str))
500 },
501 None => Ok(None)
502 }
503 }
504 }
505
506 impl<'a> CompoundTryGetInto<&'a mut [$ty]> for &'a mut Compound {
507 type Error = TagConversionError<'a>;
508 fn try_get_into(self, key: &str) -> Result<Option<&'a mut [$ty]>, TagConversionError<'a>> {
509 match self.get_mut(key) {
510 Some(x) => match x {
511 Tag::List(List::$tag(y)) => Ok(Some(y)),
512 _ => Err(TagConversionError::Tag(x.tag_type(), $str))
513 },
514 None => Ok(None)
515 }
516 }
517 }
518
519 impl<'a> TryInto<&'a [$ty]> for &'a List {
520 type Error = TagConversionError<'a>;
521 fn try_into(self) -> Result<&'a [$ty], TagConversionError<'a>> {
522 match self {
523 List::$tag(x) => Ok(x),
524 _ => Err(TagConversionError::List(self.tag_type(), $str))
525 }
526 }
527 }
528
529 impl<'a> TryInto<&'a mut [$ty]> for &'a mut List {
530 type Error = TagConversionError<'a>;
531 fn try_into(self) -> Result<&'a mut [$ty], TagConversionError<'a>> {
532 match self {
533 List::$tag(x) => Ok(x),
534 _ => Err(TagConversionError::List(self.tag_type(), $str))
535 }
536 }
537 }
538 };
539 ($tag:ident, $ty:ty, $str:expr) => {
540 impl<'a> TryInto<$ty> for &'a Tag {
541 type Error = TagConversionError<'a>;
542 fn try_into(self) -> Result<$ty, TagConversionError<'a>> {
543 match self {
544 Tag::$tag(x) => Ok(*x),
545 _ => Err(TagConversionError::Tag(self.tag_type(), $str))
546 }
547 }
548 }
549
550 impl<'a> CompoundTryGetInto<$ty> for &'a Compound {
551 type Error = TagConversionError<'a>;
552 fn try_get_into(self, key: &str) -> Result<Option<$ty>, TagConversionError<'a>> {
553 match self.get(key) {
554 Some(x) => match x {
555 Tag::$tag(y) => Ok(Some(*y)),
556 _ => Err(TagConversionError::Tag(x.tag_type(), $str))
557 },
558 None => Ok(None)
559 }
560 }
561 }
562 tag_conversion!($tag, &$ty, $str);
563 }
564}
565
566tag_conversion!(Byte, i8, "i8");
567tag_conversion!(Short, i16, "i16");
568tag_conversion!(Int, i32, "i32");
569tag_conversion!(Long, i64, "i64");
570tag_conversion!(Float, f32, "f32");
571tag_conversion!(Double, f64, "f64");
572tag_conversion!(List, &List, "List");
573tag_conversion!(Compound, &Compound, "Compound");
574
575impl<'a> TryInto<&'a str> for &'a Tag {
576 type Error = TagConversionError<'a>;
577 fn try_into(self) -> Result<&'a str, TagConversionError<'a>> {
578 match self {
579 Tag::String(x) => Ok(x),
580 _ => Err(TagConversionError::Tag(self.tag_type(), "str"))
581 }
582 }
583}
584
585impl<'a> TryInto<&'a mut String> for &'a mut Tag {
586 type Error = TagConversionError<'a>;
587 fn try_into(self) -> Result<&'a mut String, TagConversionError<'a>> {
588 match self {
589 Tag::String(x) => Ok(x),
590 _ => Err(TagConversionError::Tag(self.tag_type(), "str"))
591 }
592 }
593}
594
595impl<'a> TryInto<&'a [String]> for &'a List {
596 type Error = TagConversionError<'a>;
597 fn try_into(self) -> Result<&'a [String], TagConversionError<'a>> {
598 match self {
599 List::String(x) => Ok(x),
600 _ => Err(TagConversionError::List(self.tag_type(), "str"))
601 }
602 }
603}
604
605impl<'a> TryInto<&'a mut [String]> for &'a mut List {
606 type Error = TagConversionError<'a>;
607 fn try_into(self) -> Result<&'a mut [String], TagConversionError<'a>> {
608 match self {
609 List::String(x) => Ok(x),
610 _ => Err(TagConversionError::List(self.tag_type(), "str"))
611 }
612 }
613}
614
615impl<'a> CompoundTryGetInto<&'a str> for &'a Compound {
616 type Error = TagConversionError<'a>;
617 fn try_get_into(self, key: &str) -> Result<Option<&'a str>, TagConversionError<'a>> {
618 match self.get(key) {
619 Some(x) => match x {
620 Tag::String(y) => Ok(Some(y)),
621 _ => Err(TagConversionError::Tag(x.tag_type(), "str"))
622 },
623 None => Ok(None)
624 }
625 }
626}
627
628impl<'a> CompoundTryGetInto<&'a mut String> for &'a mut Compound {
629 type Error = TagConversionError<'a>;
630 fn try_get_into(self, key: &str) -> Result<Option<&'a mut String>, TagConversionError<'a>> {
631 match self.get_mut(key) {
632 Some(x) => match x {
633 Tag::String(y) => Ok(Some(y)),
634 _ => Err(TagConversionError::Tag(x.tag_type(), "str"))
635 },
636 None => Ok(None)
637 }
638 }
639}
640
641impl Tag {
642 pub fn try_get(&self, key: &String) -> Result<Option<&Tag>, TagConversionError> {
643 let compound: &Compound = self.try_into()?;
644 Ok(compound.get(key))
645 }
646
647 pub fn tag_type(&self) -> TagType {
648 match self {
649 Tag::Byte(_) => TagType::Byte,
650 Tag::Short(_) => TagType::Short,
651 Tag::Int(_) => TagType::Int,
652 Tag::Long(_) => TagType::Long,
653 Tag::Float(_) => TagType::Float,
654 Tag::Double(_) => TagType::Double,
655 Tag::ByteArray(_) => TagType::ByteArray,
656 Tag::String(_) => TagType::String,
657 Tag::List(_) => TagType::List,
658 Tag::Compound(_) => TagType::Compound,
659 Tag::IntArray(_) => TagType::IntArray,
660 Tag::LongArray(_) => TagType::LongArray
661 }
662 }
663}
664
665impl List {
666 pub fn tag_type(&self) -> TagType {
667 match self {
668 List::Empty => TagType::End,
669 List::Byte(_) => TagType::Byte,
670 List::Short(_) => TagType::Short,
671 List::Int(_) => TagType::Int,
672 List::Long(_) => TagType::Long,
673 List::Float(_) => TagType::Float,
674 List::Double(_) => TagType::Double,
675 List::ByteArray(_) => TagType::ByteArray,
676 List::String(_) => TagType::String,
677 List::List(_) => TagType::List,
678 List::Compound(_) => TagType::Compound,
679 List::IntArray(_) => TagType::IntArray,
680 List::LongArray(_) => TagType::LongArray
681 }
682 }
683}