typst_as_lib/
cached_file_resolver.rs1use std::{
2 borrow::Cow,
3 collections::HashMap,
4 sync::{Arc, Mutex},
5};
6
7use typst::{
8 diag::FileResult,
9 foundations::Bytes,
10 syntax::{FileId, Source},
11};
12
13use crate::file_resolver::FileResolver;
14
15pub struct CachedFileResolver<T> {
17 pub file_resolver: T,
19 pub in_memory_source_cache: Option<Arc<Mutex<HashMap<FileId, Source>>>>,
21 pub in_memory_binary_cache: Option<Arc<Mutex<HashMap<FileId, Bytes>>>>,
23}
24
25impl<T> CachedFileResolver<T> {
26 pub fn new(file_resolver: T) -> Self {
28 CachedFileResolver {
29 file_resolver,
30 in_memory_source_cache: None,
31 in_memory_binary_cache: None,
32 }
33 }
34
35 pub fn with_in_memory_source_cache(self) -> Self {
37 Self {
38 in_memory_source_cache: Some(Default::default()),
39 ..self
40 }
41 }
42
43 pub fn with_in_memory_binary_cache(self) -> Self {
45 Self {
46 in_memory_binary_cache: Some(Default::default()),
47 ..self
48 }
49 }
50}
51
52impl<T> FileResolver for CachedFileResolver<T>
53where
54 T: FileResolver,
55{
56 fn resolve_binary(&self, id: FileId) -> FileResult<Cow<'_, Bytes>> {
57 let Self {
58 in_memory_binary_cache,
59 ..
60 } = self;
61
62 if let Some(in_memory_binary_cache) = in_memory_binary_cache
63 && let Ok(in_memory_binary_cache) = in_memory_binary_cache.lock()
64 && let Some(cached) = in_memory_binary_cache.get(&id)
65 {
66 return Ok(Cow::Owned(cached.clone()));
67 }
68 let resolved = self.file_resolver.resolve_binary(id)?;
69 if let Some(in_memory_binary_cache) = in_memory_binary_cache
70 && let Ok(mut in_memory_binary_cache) = in_memory_binary_cache.lock()
71 {
72 in_memory_binary_cache.insert(id, resolved.as_ref().clone());
73 }
74 Ok(resolved)
75 }
76
77 fn resolve_source(&self, id: FileId) -> FileResult<Cow<'_, Source>> {
78 let Self {
79 in_memory_source_cache,
80 ..
81 } = self;
82
83 if let Some(in_memory_source_cache) = in_memory_source_cache
84 && let Ok(in_memory_source_cache) = in_memory_source_cache.lock()
85 && let Some(cached) = in_memory_source_cache.get(&id)
86 {
87 return Ok(Cow::Owned(cached.clone()));
88 }
89 let resolved = self.file_resolver.resolve_source(id)?;
90 if let Some(in_memory_source_cache) = in_memory_source_cache
91 && let Ok(mut in_memory_source_cache) = in_memory_source_cache.lock()
92 {
93 in_memory_source_cache.insert(id, resolved.as_ref().clone());
94 }
95 Ok(resolved)
96 }
97}
98
99pub trait IntoCachedFileResolver {
101 fn into_cached(self) -> CachedFileResolver<Self>
103 where
104 Self: Sized;
105}