use super::*;
use crate::internal_prelude::*;
pub trait ProtocolUpdateGenerator: 'static {
fn insert_status_tracking_flash_transactions(&self) -> bool {
true
}
fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator<'_> + '_>>;
}
pub trait ProtocolUpdateBatchGroupGenerator<'a> {
fn batch_group_name(&self) -> &'static str;
fn generate_batches(
self: Box<Self>,
store: &dyn SubstateDatabase,
) -> Vec<Box<dyn ProtocolUpdateBatchGenerator + 'a>>;
}
pub trait ProtocolUpdateBatchGenerator {
fn batch_name(&self) -> &str;
fn generate_batch(self: Box<Self>, store: &dyn SubstateDatabase) -> ProtocolUpdateBatch;
}
pub(super) struct NoOpGenerator;
impl ProtocolUpdateGenerator for NoOpGenerator {
fn batch_groups(&self) -> Vec<Box<dyn ProtocolUpdateBatchGroupGenerator<'_>>> {
vec![]
}
}
pub struct FixedBatchGroupGenerator<'a> {
name: &'static str,
batches: Vec<Box<dyn ProtocolUpdateBatchGenerator + 'a>>,
}
impl<'a> FixedBatchGroupGenerator<'a> {
pub fn named(name: &'static str) -> Self {
if name != name.to_ascii_lowercase().as_str() {
panic!("Protocol update batch group names should be in kebab-case for consistency");
}
Self {
name,
batches: vec![],
}
}
pub fn add_bespoke_batch(mut self, batch: impl ProtocolUpdateBatchGenerator + 'a) -> Self {
self.batches.push(Box::new(batch));
self
}
pub fn add_batch(
self,
name: impl Into<String>,
generator: impl FnOnce(&dyn SubstateDatabase) -> ProtocolUpdateBatch + 'a,
) -> Self {
self.add_bespoke_batch(BatchGenerator::new(name, generator))
}
pub fn build(self) -> Box<dyn ProtocolUpdateBatchGroupGenerator<'a> + 'a> {
Box::new(self)
}
}
impl<'a> ProtocolUpdateBatchGroupGenerator<'a> for FixedBatchGroupGenerator<'a> {
fn batch_group_name(&self) -> &'static str {
self.name
}
fn generate_batches(
self: Box<Self>,
_store: &dyn SubstateDatabase,
) -> Vec<Box<dyn ProtocolUpdateBatchGenerator + 'a>> {
self.batches
}
}
#[allow(clippy::type_complexity)]
pub struct BatchGenerator<'a> {
name: String,
generator: Box<dyn FnOnce(&dyn SubstateDatabase) -> ProtocolUpdateBatch + 'a>,
}
impl<'a> BatchGenerator<'a> {
pub fn new(
name: impl Into<String>,
generator: impl FnOnce(&dyn SubstateDatabase) -> ProtocolUpdateBatch + 'a,
) -> Self {
let name = name.into();
if name.to_ascii_lowercase() != name {
panic!("Protocol update batch names should be in kebab-case for consistency");
}
Self {
name,
generator: Box::new(generator),
}
}
pub fn build(self) -> Box<dyn ProtocolUpdateBatchGenerator + 'a> {
Box::new(self)
}
}
impl<'a> ProtocolUpdateBatchGenerator for BatchGenerator<'a> {
fn batch_name(&self) -> &str {
self.name.as_str()
}
fn generate_batch(self: Box<Self>, store: &dyn SubstateDatabase) -> ProtocolUpdateBatch {
(self.generator)(store)
}
}