1use std::{io, path::PathBuf};
18
19pub type ServerResult<T> = Result<T, ServerError>;
20
21#[derive(Debug, thiserror::Error)]
22#[non_exhaustive]
23pub enum ServerError {
24 #[error("TLS material load failed ({kind}) at `{path}`: {reason}")]
26 TlsLoad {
27 kind: TlsKind,
28 path: PathBuf,
29 reason: String,
30 },
31
32 #[error("invalid listener address `{addr}`: {reason}")]
34 ListenerAddress { addr: String, reason: String },
35
36 #[error("middleware script not found: `{path}`")]
38 MiddlewareMissing { path: PathBuf },
39
40 #[error("failed to compile middleware `{path}`: {reason}")]
42 MiddlewareCompile { path: PathBuf, reason: String },
43
44 #[error("i/o error: {0}")]
46 Io(#[from] io::Error),
47
48 #[error(transparent)]
51 Config(#[from] apimock_config::ConfigError),
52}
53
54#[non_exhaustive]
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum ServerErrorKind {
58 TlsLoad,
59 ListenerAddress,
60 MiddlewareMissing,
61 MiddlewareCompile,
62 Io,
63 Config,
64}
65
66impl ServerError {
67 pub fn kind(&self) -> ServerErrorKind {
68 match self {
69 ServerError::TlsLoad { .. } => ServerErrorKind::TlsLoad,
70 ServerError::ListenerAddress { .. } => ServerErrorKind::ListenerAddress,
71 ServerError::MiddlewareMissing { .. } => ServerErrorKind::MiddlewareMissing,
72 ServerError::MiddlewareCompile { .. } => ServerErrorKind::MiddlewareCompile,
73 ServerError::Io(_) => ServerErrorKind::Io,
74 ServerError::Config(_) => ServerErrorKind::Config,
75 }
76 }
77}
78
79#[derive(Debug, Clone, Copy)]
80#[non_exhaustive]
81pub enum TlsKind {
82 Certificate,
83 PrivateKey,
84}
85
86impl std::fmt::Display for TlsKind {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 match self {
89 TlsKind::Certificate => f.write_str("certificate"),
90 TlsKind::PrivateKey => f.write_str("private key"),
91 }
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
101 fn server_error_kind_matches_every_variant() {
102 assert_eq!(
103 ServerError::TlsLoad {
104 kind: TlsKind::Certificate,
105 path: PathBuf::from("x"),
106 reason: "x".to_owned(),
107 }
108 .kind(),
109 ServerErrorKind::TlsLoad
110 );
111 assert_eq!(
112 ServerError::ListenerAddress {
113 addr: "x".to_owned(),
114 reason: "x".to_owned(),
115 }
116 .kind(),
117 ServerErrorKind::ListenerAddress
118 );
119 assert_eq!(
120 ServerError::MiddlewareMissing {
121 path: PathBuf::from("x"),
122 }
123 .kind(),
124 ServerErrorKind::MiddlewareMissing
125 );
126 assert_eq!(
127 ServerError::MiddlewareCompile {
128 path: PathBuf::from("x"),
129 reason: "x".to_owned(),
130 }
131 .kind(),
132 ServerErrorKind::MiddlewareCompile
133 );
134 assert_eq!(
135 ServerError::Io(io::Error::other("x")).kind(),
136 ServerErrorKind::Io
137 );
138 assert_eq!(
139 ServerError::Config(apimock_config::ConfigError::Validation {
140 reason: "x".to_owned()
141 })
142 .kind(),
143 ServerErrorKind::Config
144 );
145 }
146}