1 | //! This module contains the current mess that is error handling. |
2 | |
3 | use crate::x11_utils::X11Error; |
4 | |
5 | pub use x11rb_protocol::errors::{ConnectError, IdsExhausted, ParseError}; |
6 | |
7 | /// An error occurred while dynamically loading libxcb. |
8 | #[cfg (feature = "dl-libxcb" )] |
9 | #[derive (Debug, Clone)] |
10 | pub enum LibxcbLoadError { |
11 | /// Could not open the library. The `OsString` is the library |
12 | /// file name and the string is the reason. |
13 | OpenLibError(std::ffi::OsString, String), |
14 | /// Could not get a symbol from the library. The byte vector is the |
15 | /// symbol name and the string is the reason. |
16 | GetSymbolError(Vec<u8>, String), |
17 | } |
18 | |
19 | #[cfg (feature = "dl-libxcb" )] |
20 | impl std::fmt::Display for LibxcbLoadError { |
21 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
22 | match self { |
23 | LibxcbLoadError::OpenLibError(lib_name: &OsString, e: &String) => { |
24 | write!(f, "failed to open library {:?}: {}" , lib_name, e) |
25 | } |
26 | LibxcbLoadError::GetSymbolError(symbol: &Vec, e: &String) => write!( |
27 | f, |
28 | "failed to get symbol \"{}\": {}" , |
29 | symbol |
30 | .iter() |
31 | .flat_map(|&c| std::ascii::escape_default(c)) |
32 | .map(char::from) |
33 | .collect::<String>(), |
34 | e, |
35 | ), |
36 | } |
37 | } |
38 | } |
39 | |
40 | #[cfg (feature = "dl-libxcb" )] |
41 | impl std::error::Error for LibxcbLoadError {} |
42 | |
43 | /// An error that occurred on an already established X11 connection |
44 | #[derive (Debug)] |
45 | #[non_exhaustive ] |
46 | pub enum ConnectionError { |
47 | /// An unknown error occurred. |
48 | /// |
49 | /// One situation were this error is used when libxcb indicates an error that does not match |
50 | /// any of the defined error conditions. Thus, libxcb is violating its own API (or new error |
51 | /// cases were defined, but are not yet handled by x11rb). |
52 | UnknownError, |
53 | |
54 | /// An X11 extension was not supported by the server. |
55 | /// |
56 | /// This corresponds to `XCB_CONN_CLOSED_EXT_NOTSUPPORTED`. |
57 | UnsupportedExtension, |
58 | |
59 | /// A request larger than the maximum request length was sent. |
60 | /// |
61 | /// This corresponds to `XCB_CONN_CLOSED_REQ_LEN_EXCEED`. |
62 | MaximumRequestLengthExceeded, |
63 | |
64 | /// File descriptor passing failed. |
65 | /// |
66 | /// This corresponds to `XCB_CONN_CLOSED_FDPASSING_FAILED`. |
67 | FdPassingFailed, |
68 | |
69 | /// Error while parsing some data, see `ParseError`. |
70 | ParseError(ParseError), |
71 | |
72 | /// Out of memory. |
73 | /// |
74 | /// This is `XCB_CONN_CLOSED_MEM_INSUFFICIENT`. |
75 | InsufficientMemory, |
76 | |
77 | /// An I/O error occurred on the connection. |
78 | IoError(std::io::Error), |
79 | } |
80 | |
81 | impl std::error::Error for ConnectionError {} |
82 | |
83 | impl std::fmt::Display for ConnectionError { |
84 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
85 | match self { |
86 | ConnectionError::UnknownError => write!(f, "Unknown connection error" ), |
87 | ConnectionError::UnsupportedExtension => write!(f, "Unsupported extension" ), |
88 | ConnectionError::InsufficientMemory => write!(f, "Insufficient memory" ), |
89 | ConnectionError::MaximumRequestLengthExceeded => { |
90 | write!(f, "Maximum request length exceeded" ) |
91 | } |
92 | ConnectionError::FdPassingFailed => write!(f, "FD passing failed" ), |
93 | ConnectionError::ParseError(err: &ParseError) => err.fmt(f), |
94 | ConnectionError::IoError(err: &Error) => err.fmt(f), |
95 | } |
96 | } |
97 | } |
98 | |
99 | impl From<ParseError> for ConnectionError { |
100 | fn from(err: ParseError) -> Self { |
101 | ConnectionError::ParseError(err) |
102 | } |
103 | } |
104 | |
105 | impl From<std::io::Error> for ConnectionError { |
106 | fn from(err: std::io::Error) -> Self { |
107 | ConnectionError::IoError(err) |
108 | } |
109 | } |
110 | |
111 | /// An error that occurred with some request. |
112 | #[derive (Debug)] |
113 | pub enum ReplyError { |
114 | /// Some error occurred on the X11 connection. |
115 | ConnectionError(ConnectionError), |
116 | /// The X11 server sent an error in response to a request. |
117 | X11Error(X11Error), |
118 | } |
119 | |
120 | impl std::error::Error for ReplyError {} |
121 | |
122 | impl std::fmt::Display for ReplyError { |
123 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
124 | match self { |
125 | ReplyError::ConnectionError(e: &ConnectionError) => write!(f, " {}" , e), |
126 | ReplyError::X11Error(e: &X11Error) => write!(f, "X11 error {:?}" , e), |
127 | } |
128 | } |
129 | } |
130 | |
131 | impl From<ParseError> for ReplyError { |
132 | fn from(err: ParseError) -> Self { |
133 | Self::from(ConnectionError::from(err)) |
134 | } |
135 | } |
136 | |
137 | impl From<std::io::Error> for ReplyError { |
138 | fn from(err: std::io::Error) -> Self { |
139 | ConnectionError::from(err).into() |
140 | } |
141 | } |
142 | |
143 | impl From<ConnectionError> for ReplyError { |
144 | fn from(err: ConnectionError) -> Self { |
145 | Self::ConnectionError(err) |
146 | } |
147 | } |
148 | |
149 | impl From<X11Error> for ReplyError { |
150 | fn from(err: X11Error) -> Self { |
151 | Self::X11Error(err) |
152 | } |
153 | } |
154 | |
155 | /// An error caused by some request or by the exhaustion of IDs. |
156 | #[derive (Debug)] |
157 | pub enum ReplyOrIdError { |
158 | /// All available IDs have been exhausted. |
159 | IdsExhausted, |
160 | /// Some error occurred on the X11 connection. |
161 | ConnectionError(ConnectionError), |
162 | /// The X11 server sent an error in response to a request. |
163 | X11Error(X11Error), |
164 | } |
165 | |
166 | impl std::fmt::Display for ReplyOrIdError { |
167 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
168 | match self { |
169 | ReplyOrIdError::IdsExhausted => f.write_str(data:"X11 IDs have been exhausted" ), |
170 | ReplyOrIdError::ConnectionError(e: &ConnectionError) => write!(f, " {}" , e), |
171 | ReplyOrIdError::X11Error(e: &X11Error) => write!(f, "X11 error {:?}" , e), |
172 | } |
173 | } |
174 | } |
175 | |
176 | impl std::error::Error for ReplyOrIdError {} |
177 | |
178 | impl From<ParseError> for ReplyOrIdError { |
179 | fn from(err: ParseError) -> Self { |
180 | ConnectionError::from(err).into() |
181 | } |
182 | } |
183 | |
184 | impl From<ConnectionError> for ReplyOrIdError { |
185 | fn from(err: ConnectionError) -> Self { |
186 | ReplyOrIdError::ConnectionError(err) |
187 | } |
188 | } |
189 | |
190 | impl From<X11Error> for ReplyOrIdError { |
191 | fn from(err: X11Error) -> Self { |
192 | ReplyOrIdError::X11Error(err) |
193 | } |
194 | } |
195 | |
196 | impl From<ReplyError> for ReplyOrIdError { |
197 | fn from(err: ReplyError) -> Self { |
198 | match err { |
199 | ReplyError::ConnectionError(err: ConnectionError) => ReplyOrIdError::ConnectionError(err), |
200 | ReplyError::X11Error(err: X11Error) => ReplyOrIdError::X11Error(err), |
201 | } |
202 | } |
203 | } |
204 | |
205 | impl From<IdsExhausted> for ReplyOrIdError { |
206 | fn from(_: IdsExhausted) -> Self { |
207 | ReplyOrIdError::IdsExhausted |
208 | } |
209 | } |
210 | |