1use js_sys::Uint8Array;
9use wasm_bindgen::JsCast as _;
10use web_sys::{
11 File, FileSystemCreateWritableOptions, FileSystemFileHandle, FileSystemWritableFileStream,
12};
13
14use crate::fault::{faulted, mistaken, settled};
15
16#[derive(Clone, Copy, PartialEq, Eq, Debug)]
19enum Keeping {
20 Nothing,
21 Everything,
22}
23
24pub async fn read(handle: &FileSystemFileHandle) -> std::io::Result<Vec<u8>> {
28 let bytes = settled(opened(handle).await?.array_buffer()).await?;
29 Ok(Uint8Array::new(&bytes).to_vec())
30}
31
32pub async fn write(handle: &FileSystemFileHandle, bytes: &[u8]) -> std::io::Result<()> {
37 let stream = writable(handle, Keeping::Nothing).await?;
38 put(&stream, bytes).await?;
39 close(stream).await
40}
41
42pub async fn append(handle: &FileSystemFileHandle, bytes: &[u8]) -> std::io::Result<()> {
47 let end = opened(handle).await?.size();
48 let stream = writable(handle, Keeping::Everything).await?;
49 settled(stream.seek_with_f64(end).map_err(faulted)?).await?;
50 put(&stream, bytes).await?;
51 close(stream).await
52}
53
54pub async fn truncate(handle: &FileSystemFileHandle, len: u64) -> std::io::Result<()> {
57 let stream = writable(handle, Keeping::Everything).await?;
58 settled(stream.truncate_with_f64(len as f64).map_err(faulted)?).await?;
59 close(stream).await
60}
61
62async fn opened(handle: &FileSystemFileHandle) -> std::io::Result<File> {
63 settled(handle.get_file())
64 .await?
65 .dyn_into()
66 .map_err(mistaken("a file"))
67}
68
69async fn writable(
70 handle: &FileSystemFileHandle,
71 keeping: Keeping,
72) -> std::io::Result<FileSystemWritableFileStream> {
73 let options = FileSystemCreateWritableOptions::new();
74 options.set_keep_existing_data(matches!(keeping, Keeping::Everything));
75 settled(handle.create_writable_with_options(&options))
76 .await?
77 .dyn_into()
78 .map_err(mistaken("a writable stream"))
79}
80
81async fn put(stream: &FileSystemWritableFileStream, bytes: &[u8]) -> std::io::Result<()> {
82 settled(stream.write_with_u8_array(bytes).map_err(faulted)?).await?;
83 Ok(())
84}
85
86async fn close(stream: FileSystemWritableFileStream) -> std::io::Result<()> {
89 settled(stream.close()).await?;
90 Ok(())
91}