sphinx_packet/
error.rs

1// Copyright 2020 Nym Technologies SA
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::Formatter;
16use std::{
17    error::Error as StdError,
18    fmt::{self, Display},
19};
20
21/// A `Result` alias where the `Err` case is `Sphinx::Error`.
22pub type Result<T> = std::result::Result<T, Error>;
23
24// type alias for local easy of use
25// there's nothing fancy about it, we just ensure it implements std::error::Error and
26// that it can be safely sent to another thread (`Send`) and shared between threads (`Sync`), i.e.
27// &T is `Send`. In most cases those are usually true by default.
28type StdThreadError = dyn StdError + Send + Sync;
29
30/// Possible Sphinx errors, very strongly based on std::io::Error implementation
31pub struct Error {
32    repr: Repr,
33}
34
35// it has a StdError as long as it has Display and Debug
36impl StdError for Error {}
37
38#[derive(Debug)]
39enum Repr {
40    Simple(ErrorKind),
41    Custom(Box<Custom>),
42}
43
44#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
45pub enum ErrorKind {
46    /// Error originating from packet related functionality.
47    InvalidPacket,
48
49    /// Error originating from general header related functionality.
50    InvalidHeader,
51
52    /// Error originating from payload related functionality.
53    InvalidPayload,
54
55    /// Error originating from SURB related functionality.
56    InvalidSURB,
57
58    /// Error originating routing information related functionality.
59    InvalidRouting,
60}
61
62impl ErrorKind {
63    pub(crate) fn as_str(&self) -> &'static str {
64        match &self {
65            ErrorKind::InvalidPacket => "packet processing failure",
66            ErrorKind::InvalidHeader => "header processing failure",
67            ErrorKind::InvalidPayload => "payload processing failure",
68            ErrorKind::InvalidSURB => "SURB processing failure",
69            ErrorKind::InvalidRouting => "routing information processing failure",
70        }
71    }
72}
73
74impl From<ErrorKind> for Error {
75    fn from(kind: ErrorKind) -> Self {
76        Error {
77            repr: Repr::Simple(kind),
78        }
79    }
80}
81
82impl Display for Error {
83    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), fmt::Error> {
84        match self.repr {
85            Repr::Simple(kind) => write!(f, "{}", kind.as_str()),
86            Repr::Custom(ref c) => write!(f, "{}: {}", c.kind.as_str(), c.error),
87        }
88    }
89}
90
91impl fmt::Debug for Error {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        fmt::Debug::fmt(&self.repr, f)
94    }
95}
96
97#[derive(Debug)]
98struct Custom {
99    kind: ErrorKind,
100    error: Box<StdThreadError>,
101}
102
103impl Error {
104    pub fn new<E>(kind: ErrorKind, error: E) -> Self
105    where
106        E: Into<Box<StdThreadError>>,
107    {
108        Error {
109            repr: Repr::Custom(Box::new(Custom {
110                kind,
111                error: error.into(),
112            })),
113        }
114    }
115
116    pub fn kind(&self) -> ErrorKind {
117        match self.repr {
118            Repr::Custom(ref c) => c.kind,
119            Repr::Simple(kind) => kind,
120        }
121    }
122}