tinymist_vfs/
system.rs

1use std::{fs::File, io::Read, path::Path};
2
3use tinymist_std::ReadAllOnce;
4use typst::diag::{FileError, FileResult};
5
6use crate::{Bytes, PathAccessModel};
7
8/// Provides SystemAccessModel that makes access to the local file system for
9/// system compilation.
10#[derive(Debug, Clone, Copy)]
11pub struct SystemAccessModel;
12
13impl SystemAccessModel {
14    fn stat(&self, src: &Path) -> std::io::Result<SystemFileMeta> {
15        let meta = std::fs::metadata(src)?;
16        Ok(SystemFileMeta {
17            is_dir: meta.is_dir(),
18        })
19    }
20}
21
22impl PathAccessModel for SystemAccessModel {
23    fn content(&self, src: &Path) -> FileResult<Bytes> {
24        let f = |e| FileError::from_io(e, src);
25        let mut buf = Vec::<u8>::new();
26
27        let meta = self.stat(src).map_err(f)?;
28
29        if meta.is_dir {
30            return Err(FileError::IsDirectory);
31        }
32
33        std::fs::File::open(src)
34            .map_err(f)?
35            .read_to_end(&mut buf)
36            .map_err(f)?;
37        Ok(Bytes::new(buf))
38    }
39}
40
41/// Lazily opened file entry corresponding to a file in the local file system.
42///
43/// This is used by font loading instead of the [`SystemAccessModel`].
44#[derive(Debug)]
45pub struct LazyFile {
46    path: std::path::PathBuf,
47    file: Option<std::io::Result<File>>,
48}
49
50impl LazyFile {
51    /// Create a new [`LazyFile`] with the given path.
52    pub fn new(path: std::path::PathBuf) -> Self {
53        Self { path, file: None }
54    }
55}
56
57impl ReadAllOnce for LazyFile {
58    fn read_all(mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
59        let mut file = self.file.get_or_insert_with(|| File::open(&self.path));
60        let Ok(file) = &mut file else {
61            let err = file.as_ref().unwrap_err();
62            // todo: clone error or hide error
63            return Err(std::io::Error::new(err.kind(), err.to_string()));
64        };
65
66        file.read_to_end(buf)
67    }
68}
69
70/// Meta data of a file in the local file system.
71#[derive(Debug, Clone, Copy)]
72pub struct SystemFileMeta {
73    is_dir: bool,
74}