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}