interledger_packet/
error.rs1use std::fmt;
2use std::str;
3
4#[derive(Clone, Copy, Eq, PartialEq)]
5pub struct ErrorCode([u8; 3]);
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum ErrorClass {
9 Final,
10 Temporary,
11 Relative,
12 Unknown,
13}
14
15impl ErrorCode {
16 #[inline]
17 pub const fn new(bytes: [u8; 3]) -> Self {
18 ErrorCode(bytes)
19 }
20
21 #[inline]
22 pub fn class(self) -> ErrorClass {
23 match self.0[0] {
24 b'F' => ErrorClass::Final,
25 b'T' => ErrorClass::Temporary,
26 b'R' => ErrorClass::Relative,
27 _ => ErrorClass::Unknown,
28 }
29 }
30
31 pub const F00_BAD_REQUEST: Self = ErrorCode(*b"F00");
35 pub const F01_INVALID_PACKET: Self = ErrorCode(*b"F01");
36 pub const F02_UNREACHABLE: Self = ErrorCode(*b"F02");
37 pub const F03_INVALID_AMOUNT: Self = ErrorCode(*b"F03");
38 pub const F04_INSUFFICIENT_DESTINATION_AMOUNT: Self = ErrorCode(*b"F04");
39 pub const F05_WRONG_CONDITION: Self = ErrorCode(*b"F05");
40 pub const F06_UNEXPECTED_PAYMENT: Self = ErrorCode(*b"F06");
41 pub const F07_CANNOT_RECEIVE: Self = ErrorCode(*b"F07");
42 pub const F08_AMOUNT_TOO_LARGE: Self = ErrorCode(*b"F08");
43 pub const F09_INVALID_PEER_RESPONSE: Self = ErrorCode(*b"F09");
44 pub const F99_APPLICATION_ERROR: Self = ErrorCode(*b"F99");
45
46 pub const T00_INTERNAL_ERROR: Self = ErrorCode(*b"T00");
48 pub const T01_PEER_UNREACHABLE: Self = ErrorCode(*b"T01");
49 pub const T02_PEER_BUSY: Self = ErrorCode(*b"T02");
50 pub const T03_CONNECTOR_BUSY: Self = ErrorCode(*b"T03");
51 pub const T04_INSUFFICIENT_LIQUIDITY: Self = ErrorCode(*b"T04");
52 pub const T05_RATE_LIMITED: Self = ErrorCode(*b"T05");
53 pub const T99_APPLICATION_ERROR: Self = ErrorCode(*b"T99");
54
55 pub const R00_TRANSFER_TIMED_OUT: Self = ErrorCode(*b"R00");
57 pub const R01_INSUFFICIENT_SOURCE_AMOUNT: Self = ErrorCode(*b"R01");
58 pub const R02_INSUFFICIENT_TIMEOUT: Self = ErrorCode(*b"R02");
59 pub const R99_APPLICATION_ERROR: Self = ErrorCode(*b"R99");
60}
61
62impl From<ErrorCode> for [u8; 3] {
63 fn from(error_code: ErrorCode) -> Self {
64 error_code.0
65 }
66}
67
68impl fmt::Debug for ErrorCode {
69 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
70 formatter
71 .debug_tuple("ErrorCode")
72 .field(&str::from_utf8(&self.0[..]).map_err(|_| fmt::Error)?)
73 .finish()
74 }
75}
76
77impl fmt::Display for ErrorCode {
78 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
79 let as_str = str::from_utf8(&self.0[..]).map_err(|_| fmt::Error)?;
80 formatter.write_str(as_str)
81 }
82}
83
84#[cfg(test)]
85mod test_error_code {
86 use super::*;
87
88 #[test]
89 fn test_class() {
90 assert_eq!(ErrorCode::F00_BAD_REQUEST.class(), ErrorClass::Final);
91 assert_eq!(ErrorCode::T00_INTERNAL_ERROR.class(), ErrorClass::Temporary);
92 assert_eq!(
93 ErrorCode::R00_TRANSFER_TIMED_OUT.class(),
94 ErrorClass::Relative
95 );
96 assert_eq!(ErrorCode::new(*b"???").class(), ErrorClass::Unknown);
97 }
98
99 #[test]
100 fn test_debug_printing() {
101 assert_eq!(
102 format!("{:?}", ErrorCode::F00_BAD_REQUEST),
103 String::from("ErrorCode(\"F00\")")
104 );
105 }
106
107 #[test]
108 fn test_final_error_values() {
109 assert_eq!(
110 format!("{}", ErrorCode::F00_BAD_REQUEST),
111 String::from("F00")
112 );
113 assert_eq!(
114 format!("{}", ErrorCode::F01_INVALID_PACKET),
115 String::from("F01")
116 );
117 assert_eq!(
118 format!("{}", ErrorCode::F02_UNREACHABLE),
119 String::from("F02")
120 );
121 assert_eq!(
122 format!("{}", ErrorCode::F03_INVALID_AMOUNT),
123 String::from("F03")
124 );
125 assert_eq!(
126 format!("{}", ErrorCode::F04_INSUFFICIENT_DESTINATION_AMOUNT),
127 String::from("F04")
128 );
129 assert_eq!(
130 format!("{}", ErrorCode::F05_WRONG_CONDITION),
131 String::from("F05")
132 );
133 assert_eq!(
134 format!("{}", ErrorCode::F06_UNEXPECTED_PAYMENT),
135 String::from("F06")
136 );
137 assert_eq!(
138 format!("{}", ErrorCode::F07_CANNOT_RECEIVE),
139 String::from("F07")
140 );
141 assert_eq!(
142 format!("{}", ErrorCode::F08_AMOUNT_TOO_LARGE),
143 String::from("F08")
144 );
145 assert_eq!(
146 format!("{}", ErrorCode::F09_INVALID_PEER_RESPONSE),
147 String::from("F09")
148 );
149 assert_eq!(
150 format!("{}", ErrorCode::F99_APPLICATION_ERROR),
151 String::from("F99")
152 );
153 }
154
155 #[test]
156 fn test_temporary_error_values() {
157 assert_eq!(
158 format!("{}", ErrorCode::T00_INTERNAL_ERROR),
159 String::from("T00")
160 );
161 assert_eq!(
162 format!("{}", ErrorCode::T01_PEER_UNREACHABLE),
163 String::from("T01")
164 );
165 assert_eq!(format!("{}", ErrorCode::T02_PEER_BUSY), String::from("T02"));
166 assert_eq!(
167 format!("{}", ErrorCode::T03_CONNECTOR_BUSY),
168 String::from("T03")
169 );
170 assert_eq!(
171 format!("{}", ErrorCode::T04_INSUFFICIENT_LIQUIDITY),
172 String::from("T04")
173 );
174 assert_eq!(
175 format!("{}", ErrorCode::T05_RATE_LIMITED),
176 String::from("T05")
177 );
178 assert_eq!(
179 format!("{}", ErrorCode::T99_APPLICATION_ERROR),
180 String::from("T99")
181 );
182 }
183
184 #[test]
185 fn test_relative_error_values() {
186 assert_eq!(
187 format!("{}", ErrorCode::R00_TRANSFER_TIMED_OUT),
188 String::from("R00")
189 );
190 assert_eq!(
191 format!("{}", ErrorCode::R01_INSUFFICIENT_SOURCE_AMOUNT),
192 String::from("R01")
193 );
194 assert_eq!(
195 format!("{}", ErrorCode::R02_INSUFFICIENT_TIMEOUT),
196 String::from("R02")
197 );
198 assert_eq!(
199 format!("{}", ErrorCode::R99_APPLICATION_ERROR),
200 String::from("R99")
201 );
202 }
203}