1use std::{
2 borrow::Borrow,
3 collections::{BTreeMap, HashMap},
4 hash::Hash,
5 ops::Deref,
6 sync::{atomic::AtomicU64, Arc},
7};
8
9use comemo::Prehashed;
10
11use crate::{hash::Fingerprint, ImmutStr, TakeAs};
12
13use super::{preludes::*, *};
14
15pub type ItemMap = BTreeMap<Fingerprint, VecItem>;
16
17pub type RefItemMap = HashMap<Fingerprint, (u64, VecItem)>;
18#[cfg(feature = "item-dashmap")]
19pub type RefItemMapSync = crate::adt::CHashMap<Fingerprint, (AtomicU64, VecItem)>;
20pub type RefItemMapT<V> = crate::adt::FingerprintMap<V>;
21pub type RefItemMapSync = RefItemMapT<(AtomicU64, VecItem)>;
22
23pub trait ToItemMap {
24 fn to_item_map(self) -> ItemMap;
25}
26
27impl ToItemMap for RefItemMap {
28 fn to_item_map(self) -> ItemMap {
29 self.into_iter().map(|(k, (_, v))| (k, v)).collect::<_>()
30 }
31}
32
33impl ToItemMap for RefItemMapSync {
34 fn to_item_map(self) -> ItemMap {
35 self.into_items().map(|(k, (_, v))| (k, v)).collect::<_>()
36 }
37}
38
39pub trait ModuleStream {
41 fn items(&self) -> ItemPack;
42 fn layouts(&self) -> Arc<Vec<LayoutRegion>>;
43 fn fonts(&self) -> Arc<IncrFontPack>;
44 fn glyphs(&self) -> Arc<IncrGlyphPack>;
45 fn gc_items(&self) -> Option<Vec<Fingerprint>> {
46 None
48 }
49}
50
51#[derive(Debug, Default, Clone, Hash)]
55pub struct Module {
56 pub fonts: Vec<FontItem>,
57 pub glyphs: Vec<(GlyphRef, FlatGlyphItem)>,
58 pub items: ItemMap,
59}
60
61impl Module {
62 pub fn freeze(self) -> FrozenModule {
63 FrozenModule(Arc::new(Prehashed::new(self)))
64 }
65
66 pub fn prepare_glyphs(&mut self) {
67 let glyphs = std::mem::take(&mut self.glyphs);
68 if glyphs.is_empty() {
69 return;
70 }
71 let mut hash2idx = HashMap::new();
72 for (id, item) in glyphs.into_iter() {
73 let idx = hash2idx.entry(id.font_hash).or_insert_with(|| {
74 self.fonts
75 .iter()
76 .position(|f| f.hash == id.font_hash)
77 .unwrap()
78 });
79 let font = &mut self.fonts[*idx];
80 if font.glyphs.len() <= id.glyph_idx as usize {
81 font.glyphs
82 .resize(id.glyph_idx as usize + 1, Arc::new(FlatGlyphItem::None));
83 }
84 font.glyphs[id.glyph_idx as usize] = Arc::new(item);
85 if font.glyph_cov.is_empty() {
86 font.glyph_cov = bitvec::vec::BitVec::repeat(false, 65536);
87 }
88 font.glyph_cov.set(id.glyph_idx as usize, true);
89 }
90 }
91
92 pub fn get_font(&self, id: &FontRef) -> Option<&FontItem> {
94 self.fonts.get(id.idx as usize)
95 }
96
97 pub fn get_item(&self, id: &Fingerprint) -> Option<&VecItem> {
99 self.items.get(id)
100 }
101
102 pub fn merge_delta(&mut self, v: impl ModuleStream) {
103 let item_pack: ItemPack = v.items();
104 if let Some(gc_items) = v.gc_items() {
105 for id in gc_items {
106 self.items.remove(&id);
107 }
108 }
109 self.items.extend(item_pack.0);
110
111 let fonts = v.fonts();
112 self.fonts.extend(fonts.take().items);
113
114 let glyphs = v.glyphs();
115 if !glyphs.items.is_empty() {
116 self.glyphs = glyphs.take().items;
117 self.prepare_glyphs();
118 }
119 }
120
121 pub fn glyphs_all(&self) -> impl Iterator<Item = (GlyphRef, &FlatGlyphItem)> {
122 self.fonts.iter().flat_map(|font| {
123 font.glyph_cov.iter_ones().map(move |glyph_idx| {
124 (
125 GlyphRef {
126 font_hash: font.hash,
127 glyph_idx: glyph_idx as u32,
128 },
129 font.glyphs[glyph_idx].deref(),
130 )
131 })
132 })
133 }
134}
135
136#[derive(Debug, Clone, Hash, PartialEq, Eq)]
137pub struct FrozenModule(pub Arc<Prehashed<Module>>);
138
139pub struct ModuleView {
140 module: Module,
141}
142
143impl ModuleView {
144 pub fn new<M: AsRef<Module> + ?Sized>(m: &M) -> &Self {
146 unsafe { &*(m.as_ref() as *const Module as *const ModuleView) }
148 }
149}
150
151impl ToOwned for ModuleView {
152 type Owned = Module;
153
154 fn to_owned(&self) -> Self::Owned {
155 self.module.clone()
156 }
157}
158
159impl AsRef<Module> for ModuleView {
160 #[inline]
161 fn as_ref(&self) -> &Module {
162 &self.module
163 }
164}
165
166impl AsRef<Module> for Module {
167 #[inline]
168 fn as_ref(&self) -> &Module {
169 self
170 }
171}
172
173impl AsRef<Module> for FrozenModule {
174 #[inline]
175 fn as_ref(&self) -> &Module {
176 self.0.deref().deref()
177 }
178}
179
180impl AsRef<FrozenModule> for FrozenModule {
181 #[inline]
182 fn as_ref(&self) -> &FrozenModule {
183 self
184 }
185}
186
187impl Borrow<ModuleView> for FrozenModule {
188 fn borrow(&self) -> &ModuleView {
189 ModuleView::new(self)
190 }
191}
192
193impl Borrow<ModuleView> for Module {
194 fn borrow(&self) -> &ModuleView {
195 ModuleView::new(self)
196 }
197}
198
199impl Borrow<Module> for FrozenModule {
200 fn borrow(&self) -> &Module {
201 self.0.deref().deref()
202 }
203}
204
205#[derive(Clone)]
207#[cfg_attr(feature = "rkyv", derive(Archive, rDeser, rSer))]
208#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
209#[repr(C, align(32))]
210pub enum PageMetadata {
211 GarbageCollection(Vec<Fingerprint>),
212 Item(ItemPack),
213 Glyph(Arc<IncrGlyphPack>),
214 Custom(Vec<(ImmutStr, ImmutBytes)>),
215}
216
217impl fmt::Debug for PageMetadata {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 match self {
220 PageMetadata::GarbageCollection(v) => f
221 .debug_struct("GarbageCollection")
222 .field("len", &v.len())
223 .finish(),
224 PageMetadata::Item(v) => f.debug_struct("Item").field("len", &v.0.len()).finish(),
225 PageMetadata::Glyph(v) => f
226 .debug_struct("Glyph")
227 .field("len", &v.items.len())
228 .field("base", &v.incremental_base)
229 .finish(),
230 PageMetadata::Custom(v) => {
231 write!(f, "Custom")?;
232 f.debug_map()
233 .entries(
234 v.iter()
235 .map(|(k, v)| (k.as_ref(), format!("Bytes({})", v.len()))),
236 )
237 .finish()
238 }
239 }
240 }
241}
242
243#[derive(Debug, Clone, PartialEq)]
244#[cfg_attr(feature = "rkyv", derive(Archive, rDeser, rSer))]
245#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
246pub struct BuildInfo {
247 pub version: ImmutStr,
248 pub compiler: ImmutStr,
249}
250
251#[derive(Debug, Clone)]
253#[repr(C, align(32))]
254#[cfg_attr(feature = "rkyv", derive(Archive, rDeser, rSer))]
255#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
256pub enum ModuleMetadata {
257 BuildVersion(Arc<BuildInfo>),
258 SourceMappingData(Vec<SourceMappingNode>),
259 PageSourceMapping(Arc<LayoutSourceMapping>),
260 GarbageCollection(Vec<Fingerprint>),
261 Item(ItemPack),
262 Font(Arc<IncrFontPack>),
263 Glyph(Arc<IncrGlyphPack>),
264 Layout(Arc<Vec<LayoutRegion>>),
265}
266
267const _: () = assert!(core::mem::size_of::<ModuleMetadata>() == 32);
268
269#[repr(usize)]
270#[allow(dead_code)]
271enum MetaIndices {
272 Version,
273 SourceMapping,
274 PageSourceMapping,
275 GarbageCollection,
276 Item,
277 Font,
278 Glyph,
279 Layout,
280 Max,
281}
282
283const META_INDICES_MAX: usize = MetaIndices::Max as usize;
284
285#[derive(Debug)]
287#[cfg_attr(feature = "rkyv", derive(Archive, rDeser, rSer))]
288#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
289pub struct FlatModule {
290 pub magic: [u8; 8],
291 pub metadata: Vec<ModuleMetadata>,
292
293 #[cfg_attr(feature = "rkyv", with(rkyv::with::Skip))]
294 #[allow(unused)]
295 meta_indices: [std::sync::OnceLock<usize>; META_INDICES_MAX],
296}
297
298impl Default for FlatModule {
299 fn default() -> Self {
300 Self {
301 magic: *b"tsvr\x00\x00\x00\x00",
302 metadata: vec![],
303 meta_indices: Default::default(),
304 }
305 }
306}
307
308#[cfg(feature = "rkyv")]
309impl FlatModule {
310 pub fn new(metadata: Vec<ModuleMetadata>) -> Self {
311 Self {
312 metadata,
313 ..Default::default()
314 }
315 }
316
317 pub fn to_bytes(self: &FlatModule) -> Vec<u8> {
318 use rkyv::ser::{serializers::AllocSerializer, Serializer};
321
322 let mut serializer = AllocSerializer::<0>::default();
323 serializer.serialize_value(self).unwrap();
324 let bytes = serializer.into_serializer().into_inner();
325
326 bytes.into_vec()
327 }
328}
329
330#[cfg(feature = "rkyv")]
333impl ModuleStream for &FlatModule {
334 fn items(&self) -> ItemPack {
335 let sz = &self.meta_indices[MetaIndices::Item as usize];
337 let sz = sz.get_or_init(|| {
338 let mut sz = usize::MAX; for (idx, m) in self.metadata.iter().enumerate() {
340 if let ModuleMetadata::Item(_) = m {
341 sz = idx;
342 break;
343 }
344 }
345 sz
346 });
347
348 let m = &self.metadata[*sz];
350 if let ModuleMetadata::Item(v) = m {
351 v.clone()
352 } else {
353 unreachable!()
354 }
355 }
356
357 fn layouts(&self) -> Arc<Vec<LayoutRegion>> {
358 let sz = &self.meta_indices[MetaIndices::Layout as usize];
360 let sz = sz.get_or_init(|| {
361 let mut sz = usize::MAX; for (idx, m) in self.metadata.iter().enumerate() {
363 if let ModuleMetadata::Layout(_) = m {
364 sz = idx;
365 break;
366 }
367 }
368 sz
369 });
370
371 let m = &self.metadata[*sz];
373 if let ModuleMetadata::Layout(v) = m {
374 v.clone()
375 } else {
376 unreachable!()
377 }
378 }
379
380 fn fonts(&self) -> Arc<IncrFontPack> {
381 let sz = &self.meta_indices[MetaIndices::Font as usize];
383 let sz = sz.get_or_init(|| {
384 let mut sz = usize::MAX; for (idx, m) in self.metadata.iter().enumerate() {
386 if let ModuleMetadata::Font(_) = m {
387 sz = idx;
388 break;
389 }
390 }
391 sz
392 });
393
394 let m = &self.metadata[*sz];
396 if let ModuleMetadata::Font(v) = m {
397 v.clone()
398 } else {
399 unreachable!()
400 }
401 }
402
403 fn glyphs(&self) -> Arc<IncrGlyphPack> {
404 let sz = &self.meta_indices[MetaIndices::Glyph as usize];
406 let sz = sz.get_or_init(|| {
407 let mut sz = usize::MAX; for (idx, m) in self.metadata.iter().enumerate() {
409 if let ModuleMetadata::Glyph(_) = m {
410 sz = idx;
411 break;
412 }
413 }
414 sz
415 });
416
417 let m = &self.metadata[*sz];
419 if let ModuleMetadata::Glyph(v) = m {
420 v.clone()
421 } else {
422 unreachable!()
423 }
424 }
425
426 fn gc_items(&self) -> Option<Vec<Fingerprint>> {
427 for m in &self.metadata {
428 if let ModuleMetadata::GarbageCollection(v) = m {
429 return Some(v.clone());
430 }
431 }
432 None
433 }
434}