Skip to main content

webtrans_wasm/
error.rs

1use wasm_bindgen::prelude::*;
2
3/// A WebTransport error classified by source.
4#[derive(Clone, Debug, thiserror::Error)]
5pub enum Error {
6    #[error("webtransport session closed: code={code} reason={reason}")]
7    /// Session closed cleanly with application-provided details.
8    SessionClosed {
9        /// Application close code.
10        code: u32,
11        /// Application close reason.
12        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    /// Return the error code used when closing the stream or session.
30    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    /// Convert a generic `JsValue` into a `WebTransportError` when possible, otherwise `Error::Unknown`.
41    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}