#![allow( clippy::type_complexity, clippy::too_many_arguments, clippy::large_enum_variant )] use mpstthree::binary::struct_trait::end::End; use mpstthree::binary::struct_trait::session::Session; use mpstthree::binary_atmp::struct_trait::{recv::RecvTimed, send::SendTimed}; use mpstthree::generate_atmp; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use rand::{thread_rng, Rng}; use std::collections::HashMap; use std::error::Error; use std::thread::sleep; use std::time::{Duration, Instant}; // Create the new MeshedChannels for three participants and the close and fork functions generate_atmp!(MeshedChannels, Car, Key); // Labels struct Wake {} struct Present {} struct Challenge {} struct Response {} struct Absent {} struct Stop {} // Types // Car type Choice0FromKeyToCar = RecvTimed; type Loop0FromKeyToCar = SendTimed; type CarToKeyPresent0 = RecvTimed; type Choice1FromKeyToCar = RecvTimed; type CarToKeyPresent1 = SendTimed; type Choice2FromKeyToCar = RecvTimed; type CarToKeyPresent2 = RecvTimed; type CarToKeyAbsent = RecvTimed; type CarToKeyStop = RecvTimed; enum Branching0FromKeyToCar { Present(MeshedChannels>, NameCar>), Absent(MeshedChannels>>, NameCar>), Stop(MeshedChannels, NameCar>), } enum Branching1FromKeyToCar { Present(MeshedChannels>, NameCar>), } enum Branching2FromKeyToCar { Present(MeshedChannels>>, NameCar>), } // Key type ChooseFromKeyToCar = ::Dual; type KeyToCarPresent1 = ::Dual; type KeyToCarPresent2 = ::Dual; type KeyToCarPresent3 = ::Dual; type KeyToCarAbsent = ::Dual; type KeyToCarStop = ::Dual; // Endpoints // Car type Endpoint0Car = MeshedChannels, NameCar>; // Key type Endpoint0Key = MeshedChannels; type Endpoint1KeyData = MeshedChannels, NameKey>; type Endpoint2KeyData = MeshedChannels, NameKey>; type Endpoint3KeyData = MeshedChannels>, NameKey>; type Endpoint1KeyAbsent = MeshedChannels>, NameKey>; type Endpoint1KeyStop = MeshedChannels, NameKey>; // Functions ///////////////////////// // Car fn endpoint_car( s: Endpoint0Car, all_clocks: &mut HashMap, ) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); recurs_car(s, all_clocks) } fn recurs_car( s: Endpoint0Car, all_clocks: &mut HashMap, ) -> Result<(), Box> { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); offer_mpst!(s, all_clocks, { Branching0FromKeyToCar::Stop(s) => { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let (_stop, s) = s.recv(all_clocks)?; s.close() }, Branching0FromKeyToCar::Absent(s) => { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let (_absent, s) = s.recv(all_clocks)?; let s = s.send(Wake {}, all_clocks)?; recurs_car(s, all_clocks) }, Branching0FromKeyToCar::Present(s) => { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let (_present, s) = s.recv(all_clocks)?; offer_mpst!(s, all_clocks, { Branching1FromKeyToCar::Present(s) => { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let s = s.send(Challenge {}, all_clocks)?; offer_mpst!(s, all_clocks, { Branching2FromKeyToCar::Present(s) => { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let (_response, s) = s.recv(all_clocks)?; let s = s.send(Wake {}, all_clocks)?; recurs_car(s, all_clocks) }, }) }, }) }, }) } ///////////////////////// // Key fn endpoint_key( s: Endpoint0Key, all_clocks: &mut HashMap, ) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); recurs_key(s, all_clocks, LOOPS) } fn recurs_key( s: Endpoint0Key, all_clocks: &mut HashMap, loops: i64, ) -> Result<(), Box> { sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); match loops { 0 => { let s: Endpoint1KeyStop = choose_mpst_key_to_all!(s, all_clocks, Branching0FromKeyToCar::Stop,); sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let s = s.send(Stop {}, all_clocks)?; s.close() } i => { if thread_rng().gen_range(0..=5) == 1 { let s: Endpoint1KeyAbsent = choose_mpst_key_to_all!(s, all_clocks, Branching0FromKeyToCar::Absent); sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let s = s.send(Absent {}, all_clocks)?; let (_wake, s) = s.recv(all_clocks)?; recurs_key(s, all_clocks, i - 1) } else { let s: Endpoint1KeyData = choose_mpst_key_to_all!(s, all_clocks, Branching0FromKeyToCar::Present); sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let s = s.send(Present {}, all_clocks)?; let s: Endpoint2KeyData = choose_mpst_key_to_all!(s, all_clocks, Branching1FromKeyToCar::Present); sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let (_challenge, s) = s.recv(all_clocks)?; sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let s: Endpoint3KeyData = choose_mpst_key_to_all!(s, all_clocks, Branching2FromKeyToCar::Present); sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let s = s.send(Response {}, all_clocks)?; sleep(Duration::from_millis(thread_rng().gen_range(0..=100))); let (_wake, s) = s.recv(all_clocks)?; recurs_key(s, all_clocks, i - 1) } } } } ///////////////////////// fn main() { let (thread_car, thread_key) = fork_mpst(endpoint_car, endpoint_key); thread_car.join().unwrap(); thread_key.join().unwrap(); } static LOOPS: i64 = 100;