Skip to main content

trailbase_wasm/
fs.rs

1pub use crate::wit::wasi::filesystem::preopens::{Descriptor, get_directories};
2pub use crate::wit::wasi::filesystem::types::{DescriptorFlags, ErrorCode, OpenFlags, PathFlags};
3use std::path::Path;
4
5#[derive(Debug, thiserror::Error)]
6pub enum Error {
7  #[error("MissingRoot")]
8  MissingRoot,
9  #[error("NotFound")]
10  NotFound,
11  #[error("InvalidPath")]
12  InvalidPath,
13  #[error("Open {0}")]
14  Open(ErrorCode),
15  #[error("Read {0}")]
16  Read(ErrorCode),
17}
18
19pub fn read_file(path: impl AsRef<Path>) -> Result<Vec<u8>, Error> {
20  let path = path.as_ref();
21  let segments: Vec<_> = path.iter().collect();
22
23  let (root, _) = get_directories()
24    .into_iter()
25    .find(|(_, path)| path == "/")
26    .ok_or(Error::MissingRoot)?;
27
28  let mut descriptor: Descriptor = root;
29  for (i, segment) in segments.iter().enumerate() {
30    let path = segment.to_str().ok_or(Error::InvalidPath)?;
31
32    // First.
33    if i == 0 {
34      if path != "/" {
35        return Err(Error::InvalidPath);
36      }
37      continue;
38    }
39
40    let last = i == segments.len() - 1;
41    descriptor = descriptor
42      .open_at(
43        PathFlags::empty(),
44        path,
45        if last {
46          OpenFlags::empty()
47        } else {
48          OpenFlags::DIRECTORY
49        },
50        DescriptorFlags::READ,
51      )
52      .map_err(Error::Open)?;
53
54    if last {
55      const MAX: u64 = 1024 * 1024;
56
57      let mut buffer: Vec<u8> = vec![];
58      loop {
59        let (bytes, eof) = descriptor
60          .read(MAX, buffer.len() as u64)
61          .map_err(Error::Read)?;
62
63        buffer.extend(bytes);
64
65        if eof {
66          break;
67        }
68      }
69
70      return Ok(buffer);
71    }
72  }
73
74  return Err(Error::NotFound);
75}