easyofd_reader/
resource_manage.rs1use std::collections::HashMap;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum ResourceType {
16 Font,
18 Image,
20 VectorGraphic,
22 ColorSpace,
24 DrawParam,
26 Other,
28}
29
30#[derive(Debug, Clone)]
34pub struct ResourceItem {
35 pub id: String,
37 pub resource_type: ResourceType,
39 pub file_path: Option<String>,
41 pub format: Option<String>,
43}
44
45impl ResourceItem {
46 #[must_use]
48 pub fn new(id: impl Into<String>, resource_type: ResourceType) -> Self {
49 Self {
50 id: id.into(),
51 resource_type,
52 file_path: None,
53 format: None,
54 }
55 }
56
57 #[must_use]
59 pub fn with_file_path(mut self, path: impl Into<String>) -> Self {
60 self.file_path = Some(path.into());
61 self
62 }
63
64 #[must_use]
66 pub fn with_format(mut self, format: impl Into<String>) -> Self {
67 self.format = Some(format.into());
68 self
69 }
70}
71
72#[derive(Debug, Clone, Default)]
79pub struct ResourceManage {
80 resources: HashMap<String, ResourceItem>,
82 by_type: HashMap<ResourceType, Vec<String>>,
84}
85
86impl ResourceManage {
87 #[must_use]
89 pub fn new() -> Self {
90 Self::default()
91 }
92
93 #[must_use]
95 pub fn from_items(items: Vec<ResourceItem>) -> Self {
96 let mut mgr = Self::new();
97 for item in items {
98 mgr.insert(item);
99 }
100 mgr
101 }
102
103 pub fn insert(&mut self, item: ResourceItem) {
105 let id = item.id.clone();
106 let resource_type = item.resource_type;
107 self.by_type
108 .entry(resource_type)
109 .or_default()
110 .push(id.clone());
111 self.resources.insert(id, item);
112 }
113
114 #[must_use]
118 pub fn get(&self, id: &str) -> Option<&ResourceItem> {
119 self.resources.get(id)
120 }
121
122 #[must_use]
124 pub fn all(&self) -> &HashMap<String, ResourceItem> {
125 &self.resources
126 }
127
128 #[must_use]
130 pub fn ids_by_type(&self, resource_type: ResourceType) -> &[String] {
131 self.by_type.get(&resource_type).map_or(&[], Vec::as_slice)
132 }
133
134 #[must_use]
136 pub fn items_by_type(&self, resource_type: ResourceType) -> Vec<&ResourceItem> {
137 self.ids_by_type(resource_type)
138 .iter()
139 .filter_map(|id| self.resources.get(id))
140 .collect()
141 }
142
143 #[must_use]
145 pub fn len(&self) -> usize {
146 self.resources.len()
147 }
148
149 #[must_use]
151 pub fn is_empty(&self) -> bool {
152 self.resources.is_empty()
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_empty_manager() {
162 let mgr = ResourceManage::new();
163 assert!(mgr.is_empty());
164 assert_eq!(mgr.len(), 0);
165 assert!(mgr.get("nonexistent").is_none());
166 }
167
168 #[test]
169 fn test_insert_and_get() {
170 let mut mgr = ResourceManage::new();
171 mgr.insert(
172 ResourceItem::new("1", ResourceType::Image)
173 .with_file_path("Res/image.png")
174 .with_format("PNG"),
175 );
176 assert_eq!(mgr.len(), 1);
177 let item = mgr.get("1").unwrap();
178 assert_eq!(item.resource_type, ResourceType::Image);
179 assert_eq!(item.file_path.as_deref(), Some("Res/image.png"));
180 }
181
182 #[test]
183 fn test_from_items() {
184 let items = vec![
185 ResourceItem::new("1", ResourceType::Font),
186 ResourceItem::new("2", ResourceType::Image),
187 ResourceItem::new("3", ResourceType::Font),
188 ];
189 let mgr = ResourceManage::from_items(items);
190 assert_eq!(mgr.len(), 3);
191 assert_eq!(mgr.ids_by_type(ResourceType::Font).len(), 2);
192 assert_eq!(mgr.ids_by_type(ResourceType::Image).len(), 1);
193 }
194
195 #[test]
196 fn test_items_by_type() {
197 let mut mgr = ResourceManage::new();
198 mgr.insert(ResourceItem::new("10", ResourceType::ColorSpace));
199 mgr.insert(ResourceItem::new("20", ResourceType::DrawParam));
200 mgr.insert(ResourceItem::new("30", ResourceType::ColorSpace));
201 let cs_items = mgr.items_by_type(ResourceType::ColorSpace);
202 assert_eq!(cs_items.len(), 2);
203 }
204
205 #[test]
206 fn test_insert_overwrite() {
207 let mut mgr = ResourceManage::new();
208 mgr.insert(ResourceItem::new("1", ResourceType::Image));
209 mgr.insert(ResourceItem::new("1", ResourceType::Font));
210 assert_eq!(mgr.len(), 1);
211 assert_eq!(mgr.get("1").unwrap().resource_type, ResourceType::Font);
212 }
213}