#![allow(async_fn_in_trait)]
extern crate self as alux_ext;
pub use alux_ext_macros as macros;
pub use alux_ext_macros::ext;
pub use extend;
use core::future::Future;
pub trait ApplyAlg<Context, Args> {
type Output;
fn apply(&self, context: Context, args: Args) -> impl Future<Output = Self::Output> + Send;
}
pub trait HandlerContextAlg<Context> {
type Handle: AsRef<Context> + Clone + Send + Sync + 'static;
}
pub trait OperationAlg {
type Context;
type Args;
const ARG_NAMES: &'static [&'static str];
}
#[cfg(test)]
mod tests {
use super::{ApplyAlg, OperationAlg, ext};
use std::sync::Arc;
trait ValueAlg {
fn value(&self) -> u32;
}
struct Value(u32);
impl ValueAlg for Value {
fn value(&self) -> u32 {
self.0
}
}
#[ext(name = ValueExt, defunc)]
impl<This> This
where
This: ValueAlg,
{
async fn value_plus(&self, increment: u32) -> u32 {
self.value() + increment
}
}
#[ext(name = DescribeExt, supertraits = ValueAlg + Sized)]
impl<This> This
where
This: ValueAlg,
{
fn describe(&self) -> String {
self.value().to_string()
}
}
#[tokio::test]
async fn preserves_extension_methods_and_defunctionalizes_their_application() {
let value = Arc::new(Value(40));
assert_eq!(value.value_plus(2).await, 42);
assert_eq!(ValuePlusOperation::<Value>::default().apply(value, (2,)).await, 42);
assert_eq!(<ValuePlusOperation<Value> as OperationAlg>::ARG_NAMES, &["increment"]);
}
#[test]
fn remains_compatible_with_ordinary_extensions() {
assert_eq!(Value(42).describe(), "42");
}
}