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