rustex_lib/engine/
files.rs1use std::path::PathBuf;
2use tex_engine::engine::filesystem::{File, FileSystem, NoOutputFileSystem, VirtualFile};
3use tex_engine::engine::{EngineAux, EngineTypes};
4use tex_engine::prelude::CSName;
5use tex_engine::tex::characters::{StringLineSource, TextLine};
6use tex_engine::utils::errors::TeXResult;
7use tex_engine::utils::Ptr;
8
9static PGFSYS: &str = include_str!("../resources/pgfsys.def");
10static RUSTEX_DEFS: &str = include_str!("../resources/patches.tex");
11
12#[derive(Clone)]
13pub struct RusTeXFileSystem {
14 pub(crate) inner: NoOutputFileSystem<u8>,
15 pub(crate) svg: (<VirtualFile<u8> as File>::SourceRefID, Ptr<[TextLine<u8>]>),
16 pub(crate) defs: (<VirtualFile<u8> as File>::SourceRefID, Ptr<[TextLine<u8>]>),
17}
18impl RusTeXFileSystem {
19 pub fn new_with_envs<I: IntoIterator<Item = (String, String)>>(pwd: PathBuf, envs: I) -> Self {
20 let mut ret = Self::new(pwd);
21 ret.inner.envs.extend(envs);
22 ret
23 }
24
25 pub fn add_file(&mut self, path: PathBuf, file_content: &str) {
26 self.inner.add_file(path, file_content);
27 }
28
29 pub fn add_envs<I: IntoIterator<Item = (String, String)>>(&mut self, envs: I) {
30 self.inner.envs.extend(envs);
31 }
32}
33
34impl FileSystem for RusTeXFileSystem {
35 type File = VirtualFile<u8>;
36
37 fn new(pwd: PathBuf) -> Self {
38 let mut inner = NoOutputFileSystem::new(pwd);
39 let svg_id = inner
40 .interner
41 .get_or_intern("<TEXINPUTS>/pgfsys-rustex.def");
42 let ext_id = inner.interner.get_or_intern("<TEXINPUTS>/rustex_defs.def");
43 Self {
44 inner,
45 svg: (
46 Some(svg_id),
47 StringLineSource::make_lines(PGFSYS.as_bytes().iter().copied()).into(),
48 ),
49 defs: (
50 Some(ext_id),
51 StringLineSource::make_lines(RUSTEX_DEFS.as_bytes().iter().copied()).into(),
52 ),
53 }
54 }
55 fn ref_str(&self, id: <Self::File as File>::SourceRefID) -> &str {
56 self.inner.ref_str(id)
57 }
58
59 fn get<S: AsRef<str>>(&mut self, path: S) -> Self::File {
60 let sr = path.as_ref();
61 if sr.ends_with("pgfsys-rustex.def") {
62 VirtualFile {
63 path: self.inner.kpse.pwd.join("pgfsys-rustex.def"),
64 id: self.svg.0,
65 pipe: false,
66 exists: true,
67 source: Some(self.svg.1.clone()),
68 }
69 } else if sr.ends_with("rustex_defs.def") {
70 VirtualFile {
71 path: self.inner.kpse.pwd.join("rustex_defs.def"),
72 id: self.defs.0,
73 pipe: false,
74 exists: true,
75 source: Some(self.defs.1.clone()),
76 }
77 } else {
78 self.inner.get(sr)
79 }
80 }
81
82 fn set_pwd(&mut self, pwd: PathBuf) -> PathBuf {
83 self.inner.set_pwd(pwd)
84 }
85
86 fn open_out(&mut self, idx: u8, file: Self::File) {
87 self.inner.open_out(idx, file)
88 }
89
90 fn open_in(&mut self, idx: u8, file: Self::File) {
91 self.inner.open_in(idx, file)
92 }
93
94 fn close_in(&mut self, idx: u8) {
95 self.inner.close_in(idx)
96 }
97
98 fn close_out(&mut self, idx: u8) {
99 self.inner.close_out(idx)
100 }
101
102 fn eof(&self, idx: u8) -> bool {
103 self.inner.eof(idx)
104 }
105
106 fn write<ET: EngineTypes, D: std::fmt::Display>(
107 &mut self,
108 idx: i64,
109 string: D,
110 newlinechar: Option<ET::Char>,
111 aux: &mut EngineAux<ET>,
112 ) {
113 self.inner.write(idx, string, newlinechar, aux)
114 }
115
116 fn read<ET: EngineTypes<Char = <Self::File as File>::Char>, F: FnMut(ET::Token)>(
117 &mut self,
118 idx: u8,
119 handler: &mut <ET::CSName as CSName<ET::Char>>::Handler,
120 state: &ET::State,
121 cont: F,
122 ) -> TeXResult<(), ET> {
123 self.inner.read::<ET, F>(idx, handler, state, cont)
124 }
125
126 fn readline<ET: EngineTypes<Char = <Self::File as File>::Char>, F: FnMut(ET::Token)>(
127 &mut self,
128 idx: u8,
129 state: &ET::State,
130 cont: F,
131 ) -> TeXResult<(), ET> {
132 self.inner.readline(idx, state, cont)
133 }
134}