1use thiserror::Error;
4
5#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum Error {
9 #[error("failed to bind {addr}: {source}")]
11 Bind {
12 addr: String,
14 #[source]
16 source: std::io::Error,
17 },
18
19 #[error("server I/O: {0}")]
21 Io(#[from] std::io::Error),
22
23 #[error("server configuration: {0}")]
25 Configuration(String),
26
27 #[error("graceful shutdown timed out after {0:?}")]
30 ShutdownTimeout(std::time::Duration),
31}
32
33pub type Result<T> = std::result::Result<T, Error>;
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn bind_error_renders_addr_and_source() {
42 let e = Error::Bind {
43 addr: "0.0.0.0:8080".into(),
44 source: std::io::Error::other("address in use"),
45 };
46 let s = e.to_string();
47 assert!(s.contains("0.0.0.0:8080"));
48 assert!(s.contains("address in use"));
49 }
50
51 #[test]
52 fn io_error_renders() {
53 let io = std::io::Error::other("disk full");
54 let e: Error = io.into();
55 assert!(e.to_string().contains("disk full"));
56 }
57
58 #[test]
59 fn configuration_error_renders() {
60 let e = Error::Configuration("invalid port".into());
61 assert_eq!(e.to_string(), "server configuration: invalid port");
62 }
63}