1use wasm_bindgen::prelude::*;
2
3#[derive(Clone, Debug, thiserror::Error)]
5pub enum Error {
6 #[error("webtransport session closed: code={code} reason={reason}")]
7 SessionClosed {
9 code: u32,
11 reason: String,
13 },
14
15 #[error("webtransport session error: {0:?}")]
16 Session(web_sys::WebTransportError),
17
18 #[error("webtransport stream error: {0:?}")]
19 Stream(web_sys::WebTransportError),
20
21 #[error("web streams error: {0:?}")]
22 Streams(#[from] web_streams::Error),
23
24 #[error("unknown error: {0:?}")]
25 Unknown(JsValue),
26}
27
28impl Error {
29 pub fn code(&self) -> Option<u8> {
31 match self {
32 Error::SessionClosed { .. } => None,
33 Error::Session(e) | Error::Stream(e) => e.stream_error_code(),
34 _ => None,
35 }
36 }
37}
38
39impl From<JsValue> for Error {
40 fn from(v: JsValue) -> Self {
42 if let Some(e) = v.dyn_ref::<web_sys::WebTransportError>().cloned() {
43 match e.source() {
44 web_sys::WebTransportErrorSource::Stream => Error::Stream(e),
45 web_sys::WebTransportErrorSource::Session => Error::Session(e),
46 _ => Error::Unknown(v),
47 }
48 } else {
49 Error::Unknown(v)
50 }
51 }
52}
53
54#[cfg(target_family = "wasm")]
55impl webtrans_trait::Error for Error {
56 fn session_error(&self) -> Option<(u32, String)> {
57 match self {
58 Error::SessionClosed { code, reason } => Some((*code, reason.clone())),
59 Error::Session(err) => err
60 .stream_error_code()
61 .map(|code| (u32::from(code), format!("{err:?}"))),
62 _ => None,
63 }
64 }
65
66 fn stream_error(&self) -> Option<u32> {
67 match self {
68 Error::Stream(err) => err.stream_error_code().map(u32::from),
69 _ => None,
70 }
71 }
72}