ftswarm 0.2.5

A simple swarm protocol communication library
Documentation
use std::{future::Future, sync::Arc};

use ftswarm_macros::Updateable;
use ftswarm_proto::{command::{argument::Argument, rpc::{FtSwarmRPCCommand, RpcFunction}, FtSwarmCommand}, message_parser::rpc::RPCReturnParam};

use crate::{lock, FtSwarm, Mutex};

pub mod analog;
pub mod digital;

pub mod servo;
pub mod actor;
pub mod led;
pub mod controller;


pub type Io<T> = Arc<Mutex<Box<T>>>;

pub trait Updateable {
    fn handle_subscription(&mut self, message: &RPCReturnParam);
}

pub trait NewSwarmObject<Params> {
    fn new(name: &str, swarm: FtSwarm, params: Params) -> Box<Self>;
    fn init(&mut self) -> impl Future<Output=()> {
        async move {}
    }
    fn name(&self) -> &str;
    fn swarm(&self) -> &FtSwarm;
}

pub trait SwarmObject<Params>: NewSwarmObject<Params> + Updateable + Clone + Sync + Send {
    fn create(swarm: &FtSwarm, name: &str, params: Params) -> impl Future<Output=Io<Self>>
    where
        Self: 'static,
    {
        let obj = Self::new(name, swarm.clone(), params);
        let arc = Arc::new(Mutex::new(obj));
        let for_closure = arc.clone();

        async move {
            swarm.push_cache(Box::new(move |subscription| {
                let for_task = for_closure.clone();
                tokio::spawn(async move {
                    let mut obj = lock(&for_task).await;
                    obj.handle_subscription(&subscription);
                });
            }), name).await;
            {
                let mut obj = lock(&arc).await;
                obj.init().await;
            }
            arc
        }
    }

    fn run_command(&self, func: RpcFunction, args: Vec<Argument>) -> impl Future<Output=Result<RPCReturnParam, String>> {
        let command = FtSwarmRPCCommand {
            target: self.name().to_string(),
            function: func,
            args,
        };

        self.swarm().transact(FtSwarmCommand::RPC(command))
    }
}

#[derive(Clone)]
pub struct Hysteresis(pub i32);


#[derive(Clone)]
pub enum NormallyOpen {
    Open,
    Closed,
}

impl Into<Argument> for NormallyOpen {
    fn into(self) -> Argument {
        match self {
            NormallyOpen::Open => Argument::Int(0),
            NormallyOpen::Closed => Argument::Int(1),
        }
    }
}