microcad_lang/builtin/
file_io.rs1use std::{collections::HashMap, rc::Rc};
7
8use crate::Id;
9
10pub trait FileIoInterface {
12 fn id(&self) -> Id;
14
15 fn file_extensions(&self) -> Vec<Id> {
17 vec![self.id()]
18 }
19}
20
21pub(crate) struct FileIoRegistry<T> {
23 by_id: std::collections::HashMap<Id, T>,
25 by_file_extension: std::collections::HashMap<Id, Vec<T>>,
27}
28
29impl<T> Default for FileIoRegistry<T> {
30 fn default() -> Self {
31 Self {
32 by_id: HashMap::default(),
33 by_file_extension: HashMap::default(),
34 }
35 }
36}
37
38impl<T: FileIoInterface + ?Sized> FileIoRegistry<Rc<T>> {
39 pub fn insert(&mut self, rc: Rc<T>) {
43 let id = rc.id();
44 assert!(!id.is_empty());
45
46 if self.by_id.contains_key(&id) {
47 panic!("Importer already exists");
48 }
49
50 self.by_id.insert(id, rc.clone());
51
52 let extensions = rc.file_extensions();
53 for ext in extensions {
54 if !ext.is_empty() && self.by_file_extension.contains_key(&ext) {
55 self.by_file_extension
56 .get_mut(&ext)
57 .expect("Exporter list")
58 .push(rc.clone());
59 } else {
60 self.by_file_extension.insert(ext, vec![rc.clone()]);
61 }
62 }
63 }
64
65 pub fn by_filename(&self, filename: impl AsRef<std::path::Path>) -> Vec<Rc<T>> {
67 let ext: Id = filename
68 .as_ref()
69 .extension()
70 .unwrap_or_default()
71 .to_str()
72 .unwrap_or_default()
73 .into();
74
75 self.by_file_extension
76 .get(&ext)
77 .cloned()
78 .unwrap_or_default()
79 }
80
81 pub fn by_id(&self, id: &Id) -> Option<Rc<T>> {
83 self.by_id.get(id).cloned()
84 }
85}