1use crate::kv::KvError;
2use wasm_bindgen::{JsCast, JsValue};
3
4#[derive(Debug)]
6#[non_exhaustive]
7pub enum Error {
8 BadEncoding,
9 BodyUsed,
10 Json((String, u16)),
11 JsError(String),
12 #[cfg(feature = "http")]
13 Http(http::Error),
14 Infallible,
15 Internal(JsValue),
16 Io(std::io::Error),
17 BindingError(String),
18 RouteInsertError(matchit::InsertError),
19 RouteNoDataError,
20 RustError(String),
21 SerdeJsonError(serde_json::Error),
22 SerdeWasmBindgenError(serde_wasm_bindgen::Error),
23 #[cfg(feature = "http")]
24 StatusCode(http::status::InvalidStatusCode),
25 #[cfg(feature = "d1")]
26 D1(crate::d1::D1Error),
27 Utf8Error(std::str::Utf8Error),
28 #[cfg(feature = "timezone")]
29 TimezoneError,
30 KvError(KvError),
31}
32
33unsafe impl Sync for Error {}
34unsafe impl Send for Error {}
35
36#[cfg(feature = "http")]
37impl From<http::Error> for Error {
38 fn from(value: http::Error) -> Self {
39 Self::Http(value)
40 }
41}
42
43#[cfg(feature = "http")]
44impl From<http::status::InvalidStatusCode> for Error {
45 fn from(value: http::status::InvalidStatusCode) -> Self {
46 Self::StatusCode(value)
47 }
48}
49
50#[cfg(feature = "http")]
51impl From<http::header::InvalidHeaderName> for Error {
52 fn from(value: http::header::InvalidHeaderName) -> Self {
53 Self::RustError(format!("Invalid header name: {value:?}"))
54 }
55}
56
57#[cfg(feature = "http")]
58impl From<http::header::InvalidHeaderValue> for Error {
59 fn from(value: http::header::InvalidHeaderValue) -> Self {
60 Self::RustError(format!("Invalid header value: {value:?}"))
61 }
62}
63
64#[cfg(feature = "timezone")]
65impl From<chrono_tz::ParseError> for Error {
66 fn from(_value: chrono_tz::ParseError) -> Self {
67 Self::RustError("Invalid timezone".to_string())
68 }
69}
70
71impl From<std::str::Utf8Error> for Error {
72 fn from(value: std::str::Utf8Error) -> Self {
73 Self::Utf8Error(value)
74 }
75}
76
77impl From<core::convert::Infallible> for Error {
78 fn from(_value: core::convert::Infallible) -> Self {
79 Error::Infallible
80 }
81}
82
83impl From<KvError> for Error {
84 fn from(e: KvError) -> Self {
85 Self::KvError(e)
86 }
87}
88
89impl From<url::ParseError> for Error {
90 fn from(e: url::ParseError) -> Self {
91 Self::RustError(e.to_string())
92 }
93}
94
95impl From<serde_urlencoded::de::Error> for Error {
96 fn from(e: serde_urlencoded::de::Error) -> Self {
97 Self::RustError(e.to_string())
98 }
99}
100
101impl From<serde_wasm_bindgen::Error> for Error {
102 fn from(e: serde_wasm_bindgen::Error) -> Self {
103 let val: JsValue = e.into();
104 val.into()
105 }
106}
107
108#[cfg(feature = "d1")]
109impl From<crate::d1::D1Error> for Error {
110 fn from(e: crate::d1::D1Error) -> Self {
111 Self::D1(e)
112 }
113}
114
115impl std::fmt::Display for Error {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 match self {
118 Error::BadEncoding => write!(f, "content-type mismatch"),
119 Error::BodyUsed => write!(f, "body has already been read"),
120 Error::Json((msg, status)) => write!(f, "{msg} (status: {status})"),
121 Error::JsError(s) | Error::RustError(s) => {
122 write!(f, "{s}")
123 }
124 #[cfg(feature = "http")]
125 Error::Http(e) => write!(f, "http::Error: {e}"),
126 Error::Infallible => write!(f, "infallible"),
127 Error::Internal(_) => write!(f, "unrecognized JavaScript object"),
128 Error::Io(e) => write!(f, "IO Error: {e}"),
129 Error::BindingError(name) => write!(f, "no binding found for `{name}`"),
130 Error::RouteInsertError(e) => write!(f, "failed to insert route: {e}"),
131 Error::RouteNoDataError => write!(f, "route has no corresponding shared data"),
132 Error::SerdeJsonError(e) => write!(f, "Serde Error: {e}"),
133 Error::SerdeWasmBindgenError(e) => write!(f, "Serde Error: {e}"),
134 #[cfg(feature = "http")]
135 Error::StatusCode(e) => write!(f, "{e}"),
136 #[cfg(feature = "d1")]
137 Error::D1(e) => write!(f, "D1: {e:#?}"),
138 Error::Utf8Error(e) => write!(f, "{e}"),
139 #[cfg(feature = "timezone")]
140 Error::TimezoneError => write!(f, "Timezone Error"),
141 Error::KvError(KvError::JavaScript(s)) => write!(f, "js error: {s:?}"),
142 Error::KvError(KvError::Serialization(s)) => {
143 write!(f, "unable to serialize/deserialize: {s}")
144 }
145 Error::KvError(KvError::InvalidKvStore(s)) => write!(f, "invalid kv store: {s}"),
146 }
147 }
148}
149
150impl std::error::Error for Error {}
151
152impl From<JsValue> for Error {
154 fn from(v: JsValue) -> Self {
155 match v.as_string().or_else(|| {
156 v.dyn_ref::<js_sys::Error>().map(|e| {
157 format!(
158 "Error: {} - Cause: {}",
159 e.to_string(),
160 e.cause()
161 .as_string()
162 .or_else(|| { Some(e.to_string().into()) })
163 .unwrap_or(String::from("N/A"))
164 )
165 })
166 }) {
167 Some(s) => Self::JsError(s),
168 None => Self::Internal(v),
169 }
170 }
171}
172
173impl From<std::io::Error> for Error {
174 fn from(error: std::io::Error) -> Self {
175 Self::Io(error)
176 }
177}
178
179impl From<Error> for JsValue {
180 fn from(e: Error) -> Self {
181 JsValue::from_str(&e.to_string())
182 }
183}
184
185impl From<&str> for Error {
186 fn from(a: &str) -> Self {
187 Error::RustError(a.to_string())
188 }
189}
190
191impl From<String> for Error {
192 fn from(a: String) -> Self {
193 Error::RustError(a)
194 }
195}
196
197impl From<matchit::InsertError> for Error {
198 fn from(e: matchit::InsertError) -> Self {
199 Error::RouteInsertError(e)
200 }
201}
202
203impl From<serde_json::Error> for Error {
204 fn from(e: serde_json::Error) -> Self {
205 Error::SerdeJsonError(e)
206 }
207}