1use js_sys::{Object, Reflect, Uint8Array};
2use url::Url;
3use wasm_bindgen_futures::JsFuture;
4use web_sys::{WebTransport, WebTransportOptions};
5
6use crate::{Error, Session};
7
8pub use web_sys::WebTransportCongestionControl as CongestionControl;
9
10#[derive(Debug, Default)]
12pub struct ClientBuilder {
13 options: WebTransportOptions,
14}
15
16impl ClientBuilder {
17 pub fn new() -> Self {
18 Self::default()
19 }
20
21 pub fn with_pooling(self, val: bool) -> Self {
24 self.options.set_allow_pooling(val);
25 self
26 }
27
28 pub fn with_unreliable(self, val: bool) -> Self {
30 self.options.set_require_unreliable(val);
31 self
32 }
33
34 pub fn with_congestion_control(self, control: CongestionControl) -> Self {
36 self.options.set_congestion_control(control);
37 self
38 }
39
40 pub fn with_server_certificate_hashes(self, hashes: Vec<Vec<u8>>) -> Client {
42 let hashes = hashes
44 .into_iter()
45 .map(|hash| {
46 let hash = Uint8Array::from(&hash[..]);
47 let obj = Object::new();
48 Reflect::set(&obj, &"algorithm".into(), &"sha-256".into()).unwrap();
49 Reflect::set(&obj, &"value".into(), &hash.into()).unwrap();
50 obj
51 })
52 .collect::<js_sys::Array>();
53
54 self.options.set_server_certificate_hashes(&hashes);
55 Client {
56 options: self.options,
57 }
58 }
59
60 pub fn with_system_roots(self) -> Client {
61 Client {
62 options: self.options,
63 }
64 }
65}
66
67#[derive(Clone, Debug, Default)]
71pub struct Client {
72 options: WebTransportOptions,
73}
74
75impl Client {
76 pub async fn connect(&self, url: Url) -> Result<Session, Error> {
78 let inner = WebTransport::new_with_options(url.as_str(), &self.options)?;
79 JsFuture::from(inner.ready()).await?;
80
81 Ok(Session::new(inner, url))
82 }
83}