Skip to main content

simdnbt/
error.rs

1use std::fmt::Debug;
2
3use thiserror::Error;
4
5use crate::common::MAX_DEPTH;
6
7#[derive(Error, Debug, PartialEq)]
8pub enum Error {
9    #[error("Invalid root type {0}")]
10    InvalidRootType(u8),
11    #[error("Unknown tag id {0}")]
12    UnknownTagId(u8),
13    #[error("Unexpected end of data")]
14    UnexpectedEof,
15    #[error("Tried to read NBT tag with too high complexity, depth > {MAX_DEPTH}")]
16    MaxDepthExceeded,
17}
18
19// these two structs exist to optimize errors, since Error is an entire 2 bytes
20// which are often unnecessary
21pub(crate) struct UnexpectedEofError;
22impl From<UnexpectedEofError> for Error {
23    fn from(_: UnexpectedEofError) -> Self {
24        Error::UnexpectedEof
25    }
26}
27pub struct NonRootError {
28    // 0 = unexpected eof
29    // 1 = max depth exceeded
30    // anything else = unknown tag id, the id is value-1
31    value: u8,
32}
33impl From<NonRootError> for Error {
34    #[inline]
35    fn from(e: NonRootError) -> Self {
36        match e.value {
37            0 => Error::UnexpectedEof,
38            1 => Error::MaxDepthExceeded,
39            _ => Error::UnknownTagId(e.value.wrapping_add(1)),
40        }
41    }
42}
43
44impl NonRootError {
45    #[inline]
46    pub fn unexpected_eof() -> Self {
47        NonRootError { value: 0 }
48    }
49    #[inline]
50    pub fn max_depth_exceeded() -> Self {
51        NonRootError { value: 1 }
52    }
53    #[inline]
54    pub fn unknown_tag_id(id: u8) -> Self {
55        // the value can't be 1 or 2 (because those are always valid tag ids),
56        // so we take advantage of that in our encoding
57        NonRootError {
58            value: id.wrapping_sub(1),
59        }
60    }
61}
62impl From<UnexpectedEofError> for NonRootError {
63    #[inline]
64    fn from(_: UnexpectedEofError) -> Self {
65        NonRootError::unexpected_eof()
66    }
67}
68impl Debug for NonRootError {
69    #[inline]
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        match self.value {
72            0 => write!(f, "UnexpectedEofError"),
73            1 => write!(f, "MaxDepthExceededError"),
74            _ => write!(f, "UnknownTagId({})", self.value.wrapping_add(1)),
75        }
76    }
77}
78
79#[derive(Error, Debug)]
80pub enum DeserializeError {
81    #[error("Missing field")]
82    MissingField,
83    #[error("Mismatched type for {0}")]
84    MismatchedFieldType(String),
85    #[error("Unknown field {0:?}")]
86    UnknownField(String),
87}