mod counter; use rand::distributions::{Alphanumeric, DistString}; use std::{ collections::HashMap, fmt, sync::mpsc::{channel, Receiver, Sender}, thread::spawn, }; pub enum Session { Ok, New(String), } struct ValidateSession { id: Option, tx: Sender, } impl ValidateSession { fn new(id: Option, tx: Sender) -> Self { Self { id: id, tx: tx } } } enum SendMsg { ValidateSess(ValidateSession), } struct Cache { data: HashMap, rx: Receiver, } impl Cache { fn new(recv: Receiver) -> Self { Self { rx: recv, data: HashMap::new(), } } fn gen_id(&self) -> String { Alphanumeric.sample_string(&mut rand::thread_rng(), 16) } fn listen(&mut self) { loop { match self.rx.recv().unwrap() { SendMsg::ValidateSess(vsess) => { vsess.tx.send(self.validate_session(vsess.id)).unwrap() } } } } fn validate_session(&mut self, sess: Option) -> Session { let session: Session; if sess.is_some_and(|sess| true) {// self.data.contains(&sess)) { session = Session::Ok; } else { let id = self.gen_id(); // `self.data.push(id.clone()); session = Session::New(id); } session } } #[derive(Clone)] pub struct MoreThanText { tx: Sender, } impl MoreThanText { pub fn new() -> Self { let (tx, rx) = channel(); spawn(move || { let mut cache = Cache::new(rx); cache.listen(); }); Self { tx: tx } } pub fn get_session(&self, id: Option) -> Session { let (tx, rx) = channel(); self.tx .send(SendMsg::ValidateSess(ValidateSession::new(id, tx))) .unwrap(); rx.recv().unwrap() } } #[cfg(test)] mod client { use super::*; #[test] fn session_ids_are_unique() { let conn = MoreThanText::new(); let mut ids: Vec = Vec::new(); for _ in 1..10 { match conn.get_session(None) { Session::New(id) => { if ids.contains(&id) { assert!(false, "{} is a duplicate id", id); } ids.push(id) } Session::Ok => assert!(false, "Should have returned a new id."), } } } #[test] fn existing_ids_return_ok() { let conn = MoreThanText::new(); let sid: String; match conn.get_session(None) { Session::New(id) => sid = id, Session::Ok => unreachable!(), } match conn.get_session(Some(sid.clone())) { Session::New(_) => assert!(false, "should not create a new session"), Session::Ok => {} } } #[test] fn bad_ids_get_new_session() { let conn = MoreThanText::new(); let sid = "bad id"; match conn.get_session(Some(sid.to_string())) { Session::New(id) => assert_ne!(sid, id, "do not reuse original id"), Session::Ok => assert!(false, "shouuld generate a new id"), } } } enum Field { StaticString(String), } impl fmt::Display for Field { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Field::StaticString(data) => write!(f, "{}", data), } } } struct Record { data: HashMap, } impl Record { fn new(data: HashMap) -> Self { Self { data: data, } } fn get(&self, fieldname: &str) -> &Field { match self.data.get(fieldname) { Some(field) => field, None => unreachable!(), } } } #[cfg(test)] mod records { use super::*; #[test] fn create_record() { let input = HashMap::from([ ("one".to_string(), Field::StaticString("1".to_string())), ("two".to_string(), Field::StaticString("2".to_string())), ("three".to_string(), Field::StaticString("3".to_string())), ]); let rec = Record::new(input); assert_eq!(rec.get("one").to_string(), "1"); assert_eq!(rec.get("two").to_string(), "2"); assert_eq!(rec.get("three").to_string(), "3"); } } struct Column; struct Table { columns: HashMap, } impl Table { fn new() -> Self { Self { columns: HashMap::new(), } } } #[cfg(test)] mod tables { use super::*; #[test] fn create_table() { let tbl = Table::new(); } } enum DataType { Table(Table), Record(Record), }