reflexo_typst2vec/
incr.rs

1use reflexo::error::prelude::*;
2use reflexo::typst::TypstDocument;
3use reflexo::vector::ir::{ModuleMetadata, Page};
4
5use super::ir::FlatModule;
6use super::pass::IncrTypst2VecPass;
7use crate::debug_loc::{ElementPoint, SourceSpanOffset};
8
9/// Client side implementation is free from typst details.
10pub use reflexo::vector::incr::{IncrDocClient, IncrDocClientKern};
11
12/// maintains the data of the incremental rendering at server side
13#[derive(Default)]
14pub struct IncrDocServer {
15    /// The references of pages of the document.
16    /// Initially it is None meaning no completed compilation.
17    pages: Option<Vec<Page>>,
18
19    /// Maintaining typst -> vector status
20    typst2vec: IncrTypst2VecPass,
21}
22
23impl IncrDocServer {
24    /// Set whether to attach debug info to the spans.
25    pub fn set_should_attach_debug_info(&mut self, should_attach_debug_info: bool) {
26        self.typst2vec
27            .spans
28            .set_should_attach_debug_info(should_attach_debug_info);
29    }
30
31    /// Pack the delta into a binary blob.
32    pub fn pack_delta(&mut self, output: &TypstDocument) -> Vec<u8> {
33        self.typst2vec.spans.reset();
34
35        // Increment the lifetime of all items to touch.
36        self.typst2vec.increment_lifetime();
37
38        // it is important to call gc before building pages
39        let gc_items = self.typst2vec.gc(5 * 2);
40
41        // run typst2vec pass
42        let pages = self.typst2vec.doc(output);
43        self.pages = Some(pages.clone());
44
45        // let new_items = builder.new_items.get_mut().len();
46        // let new_fonts = builder.glyphs.new_fonts.get_mut().len();
47        // let new_glyphs = builder.glyphs.new_glyphs.get_mut().len();
48
49        let delta = self.typst2vec.finalize_delta();
50
51        // max, min lifetime current, gc_items
52        #[cfg(feature = "debug-gc")]
53        {
54            let mi = self
55                .typst2vec
56                .items
57                .clone()
58                .into_iter()
59                .map(|i| i.1 .0)
60                .min()
61                .unwrap_or(0);
62            eprintln!(
63                "gc[{}]: max: {}, min: {}, remove: {}",
64                self.typst2vec.lifetime,
65                self.typst2vec
66                    .items
67                    .clone()
68                    .into_iter()
69                    .map(|i| i.1 .0)
70                    .max()
71                    .unwrap_or(0xffffffff),
72                mi,
73                gc_items.len()
74            );
75
76            // for (fg, (_, item)) in
77            //     self.typst2vec.items.iter().filter(|(_, i)| i.0 == mi) {
78            //     eprintln!("mi {fg:?} => {item:#?}");
79            // }
80        }
81
82        let mut m = FlatModule::with_capacity(5);
83        m.push(ModuleMetadata::GarbageCollection(gc_items));
84        m.add_module(delta);
85        m.add_single_layout(pages);
86        let delta = m.to_bytes();
87
88        // log::info!("svg render time (incremental bin): {:?}", instant.elapsed());
89        [b"diff-v1,", delta.as_slice()].concat()
90    }
91
92    /// Pack the current entirely into a binary blob.
93    pub fn pack_current(&mut self) -> Option<Vec<u8>> {
94        let pages = self.pages.as_ref()?.clone();
95        let full = self.typst2vec.finalize_ref();
96
97        let mut m = FlatModule::with_capacity(4);
98        m.add_module(full);
99        m.add_single_layout(pages);
100        let full = m.to_bytes();
101
102        Some([b"new,", full.as_slice()].concat())
103    }
104
105    /// Gets element paths by the given span.
106    ///
107    /// See [`crate::pass::Span2VecPass::query_element_paths`] for more
108    /// information.
109    pub fn resolve_element_paths_by_span(
110        &mut self,
111        span_offset: SourceSpanOffset,
112    ) -> Result<Vec<Vec<ElementPoint>>> {
113        self.typst2vec.spans.query_element_paths(span_offset)
114    }
115
116    /// Gets the span range of the given element path.
117    pub fn resolve_span_by_element_path(
118        &mut self,
119        path: &[ElementPoint],
120    ) -> Result<Option<(SourceSpanOffset, SourceSpanOffset)>> {
121        self.typst2vec.spans.query(path)
122    }
123}