use crate::{ action::{Field, MsgAction}, name::NameType, queue::data_director::{Include, Path, Route}, }; use uuid::Uuid; pub trait MessageAction { fn doc_name(&self) -> &NameType { &NameType::None } } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct MessageID { data: Uuid, } impl MessageID { pub fn new() -> Self { Self { data: Uuid::new_v4(), } } } #[cfg(test)] mod message_ids { use super::*; #[test] fn are_message_ids_unique() { let id1 = MessageID::new(); let id2 = MessageID::new(); assert!(id1 != id2); } } #[derive(Clone, Debug)] pub struct Message { msg_id: MessageID, action: MsgAction, route: Route, session: Field, } impl Message { pub fn new(action: A) -> Self where A: Into, { Self { msg_id: MessageID::new(), action: action.into(), route: Route::default(), session: Field::None, } } pub fn set_id(&self, msg_id: MessageID) -> Self { let mut output = self.clone(); output.msg_id = msg_id; output } pub fn set_session(&self, session: Field) -> Self { let mut output = self.clone(); output.session = session; output } pub fn set_action(&self, action: A) -> Self where A: Into, { let mut output = self.clone(); output.action = action.into(); output } pub fn get_message_id(&self) -> &MessageID { &self.msg_id } pub fn get_action(&self) -> &MsgAction { &self.action } pub fn get_path(&self) -> Path { Path::new( Include::Just(self.msg_id.clone()), Include::Just(self.action.doc_name().clone()), Include::Just(self.action.clone().into()), ) } pub fn get_route(&self) -> Route { self.route.clone() } pub fn set_route(&mut self, route: Route) { self.route = route; } } impl Default for Message { fn default() -> Self { Self { msg_id: MessageID::new(), action: MsgAction::None, route: Route::default(), session: Field::None, } } } impl MessageAction for Message { fn doc_name(&self) -> &NameType { self.get_action().doc_name() } } #[cfg(test)] mod messages { use super::*; use crate::{ action::{DocDef, Query, Reply}, name::{name_id_support::test_name_id, Name}, ErrorID, MTTError, }; fn is_there_a_default_message() { let msg = Message::default(); match msg.action { MsgAction::None => {} _ => panic!("should have been no action"), } assert_eq!(msg.session, Field::None); } #[test] fn can_create_new_messsage() { let doc_name = Name::english("something"); let qry = Query::new(doc_name.clone()); let msg = Message::new(qry); let expected: NameType = doc_name.into(); match msg.action { MsgAction::Query(data) => assert_eq!(data.doc_name(), &expected), _ => unreachable!("should have been a query"), } match msg.session { Field::None => {} _ => unreachable!("should have been none"), } } #[test] fn can_id_be_set() { let doc_name = Name::english("identification"); let qry = Query::new(doc_name.clone()); let msg_id = MessageID::new(); let msg = Message::new(qry).set_id(msg_id.clone()); assert_eq!(msg.msg_id, msg_id); } #[test] fn can_session_be_set() { let doc_name = Name::english("identification"); let qry = Query::new(doc_name.clone()); let sess_id: Field = Uuid::new_v4().into(); let msg = Message::new(qry).set_session(sess_id.clone()); assert_eq!(msg.session, sess_id); } #[test] fn can_action_be_set() { let doc_name = Name::english("action"); let expected: NameType = doc_name.clone().into(); let docdef = DocDef::new(doc_name.clone()); let qry = Query::new(doc_name.clone()); let msg = Message::new(docdef).set_action(qry); match msg.action { MsgAction::Query(data) => assert_eq!(data.doc_name(), &expected), _ => unreachable!("should have been a query"), } } #[test] fn can_the_document_be_a_named_reference() { let dts = [Name::english("one"), Name::english("two")]; for document in dts.into_iter() { let msg = Message::new(MsgAction::Create(DocDef::new(document.clone()))); match msg.get_action() { MsgAction::Create(_) => {} _ => unreachable!("should have been a create document"), } } } #[test] fn can_the_document_be_an_id() { let document = test_name_id(); let msg = Message::new(Query::new(document.clone())); match msg.get_action() { MsgAction::Query(_) => {} _ => unreachable!("should have been an access query"), } } #[test] fn do_messages_contain_routes() { let name = Name::english("whatever"); let mut msg = Message::new(Query::new(name.clone())); let default_route = msg.get_route(); match default_route.msg_id { Include::Just(_) => unreachable!("should defalt to all"), Include::All => {} } match default_route.doc_id { Include::Just(_) => unreachable!("should defalt to all"), Include::All => {} } match default_route.action { Include::Just(_) => unreachable!("should defalt to all"), Include::All => {} } let doc_id = test_name_id(); let route = Route::new( Include::Just(msg.get_message_id().clone()), Include::Just(doc_id.clone()), Include::Just(msg.get_action().into()), ); msg.set_route(route); let result = msg.get_route(); match result.msg_id { Include::Just(data) => assert_eq!(&data, msg.get_message_id()), Include::All => unreachable!("should have message id"), } match result.doc_id { Include::Just(data) => assert_eq!(data, doc_id), Include::All => unreachable!("should have document id"), } match result.action { Include::Just(data) => assert_eq!(data, msg.get_action().into()), Include::All => unreachable!("should have action"), } } #[test] fn is_the_message_id_random() { let mut ids: Vec = Vec::new(); for _ in 0..5 { let msg = Message::new(Query::new(Name::english("test"))); let id = msg.get_message_id().clone(); assert!(!ids.contains(&id), "{:?} containts {:?}", ids, id); ids.push(id); } } #[test] fn can_make_reply_message() { let name = Name::english("testing"); let msg = Message::new(Query::new(name.clone())); let responce = Reply::new(Name::english("something")); let reply = msg.set_action(responce); assert_eq!(reply.get_message_id(), msg.get_message_id()); match reply.get_action() { MsgAction::Reply(_) => {} _ => unreachable!("should have been a reply"), } } #[test] fn can_make_error_message() { let name = Name::english("testing"); let msg = Message::new(Query::new(name.clone())); let err_msg = Uuid::new_v4().to_string(); let result = msg.set_action(MTTError::new(ErrorID::DocumentNotFound)); assert_eq!(result.get_message_id(), msg.get_message_id()); match result.get_action() { MsgAction::Error(data) => match data.get_error_ids().back().unwrap() { ErrorID::DocumentNotFound => {} _ => unreachable!("got {:?}, should have received not found", data), }, _ => unreachable!("should have been a reply"), } } #[test] fn can_make_a_response_message() { let doc_id = test_name_id(); let msg = Message::new(Query::new(doc_id.clone())); let data = Uuid::new_v4().to_string(); let result1 = msg.set_action(MTTError::new(ErrorID::DocumentNotFound)); let result2 = msg.set_action(Reply::new(NameType::None)); assert_eq!(result1.get_message_id(), msg.get_message_id()); assert_eq!(result2.get_message_id(), msg.get_message_id()); let action1 = result1.get_action(); match action1 { MsgAction::Error(err) => match err.get_error_ids().back().unwrap() { ErrorID::DocumentNotFound => {} _ => unreachable!("got {:?}: should have received document not found", err), }, _ => unreachable!("got {:?}: should have received error", action1), } let action2 = result2.get_action(); match action2 { MsgAction::Reply(data) => assert_eq!(data.len(), 0), _ => unreachable!("got {:?}: should have received a reply", action2), } } }