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> {
16 pub file_resolver: T,
17 pub in_memory_source_cache: Option<Arc<Mutex<HashMap<FileId, Source>>>>,
18 pub in_memory_binary_cache: Option<Arc<Mutex<HashMap<FileId, Bytes>>>>,
19}
20
21impl<T> CachedFileResolver<T> {
22 pub fn new(file_resolver: T) -> Self {
23 CachedFileResolver {
24 file_resolver,
25 in_memory_source_cache: None,
26 in_memory_binary_cache: None,
27 }
28 }
29
30 pub fn with_in_memory_source_cache(self) -> Self {
31 Self {
32 in_memory_source_cache: Some(Default::default()),
33 ..self
34 }
35 }
36
37 pub fn with_in_memory_binary_cache(self) -> Self {
38 Self {
39 in_memory_binary_cache: Some(Default::default()),
40 ..self
41 }
42 }
43}
44
45impl<T> FileResolver for CachedFileResolver<T>
46where
47 T: FileResolver,
48{
49 fn resolve_binary(&self, id: FileId) -> FileResult<Cow<Bytes>> {
50 let Self {
51 in_memory_binary_cache,
52 ..
53 } = self;
54
55 if let Some(in_memory_binary_cache) = in_memory_binary_cache {
56 if let Ok(in_memory_binary_cache) = in_memory_binary_cache.lock() {
57 if let Some(cached) = in_memory_binary_cache.get(&id) {
58 return Ok(Cow::Owned(cached.clone()));
59 }
60 }
61 }
62 let resolved = self.file_resolver.resolve_binary(id)?;
63 if let Some(in_memory_binary_cache) = in_memory_binary_cache {
64 if let Ok(mut in_memory_binary_cache) = in_memory_binary_cache.lock() {
65 in_memory_binary_cache.insert(id, resolved.as_ref().clone());
66 }
67 }
68 Ok(resolved)
69 }
70
71 fn resolve_source(&self, id: FileId) -> FileResult<Cow<Source>> {
72 let Self {
73 in_memory_source_cache,
74 ..
75 } = self;
76
77 if let Some(in_memory_source_cache) = in_memory_source_cache {
78 if let Ok(in_memory_source_cache) = in_memory_source_cache.lock() {
79 if let Some(cached) = in_memory_source_cache.get(&id) {
80 return Ok(Cow::Owned(cached.clone()));
81 }
82 }
83 }
84 let resolved = self.file_resolver.resolve_source(id)?;
85 if let Some(in_memory_source_cache) = in_memory_source_cache {
86 if let Ok(mut in_memory_source_cache) = in_memory_source_cache.lock() {
87 in_memory_source_cache.insert(id, resolved.as_ref().clone());
88 }
89 }
90 Ok(resolved)
91 }
92}
93
94pub trait IntoCachedFileResolver {
95 fn into_cached(self) -> CachedFileResolver<Self>
96 where
97 Self: Sized;
98}