morethantext/src/lib.rs

218 lines
4.7 KiB
Rust
Raw Normal View History

2024-05-05 23:18:42 -04:00
mod counter;
2024-03-19 19:54:14 -04:00
use rand::distributions::{Alphanumeric, DistString};
use std::{
2024-05-05 23:18:42 -04:00
collections::HashMap,
fmt,
2024-03-29 07:51:14 -04:00
sync::mpsc::{channel, Receiver, Sender},
2024-03-19 19:54:14 -04:00
thread::spawn,
};
pub enum Session {
Ok,
New(String),
}
struct ValidateSession {
id: Option<String>,
tx: Sender<Session>,
}
impl ValidateSession {
fn new(id: Option<String>, tx: Sender<Session>) -> Self {
Self { id: id, tx: tx }
}
}
enum SendMsg {
ValidateSess(ValidateSession),
}
2024-03-29 07:51:14 -04:00
struct Cache {
2024-05-05 23:18:42 -04:00
data: HashMap<String, DataType>,
2024-03-29 07:51:14 -04:00
rx: Receiver<SendMsg>,
}
impl Cache {
fn new(recv: Receiver<SendMsg>) -> Self {
Self {
rx: recv,
2024-05-05 23:18:42 -04:00
data: HashMap::new(),
2024-03-29 07:51:14 -04:00
}
}
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<String>) -> Session {
let session: Session;
2024-05-05 23:18:42 -04:00
if sess.is_some_and(|sess| true) {// self.data.contains(&sess)) {
2024-03-29 07:51:14 -04:00
session = Session::Ok;
} else {
let id = self.gen_id();
2024-05-05 23:18:42 -04:00
// `self.data.push(id.clone());
2024-03-29 07:51:14 -04:00
session = Session::New(id);
}
session
}
}
2024-03-19 19:54:14 -04:00
#[derive(Clone)]
pub struct MoreThanText {
tx: Sender<SendMsg>,
}
impl MoreThanText {
pub fn new() -> Self {
let (tx, rx) = channel();
spawn(move || {
2024-03-29 07:51:14 -04:00
let mut cache = Cache::new(rx);
cache.listen();
2024-03-19 19:54:14 -04:00
});
Self { tx: tx }
}
pub fn get_session(&self, id: Option<String>) -> 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<String> = 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"),
}
}
}
2024-05-05 23:18:42 -04:00
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<String, Field>,
}
impl Record {
fn new(data: HashMap<String, Field>) -> 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<String, Column>,
}
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),
}