use std::sync::Arc;
use hitbox::backend::CacheBackend;
use hitbox::concurrency::NoopConcurrencyManager;
use hitbox::policy::PolicyConfig;
use hitbox_core::DisabledOffload;
pub struct NoBackend;
pub struct NoPolicy;
pub struct NoContext;
pub struct WithContext;
pub struct WithBackend<B>(pub Arc<B>);
pub struct WithPolicy(pub Arc<PolicyConfig>);
pub struct Cache<B, CM = NoopConcurrencyManager, O = DisabledOffload> {
pub(crate) backend: Arc<B>,
pub(crate) policy: Arc<PolicyConfig>,
pub(crate) concurrency_manager: CM,
pub(crate) offload: O,
}
impl<B, CM, O> Cache<B, CM, O> {
pub fn backend(&self) -> &Arc<B> {
&self.backend
}
pub fn policy(&self) -> &Arc<PolicyConfig> {
&self.policy
}
pub fn concurrency_manager(&self) -> &CM {
&self.concurrency_manager
}
pub fn offload(&self) -> &O {
&self.offload
}
}
pub trait CacheAccess {
type Backend;
type ConcurrencyManager;
type Offload;
fn backend(&self) -> Arc<Self::Backend>;
fn policy(&self) -> Arc<PolicyConfig>;
fn concurrency_manager(&self) -> Self::ConcurrencyManager;
fn offload(&self) -> Self::Offload;
}
impl<B, CM: Clone, O: Clone> CacheAccess for Cache<B, CM, O> {
type Backend = B;
type ConcurrencyManager = CM;
type Offload = O;
fn backend(&self) -> Arc<B> {
Arc::clone(&self.backend)
}
fn policy(&self) -> Arc<PolicyConfig> {
Arc::clone(&self.policy)
}
fn concurrency_manager(&self) -> CM {
self.concurrency_manager.clone()
}
fn offload(&self) -> O {
self.offload.clone()
}
}
impl<T: CacheAccess> CacheAccess for &T {
type Backend = T::Backend;
type ConcurrencyManager = T::ConcurrencyManager;
type Offload = T::Offload;
fn backend(&self) -> Arc<Self::Backend> {
(**self).backend()
}
fn policy(&self) -> Arc<PolicyConfig> {
(**self).policy()
}
fn concurrency_manager(&self) -> Self::ConcurrencyManager {
(**self).concurrency_manager()
}
fn offload(&self) -> Self::Offload {
(**self).offload()
}
}
impl<T: CacheAccess> CacheAccess for Arc<T> {
type Backend = T::Backend;
type ConcurrencyManager = T::ConcurrencyManager;
type Offload = T::Offload;
fn backend(&self) -> Arc<Self::Backend> {
(**self).backend()
}
fn policy(&self) -> Arc<PolicyConfig> {
(**self).policy()
}
fn concurrency_manager(&self) -> Self::ConcurrencyManager {
(**self).concurrency_manager()
}
fn offload(&self) -> Self::Offload {
(**self).offload()
}
}
impl<B, CM: Clone, O: Clone> Clone for Cache<B, CM, O> {
fn clone(&self) -> Self {
Self {
backend: Arc::clone(&self.backend),
policy: Arc::clone(&self.policy),
concurrency_manager: self.concurrency_manager.clone(),
offload: self.offload.clone(),
}
}
}
impl Cache<(), NoopConcurrencyManager, DisabledOffload> {
pub fn builder() -> CacheBuilder<NoBackend, NoPolicy, NoopConcurrencyManager, DisabledOffload> {
CacheBuilder {
backend: NoBackend,
policy: NoPolicy,
concurrency_manager: NoopConcurrencyManager,
offload: DisabledOffload,
}
}
}
pub struct CacheBuilder<B, P, CM, O> {
pub(crate) backend: B,
pub(crate) policy: P,
pub(crate) concurrency_manager: CM,
pub(crate) offload: O,
}
impl<P, CM, O> CacheBuilder<NoBackend, P, CM, O> {
pub fn backend<B: CacheBackend>(self, backend: B) -> CacheBuilder<WithBackend<B>, P, CM, O> {
CacheBuilder {
backend: WithBackend(Arc::new(backend)),
policy: self.policy,
concurrency_manager: self.concurrency_manager,
offload: self.offload,
}
}
}
impl<B, CM, O> CacheBuilder<B, NoPolicy, CM, O> {
pub fn policy(self, policy: PolicyConfig) -> CacheBuilder<B, WithPolicy, CM, O> {
CacheBuilder {
backend: self.backend,
policy: WithPolicy(Arc::new(policy)),
concurrency_manager: self.concurrency_manager,
offload: self.offload,
}
}
}
impl<B, P, CM, O> CacheBuilder<B, P, CM, O> {
pub fn concurrency_manager<CM2>(self, cm: CM2) -> CacheBuilder<B, P, CM2, O> {
CacheBuilder {
backend: self.backend,
policy: self.policy,
concurrency_manager: cm,
offload: self.offload,
}
}
pub fn offload<O2>(self, offload: O2) -> CacheBuilder<B, P, CM, O2> {
CacheBuilder {
backend: self.backend,
policy: self.policy,
concurrency_manager: self.concurrency_manager,
offload,
}
}
}
impl<B, CM, O> CacheBuilder<WithBackend<B>, WithPolicy, CM, O>
where
B: CacheBackend,
{
pub fn build(self) -> Cache<B, CM, O> {
Cache {
backend: self.backend.0,
policy: self.policy.0,
concurrency_manager: self.concurrency_manager,
offload: self.offload,
}
}
}