lakka 0.1.0

Simple actors with macros
Documentation
use std::{future::Future, pin::Pin, time::Duration};

use crate::{ActorError, Channel};

#[derive(Debug, Clone)]
pub struct IntervalMessage<T> {
    pub msg: T,
    pub counter: u32,
}

impl<T> IntervalMessage<T> {
    pub fn new(msg: T) -> Self {
        Self { msg, counter: 0 }
    }
}

pub struct Intervaller<Variant, Message: Clone> {
    variant: fn(IntervalMessage<Message>) -> Variant,
    msg: Message,
    counter: u32,
    interval: tokio::time::Interval,
    tick_limit: Option<u32>,
}

impl<Variant, Message: Clone> Intervaller<Variant, Message> {
    pub fn new(
        interval: Duration,
        variant: fn(IntervalMessage<Message>) -> Variant,
        msg: Message,
    ) -> Self {
        Self::new_with_limit(interval, variant, msg, None)
    }

    pub fn new_with_limit(
        interval: Duration,
        variant: fn(IntervalMessage<Message>) -> Variant,
        msg: Message,
        tick_limit: Option<u32>,
    ) -> Self {
        let interval = tokio::time::interval(interval);
        Self {
            interval,
            variant,
            msg,
            tick_limit,
            counter: 0,
        }
    }

    pub fn construct(&self) -> Variant {
        let msg = IntervalMessage {
            msg: self.msg.clone(),
            counter: self.counter,
        };

        (self.variant)(msg)
    }
}

impl<Variant, Message: Clone + Send> Channel<Variant> for Intervaller<Variant, Message> {
    fn recv(&mut self) -> Pin<Box<dyn Future<Output = Result<Variant, ActorError>> + Send + '_>> {
        Box::pin(async move {
            if self.tick_limit.map(|limit| self.counter > limit).is_some() {
                return Err(ActorError::ActorClosed);
            }

            let _ = self.interval.tick().await;
            let msg = self.construct();
            self.counter += 1;

            Ok(msg)
        })
    }
}

#[tokio::test]
async fn test() {
    #[derive(Debug, Clone, PartialEq)]
    pub struct Keke(u32);

    pub enum Test {
        Asd(IntervalMessage<Keke>),
    }

    let asd = Intervaller::new(Duration::from_secs(1), Test::Asd, Keke(15));
    let enummi = asd.construct();
    let Test::Asd(IntervalMessage { msg, .. }) = enummi;
    assert_eq!(msg, Keke(15))
}