use std::collections::BTreeMap;
use crate::core::Core;
use crate::error::BuildError;
use crate::receipt::ReceiptHashPolicy;
use crate::{handler, module, operation, receipt, register};
type BoxedHandler = Box<dyn handler::Handler + 'static>;
type BoxedReceiptSink = Box<dyn receipt::ReceiptSink + 'static>;
#[derive(Default)]
pub struct CoreBuilder {
descriptors: BTreeMap<String, operation::OperationDescriptor>,
handlers: BTreeMap<String, BoxedHandler>,
receipt_sink: Option<BoxedReceiptSink>,
receipt_hash_policy: ReceiptHashPolicy,
}
impl CoreBuilder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn mount(&mut self, module: module::Module) -> Result<&mut Self, BuildError> {
let module_name = module.name().to_owned();
let register = module
.into_register()
.map_err(|error| BuildError::invalid_module(&module_name, error.to_string()))?;
for (_, descriptor) in register.into_map() {
self.register_operation(descriptor)?;
}
Ok(self)
}
pub fn register_operation(
&mut self,
descriptor: operation::OperationDescriptor,
) -> Result<&mut Self, BuildError> {
let name = descriptor.name().to_owned();
descriptor
.validate()
.map_err(|error| BuildError::invalid_operation(&name, error.to_string()))?;
if self.descriptors.contains_key(&name) {
return Err(BuildError::duplicate_operation(name));
}
self.descriptors.insert(name, descriptor);
Ok(self)
}
pub fn register_handler<H>(
&mut self,
name: impl Into<String>,
handler: H,
) -> Result<&mut Self, BuildError>
where
H: handler::Handler + 'static,
{
let name = name.into();
register::validate_module_name(&name)
.map_err(|error| BuildError::invalid_handler(&name, error.to_string()))?;
if self.handlers.contains_key(&name) {
return Err(BuildError::duplicate_handler(name));
}
self.handlers.insert(name, Box::new(handler));
Ok(self)
}
pub fn register<H>(
&mut self,
descriptor: operation::OperationDescriptor,
handler: H,
) -> Result<&mut Self, BuildError>
where
H: handler::Handler + 'static,
{
let name = descriptor.name().to_owned();
descriptor
.validate()
.map_err(|error| BuildError::invalid_operation(&name, error.to_string()))?;
if self.descriptors.contains_key(&name) {
return Err(BuildError::duplicate_operation(name));
}
if self.handlers.contains_key(&name) {
return Err(BuildError::duplicate_handler(name));
}
self.descriptors.insert(name.clone(), descriptor);
self.handlers.insert(name, Box::new(handler));
Ok(self)
}
pub fn register_item(
&mut self,
item: operation::OperationRegisterItem,
) -> Result<&mut Self, BuildError> {
let (descriptor, handler) = item.into_parts();
self.register(descriptor, handler)
}
pub fn receipt_sink<S>(&mut self, sink: S) -> &mut Self
where
S: receipt::ReceiptSink + 'static,
{
self.receipt_sink = Some(Box::new(sink));
self
}
pub fn clear_receipt_sink(&mut self) -> &mut Self {
self.receipt_sink = None;
self
}
pub fn receipt_hash_policy(&mut self, policy: ReceiptHashPolicy) -> &mut Self {
self.receipt_hash_policy = policy;
self
}
pub fn build(self) -> Result<Core, BuildError> {
for name in self.descriptors.keys() {
if !self.handlers.contains_key(name) {
return Err(BuildError::missing_handler(name.clone()));
}
}
for name in self.handlers.keys() {
if !self.descriptors.contains_key(name) {
return Err(BuildError::missing_descriptor(name.clone()));
}
}
Ok(Core {
descriptors: self.descriptors,
handlers: self.handlers,
receipt_sink: self.receipt_sink,
receipt_hash_policy: self.receipt_hash_policy,
})
}
}