par_term_config/shader_metadata/
cache.rs1use super::parsing::extract_yaml_block;
11use crate::types::{CursorShaderMetadata, ShaderMetadata};
12use std::collections::HashMap;
13use std::path::PathBuf;
14
15#[derive(Debug)]
24pub struct MetadataCache<T>
25where
26 T: for<'de> serde::Deserialize<'de>,
27{
28 cache: HashMap<String, Option<T>>,
30 shaders_dir: Option<PathBuf>,
32}
33
34impl<T> Default for MetadataCache<T>
35where
36 T: for<'de> serde::Deserialize<'de>,
37{
38 fn default() -> Self {
39 Self {
40 cache: HashMap::new(),
41 shaders_dir: None,
42 }
43 }
44}
45
46impl<T> MetadataCache<T>
47where
48 T: for<'de> serde::Deserialize<'de>,
49{
50 pub fn new() -> Self {
52 Self::default()
53 }
54
55 pub fn with_shaders_dir(shaders_dir: PathBuf) -> Self {
57 Self {
58 cache: HashMap::new(),
59 shaders_dir: Some(shaders_dir),
60 }
61 }
62
63 pub fn set_shaders_dir(&mut self, shaders_dir: PathBuf) {
65 self.shaders_dir = Some(shaders_dir);
66 }
67
68 pub fn get(&mut self, shader_name: &str) -> Option<&T>
77 where
78 T: std::fmt::Debug,
79 {
80 if self.cache.contains_key(shader_name) {
81 return self.cache.get(shader_name).and_then(|m| m.as_ref());
82 }
83
84 let metadata = self.load_metadata(shader_name);
85 self.cache.insert(shader_name.to_string(), metadata);
86 self.cache.get(shader_name).and_then(|m| m.as_ref())
87 }
88
89 pub fn get_fresh(&self, shader_name: &str) -> Option<T> {
93 self.load_metadata(shader_name)
94 }
95
96 fn load_metadata(&self, shader_name: &str) -> Option<T> {
98 let path = self.resolve_shader_path(shader_name)?;
99 let source = std::fs::read_to_string(&path)
100 .map_err(|e| {
101 log::warn!("Failed to read shader file '{}': {}", path.display(), e);
102 })
103 .ok()?;
104 let yaml_trimmed = extract_yaml_block(&source)?;
105 match serde_yaml_ng::from_str(yaml_trimmed) {
106 Ok(metadata) => Some(metadata),
107 Err(e) => {
108 log::warn!(
109 "Failed to parse shader metadata YAML from '{}': {}",
110 path.display(),
111 e
112 );
113 None
114 }
115 }
116 }
117
118 fn resolve_shader_path(&self, shader_name: &str) -> Option<PathBuf> {
120 let shader_path = PathBuf::from(shader_name);
121
122 if shader_path.is_absolute() && shader_path.exists() {
123 return Some(shader_path);
124 }
125
126 if let Some(ref shaders_dir) = self.shaders_dir {
127 let full_path = shaders_dir.join(shader_name);
128 if full_path.exists() {
129 return Some(full_path);
130 }
131 }
132
133 let default_path = crate::config::Config::shader_path(shader_name);
134 if default_path.exists() {
135 return Some(default_path);
136 }
137
138 None
139 }
140
141 pub fn invalidate(&mut self, shader_name: &str) {
145 self.cache.remove(shader_name);
146 log::debug!("Invalidated metadata cache for: {}", shader_name);
147 }
148
149 pub fn invalidate_all(&mut self) {
153 self.cache.clear();
154 log::debug!("Invalidated all metadata cache entries");
155 }
156
157 pub fn is_cached(&self, shader_name: &str) -> bool {
159 self.cache.contains_key(shader_name)
160 }
161
162 pub fn cache_size(&self) -> usize {
164 self.cache.len()
165 }
166}
167
168pub type ShaderMetadataCache = MetadataCache<ShaderMetadata>;
176
177pub type CursorShaderMetadataCache = MetadataCache<CursorShaderMetadata>;