1mod bindings;
2
3pub use bindings::{
4 delete_object, get_download_url, get_storage, ref_, upload_bytes, FullMetadata, Ref,
5 SettableMetadata, Storage, UploadMetadata, UploadMetadataOptions, UploadTask,
6 UploadTaskSnapshot,
7};
8use futures::Stream;
9use std::{
10 cell::RefCell,
11 pin::Pin,
12 rc::Rc,
13 task::{Context, Poll, Waker},
14};
15use wasm_bindgen::prelude::*;
16use wasm_bindgen::JsCast;
17
18impl UploadTask {
19 pub fn async_iter(&self) -> UploadTaskAsyncIter {
20 let waker: Rc<RefCell<Option<Waker>>> = Rc::default();
21 let completed: Rc<RefCell<bool>> = Rc::default();
22 let snapshot: Rc<RefCell<Option<UploadTaskSnapshot>>> = Rc::default();
23 let err: Rc<RefCell<Option<JsValue>>> = Rc::default();
24
25 let on_snapshot = Closure::new(clone!([snapshot, waker], move |js_snapshot| {
26 *snapshot.borrow_mut() = Some(js_snapshot);
27
28 if let Some(w) = waker.borrow().as_ref() {
29 w.wake_by_ref();
30 }
31 }));
32 let on_err = Closure::new(clone!([completed, err, waker], move |js_err| {
33 *err.borrow_mut() = Some(js_err);
34
35 *completed.borrow_mut() = true;
37
38 if let Some(w) = waker.borrow().as_ref() {
39 w.wake_by_ref()
40 }
41 }));
42 let on_complete = Closure::new(clone!([completed, waker], move || {
43 *completed.borrow_mut() = true;
44
45 let waker_borrow = waker.borrow();
47
48 if let Some(w) = waker_borrow.as_ref() {
49 w.wake_by_ref();
50 }
51 }));
52
53 let unsub = self.on(
54 "state_changed",
55 &on_snapshot,
56 Some(&on_err),
57 Some(&on_complete),
58 );
59
60 UploadTaskAsyncIter {
61 _on_snapshot: on_snapshot,
62 _on_err: on_err,
63 _on_complete: on_complete,
64 snapshot,
65 err,
66 completed,
67 waker,
68 unsub,
69 }
70 }
71}
72
73pub struct UploadTaskAsyncIter {
74 _on_snapshot: Closure<dyn FnMut(UploadTaskSnapshot)>,
75 _on_err: Closure<dyn FnMut(JsValue)>,
76 _on_complete: Closure<dyn FnMut()>,
77 snapshot: Rc<RefCell<Option<UploadTaskSnapshot>>>,
78 err: Rc<RefCell<Option<JsValue>>>,
79 completed: Rc<RefCell<bool>>,
80 waker: Rc<RefCell<Option<Waker>>>,
81 unsub: js_sys::Function,
82}
83
84impl Drop for UploadTaskAsyncIter {
85 fn drop(&mut self) {
86 self.unsub.call0(&JsValue::UNDEFINED).unwrap();
87 }
88}
89
90impl Stream for UploadTaskAsyncIter {
91 type Item = Result<UploadTaskSnapshot, JsValue>;
92
93 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
94 *self.waker.borrow_mut() = Some(cx.waker().to_owned());
96
97 if *self.completed.borrow() {
98 if let Some(err) = self.err.borrow_mut().take() {
99 Poll::Ready(Some(Err(err)))
100 } else {
101 Poll::Ready(None)
102 }
103 } else if let Some(snapshot) = self.snapshot.borrow_mut().take() {
104 Poll::Ready(Some(Ok(snapshot)))
105 } else {
106 Poll::Pending
107 }
108 }
109}
110
111pub async fn get_metadata(ref_: Ref) -> Result<FullMetadata, JsValue> {
112 bindings::get_metadata(ref_)
113 .await
114 .map(|m| m.unchecked_into())
115}