use super::{PluginError, Result, SectionProcessor, SectionResult, TagHandler, TagResult};
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use core::fmt;
#[cfg(feature = "std")]
use std::collections::HashMap;
#[cfg(not(feature = "std"))]
use hashbrown::HashMap;
pub struct ExtensionRegistry {
tag_handlers: HashMap<String, Box<dyn TagHandler>>,
section_processors: HashMap<String, Box<dyn SectionProcessor>>,
}
impl ExtensionRegistry {
#[must_use]
pub fn new() -> Self {
Self {
tag_handlers: HashMap::new(),
section_processors: HashMap::new(),
}
}
pub fn register_tag_handler(&mut self, handler: Box<dyn TagHandler>) -> Result<()> {
let name = handler.name().to_string();
if self.tag_handlers.contains_key(&name) {
return Err(PluginError::DuplicateHandler(name));
}
self.tag_handlers.insert(name, handler);
Ok(())
}
pub fn register_section_processor(
&mut self,
processor: Box<dyn SectionProcessor>,
) -> Result<()> {
let name = processor.name().to_string();
if self.section_processors.contains_key(&name) {
return Err(PluginError::DuplicateHandler(name));
}
self.section_processors.insert(name, processor);
Ok(())
}
#[must_use]
pub fn process_tag(&self, tag_name: &str, args: &str) -> Option<TagResult> {
self.tag_handlers
.get(tag_name)
.map(|handler| handler.process(args))
}
#[must_use]
pub fn process_section(
&self,
section_name: &str,
header: &str,
lines: &[&str],
) -> Option<SectionResult> {
self.section_processors
.get(section_name)
.map(|processor| processor.process(header, lines))
}
#[must_use]
pub fn tag_handler_names(&self) -> Vec<&str> {
self.tag_handlers.keys().map(String::as_str).collect()
}
#[must_use]
pub fn section_processor_names(&self) -> Vec<&str> {
self.section_processors.keys().map(String::as_str).collect()
}
#[must_use]
pub fn has_tag_handler(&self, name: &str) -> bool {
self.tag_handlers.contains_key(name)
}
#[must_use]
pub fn has_section_processor(&self, name: &str) -> bool {
self.section_processors.contains_key(name)
}
pub fn remove_tag_handler(&mut self, name: &str) -> Option<Box<dyn TagHandler>> {
self.tag_handlers.remove(name)
}
pub fn remove_section_processor(&mut self, name: &str) -> Option<Box<dyn SectionProcessor>> {
self.section_processors.remove(name)
}
pub fn clear(&mut self) {
self.tag_handlers.clear();
self.section_processors.clear();
}
#[must_use]
pub fn extension_count(&self) -> usize {
self.tag_handlers.len() + self.section_processors.len()
}
}
impl Default for ExtensionRegistry {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for ExtensionRegistry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExtensionRegistry")
.field("tag_handlers", &self.tag_handler_names())
.field("section_processors", &self.section_processor_names())
.finish()
}
}