tinymist_debug/
instrument.rs1use std::sync::Arc;
4
5use parking_lot::Mutex;
6use tinymist_std::hash::FxHashMap;
7use tinymist_world::SourceWorld;
8use tinymist_world::vfs::PathResolution;
9use tinymist_world::{CompilerFeat, CompilerWorld, vfs::FileId};
10use typst::Library;
11use typst::diag::FileResult;
12use typst::foundations::{Bytes, Datetime};
13use typst::syntax::Source;
14use typst::text::{Font, FontBook};
15use typst::utils::LazyHash;
16
17pub trait Instrumenter: Send + Sync {
18 fn instrument(&self, source: Source) -> FileResult<Source>;
19}
20
21pub struct InstrumentWorld<'a, F: CompilerFeat, I> {
22 pub base: &'a CompilerWorld<F>,
23 pub library: Arc<LazyHash<Library>>,
24 pub instr: I,
25 pub instrumented: Mutex<FxHashMap<FileId, FileResult<Source>>>,
26}
27
28impl<F: CompilerFeat, I: Instrumenter> typst::World for InstrumentWorld<'_, F, I>
29where
30 I:,
31{
32 fn library(&self) -> &LazyHash<Library> {
33 &self.library
34 }
35
36 fn book(&self) -> &LazyHash<FontBook> {
37 self.base.book()
38 }
39
40 fn main(&self) -> FileId {
41 self.base.main()
42 }
43
44 fn source(&self, id: FileId) -> FileResult<Source> {
45 let mut instrumented = self.instrumented.lock();
46 if let Some(source) = instrumented.get(&id) {
47 return source.clone();
48 }
49
50 let source = self.base.source(id).and_then(|s| self.instr.instrument(s));
51 instrumented.insert(id, source.clone());
52 source
53 }
54
55 fn file(&self, id: FileId) -> FileResult<Bytes> {
56 self.base.file(id)
57 }
58
59 fn font(&self, index: usize) -> Option<Font> {
60 self.base.font(index)
61 }
62
63 fn today(&self, offset: Option<i64>) -> Option<Datetime> {
64 self.base.today(offset)
65 }
66}
67
68impl<F: CompilerFeat, I: Instrumenter> SourceWorld for InstrumentWorld<'_, F, I> {
69 fn as_world(&self) -> &dyn typst::World {
70 self
71 }
72
73 fn path_for_id(&self, id: FileId) -> FileResult<PathResolution> {
74 self.base.path_for_id(id)
75 }
76}