#![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 ServerImpl; impl Server for ServerImpl { actor_name!("minimal_server"); type HandleMsgFut = Ready>; fn handle_msg(self, _msg: Msg) -> Self::HandleMsgFut { ready(TransResult::Ok(End)) } } struct ClientImpl; impl Client for ClientImpl { actor_name!("minimal_client"); type OnSendMsgReturn = usize; type OnSendMsgFut = Ready>; fn on_send_msg(self) -> Self::OnSendMsgFut { ready(TransResult::Ok((End, 42))) } } } #[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 ListeningImpl; impl Listening for ListeningImpl { actor_name!("reply_server"); type HandlePingListening = Self; type HandlePingFut = Ready::Reply)>>; fn handle_ping(self, _msg: Ping) -> Self::HandlePingFut { ready(TransResult::Ok((self, ()))) } } struct ClientImpl; impl Client for ClientImpl { actor_name!("reply_client"); type OnSendPingReturn = (); type OnSendPingClient = Self; type OnSendPingFut = Ready>; fn on_send_ping(self, _ping: ::Reply) -> 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), None => (), } let client_state: Option> = None; match client_state { Some(ClientState::Unregistered(state)) => assert_type!(state, UnregisteredImpl), Some(ClientState::Registered(state)) => assert_type!(state, RegisteredImpl), Some(ClientState::End(state)) => assert_type!(state, End), None => (), } struct UnregisteredImpl; impl Unregistered for UnregisteredImpl { actor_name!("callback_client"); type OnSendRegisterReturn = (); type OnSendRegisterRegistered = RegisteredImpl; type OnSendRegisterFut = Ready>; fn on_send_register(self) -> Self::OnSendRegisterFut { ready(TransResult::Ok((RegisteredImpl, ()))) } } struct RegisteredImpl; impl Registered for RegisteredImpl { type HandleCompletedFut = Ready>; fn handle_completed(self, _arg: Completed) -> Self::HandleCompletedFut { ready(TransResult::Ok(End)) } } struct ListeningImpl; impl Listening for ListeningImpl { actor_name!("callback_server"); type HandleRegisterListening = ListeningImpl; type HandleRegisterWorking = WorkingImpl; type HandleRegisterFut = Ready>; fn handle_register(self, _arg: Register) -> Self::HandleRegisterFut { ready(TransResult::Ok((self, WorkingImpl))) } } struct WorkingImpl; impl Working for WorkingImpl { actor_name!("callback_worker"); type OnSendCompletedFut = Ready>; fn on_send_completed(self) -> Self::OnSendCompletedFut { ready(TransResult::Ok((End, Completed))) } } }