1#![warn(clippy::pedantic)]
4#![allow(clippy::cast_possible_wrap)]
5#![allow(clippy::cast_possible_truncation)]
6#![allow(clippy::cast_lossless)]
7#![allow(clippy::enum_glob_use)]
8#![allow(clippy::must_use_candidate)]
9#![allow(clippy::missing_errors_doc)]
10#![cfg_attr(docsrs, feature(doc_cfg))]
12
13use crate::error::TypeOutOfRange;
14pub use crate::nbt::de::{Deserializer, from_be_bytes, from_bytes, from_le_bytes, from_net_bytes};
15pub use crate::nbt::ser::{
16 Serializer, to_be_bytes, to_be_bytes_in, to_bytes, to_bytes_in, to_le_bytes, to_le_bytes_in,
17 to_net_bytes, to_net_bytes_in,
18};
19pub use crate::value::Value;
20pub use byteorder::{BigEndian, LittleEndian};
21
22use std::fmt::{self, Debug, Display};
23
24pub use error::{Error, Result};
25
26#[cfg(test)]
27mod test;
28
29mod error;
30mod nbt;
31
32#[cfg(feature = "snbt")]
33pub mod snbt;
34#[cfg(feature = "snbt")]
35pub use snbt::{from_string, to_string};
36
37mod value;
38
39mod private {
40 use byteorder::{BigEndian, LittleEndian};
41
42 use crate::{EndiannessImpl, NetworkLittleEndian, Variant};
43
44 pub trait Sealed {}
47
48 impl Sealed for BigEndian {}
49 impl EndiannessImpl for BigEndian {
50 const AS_ENUM: Variant = Variant::BigEndian;
51 }
52
53 impl Sealed for LittleEndian {}
54 impl EndiannessImpl for LittleEndian {
55 const AS_ENUM: Variant = Variant::LittleEndian;
56 }
57
58 impl Sealed for NetworkLittleEndian {}
59 impl EndiannessImpl for NetworkLittleEndian {
60 const AS_ENUM: Variant = Variant::NetworkEndian;
61 }
62}
63
64pub trait EndiannessImpl: private::Sealed {
66 const AS_ENUM: Variant;
70}
71
72#[derive(Debug, Copy, Clone, PartialEq, Eq)]
74pub enum Variant {
75 LittleEndian,
78 BigEndian,
81 NetworkEndian,
86}
87
88pub enum NetworkLittleEndian {}
93
94#[allow(dead_code)]
97#[derive(Debug, Copy, Clone, PartialEq, Eq)]
98#[repr(u8)]
99pub enum FieldType {
100 End = 0,
102 Byte = 1,
104 Short = 2,
106 Int = 3,
108 Long = 4,
110 Float = 5,
112 Double = 6,
114 ByteArray = 7,
116 String = 8,
118 List = 9,
121 Compound = 10,
123 IntArray = 11,
125 LongArray = 12,
127}
128
129impl Display for FieldType {
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 use FieldType::*;
132
133 let str = match self {
134 End => "end",
135 Byte => "byte",
136 Short => "short",
137 Int => "int",
138 Long => "long",
139 Float => "float",
140 Double => "double",
141 ByteArray => "byte array",
142 String => "string",
143 List => "list",
144 Compound => "compound",
145 IntArray => "int array",
146 LongArray => "long array",
147 };
148
149 f.write_str(str)
150 }
151}
152
153impl FieldType {
154 pub(crate) fn try_from(
155 v: u8,
156 #[cfg(feature = "error-context")] at: &mut Option<String>,
157 #[cfg(feature = "error-context")] at_index: Option<usize>,
158 ) -> Result<Self> {
159 const LAST_DISC: u8 = FieldType::LongArray as u8;
160 if v > LAST_DISC {
161 return Err(Error::TypeOutOfRange(TypeOutOfRange {
162 found: v,
163
164 #[cfg(feature = "error-context")]
165 at: at.take().unwrap_or_else(|| String::from("unknown")),
166 #[cfg(feature = "error-context")]
167 index: at_index,
168 }));
169 }
170
171 Ok(unsafe { std::mem::transmute::<u8, FieldType>(v) })
175 }
176}
177
178impl serde::de::Error for Error {
195 fn custom<T>(msg: T) -> Self
196 where
197 T: Display,
198 {
199 Error::Other(msg.to_string())
200 }
201}
202
203impl serde::ser::Error for Error {
204 fn custom<T>(msg: T) -> Self
205 where
206 T: Display,
207 {
208 Error::Other(msg.to_string())
209 }
210}