use alux_sdk::{AlgebraCall, trait_algebra};
use tokio::sync::Mutex;
#[trait_algebra(derive(Debug, PartialEq), proxy)]
trait Counter {
async fn add(&self, amount: u64) -> u64;
async fn reset(&self);
}
#[derive(Default)]
struct Total(u64);
impl CounterInterpreter for Total {
async fn add(&mut self, amount: u64) -> u64 {
self.0 += amount;
self.0
}
async fn reset(&mut self) {
self.0 = 0;
}
}
#[derive(Default)]
struct Here(Mutex<Total>);
impl AlgebraCall<CounterOp, CounterReply> for Here {
async fn ask(&self, operation: CounterOp) -> Option<CounterReply> {
Some(operation.interpret(&mut *self.0.lock().await).await)
}
}
struct Nowhere;
impl AlgebraCall<CounterOp, CounterReply> for Nowhere {
async fn ask(&self, _operation: CounterOp) -> Option<CounterReply> {
None
}
}
#[tokio::test]
async fn a_proxy_is_the_trait_it_states() {
let counter = CounterProxy::new(Here::default());
assert_eq!(counter.add(2).await, 2);
assert_eq!(counter.add(3).await, 5);
counter.reset().await;
assert_eq!(counter.add(1).await, 1);
}
#[tokio::test]
async fn a_proxy_is_cloneable_when_its_sender_is() {
#[derive(Clone)]
struct Shared;
impl AlgebraCall<CounterOp, CounterReply> for Shared {
async fn ask(&self, _operation: CounterOp) -> Option<CounterReply> {
Some(CounterReply::Add(7))
}
}
let counter = CounterProxy::new(Shared);
let another = counter.clone();
assert_eq!(counter.add(1).await, 7);
assert_eq!(another.add(1).await, 7);
}
#[tokio::test]
async fn a_method_stating_no_value_carries_on_where_nothing_answers() {
let counter = CounterProxy::new(Nowhere);
counter.reset().await;
}