1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// SPDX-License-Identifier: AGPL-3.0-or-later
use serde::{de, ser};
use std::{
    fmt::{self, Display},
    io,
};

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    Message(String),
    Io(std::io::Error),
    Eof,
    UnknownLength,
    SequenceTooLong(usize),
    TooManyVariants(u32),
    TypeConversion,
    NotSupported(&'static str),
    InvalidUtf8,
    Format(std::fmt::Error),
    Custom(Box<dyn std::error::Error + Send + Sync>),
}

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

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Message(message) => formatter.write_str(message),
            Error::Io(io_error) => io_error.fmt(formatter),
            Error::Eof => formatter.write_str("unexpected end of input"),
            Error::UnknownLength => formatter.write_str("sequence had an unknown length"),
            Error::SequenceTooLong(length) => {
                formatter.write_fmt(format_args!("sequence was longer than 2**32 - 1: {length}",))
            }
            Error::TooManyVariants(length) => formatter.write_fmt(format_args!(
                "too many variants to be serialized, the limit is 2**16: {length}",
            )),
            Error::TypeConversion => formatter.write_str("type conversion failed"),
            Error::NotSupported(message) => {
                formatter.write_fmt(format_args!("Operation is not supported: {message}"))
            }
            Error::InvalidUtf8 => formatter.write_str("Invalid UTF-8 character encountered."),
            Error::Format(fmt_error) => fmt_error.fmt(formatter),
            Error::Custom(err) => err.fmt(formatter),
        }
    }
}

impl Error {
    pub fn custom<E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static>(err: E) -> Error {
        Error::Custom(err.into())
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(message: T) -> Self {
        Error::Message(message.to_string())
    }
}

impl de::Error for Error {
    fn custom<T: Display>(message: T) -> Self {
        Error::Message(message.to_string())
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        io::Error::new(io::ErrorKind::Other, err)
    }
}

pub trait MapError<T> {
    /// Returns self if no error occurred, otherwise converts the error to a serde_blocktree error.
    fn map_error(self) -> Result<T>;
}

impl<T> MapError<T> for std::io::Result<T> {
    fn map_error(self) -> Result<T> {
        self.map_err(Error::Io)
    }
}