turbo_tasks_fs/embed/
fs.rs

1use anyhow::{Result, bail};
2use auto_hash_map::AutoMap;
3use include_dir::{Dir, DirEntry};
4use turbo_rcstr::RcStr;
5use turbo_tasks::{ValueToString, Vc};
6
7use crate::{
8    File, FileContent, FileMeta, FileSystem, FileSystemPath, LinkContent, RawDirectoryContent,
9    RawDirectoryEntry,
10};
11
12#[turbo_tasks::value(serialization = "none", cell = "new", eq = "manual")]
13pub struct EmbeddedFileSystem {
14    name: RcStr,
15    #[turbo_tasks(trace_ignore)]
16    dir: &'static Dir<'static>,
17}
18
19impl EmbeddedFileSystem {
20    pub(super) fn new(name: RcStr, dir: &'static Dir<'static>) -> Vc<EmbeddedFileSystem> {
21        EmbeddedFileSystem { name, dir }.cell()
22    }
23}
24
25#[turbo_tasks::value_impl]
26impl FileSystem for EmbeddedFileSystem {
27    #[turbo_tasks::function]
28    async fn read(&self, path: FileSystemPath) -> Result<Vc<FileContent>> {
29        let file = match self.dir.get_file(&path.path) {
30            Some(file) => file,
31            None => return Ok(FileContent::NotFound.cell()),
32        };
33
34        Ok(File::from(file.contents()).into())
35    }
36
37    #[turbo_tasks::function]
38    fn read_link(&self, _path: FileSystemPath) -> Vc<LinkContent> {
39        LinkContent::NotFound.cell()
40    }
41
42    #[turbo_tasks::function]
43    async fn raw_read_dir(&self, path: FileSystemPath) -> Result<Vc<RawDirectoryContent>> {
44        let path_str = &path.path;
45        let dir = match (path_str.as_str(), self.dir.get_dir(path_str)) {
46            ("", _) => self.dir,
47            (_, Some(dir)) => dir,
48            (_, None) => return Ok(RawDirectoryContent::NotFound.cell()),
49        };
50
51        let mut converted_entries = AutoMap::new();
52        for e in dir.entries() {
53            let entry_name: RcStr = e
54                .path()
55                .file_name()
56                .unwrap_or_default()
57                .to_string_lossy()
58                .into();
59
60            converted_entries.insert(
61                entry_name,
62                match e {
63                    DirEntry::Dir(_) => RawDirectoryEntry::Directory,
64                    DirEntry::File(_) => RawDirectoryEntry::File,
65                },
66            );
67        }
68
69        Ok(RawDirectoryContent::new(converted_entries))
70    }
71
72    #[turbo_tasks::function]
73    fn write(&self, _path: FileSystemPath, _content: Vc<FileContent>) -> Result<Vc<()>> {
74        bail!("Writing is not possible to the embedded filesystem")
75    }
76
77    #[turbo_tasks::function]
78    fn write_link(&self, _path: FileSystemPath, _target: Vc<LinkContent>) -> Result<Vc<()>> {
79        bail!("Writing is not possible to the embedded filesystem")
80    }
81
82    #[turbo_tasks::function]
83    async fn metadata(&self, path: FileSystemPath) -> Result<Vc<FileMeta>> {
84        if self.dir.get_entry(&path.path).is_none() {
85            bail!("path not found, can't read metadata");
86        }
87
88        Ok(FileMeta::default().cell())
89    }
90}
91
92#[turbo_tasks::value_impl]
93impl ValueToString for EmbeddedFileSystem {
94    #[turbo_tasks::function]
95    fn to_string(&self) -> Vc<RcStr> {
96        Vc::cell(self.name.clone())
97    }
98}