mod plugins;
pub use plugins::*;
use crate::types::PluginInput;
use crate::types::PluginOutput;
pub trait NativePlugin: Send + Sync {
fn name(&self) -> &'static str;
fn description(&self) -> &'static str;
fn process(&self, input: PluginInput) -> PluginOutput;
}
pub struct NativePluginRegistry {
plugins: Vec<Box<dyn NativePlugin>>,
}
#[inline]
fn plugin_short_name(name: &str) -> &str {
name.rsplit('.').next().unwrap_or(name)
}
impl NativePluginRegistry {
pub fn new() -> Self {
Self {
plugins: vec![
Box::new(ImplicitPricesPlugin),
Box::new(CheckCommodityPlugin),
Box::new(AutoTagPlugin::new()),
Box::new(AutoAccountsPlugin),
Box::new(LeafOnlyPlugin),
Box::new(NoDuplicatesPlugin),
Box::new(OneCommodityPlugin),
Box::new(UniquePricesPlugin),
Box::new(CheckClosingPlugin),
Box::new(CloseTreePlugin),
Box::new(CoherentCostPlugin),
Box::new(ForecastPlugin),
Box::new(SellGainsPlugin),
Box::new(PedanticPlugin),
Box::new(RxTxnPlugin),
Box::new(SplitExpensesPlugin),
Box::new(UnrealizedPlugin::new()),
Box::new(NoUnusedPlugin),
Box::new(CheckDrainedPlugin),
Box::new(CommodityAttrPlugin::new()),
Box::new(CheckAverageCostPlugin::new()),
Box::new(CurrencyAccountsPlugin::new()),
Box::new(ZerosumPlugin),
Box::new(EffectiveDatePlugin),
Box::new(GenerateBaseCcyPricesPlugin),
Box::new(RenameAccountsPlugin),
Box::new(ValuationPlugin),
Box::new(CapitalGainsLongShortPlugin),
Box::new(CapitalGainsGainLossPlugin),
Box::new(BoxAccrualPlugin),
],
}
}
pub fn find(&self, name: &str) -> Option<&dyn NativePlugin> {
let short_name = plugin_short_name(name);
self.plugins
.iter()
.find(|p| p.name() == short_name)
.map(std::convert::AsRef::as_ref)
}
pub fn list(&self) -> Vec<&dyn NativePlugin> {
self.plugins.iter().map(AsRef::as_ref).collect()
}
pub fn is_builtin(name: &str) -> bool {
let short_name = plugin_short_name(name);
let registry = Self::new();
registry.plugins.iter().any(|p| p.name() == short_name)
}
}
impl Default for NativePluginRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_short_name_bare() {
assert_eq!(plugin_short_name("zerosum"), "zerosum");
assert_eq!(plugin_short_name("implicit_prices"), "implicit_prices");
}
#[test]
fn test_plugin_short_name_beancount_plugins() {
assert_eq!(
plugin_short_name("beancount.plugins.implicit_prices"),
"implicit_prices"
);
assert_eq!(
plugin_short_name("beancount.plugins.check_commodity"),
"check_commodity"
);
}
#[test]
fn test_plugin_short_name_beanahead() {
assert_eq!(
plugin_short_name("beanahead.plugins.rx_txn_plugin"),
"rx_txn_plugin"
);
}
#[test]
fn test_plugin_short_name_reds_plugins() {
assert_eq!(
plugin_short_name("beancount_reds_plugins.zerosum.zerosum"),
"zerosum"
);
assert_eq!(
plugin_short_name("beancount_reds_plugins.capital_gains_classifier.gain_loss"),
"gain_loss"
);
assert_eq!(
plugin_short_name("beancount_reds_plugins.effective_date.effective_date"),
"effective_date"
);
}
#[test]
fn test_plugin_short_name_tarioch() {
assert_eq!(
plugin_short_name("tariochbctools.plugins.generate_base_ccy_prices"),
"generate_base_ccy_prices"
);
}
#[test]
fn test_plugin_short_name_empty() {
assert_eq!(plugin_short_name(""), "");
}
#[test]
fn test_registry_find_short_name() {
let registry = NativePluginRegistry::new();
assert!(registry.find("implicit_prices").is_some());
assert!(registry.find("zerosum").is_some());
assert!(registry.find("nonexistent").is_none());
}
#[test]
fn test_registry_find_qualified_name() {
let registry = NativePluginRegistry::new();
assert!(registry.find("beancount.plugins.implicit_prices").is_some());
assert!(registry.find("beanahead.plugins.rx_txn_plugin").is_some());
assert!(
registry
.find("beancount_reds_plugins.zerosum.zerosum")
.is_some()
);
assert!(
registry
.find("beancount_reds_plugins.capital_gains_classifier.gain_loss")
.is_some()
);
}
#[test]
fn test_is_builtin_short_name() {
assert!(NativePluginRegistry::is_builtin("implicit_prices"));
assert!(NativePluginRegistry::is_builtin("zerosum"));
assert!(!NativePluginRegistry::is_builtin("nonexistent"));
}
#[test]
fn test_is_builtin_qualified_name() {
assert!(NativePluginRegistry::is_builtin(
"beancount.plugins.implicit_prices"
));
assert!(NativePluginRegistry::is_builtin(
"beanahead.plugins.rx_txn_plugin"
));
assert!(NativePluginRegistry::is_builtin(
"beancount_reds_plugins.zerosum.zerosum"
));
assert!(!NativePluginRegistry::is_builtin("some.random.nonexistent"));
}
}