1use std::fmt;
20
21#[derive(Debug, thiserror::Error)]
23pub enum Error {
24 #[error("i/o error: `{0}`")]
26 IoError(#[from] std::io::Error),
27
28 #[error("protocol error: `{0}`")]
30 Protocol(ProtocolError),
31
32 #[error("i2p error: `{0}`")]
34 I2p(I2pError),
35
36 #[error("response is malformed")]
38 Malformed,
39}
40
41#[derive(Debug, PartialEq, Eq)]
43pub enum ProtocolError {
44 InvalidState,
46
47 InvalidMessage,
49
50 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#[derive(Debug, PartialEq, Eq)]
72pub enum I2pError {
73 CantReachPeer,
75
76 DuplicateDest,
78
79 I2pError(Option<String>),
81
82 InvalidKey,
84
85 DuplicateId,
87
88 KeyNotFound,
90
91 PeerNotFound,
93
94 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}