Skip to main content

yosemite/
error.rs

1// Permission is hereby granted, free of charge, to any person obtaining a
2// copy of this software and associated documentation files (the "Software"),
3// to deal in the Software without restriction, including without limitation
4// the rights to use, copy, modify, merge, publish, distribute, sublicense,
5// and/or sell copies of the Software, and to permit persons to whom the
6// Software is furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19use std::fmt;
20
21/// `yosemite` error type.
22#[derive(Debug, thiserror::Error)]
23pub enum Error {
24    /// I/O error.
25    #[error("i/o error: `{0}`")]
26    IoError(#[from] std::io::Error),
27
28    /// Protocol error.
29    #[error("protocol error: `{0}`")]
30    Protocol(ProtocolError),
31
32    /// I2P error, received from the router.
33    #[error("i2p error: `{0}`")]
34    I2p(I2pError),
35
36    /// Response is malformed.
37    #[error("response is malformed")]
38    Malformed,
39}
40
41/// Protocol error.
42#[derive(Debug, PartialEq, Eq)]
43pub enum ProtocolError {
44    /// Invalid state for an operation.
45    InvalidState,
46
47    /// Router sent an invalid message.
48    InvalidMessage,
49
50    /// Router error.
51    Router(I2pError),
52}
53
54impl fmt::Display for ProtocolError {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            Self::InvalidState => write!(f, "invalid state"),
58            Self::InvalidMessage => write!(f, "invalid message from router"),
59            Self::Router(error) => write!(f, "router error: {error:?}"),
60        }
61    }
62}
63
64impl From<ProtocolError> for Error {
65    fn from(value: ProtocolError) -> Self {
66        Error::Protocol(value)
67    }
68}
69
70/// I2P error.
71#[derive(Debug, PartialEq, Eq)]
72pub enum I2pError {
73    /// The peer exists, but cannot be reached.
74    CantReachPeer,
75
76    /// The specified destination is already in use.
77    DuplicateDest,
78
79    /// A generic I2P error (e.g., I2CP disconnection).
80    I2pError(Option<String>),
81
82    /// The specified key is not valid (e.g., bad format).
83    InvalidKey,
84
85    /// Dupplicate ID.
86    DuplicateId,
87
88    /// The naming system can't resolve the given name.
89    KeyNotFound,
90
91    /// The peer cannot be found on the network.
92    PeerNotFound,
93
94    /// Timeout while waiting for an event (e.g. peer answer).
95    Timeout,
96}
97
98impl fmt::Display for I2pError {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        match self {
101            Self::CantReachPeer => write!(f, "the peer exists, but cannot be reached"),
102            Self::DuplicateDest => write!(f, "the specified destination is already in use"),
103            Self::I2pError(message) => write!(
104                f,
105                "generic i2p error (e.g., i2cp disconnection): {message:?}"
106            ),
107            Self::InvalidKey => write!(f, "the specified key is not valid (e.g., bad format)"),
108            Self::KeyNotFound => write!(f, "the naming system can't resolve the given name"),
109            Self::PeerNotFound => write!(f, "the peer cannot be found on the network"),
110            Self::Timeout => write!(f, "timeout while waiting for an event (e.g. peer answer)"),
111            Self::DuplicateId => write!(f, "duplicate id"),
112        }
113    }
114}
115
116impl TryFrom<(&str, Option<&str>)> for I2pError {
117    type Error = ();
118
119    fn try_from(value: (&str, Option<&str>)) -> Result<Self, Self::Error> {
120        match value.0 {
121            "CANT_REACH_PEER" => Ok(I2pError::CantReachPeer),
122            "DUPLICATE_DEST" => Ok(I2pError::DuplicateDest),
123            "I2P_ERROR" => Ok(I2pError::I2pError(
124                value.1.map(|message| message.to_string()),
125            )),
126            "INVALID_KEY" => Ok(I2pError::InvalidKey),
127            "KEY_NOT_FOUND" => Ok(I2pError::KeyNotFound),
128            "PEER_NOT_FOUND" => Ok(I2pError::PeerNotFound),
129            "TIMEOUT" => Ok(I2pError::Timeout),
130            "DUPLICATE_ID" => Ok(I2pError::DuplicateId),
131            _ => Err(()),
132        }
133    }
134}