web_fs/
read.rs

1use std::{
2    cell::RefCell,
3    io::Result,
4    pin::Pin,
5    rc::Rc,
6    task::{Context, Poll},
7};
8
9use futures_lite::AsyncRead;
10use js_sys::{ArrayBuffer, Object, Uint8Array};
11use wasm_bindgen::JsValue;
12
13use crate::{set_value, File, Fs, Task, CURSOR, FD, FS, INDEX, READ, SIZE};
14
15pub(crate) struct ReadResult {
16    pub buf: ArrayBuffer,
17    pub size: usize,
18}
19
20impl Fs {
21    fn read(
22        &self,
23        fd: usize,
24        size: usize,
25        cursor: u64,
26        task: Rc<RefCell<Task<Result<ReadResult>>>>,
27    ) {
28        let index = self.inner.borrow_mut().reading_tasks.insert(task);
29
30        let msg = Object::new();
31        let read = Object::new();
32        set_value(&read, &FD, &JsValue::from(fd));
33        set_value(&read, &SIZE, &JsValue::from(size));
34        set_value(&read, &INDEX, &JsValue::from(index));
35        set_value(&read, &CURSOR, &JsValue::from_f64(cursor as f64));
36        set_value(&msg, &READ, &read);
37
38        self.worker.post_message(&msg).unwrap()
39    }
40}
41
42impl AsyncRead for File {
43    fn poll_read(
44        mut self: Pin<&mut Self>,
45        cx: &mut Context<'_>,
46        buf: &mut [u8],
47    ) -> Poll<Result<usize>> {
48        let task = if let Some(task) = self.read_task.clone() {
49            task
50        } else {
51            let task = Rc::new(RefCell::new(Task {
52                waker: Some(cx.waker().clone()),
53                result: None,
54            }));
55            let task_clone = task.clone();
56            FS.with_borrow(|fs| fs.read(self.fd, buf.len(), self.cursor, task_clone));
57
58            self.read_task = Some(task.clone());
59            task
60        };
61        let mut inner = task.borrow_mut();
62        if let Some(result) = inner.result.take() {
63            let result = result?;
64            let array = Uint8Array::new(&result.buf);
65            array
66                .slice(0, result.size as u32)
67                .copy_to(&mut buf[..result.size]);
68            self.read_task = None;
69            self.cursor += result.size as u64;
70            Poll::Ready(Ok(result.size))
71        } else {
72            Poll::Pending
73        }
74    }
75}