chia_query/peer/light_client/
error.rs1use dig_chainsource_interface::ChainSourceError;
15use thiserror::Error;
16
17#[derive(Debug, Error, Clone, PartialEq, Eq)]
19pub enum LightClientError {
20 #[error("chia peer transport error: {0}")]
23 Transport(String),
24
25 #[error("chia peer rejected the request: {0}")]
28 Rejected(String),
29
30 #[error("malformed chia peer response: {0}")]
33 Malformed(String),
34
35 #[error("chia peer request timed out")]
38 Timeout,
39
40 #[error("chia peer discovery failed")]
42 PeerDiscoveryFailed,
43
44 #[error("chia light client is not connected")]
46 NotConnected,
47}
48
49impl LightClientError {
50 fn looks_like_timeout(message: &str) -> bool {
53 let lower = message.to_ascii_lowercase();
54 lower.contains("timed out") || lower.contains("timeout")
55 }
56}
57
58impl From<LightClientError> for ChainSourceError {
59 fn from(error: LightClientError) -> Self {
62 match error {
63 LightClientError::Timeout => ChainSourceError::Timeout,
64 LightClientError::Transport(msg) if LightClientError::looks_like_timeout(&msg) => {
65 ChainSourceError::Timeout
66 }
67 LightClientError::Transport(msg) => ChainSourceError::Transport(msg),
68 LightClientError::Rejected(msg) => ChainSourceError::Transport(msg),
69 LightClientError::Malformed(msg) => ChainSourceError::Malformed(msg),
70 LightClientError::PeerDiscoveryFailed => {
71 ChainSourceError::Transport("peer discovery failed".to_string())
72 }
73 LightClientError::NotConnected => {
74 ChainSourceError::Transport("light client is not connected".to_string())
75 }
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn timeout_variant_maps_to_timeout() {
86 assert_eq!(
87 ChainSourceError::from(LightClientError::Timeout),
88 ChainSourceError::Timeout
89 );
90 }
91
92 #[test]
93 fn timed_out_transport_message_maps_to_timeout() {
94 let mapped =
95 ChainSourceError::from(LightClientError::Transport("request timed out".into()));
96 assert_eq!(mapped, ChainSourceError::Timeout);
97 }
98
99 #[test]
100 fn plain_transport_maps_to_transport_never_absence() {
101 let mapped = ChainSourceError::from(LightClientError::Transport("socket reset".into()));
102 assert_eq!(mapped, ChainSourceError::Transport("socket reset".into()));
103 }
104
105 #[test]
106 fn rejected_maps_to_transport() {
107 let mapped = ChainSourceError::from(LightClientError::Rejected("reorg".into()));
108 assert!(matches!(mapped, ChainSourceError::Transport(_)));
109 }
110
111 #[test]
112 fn malformed_maps_to_malformed() {
113 let mapped = ChainSourceError::from(LightClientError::Malformed("bad bytes".into()));
114 assert!(matches!(mapped, ChainSourceError::Malformed(_)));
115 }
116
117 #[test]
118 fn not_connected_and_discovery_map_to_transport() {
119 assert!(matches!(
120 ChainSourceError::from(LightClientError::NotConnected),
121 ChainSourceError::Transport(_)
122 ));
123 assert!(matches!(
124 ChainSourceError::from(LightClientError::PeerDiscoveryFailed),
125 ChainSourceError::Transport(_)
126 ));
127 }
128}