use brk_cohort::Filter;
use brk_error::Result;
use brk_types::{
Cents, Height, PartsPerMillion32, PartsPerMillionSigned32, PartsPerMillionSigned64, Version,
};
use schemars::JsonSchema;
use vecdb::{BytesVec, BytesVecValue, CachedBoxedVec, Database, ImportableVec};
use crate::{
indexes,
internal::{
CachedWindowStartVec, FiatPerBlock, FiatPerBlockCumulativeWithSums, FiatType, NumericValue,
PerBlock, PerBlockCumulativeRolling, PercentPerBlock, PercentRollingWindows, Price,
PriceWithRatioPerBlock, RatioPerBlock, RollingWindow24hPerBlock, RollingWindows,
RollingWindowsFrom1w, SpotValuePerBlock, ValuePerBlock, ValuePerBlockCumulative,
ValuePerBlockCumulativeRolling, Windows,
},
};
pub(crate) trait ConfigImport: Sized {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self>;
}
macro_rules! impl_config_import {
($($type:ty),+ $(,)?) => {
$(
impl ConfigImport for $type {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
)+
};
}
impl_config_import!(
ValuePerBlock,
ValuePerBlockCumulative,
RatioPerBlock<PartsPerMillionSigned32>,
PercentPerBlock<PartsPerMillion32>,
PercentPerBlock<PartsPerMillionSigned32>,
PercentPerBlock<PartsPerMillionSigned64>,
PercentRollingWindows<PartsPerMillion32>,
Price<PerBlock<Cents>>,
);
impl ConfigImport for PriceWithRatioPerBlock {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(
cfg.db,
&cfg.name(suffix),
cfg.version + offset,
cfg.indexes,
cfg.spot_price,
)
}
}
impl ConfigImport for SpotValuePerBlock {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(
cfg.db,
&cfg.name(suffix),
cfg.version + offset,
cfg.indexes,
cfg.spot_price,
)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for PerBlock<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<T> ConfigImport for PerBlockCumulativeRolling<T>
where
T: NumericValue + JsonSchema,
{
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(
cfg.db,
&cfg.name(suffix),
cfg.version + offset,
cfg.indexes,
cfg.cached_starts,
)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindows<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindow24hPerBlock<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl ConfigImport for ValuePerBlockCumulativeRolling {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(
cfg.db,
&cfg.name(suffix),
cfg.version + offset,
cfg.indexes,
cfg.cached_starts,
)
}
}
impl<C: FiatType> ConfigImport for FiatPerBlockCumulativeWithSums<C> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(
cfg.db,
&cfg.name(suffix),
cfg.version + offset,
cfg.indexes,
cfg.cached_starts,
)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindowsFrom1w<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<C: FiatType> ConfigImport for FiatPerBlock<C> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<T: BytesVecValue> ConfigImport for BytesVec<Height, T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Ok(Self::forced_import(
cfg.db,
&cfg.name(suffix),
cfg.version + offset,
)?)
}
}
#[derive(Clone, Copy)]
pub struct ImportConfig<'a> {
pub db: &'a Database,
pub filter: &'a Filter,
pub full_name: &'a str,
pub version: Version,
pub indexes: &'a indexes::Vecs,
pub cached_starts: &'a Windows<&'a CachedWindowStartVec>,
pub spot_price: &'a CachedBoxedVec<Height, Cents>,
}
impl<'a> ImportConfig<'a> {
pub(crate) fn name(&self, suffix: &str) -> String {
if self.full_name.is_empty() {
suffix.to_string()
} else if suffix.is_empty() {
self.full_name.to_string()
} else {
format!("{}_{suffix}", self.full_name)
}
}
pub(crate) fn import<T: ConfigImport>(&self, suffix: &str, offset: Version) -> Result<T> {
T::config_import(self, suffix, offset)
}
}