Skip to main content

wacore_binary/
error.rs

1use std::fmt;
2
3use crate::jid::JidError;
4
5#[derive(Debug)]
6pub enum BinaryError {
7    Io(std::io::Error),
8    InvalidToken(u8),
9    InvalidNode,
10    NonStringKey,
11    AttrParse(String),
12    MissingAttr(String),
13    InvalidUtf8(std::str::Utf8Error),
14    Zlib(String),
15    Jid(JidError),
16    UnexpectedEof,
17    EmptyData,
18    LeftoverData(usize),
19    AttrList(Vec<BinaryError>),
20    /// Node nesting exceeded the recursion cap — a hostile frame trying to
21    /// overflow the native stack, rejected before recursing.
22    MaxDepthExceeded,
23    /// The exact-marshal encode pass diverged from its size plan (byte count
24    /// or hint-tape consumption) — an internal encoder bug, distinct from a
25    /// malformed input node, surfaced instead of shipping corrupt bytes.
26    PlanMismatch,
27}
28
29impl fmt::Display for BinaryError {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        match self {
32            BinaryError::Io(e) => write!(f, "I/O error: {e}"),
33            BinaryError::InvalidToken(t) => write!(f, "Invalid token read from stream: {t}"),
34            BinaryError::InvalidNode => write!(f, "Invalid node format"),
35            BinaryError::PlanMismatch => {
36                write!(f, "Exact-marshal encode diverged from its size plan")
37            }
38            BinaryError::NonStringKey => write!(f, "Attribute key was not a string"),
39            BinaryError::AttrParse(s) => write!(f, "Attribute parsing failed: {s}"),
40            BinaryError::MissingAttr(s) => write!(f, "Missing required attribute: {s}"),
41            BinaryError::InvalidUtf8(e) => write!(f, "Data is not valid UTF-8: {e}"),
42            BinaryError::Zlib(s) => write!(f, "Zlib decompression error: {s}"),
43            BinaryError::Jid(e) => write!(f, "JID parsing error: {e}"),
44            BinaryError::UnexpectedEof => write!(f, "Unexpected end of binary data"),
45            BinaryError::EmptyData => write!(f, "Received empty data where payload was expected"),
46            BinaryError::LeftoverData(n) => write!(f, "Leftover data after decoding: {n} bytes"),
47            BinaryError::AttrList(list) => write!(f, "Multiple attribute parsing errors: {list:?}"),
48            BinaryError::MaxDepthExceeded => write!(f, "Node nesting exceeded the maximum depth"),
49        }
50    }
51}
52
53impl std::error::Error for BinaryError {
54    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
55        match self {
56            BinaryError::Io(e) => Some(e),
57            BinaryError::InvalidUtf8(e) => Some(e),
58            BinaryError::Jid(e) => Some(e),
59            _ => None,
60        }
61    }
62}
63
64impl From<std::io::Error> for BinaryError {
65    fn from(err: std::io::Error) -> Self {
66        BinaryError::Io(err)
67    }
68}
69impl From<std::str::Utf8Error> for BinaryError {
70    fn from(err: std::str::Utf8Error) -> Self {
71        BinaryError::InvalidUtf8(err)
72    }
73}
74impl From<JidError> for BinaryError {
75    fn from(err: JidError) -> Self {
76        BinaryError::Jid(err)
77    }
78}
79impl Clone for BinaryError {
80    fn clone(&self) -> Self {
81        match self {
82            BinaryError::Io(e) => BinaryError::Io(std::io::Error::new(e.kind(), e.to_string())),
83            BinaryError::InvalidToken(u) => BinaryError::InvalidToken(*u),
84            BinaryError::InvalidNode => BinaryError::InvalidNode,
85            BinaryError::NonStringKey => BinaryError::NonStringKey,
86            BinaryError::AttrParse(s) => BinaryError::AttrParse(s.clone()),
87            BinaryError::MissingAttr(s) => BinaryError::MissingAttr(s.clone()),
88            BinaryError::InvalidUtf8(e) => BinaryError::InvalidUtf8(*e),
89            BinaryError::Zlib(s) => BinaryError::Zlib(s.clone()),
90            BinaryError::Jid(e) => BinaryError::Jid(JidError::InvalidFormat(e.to_string())),
91            BinaryError::UnexpectedEof => BinaryError::UnexpectedEof,
92            BinaryError::EmptyData => BinaryError::EmptyData,
93            BinaryError::LeftoverData(n) => BinaryError::LeftoverData(*n),
94            BinaryError::AttrList(list) => BinaryError::AttrList(list.clone()),
95            BinaryError::MaxDepthExceeded => BinaryError::MaxDepthExceeded,
96            BinaryError::PlanMismatch => BinaryError::PlanMismatch,
97        }
98    }
99}
100
101pub type Result<T> = std::result::Result<T, BinaryError>;