webtorrent_rs_wrapper/
lib.rs

1use js_sys::{Object, Promise};
2use wasm_bindgen::prelude::*;
3use wasm_bindgen::JsValue;
4use wasm_bindgen_futures::JsFuture;
5
6// JS interop for the WebTorrent client
7#[wasm_bindgen(module = "/js/shim.js")]
8extern "C" {
9    #[wasm_bindgen(js_name = WebTorrentClient)]
10    pub type JsWebTorrentClient;
11
12    #[wasm_bindgen(js_name = createClient)]
13    pub fn create_client() -> JsWebTorrentClient;
14
15    #[wasm_bindgen(method, js_name = seed)]
16    pub fn seed(
17        this: &JsWebTorrentClient,
18        input: &JsValue,
19        opts: &JsValue,
20        onseed: &JsValue,
21    ) -> JsValue;
22
23    #[wasm_bindgen(method, js_name = add)]
24    pub fn add(
25        this: &JsWebTorrentClient,
26        torrent_id: &JsValue,
27        opts: &JsValue,
28        ontorrent: &JsValue,
29    ) -> JsValue;
30
31    #[wasm_bindgen(method, js_name = createServer)]
32    pub fn create_server(this: &JsWebTorrentClient, options: &JsValue, force: bool) -> JsValue;
33
34    #[wasm_bindgen(method, js_name = getTorrent)]
35    pub fn get_torrent(this: &JsWebTorrentClient, torrent_id: &JsValue) -> Promise;
36
37    #[wasm_bindgen(method, js_name = remove)]
38    pub fn remove(this: &JsWebTorrentClient, torrent_id: &JsValue, opts: &JsValue, cb: &JsValue);
39
40    #[wasm_bindgen(method, js_name = throttleDownload)]
41    pub fn throttle_download(this: &JsWebTorrentClient, rate: f64);
42
43    #[wasm_bindgen(method, js_name = throttleUpload)]
44    pub fn throttle_upload(this: &JsWebTorrentClient, rate: f64);
45
46    #[wasm_bindgen(method, js_name = destroy)]
47    pub fn destroy(this: &JsWebTorrentClient, cb: &JsValue);
48
49    #[wasm_bindgen(method, js_name = isReadable)]
50    pub fn is_readable(this: &JsWebTorrentClient, obj: &JsValue) -> bool;
51
52    #[wasm_bindgen(method, js_name = isFileList)]
53    pub fn is_file_list(this: &JsWebTorrentClient, obj: &JsValue) -> bool;
54}
55
56// Wrapper for the WebTorrent client
57#[wasm_bindgen]
58pub struct WebTorrentClient {
59    inner: JsWebTorrentClient,
60}
61
62#[wasm_bindgen]
63impl WebTorrentClient {
64    // Fix: Use static method pattern instead of constructor
65    #[wasm_bindgen(js_name = new)]
66    pub fn new() -> Self {
67        Self {
68            inner: create_client(),
69        }
70    }
71
72    #[wasm_bindgen]
73    pub async fn seed(&self, input: JsValue, opts_str: String) -> Result<JsValue, JsValue> {
74        // Parse JSON options from string
75        let opts = js_sys::JSON::parse(&opts_str).unwrap_or(JsValue::from(Object::new()));
76        let promise = self.inner.seed(&input, &opts, &JsValue::UNDEFINED);
77        JsFuture::from(Promise::from(promise)).await
78    }
79
80    #[wasm_bindgen]
81    pub async fn add(&self, torrent_id: String) -> Result<JsValue, JsValue> {
82        let opts = Object::new();
83        let promise = self.inner.add(
84            &JsValue::from_str(&torrent_id),
85            &JsValue::from(opts),
86            &JsValue::UNDEFINED,
87        );
88        JsFuture::from(Promise::from(promise)).await
89    }
90
91    #[wasm_bindgen]
92    pub fn create_server(&self, options: Option<String>, force: bool) -> JsValue {
93        let opts = match options {
94            Some(opts_str) => {
95                js_sys::JSON::parse(&opts_str).unwrap_or(JsValue::from(Object::new()))
96            }
97            None => JsValue::from(Object::new()),
98        };
99        self.inner.create_server(&opts, force)
100    }
101
102    #[wasm_bindgen]
103    pub async fn get_torrent(&self, torrent_id: String) -> Result<JsValue, JsValue> {
104        let promise = self.inner.get_torrent(&JsValue::from_str(&torrent_id));
105        JsFuture::from(promise).await
106    }
107
108    #[wasm_bindgen]
109    pub fn remove(&self, torrent_id: String) {
110        let opts = Object::new();
111        self.inner.remove(
112            &JsValue::from_str(&torrent_id),
113            &JsValue::from(opts),
114            &JsValue::UNDEFINED,
115        );
116    }
117
118    #[wasm_bindgen]
119    pub fn throttle_download(&self, rate: f64) {
120        self.inner.throttle_download(rate);
121    }
122
123    #[wasm_bindgen]
124    pub fn throttle_upload(&self, rate: f64) {
125        self.inner.throttle_upload(rate);
126    }
127
128    #[wasm_bindgen]
129    pub fn destroy(&self) {
130        self.inner.destroy(&JsValue::UNDEFINED);
131    }
132
133    #[wasm_bindgen]
134    pub fn is_readable(&self, obj: JsValue) -> bool {
135        self.inner.is_readable(&obj)
136    }
137
138    #[wasm_bindgen]
139    pub fn is_file_list(&self, obj: JsValue) -> bool {
140        self.inner.is_file_list(&obj)
141    }
142}