use super::descriptors::{
DYNAMIC_MODULE_MARKER, DecoratorMetadata, DerivedMacroDescriptor, DerivedMacroRegistration,
};
use crate::host::{MacroRegistry, Result};
use std::collections::BTreeSet;
inventory::collect!(DerivedMacroRegistration);
pub fn modules() -> BTreeSet<&'static str> {
inventory::iter::<DerivedMacroRegistration>
.into_iter()
.map(|entry| entry.descriptor.module)
.collect()
}
pub fn register_module(module: &str, registry: &MacroRegistry) -> Result<bool> {
let descriptors: Vec<&DerivedMacroDescriptor> = inventory::iter::<DerivedMacroRegistration>
.into_iter()
.filter(|entry| entry.descriptor.module == module)
.map(|entry| entry.descriptor)
.collect();
if descriptors.is_empty() {
return Ok(false);
}
let mut runtime: BTreeSet<String> = BTreeSet::new();
for descriptor in &descriptors {
for entry in descriptor.runtime {
runtime.insert(entry.to_string());
}
}
for descriptor in descriptors {
registry.register(module, descriptor.name, (descriptor.constructor)())?;
}
Ok(true)
}
pub fn decorator_metadata() -> Vec<DecoratorMetadata> {
inventory::iter::<DerivedMacroRegistration>
.into_iter()
.flat_map(|entry| entry.descriptor.decorators)
.map(|decorator| DecoratorMetadata {
module: decorator.module,
export: decorator.export,
kind: decorator.kind,
docs: decorator.docs,
})
.collect()
}
pub fn decorator_modules() -> BTreeSet<&'static str> {
inventory::iter::<DerivedMacroRegistration>
.into_iter()
.flat_map(|entry| entry.descriptor.decorators)
.map(|decorator| decorator.module)
.collect()
}
pub fn decorator_annotation_names() -> BTreeSet<&'static str> {
inventory::iter::<DerivedMacroRegistration>
.into_iter()
.flat_map(|entry| entry.descriptor.decorators)
.map(|decorator| decorator.export)
.collect()
}
pub fn macro_names() -> Vec<&'static str> {
inventory::iter::<DerivedMacroRegistration>
.into_iter()
.map(|entry| entry.descriptor.name)
.collect()
}
pub fn lookup_by_name(name: &str) -> Option<&'static DerivedMacroDescriptor> {
inventory::iter::<DerivedMacroRegistration>
.into_iter()
.find(|entry| entry.descriptor.name == name)
.map(|entry| entry.descriptor)
}
pub fn register_all_with_module(actual_module: &str, registry: &MacroRegistry) -> Result<usize> {
let mut count = 0;
for entry in inventory::iter::<DerivedMacroRegistration> {
let descriptor = entry.descriptor;
let module = if descriptor.module == DYNAMIC_MODULE_MARKER {
actual_module
} else {
descriptor.module
};
registry.register(module, descriptor.name, (descriptor.constructor)())?;
count += 1;
}
Ok(count)
}