mod client; mod data; mod error; mod message; mod router; mod session; use client::{Client, ClientMsg}; use message::{Message, MsgData}; use router::Router; use session::{Session, SessionData, SessionMsg}; use std::{ collections::HashMap, ops::Deref, sync::mpsc::{channel, Sender}, }; struct Request; enum Field { Static(String), } impl From for Field { fn from(value: String) -> Self { Field::Static(value) } } impl From<&str> for Field { fn from(value: &str) -> Self { Field::Static(value.into()) } } #[cfg(test)] mod fields { use super::*; #[test] fn string_to_field() { let entries = ["test1".to_string(), "test2".to_string()]; for data in entries { match data.clone().into() { Field::Static(result) => assert_eq!(result, data), } } } #[test] fn str_to_field() { let entries = ["test1", "test2"]; for data in entries { match data.into() { Field::Static(result) => assert_eq!(result, data), } } } } struct Record { data: HashMap, } impl Record { fn new() -> Self { Self { data: HashMap::new(), } } fn add(&mut self, name: S, data: F) where S: Into, F: Into, { self.data.insert(name.into(), data.into()); } } impl Deref for Record { type Target = HashMap; fn deref(&self) -> &Self::Target { &self.data } } #[cfg(test)] mod records { use super::*; #[test] fn initialize() { let rec = Record::new(); assert!(rec.is_empty()); } #[test] fn bad_get_return() { let rec = Record::new(); match rec.get("empty") { Some(_) => unreachable!("Should_have returned a None"), None => {} } } #[test] fn add_data() { let name = "name1x"; let data = "data1"; let mut rec = Record::new(); rec.add(name, data); match rec.get(name) { None => unreachable!("Should return data"), Some(result) => match result { Field::Static(txt) => assert_eq!(txt, data), }, } } #[test] fn add_data_strings() { let name = "field".to_string(); let data = "info".to_string(); let mut rec = Record::new(); rec.add(name.clone(), data.clone()); match rec.get(&name) { None => unreachable!("Should return data"), Some(result) => match result { Field::Static(txt) => assert_eq!(txt, &data), }, } } } struct Response { data: HashMap>, } impl Response { fn new() -> Self { Self { data: HashMap::new(), } } fn count(&self) -> usize { 0 } } #[cfg(test)] mod responses { use super::*; #[test] fn create_response() { let res = Response::new(); assert!(res.data.is_empty()); assert_eq!(res.count(), 0); } } /// Support functions for Messages. pub trait Msg { fn to_msgdata(&self) -> MsgData; } #[cfg(test)] mod test_message { use super::*; pub enum Tester { Test1, Test2, } impl Msg for Tester { fn to_msgdata(&self) -> MsgData { match self { Tester::Test1 => MsgData::Test1, Tester::Test2 => MsgData::Test2, } } } } /// Application client to MoreThanText pub struct MoreThanText { session: Option, tx: Sender, } impl MoreThanText { /// Create a MoreThanText database. /// /// Example: /// /// ``` /// use morethantext::MoreThanText; /// /// MoreThanText::new(); /// ``` pub fn new() -> Self { let (tx, rx) = channel(); let mut senders = Vec::new(); senders.push(Client::start(tx.clone())); senders.push(Session::start(tx.clone())); Router::start(senders, rx); Self { session: None, tx: tx, } } /// Opens an existing or new session with the database. /// /// If the string is None, incorrect, or expired, /// a new session will be created. /// /// Example: /// /// ``` /// use morethantext::MoreThanText; /// /// let mut mtt = MoreThanText::new(); /// mtt.open_session(None); /// mtt.open_session(Some("7b1ff340-7dfa-4f29-b144-601384e54423".to_string())); /// ``` pub fn open_session(&mut self, id: Option) { let (tx, rx) = channel(); let req = ClientMsg::OpenSession(id, tx); let msg = Message::new(&req); self.tx.send(msg).unwrap(); match rx.recv().unwrap().get_message() { MsgData::Session(data) => match data { SessionMsg::Opened(sess) => self.session = Some(sess.clone()), _ => {} }, _ => {} }; } /// Get the session id /// /// Example: /// /// ``` /// use morethantext::MoreThanText; /// /// let mut mtt = MoreThanText::new(); /// let id = mtt.get_id(); /// ``` pub fn get_id(&self) -> String { match &self.session { Some(id) => id.to_string(), None => "".to_string(), } } } impl Clone for MoreThanText { fn clone(&self) -> Self { Self { session: None, tx: self.tx.clone(), } } } #[cfg(test)] mod mtt_client { use super::*; #[test] fn default_values() { let mtt = MoreThanText::new(); assert!(mtt.session.is_none()); } #[test] fn new_session() { let mut mtt = MoreThanText::new(); mtt.open_session(None); assert!(mtt.session.is_some()); } #[test] fn session_ids_are_unique() { let mut mtt = MoreThanText::new(); mtt.open_session(None); let id1 = mtt.get_id(); mtt.open_session(None); assert_ne!(mtt.get_id(), id1); } #[test] fn cloned_clients_have_no_session() { let mut mtt = MoreThanText::new(); mtt.open_session(None); let result = mtt.clone(); assert!(result.session.is_none()); } }