web_fs/
write.rs

1use std::{
2    cell::RefCell,
3    io::Result,
4    pin::Pin,
5    rc::Rc,
6    task::{Context, Poll},
7};
8
9use futures_lite::AsyncWrite;
10use js_sys::{Object, Uint8Array};
11use wasm_bindgen::JsValue;
12
13use crate::{
14    set_value, File, Fs, Task, BUF, CLOSE, CURSOR, FD, FLUSH, FS, INDEX, POST_ERROR, WRITE,
15};
16
17impl Fs {
18    fn write(&self, fd: usize, buf: &[u8], cursor: u64, task: Rc<RefCell<Task<Result<usize>>>>) {
19        let write_obj = Object::new();
20        let index = self.inner.borrow_mut().writing_tasks.insert(task);
21        let typed_array = Uint8Array::new_with_length(buf.len() as u32);
22        typed_array.copy_from(buf);
23
24        set_value(&write_obj, &INDEX, &JsValue::from(index));
25        set_value(&write_obj, &FD, &JsValue::from(fd));
26        set_value(&write_obj, &BUF, &typed_array.buffer());
27        set_value(&write_obj, &CURSOR, &JsValue::from_f64(cursor as f64));
28        let msg = Object::new();
29        set_value(&msg, &WRITE, &write_obj);
30
31        self.worker.post_message(&msg).expect(POST_ERROR);
32    }
33    fn flush(&self, fd: usize, task: Rc<RefCell<Task<Result<()>>>>) {
34        let index = self.inner.borrow_mut().flushing_tasks.insert(task);
35
36        let msg = Object::new();
37        let flust = Object::new();
38        set_value(&flust, &FD, &JsValue::from(fd));
39        set_value(&flust, &INDEX, &JsValue::from(index));
40        set_value(&msg, &FLUSH, &flust);
41
42        self.worker.post_message(&msg).expect(POST_ERROR);
43    }
44    fn close(&self, fd: usize, task: Rc<RefCell<Task<Result<()>>>>) {
45        let index = self.inner.borrow_mut().closing_tasks.insert(task);
46
47        let msg = Object::new();
48        let close = Object::new();
49        set_value(&close, &FD, &JsValue::from(fd));
50        set_value(&close, &INDEX, &JsValue::from(index));
51        set_value(&msg, &CLOSE, &close);
52
53        self.worker.post_message(&msg).expect(POST_ERROR);
54    }
55}
56
57impl AsyncWrite for File {
58    fn poll_write(
59        mut self: Pin<&mut Self>,
60        cx: &mut Context<'_>,
61        buf: &[u8],
62    ) -> Poll<Result<usize>> {
63        let task = if let Some(task) = self.write_task.clone() {
64            task
65        } else {
66            let task = Rc::new(RefCell::new(Task {
67                waker: Some(cx.waker().clone()),
68                result: None,
69            }));
70            let task_clone = task.clone();
71            FS.with_borrow(|fs| fs.write(self.fd, buf, self.cursor, task_clone));
72
73            self.write_task = Some(task.clone());
74            task
75        };
76        let mut inner = task.borrow_mut();
77        if let Some(result) = inner.result.take() {
78            self.write_task = None;
79            if let Ok(size) = result {
80                self.size += size as u64;
81            }
82            Poll::Ready(result)
83        } else {
84            Poll::Pending
85        }
86    }
87    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
88        let task = if let Some(task) = self.flush_task.clone() {
89            task
90        } else {
91            let task = Rc::new(RefCell::new(Task {
92                waker: Some(cx.waker().clone()),
93                result: None,
94            }));
95            let task_clone = task.clone();
96            FS.with_borrow(|fs| fs.flush(self.fd, task_clone));
97
98            self.flush_task = Some(task.clone());
99            task
100        };
101        let mut inner = task.borrow_mut();
102        if let Some(result) = inner.result.take() {
103            self.flush_task = None;
104            Poll::Ready(result)
105        } else {
106            Poll::Pending
107        }
108    }
109    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
110        let task = if let Some(task) = self.close_task.clone() {
111            task
112        } else {
113            let task = Rc::new(RefCell::new(Task {
114                waker: Some(cx.waker().clone()),
115                result: None,
116            }));
117            let task_clone = task.clone();
118            FS.with_borrow(|fs| fs.close(self.fd, task_clone));
119
120            self.close_task = Some(task.clone());
121            task
122        };
123        let mut inner = task.borrow_mut();
124        if let Some(result) = inner.result.take() {
125            self.close_task = None;
126            Poll::Ready(result)
127        } else {
128            Poll::Pending
129        }
130    }
131}