use std::future::Future;
use std::pin::Pin;
pub trait DynamicContext: Send + Sync {
fn key(&self) -> &str;
fn resolve(&self) -> impl Future<Output = String> + Send;
}
pub trait ErasedDynamicContext: Send + Sync {
fn key(&self) -> &str;
fn resolve_erased(&self) -> Pin<Box<dyn Future<Output = String> + Send + '_>>;
}
impl<T: DynamicContext> ErasedDynamicContext for T {
fn key(&self) -> &str {
DynamicContext::key(self)
}
fn resolve_erased(&self) -> Pin<Box<dyn Future<Output = String> + Send + '_>> {
Box::pin(self.resolve())
}
}
#[cfg(test)]
mod tests {
use super::*;
struct StaticContext {
key: String,
value: String,
}
impl DynamicContext for StaticContext {
fn key(&self) -> &str {
&self.key
}
async fn resolve(&self) -> String {
self.value.clone()
}
}
#[tokio::test]
async fn test_dynamic_context_resolve() {
let ctx = StaticContext {
key: "name".into(),
value: "Alice".into(),
};
assert_eq!(DynamicContext::key(&ctx), "name");
assert_eq!(ctx.resolve().await, "Alice");
}
#[tokio::test]
async fn test_erased_dynamic_context() {
let ctx: Box<dyn ErasedDynamicContext> = Box::new(StaticContext {
key: "role".into(),
value: "developer".into(),
});
assert_eq!(ctx.key(), "role");
assert_eq!(ctx.resolve_erased().await, "developer");
}
}