1
use std::fmt::{Debug, Display};
2
use std::io;
3
use std::str::Utf8Error;
4
use std::string::FromUtf8Error;
5

            
6
use serde::{de, ser};
7

            
8
use crate::format::{Kind, UnknownSpecial};
9

            
10
/// All errors that Pot may return.
11
#[derive(Debug)]
12
#[non_exhaustive]
13
pub enum Error {
14
    /// Payload is not a Pot payload.
15
    NotAPot,
16
    /// Data was written with an incompatible version.
17
    IncompatibleVersion,
18
    /// A generic error occurred.
19
    Message(String),
20
    /// Extra data appeared at the end of the input.
21
    TrailingBytes,
22
    /// Expected more data but encountered the end of the input.
23
    Eof,
24
    /// A numerical value could not be handled without losing precision or truncation.
25
    ImpreciseCastWouldLoseData,
26
    /// An IO error occurred.
27
    Io(io::Error),
28
    /// A sequence of unknown size cannot be serialized.
29
    SequenceSizeMustBeKnown,
30
    /// String data contained invalid UTF-8 characters.
31
    InvalidUtf8(String),
32
    /// An unknown kind was encountered. Generally a sign that something else has been parsed incorrectly.
33
    InvalidKind(u8),
34
    /// Encountered an unexpected atom kind.
35
    UnexpectedKind(Kind, Kind),
36
    /// A requested symbol id was not found.
37
    UnknownSymbol(u64),
38
    /// An unsupported byte count for a numeric type was encountered.
39
    UnsupportedByteCount(Kind, usize),
40
    /// An atom header was incorrectly formatted.
41
    InvalidAtomHeader,
42
    /// The amount of data read exceeds the configured maximum number of bytes.
43
    TooManyBytesRead,
44
    /// An unknown [`Special`](crate::format::Special) was encountered.
45
    UnknownSpecial(UnknownSpecial),
46
}
47

            
48
impl Display for Error {
49
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50
        match self {
51
            Error::NotAPot => f.write_str("not a pot: invalid header"),
52
            Error::IncompatibleVersion => f.write_str("incompatible version"),
53
            Error::Message(message) => f.write_str(message),
54
            Error::TrailingBytes => f.write_str("extra data at end of input"),
55
            Error::Eof => f.write_str("unexpected end of file"),
56
            Error::ImpreciseCastWouldLoseData => f.write_str("numerical data cannot fit"),
57
            Error::Io(io) => write!(f, "io error: {io}"),
58
            Error::SequenceSizeMustBeKnown => {
59
                f.write_str("serializing sequences of unknown size is unsupported")
60
            }
61
            Error::InvalidUtf8(err) => write!(f, "invalid utf8: {err}"),
62
            Error::InvalidKind(kind) => write!(f, "invalid kind: {kind}"),
63
            Error::UnexpectedKind(encountered, expected) => write!(
64
                f,
65
                "encountered atom kind {encountered:?}, expected {expected:?}"
66
            ),
67
            Error::UnknownSymbol(sym) => write!(f, "unknown symbol {sym}"),
68
            Error::InvalidAtomHeader => f.write_str("an atom header was incorrectly formatted"),
69
            Error::TooManyBytesRead => {
70
                f.write_str("the deserialized value is larger than the allowed allocation limit")
71
            }
72
            Error::UnsupportedByteCount(kind, count) => {
73
                write!(f, "unexpected {kind:?} byte count ({count})")
74
            }
75
            Error::UnknownSpecial(err) => Display::fmt(err, f),
76
        }
77
    }
78
}
79

            
80
impl std::error::Error for Error {}
81

            
82
impl From<io::Error> for Error {
83
    fn from(err: io::Error) -> Self {
84
        Self::Io(err)
85
    }
86
}
87

            
88
impl ser::Error for Error {
89
    fn custom<T: Display>(msg: T) -> Self {
90
        Self::Message(msg.to_string())
91
    }
92
}
93

            
94
impl de::Error for Error {
95
1
    fn custom<T: Display>(msg: T) -> Self {
96
1
        Self::Message(msg.to_string())
97
1
    }
98
}
99

            
100
impl From<Utf8Error> for Error {
101
1
    fn from(err: Utf8Error) -> Self {
102
1
        Self::InvalidUtf8(err.to_string())
103
1
    }
104
}
105

            
106
impl From<FromUtf8Error> for Error {
107
    fn from(err: FromUtf8Error) -> Self {
108
        Self::InvalidUtf8(err.to_string())
109
    }
110
}
111

            
112
impl From<UnknownSpecial> for Error {
113
    fn from(err: UnknownSpecial) -> Self {
114
        Self::UnknownSpecial(err)
115
    }
116
}