use std::sync::{Arc, Mutex};
use crate::{Template, TemplateId, PapermakeError, Result};
use crate::render::{RenderResult, RenderOptions};
use crate::typst::TypstWorld;
#[derive(Debug)]
pub struct CachedTemplate {
template: Template,
world_cache: Arc<Mutex<Option<TypstWorld>>>,
}
impl CachedTemplate {
pub fn new(template: Template) -> Self {
Self {
template,
world_cache: Arc::new(Mutex::new(None)),
}
}
pub fn render(&self, data: &serde_json::Value) -> Result<RenderResult> {
self.render_with_options(data, RenderOptions::default())
}
pub fn render_with_options(&self, data: &serde_json::Value, options: RenderOptions) -> Result<RenderResult> {
let mut cache_guard = self.world_cache.lock()
.map_err(|_| PapermakeError::Rendering("Failed to acquire cache lock".to_string()))?;
match cache_guard.as_mut() {
Some(cached_world) => {
crate::render::render_pdf_with_cache(&self.template, data, Some(cached_world), Some(options))
}
None => {
let mut new_world = TypstWorld::new(
self.template.content.clone(),
serde_json::to_string(data).map_err(|e| PapermakeError::Rendering(e.to_string()))?,
);
let result = crate::render::render_pdf_with_cache(&self.template, data, Some(&mut new_world), Some(options))?;
*cache_guard = Some(new_world);
Ok(result)
}
}
}
pub fn clear_cache(&self) -> Result<()> {
let mut cache_guard = self.world_cache.lock()
.map_err(|_| PapermakeError::Rendering("Failed to acquire cache lock".to_string()))?;
*cache_guard = None;
Ok(())
}
pub fn is_cached(&self) -> bool {
self.world_cache.lock()
.map(|guard| guard.is_some())
.unwrap_or(false)
}
pub fn template(&self) -> &Template {
&self.template
}
pub fn id(&self) -> &TemplateId {
&self.template.id
}
pub fn name(&self) -> &str {
&self.template.name
}
pub fn validate_data(&self, data: &serde_json::Value) -> Result<()> {
self.template.validate_data(data)
}
}
impl Clone for CachedTemplate {
fn clone(&self) -> Self {
Self {
template: self.template.clone(),
world_cache: Arc::new(Mutex::new(None)), }
}
}
pub trait TemplateCache {
fn with_cache(self) -> CachedTemplate;
}
impl TemplateCache for Template {
fn with_cache(self) -> CachedTemplate {
CachedTemplate::new(self)
}
}