use crate::operation::OperationDescriptor;
use crate::register::{validate_module_name, Register, RegisterValidationError};
use std::collections::BTreeMap;
pub struct Module {
name: String,
operations: BTreeMap<String, OperationDescriptor>,
}
impl Module {
#[must_use]
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
operations: BTreeMap::new(),
}
}
pub fn from_operations<I>(
name: impl Into<String>,
operations: I,
) -> Result<Self, RegisterValidationError>
where
I: IntoIterator<Item = OperationDescriptor>,
{
let mut module = Self::new(name);
for descriptor in operations {
module.insert_operation(descriptor)?;
}
module.validate()?;
Ok(module)
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
pub fn insert_operation(
&mut self,
descriptor: OperationDescriptor,
) -> Result<(), RegisterValidationError> {
let name = descriptor.name().to_owned();
if self.operations.contains_key(&name) {
return Err(RegisterValidationError::DuplicateOperationName { name });
}
self.operations.insert(name, descriptor);
Ok(())
}
pub fn validate(&self) -> Result<(), RegisterValidationError> {
validate_module_name(&self.name)?;
for descriptor in self.operations.values() {
descriptor
.validate()
.map_err(|source| RegisterValidationError::InvalidDescriptor {
name: descriptor.name().to_owned(),
source,
})?;
}
Ok(())
}
#[must_use]
pub fn operation(&self, name: &str) -> Option<&OperationDescriptor> {
self.operations.get(name)
}
pub fn operations(&self) -> impl Iterator<Item = (&str, &OperationDescriptor)> + '_ {
self.operations
.iter()
.map(|(name, descriptor)| (name.as_str(), descriptor))
}
#[must_use]
pub fn operation_count(&self) -> usize {
self.operations.len()
}
pub fn into_register(self) -> Result<Register, RegisterValidationError> {
self.validate()?;
Register::from_operations(self.operations.into_values())
}
}