use crate::{client::Request, field::Field}; use std::{ collections::HashMap, sync::{ mpsc::Sender, Arc, RwLock, }, }; use uuid::Uuid; #[derive(Clone)] pub enum MsgType { ClientRequest, NoOp, } #[derive(Clone)] pub struct Message { id: Uuid, class: MsgType, data: HashMap, } impl Message { pub fn new(msg_type: MsgType) -> Self { Self { id: Uuid::new_v4(), class: msg_type, data: HashMap::new(), } } fn reply(&self, data: MsgType) -> Message { Self { id: self.id.clone(), class: data, data: HashMap::new(), } } pub fn get_class(&self) -> &MsgType { &self.class } pub fn add_data(&mut self, name: S, data: F) where S: Into, F: Into, { self.data.insert(name.into(), data.into()); } pub fn get_data(&self) -> &HashMap { &self.data } } impl From for Message { fn from(_value: Request) -> Self { let msg = Message::new(MsgType::ClientRequest); msg.reply(MsgType::ClientRequest) } } #[cfg(test)] mod messages { use super::*; #[test] fn new_message() { let msg = Message::new(MsgType::NoOp); match msg.class { MsgType::NoOp => (), _ => unreachable!("new defaults to noop"), } assert!(msg.data.is_empty()); } #[test] fn message_ids_are_random() { let mut ids: Vec = Vec::new(); for _ in 0..10 { let msg = Message::new(MsgType::NoOp); let id = msg.id.clone(); assert!(!ids.contains(&id), "{} is a duplicate", id); ids.push(id); } } #[test] fn create_reply() { let id = Uuid::new_v4(); let mut msg = Message::new(MsgType::NoOp); msg.id = id.clone(); msg.add_data("test", "test"); let data = MsgType::ClientRequest; let result = msg.reply(data); assert_eq!(result.id, id); match result.class { MsgType::ClientRequest => {} _ => unreachable!("should have been a registration request"), } assert!(result.data.is_empty()); } #[test] fn get_message_type() { let msg = Message::new(MsgType::NoOp); match msg.get_class() { MsgType::NoOp => {} _ => unreachable!("should have bneen noopn"), } } #[test] fn add_data() { let mut msg = Message::new(MsgType::NoOp); 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); } } #[derive(Clone)] pub struct Queue { store: Arc>>>, } impl Queue { pub fn new() -> Self { Self { store: Arc::new(RwLock::new(Vec::new())), } } fn add(&self, tx: Sender) { let mut store = self.store.write().unwrap(); store.push(tx); } fn send(&self, msg: Message) { let store = self.store.read().unwrap(); for sender in store.iter() { sender.send(msg.clone()).unwrap(); } } } #[cfg(test)] mod serviceredistries { use std::sync::mpsc::channel; use super::*; #[test] fn create_queue() { let queue = Queue::new(); let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); queue.add(tx1); queue.add(tx2); queue.send(Message::new(MsgType::NoOp)); rx1.recv().unwrap(); rx2.recv().unwrap(); } }