ass_core/plugin/
registry.rs1use super::{PluginError, Result, SectionProcessor, SectionResult, TagHandler, TagResult};
7use alloc::{
8 boxed::Box,
9 string::{String, ToString},
10 vec::Vec,
11};
12use core::fmt;
13
14#[cfg(feature = "std")]
15use std::collections::HashMap;
16
17#[cfg(not(feature = "std"))]
18use hashbrown::HashMap;
19
20pub struct ExtensionRegistry {
25 tag_handlers: HashMap<String, Box<dyn TagHandler>>,
27 section_processors: HashMap<String, Box<dyn SectionProcessor>>,
29}
30
31impl ExtensionRegistry {
32 #[must_use]
34 pub fn new() -> Self {
35 Self {
36 tag_handlers: HashMap::new(),
37 section_processors: HashMap::new(),
38 }
39 }
40
41 pub fn register_tag_handler(&mut self, handler: Box<dyn TagHandler>) -> Result<()> {
49 let name = handler.name().to_string();
50
51 if self.tag_handlers.contains_key(&name) {
52 return Err(PluginError::DuplicateHandler(name));
53 }
54
55 self.tag_handlers.insert(name, handler);
56 Ok(())
57 }
58
59 pub fn register_section_processor(
67 &mut self,
68 processor: Box<dyn SectionProcessor>,
69 ) -> Result<()> {
70 let name = processor.name().to_string();
71
72 if self.section_processors.contains_key(&name) {
73 return Err(PluginError::DuplicateHandler(name));
74 }
75
76 self.section_processors.insert(name, processor);
77 Ok(())
78 }
79
80 #[must_use]
90 pub fn process_tag(&self, tag_name: &str, args: &str) -> Option<TagResult> {
91 self.tag_handlers
92 .get(tag_name)
93 .map(|handler| handler.process(args))
94 }
95
96 #[must_use]
107 pub fn process_section(
108 &self,
109 section_name: &str,
110 header: &str,
111 lines: &[&str],
112 ) -> Option<SectionResult> {
113 self.section_processors
114 .get(section_name)
115 .map(|processor| processor.process(header, lines))
116 }
117
118 #[must_use]
120 pub fn tag_handler_names(&self) -> Vec<&str> {
121 self.tag_handlers.keys().map(String::as_str).collect()
122 }
123
124 #[must_use]
126 pub fn section_processor_names(&self) -> Vec<&str> {
127 self.section_processors.keys().map(String::as_str).collect()
128 }
129
130 #[must_use]
132 pub fn has_tag_handler(&self, name: &str) -> bool {
133 self.tag_handlers.contains_key(name)
134 }
135
136 #[must_use]
138 pub fn has_section_processor(&self, name: &str) -> bool {
139 self.section_processors.contains_key(name)
140 }
141
142 pub fn remove_tag_handler(&mut self, name: &str) -> Option<Box<dyn TagHandler>> {
148 self.tag_handlers.remove(name)
149 }
150
151 pub fn remove_section_processor(&mut self, name: &str) -> Option<Box<dyn SectionProcessor>> {
157 self.section_processors.remove(name)
158 }
159
160 pub fn clear(&mut self) {
162 self.tag_handlers.clear();
163 self.section_processors.clear();
164 }
165
166 #[must_use]
168 pub fn extension_count(&self) -> usize {
169 self.tag_handlers.len() + self.section_processors.len()
170 }
171}
172
173impl Default for ExtensionRegistry {
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179impl fmt::Debug for ExtensionRegistry {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 f.debug_struct("ExtensionRegistry")
182 .field("tag_handlers", &self.tag_handler_names())
183 .field("section_processors", &self.section_processor_names())
184 .finish()
185 }
186}