#![feature(impl_trait_in_assoc_type)] use std::future::{ready, Ready}; use btproto::protocol; use btrun::{ actor_name, model::{CallMsg, End, TransResult}, }; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Ping; impl CallMsg for Ping { type Reply = (); } /// Tests that the given variable is of the given type _at compile time_. macro_rules! assert_type { ($var:expr, $ty:ty) => {{ let _: $ty = $var; }}; } #[test] fn minimal_syntax() { #[derive(Serialize, Deserialize)] pub struct Msg; protocol! { named MinimalTest; let server = [Server]; let client = [Client]; Client -> End, >service(Server)!Msg; Server?Msg -> End; } let msg: Option = None; match msg { Some(MinimalTestMsgs::Msg(act)) => assert_type!(act, Msg), None => (), } struct ServerState; impl Server for ServerState { actor_name!("minimal_server"); type HandleMsgFut = Ready>; fn handle_msg(self, _msg: Msg) -> Self::HandleMsgFut { ready(TransResult::Ok(End)) } } struct ClientState; impl Client for ClientState { actor_name!("minimal_client"); type OnSendMsgFut = Ready>; fn on_send_msg(self, _msg: &mut Msg) -> Self::OnSendMsgFut { ready(TransResult::Ok(End)) } } } #[test] fn reply() { protocol! { named ReplyTest; let server = [Listening]; let client = [Client]; Client -> Client, >service(Listening)!Ping; Listening?Ping -> Listening, >Client!Ping::Reply; } let msg: Option = None; match msg { Some(ReplyTestMsgs::Ping(ping)) => assert_type!(ping, Ping), Some(ReplyTestMsgs::PingReply(reply)) => assert_type!(reply, ::Reply), None => (), } struct ListeningState; impl Listening for ListeningState { actor_name!("reply_server"); type HandlePingListening = Self; type HandlePingFut = Ready::Reply)>>; fn handle_ping(self, _msg: Ping) -> Self::HandlePingFut { ready(TransResult::Ok((self, ()))) } } struct ClientState; impl Client for ClientState { actor_name!("reply_client"); type OnSendPingClient = Self; type OnSendPingFut = Ready::Reply)>>; fn on_send_ping(self, _ping: &mut Ping) -> Self::OnSendPingFut { ready(TransResult::Ok((self, ()))) } } } #[test] fn client_callback() { #[derive(Serialize, Deserialize)] pub struct Register; #[derive(Serialize, Deserialize)] pub struct Completed; protocol! { named ClientCallback; let server = [Listening]; let worker = [Working]; let client = [Unregistered, Registered]; Unregistered -> Registered, >service(Listening)!Register[Registered]; Listening?Register[Registered] -> Listening, Working[Registered]; Working[Registered] -> End, >Registered!Completed; Registered?Completed -> End; } let msg: Option = None; match msg { Some(ClientCallbackMsgs::Register(msg)) => assert_type!(msg, Register), Some(ClientCallbackMsgs::Completed(msg)) => assert_type!(msg, Completed), _ => (), } struct UnregisteredState; impl Unregistered for UnregisteredState { actor_name!("callback_client"); type OnSendRegisterRegistered = RegisteredState; type OnSendRegisterFut = Ready>; fn on_send_register(self, _arg: &mut Register) -> Self::OnSendRegisterFut { ready(TransResult::Ok(RegisteredState)) } } struct RegisteredState; impl Registered for RegisteredState { type HandleCompletedFut = Ready>; fn handle_completed(self, _arg: Completed) -> Self::HandleCompletedFut { ready(TransResult::Ok(End)) } } struct ListeningState; impl Listening for ListeningState { actor_name!("callback_server"); type HandleRegisterListening = ListeningState; type HandleRegisterWorking = WorkingState; type HandleRegisterFut = Ready>; fn handle_register(self, _arg: Register) -> Self::HandleRegisterFut { ready(TransResult::Ok((self, WorkingState))) } } struct WorkingState; impl Working for WorkingState { actor_name!("callback_worker"); type OnSendCompletedFut = Ready>; fn on_send_completed(self) -> Self::OnSendCompletedFut { ready(TransResult::Ok((End, Completed))) } } }