// Test for Macro, exact same as usecase-recursive use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use std::error::Error; use std::marker; use rand::{thread_rng, Rng}; use mpstthree::{choose_mpst_multi_to_all, generate}; // Create new roles generate!("basic", MeshedChannels, A, B, C); // Types type AtoBVideo = Send>; type AtoCVideo = Recv>>; type InitA = Recv>>; type BtoAVideo = as Session>::Dual; type RecursAtoC = Recv, End>; type RecursBtoC = Recv, End>; enum Branches0AtoC { End(MeshedChannels), Video(MeshedChannels, AtoCVideo, StackAVideo, NameA>), } enum Branches0BtoC { End(MeshedChannels), Video(MeshedChannels, RecursBtoC, StackBVideo, NameB>), } type Choose0fromCtoA = Send, End>; type Choose0fromCtoB = Send, End>; type InitC = Send>>; // Stacks type StackAVideo = RoleC>>>>; type StackAInit = RoleC>>; type StackBVideo = RoleA>>; type StackCRecurs = RoleBroadcast; type StackCFull = RoleA>; // Creating the MP sessions // For C type EndpointCVideo = MeshedChannels< as Session>::Dual, as Session>::Dual, RoleA>, NameC, >; type EndpointCRecurs = MeshedChannels, Choose0fromCtoB, StackCRecurs, NameC>; type EndpointCFull = MeshedChannels, Choose0fromCtoB, StackCFull, NameC>; // For A type EndpointARecurs = MeshedChannels, RoleC, NameA>; type EndpointAFull = MeshedChannels, StackAInit, NameA>; // For B type EndpointBFull = MeshedChannels, RoleC, NameB>; // Functions related to endpoints fn server(s: EndpointBFull) -> Result<(), Box> { offer_mpst!(s, { Branches0BtoC::End(s) => { s.close() }, Branches0BtoC::Video(s) => { let (request, s) = s.recv(); let s = s.send(request + 1); server(s) }, }) } fn authenticator(s: EndpointAFull) -> Result<(), Box> { let (id, s) = s.recv(); let s = s.send(id + 1); authenticator_recurs(s) } fn authenticator_recurs(s: EndpointARecurs) -> Result<(), Box> { offer_mpst!(s, { Branches0AtoC::End(s) => { s.close() }, Branches0AtoC::Video(s) => { let (request, s) = s.recv(); let (video, s) = s.send(request + 1).recv(); let s = s.send(video + 1); authenticator_recurs(s) }, }) } fn client(s: EndpointCFull) -> Result<(), Box> { let mut rng = thread_rng(); let xs: Vec = (1..100).map(|_| rng.gen()).collect(); let (_, s) = s.send(0).recv(); client_recurs(s, xs, 1) } fn client_recurs( s: EndpointCRecurs, mut xs: Vec, index: i32, ) -> Result<(), Box> { match xs.pop() { Option::Some(_) => { let s: EndpointCVideo = choose_mpst_multi_to_all!( s, Branches0AtoC::Video, Branches0BtoC::Video, => NameC, MeshedChannels, 3 ); let (_, s) = s.send(1).recv(); client_recurs(s, xs, index + 1) } Option::None => { let s = choose_mpst_multi_to_all!( s, Branches0AtoC::End, Branches0BtoC::End, => NameC, MeshedChannels, 3 ); assert_eq!(index, 100); s.close() } } } ///////////////////////////////////////// pub fn run_macro_recursive() { let (thread_a, thread_b, thread_c) = fork_mpst(authenticator, server, client); assert!(thread_a.join().is_ok()); assert!(thread_b.join().is_ok()); assert!(thread_c.join().is_ok()); }