use hitbox::{
CachePolicy, CacheableRequest, Extractor, KeyPart, Predicate, RequestCachePolicy,
predicate::PredicateResult,
};
use crate::KeyExtract;
#[derive(Clone, Debug)]
pub struct Arg<T> {
name: &'static str,
value: T,
}
impl<T> Arg<T> {
pub fn new(name: &'static str, value: T) -> Self {
Self { name, value }
}
pub fn value(&self) -> &T {
&self.value
}
pub fn into_value(self) -> T {
self.value
}
}
impl<T: KeyExtract> KeyExtract for Arg<T> {
fn extract(&self) -> Vec<KeyPart> {
let inner = self.value.extract();
if inner.len() == 1 {
inner.into_iter().map(|p| p.with_key(self.name)).collect()
} else {
inner.into_iter().map(|p| p.prefixed(self.name)).collect()
}
}
}
#[derive(Clone, Debug)]
pub struct Skipped<T>(T);
impl<T> Skipped<T> {
pub fn new(value: T) -> Self {
Self(value)
}
pub fn value(&self) -> &T {
&self.0
}
pub fn into_value(self) -> T {
self.0
}
}
impl<T> KeyExtract for Skipped<T> {
fn extract(&self) -> Vec<KeyPart> {
vec![]
}
}
#[derive(Clone, Debug)]
pub struct Args<T>(pub T);
impl<T> Args<T> {
pub fn new(inner: T) -> Self {
Self(inner)
}
pub fn into_inner(self) -> T {
self.0
}
}
macro_rules! impl_cacheable_request_for_args {
() => {
impl CacheableRequest for Args<()> {
async fn cache_policy<P, E>(self, predicates: P, extractors: E) -> RequestCachePolicy<Self>
where
P: Predicate<Subject = Self> + Send + Sync,
E: Extractor<Subject = Self> + Send + Sync,
{
match predicates.check(self).await {
PredicateResult::Cacheable(subject) => {
let (subject, key) = extractors.get(subject).await.into_cache_key();
CachePolicy::Cacheable(hitbox::CacheablePolicyData::new(key, subject))
}
PredicateResult::NonCacheable(subject) => CachePolicy::NonCacheable(subject),
}
}
}
};
($($T:ident),+) => {
impl<$($T: Send + Sync + 'static),+> CacheableRequest for Args<($($T,)+)> {
async fn cache_policy<P, E>(self, predicates: P, extractors: E) -> RequestCachePolicy<Self>
where
P: Predicate<Subject = Self> + Send + Sync,
E: Extractor<Subject = Self> + Send + Sync,
{
match predicates.check(self).await {
PredicateResult::Cacheable(subject) => {
let (subject, key) = extractors.get(subject).await.into_cache_key();
CachePolicy::Cacheable(hitbox::CacheablePolicyData::new(key, subject))
}
PredicateResult::NonCacheable(subject) => CachePolicy::NonCacheable(subject),
}
}
}
};
}
impl_cacheable_request_for_args!();
impl_cacheable_request_for_args!(T0);
impl_cacheable_request_for_args!(T0, T1);
impl_cacheable_request_for_args!(T0, T1, T2);
impl_cacheable_request_for_args!(T0, T1, T2, T3);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5, T6);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5, T6, T7);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_cacheable_request_for_args!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);