use crate::field::Field; use std::{ collections::HashMap, sync::mpsc::{channel, Receiver, Sender}, thread::spawn, }; use uuid::Uuid; enum MsgType { ClientNewMessage, NoOp, Register, } pub struct Message { id: Uuid, class: MsgType, data: HashMap, } impl Message { pub fn new() -> Self { Self { id: Uuid::nil(), class: MsgType::NoOp, data: HashMap::new(), } } fn reply(&self, data: MsgType) -> Message { Self { id: self.id.clone(), class: data, data: self.data.clone(), } } fn get_class(&self) -> &MsgType { &self.class } fn add_data(&mut self, name: S, data: F) where S: Into, F: Into { self.data.insert(name.into(), data.into()); } fn get_data(&self) -> &HashMap { &self.data } } #[cfg(test)] mod messages { use super::*; #[test] fn new_message() { let msg = Message::new(); assert_eq!(msg.id, Uuid::nil()); match msg.class { MsgType::NoOp => (), _ => unreachable!("new defaults to noop"), } assert!(msg.data.is_empty()); } #[test] fn create_reply() { let id = Uuid::new_v4(); let mut msg = Message::new(); msg.id = id.clone(); let data = MsgType::Register; let result = msg.reply(data); assert_eq!(result.id, id); match result.class { MsgType::Register => {}, _ => unreachable!("should have been a registration request"), } } #[test] fn get_message_type() { let msg = Message::new(); match msg.get_class() { MsgType::NoOp => {}, _ => unreachable!("should have bneen noopn"), } } #[test] fn add_data() { let mut msg = Message::new(); let one = "one"; let two = "two".to_string(); msg.add_data(one, one); msg.add_data(two.clone(), two.clone()); let result = msg.get_data(); assert_eq!(result.get(one).unwrap().to_string(), one); assert_eq!(result.get(&two).unwrap().to_string(), two); } } struct Queue { senders: Vec>, rx: Receiver, } impl Queue { fn new(rx: Receiver) -> Self { Self { senders: Vec::new(), rx: rx, } } fn start() -> Sender { let (tx, rx) = channel(); spawn(move || { let mut queue = Queue::new(rx); queue.listen(); }); tx } fn listen(&mut self) { loop { let msg = self.rx.recv().unwrap(); match msg.get_class() { MsgType::Register => self.register(msg.get_data()).unwrap(), _ => { for sender in self.senders.iter() { sender.send(Message::new()).unwrap(); } }, } } } fn register(&mut self, data: &HashMap) -> Result<(), String> { match data.get("tx") { Some(data) => { self.senders.push(data.to_sender().unwrap()); Ok(()) }, None => Err("missing tx sender".to_string()), } } } #[cfg(test)] mod queues { use std::time::Duration; use super::*; fn start_queue() -> (Sender, Receiver) { let (tx, rx) = channel::(); let initial = Message::new(); let mut msg = initial.reply(MsgType::Register); msg.add_data("tx", tx); let queue_tx = Queue::start(); (queue_tx, rx) } #[test] fn run_queue() { let queue_tx = Queue::start(); let (tx, rx) = channel(); let msg = Message::new(); let mut reply = msg.reply(MsgType::Register); reply.add_data("tx", tx); queue_tx.send(reply); queue_tx.send(msg.reply(MsgType::NoOp)); rx.recv_timeout(Duration::from_millis(400)).unwrap(); } #[test] fn get_new_client_message() { let (tx, rx) = start_queue(); } }