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 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}