use std::{collections::HashMap, sync::Arc};
use async_trait::async_trait;
use super::error::BspError;
#[async_trait]
pub trait Merger<S>: Send + Sync {
fn merge(&self, trunk: &mut S, branch: S);
async fn finish(&self, _trunk: &mut S) -> Result<(), BspError> {
Ok(())
}
}
#[async_trait]
impl<S, F> Merger<S> for F
where
F: Fn(&mut S, S) + Send + Sync,
{
fn merge(&self, trunk: &mut S, branch: S) {
self(trunk, branch);
}
}
pub type MergerMap<S> = HashMap<String, Arc<dyn Merger<S>>>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_closure_is_a_merger() {
let merger = |trunk: &mut Vec<String>, branch: Vec<String>| {
for item in branch {
if !trunk.contains(&item) {
trunk.push(item);
}
}
};
let mut trunk = vec!["a".to_string()];
Merger::merge(&merger, &mut trunk, vec!["a".to_string(), "b".to_string()]);
assert_eq!(trunk, vec!["a".to_string(), "b".to_string()]);
}
#[test]
fn test_fold_declaration_order_is_deterministic() {
let append = |trunk: &mut Vec<&'static str>, mut branch: Vec<&'static str>| {
trunk.append(&mut branch);
};
let branches = [vec!["a"], vec!["b"], vec!["c"]];
let mut trunk = Vec::new();
for branch in branches {
Merger::merge(&append, &mut trunk, branch);
}
assert_eq!(trunk, vec!["a", "b", "c"]);
}
}