tinymist_debug/
instrument.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Tinymist instrument support for Typst.

use std::sync::Arc;

use parking_lot::Mutex;
use tinymist_std::hash::FxHashMap;
use tinymist_world::vfs::PathResolution;
use tinymist_world::SourceWorld;
use tinymist_world::{vfs::FileId, CompilerFeat, CompilerWorld};
use typst::diag::FileResult;
use typst::foundations::{Bytes, Datetime};
use typst::syntax::Source;
use typst::text::{Font, FontBook};
use typst::utils::LazyHash;
use typst::Library;

pub trait Instrumenter: Send + Sync {
    fn instrument(&self, source: Source) -> FileResult<Source>;
}

pub struct InstrumentWorld<'a, F: CompilerFeat, I> {
    pub base: &'a CompilerWorld<F>,
    pub library: Arc<LazyHash<Library>>,
    pub instr: I,
    pub instrumented: Mutex<FxHashMap<FileId, FileResult<Source>>>,
}

impl<F: CompilerFeat, I: Instrumenter> typst::World for InstrumentWorld<'_, F, I>
where
    I:,
{
    fn library(&self) -> &LazyHash<Library> {
        &self.library
    }

    fn book(&self) -> &LazyHash<FontBook> {
        self.base.book()
    }

    fn main(&self) -> FileId {
        self.base.main()
    }

    fn source(&self, id: FileId) -> FileResult<Source> {
        let mut instrumented = self.instrumented.lock();
        if let Some(source) = instrumented.get(&id) {
            return source.clone();
        }

        let source = self.base.source(id).and_then(|s| self.instr.instrument(s));
        instrumented.insert(id, source.clone());
        source
    }

    fn file(&self, id: FileId) -> FileResult<Bytes> {
        self.base.file(id)
    }

    fn font(&self, index: usize) -> Option<Font> {
        self.base.font(index)
    }

    fn today(&self, offset: Option<i64>) -> Option<Datetime> {
        self.base.today(offset)
    }
}

impl<F: CompilerFeat, I: Instrumenter> SourceWorld for InstrumentWorld<'_, F, I> {
    fn as_world(&self) -> &dyn typst::World {
        self
    }

    fn path_for_id(&self, id: FileId) -> FileResult<PathResolution> {
        self.base.path_for_id(id)
    }
}