2024-11-06 21:05:52 -05:00
|
|
|
mod client;
|
2024-11-09 12:45:19 -05:00
|
|
|
mod data;
|
2024-11-15 13:37:11 -05:00
|
|
|
mod error;
|
2024-11-06 21:05:52 -05:00
|
|
|
mod message;
|
2025-02-22 10:53:05 -05:00
|
|
|
mod queue;
|
2024-11-06 21:05:52 -05:00
|
|
|
mod router;
|
|
|
|
mod session;
|
2024-05-05 23:18:42 -04:00
|
|
|
|
2024-11-06 21:05:52 -05:00
|
|
|
use client::{Client, ClientMsg};
|
|
|
|
use message::{Message, MsgData};
|
|
|
|
use router::Router;
|
|
|
|
use session::{Session, SessionData, SessionMsg};
|
2025-02-11 11:33:54 -05:00
|
|
|
use std::{
|
|
|
|
collections::HashMap,
|
|
|
|
ops::Deref,
|
2025-02-22 10:53:05 -05:00
|
|
|
sync::mpsc::{channel, Receiver, Sender},
|
2025-02-11 11:33:54 -05:00
|
|
|
};
|
2025-02-17 14:55:36 -05:00
|
|
|
use uuid::Uuid;
|
2024-03-19 19:54:14 -04:00
|
|
|
|
2025-02-14 17:38:07 -05:00
|
|
|
#[derive(Clone)]
|
2025-02-10 08:05:59 -05:00
|
|
|
enum Field {
|
|
|
|
Static(String),
|
2025-02-17 14:55:36 -05:00
|
|
|
Uuid(Uuid),
|
2025-02-10 08:05:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<String> for Field {
|
|
|
|
fn from(value: String) -> Self {
|
2025-02-17 14:55:36 -05:00
|
|
|
match Uuid::try_from(value.as_str()) {
|
|
|
|
Ok(data) => return Field::Uuid(data),
|
2025-02-18 09:54:05 -05:00
|
|
|
Err(_) => {}
|
2025-02-17 14:55:36 -05:00
|
|
|
}
|
2025-02-10 08:05:59 -05:00
|
|
|
Field::Static(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&str> for Field {
|
|
|
|
fn from(value: &str) -> Self {
|
2025-02-17 14:55:36 -05:00
|
|
|
match Uuid::try_from(value) {
|
|
|
|
Ok(data) => return Field::Uuid(data),
|
2025-02-18 09:54:05 -05:00
|
|
|
Err(_) => {}
|
2025-02-17 14:55:36 -05:00
|
|
|
}
|
2025-02-11 11:33:54 -05:00
|
|
|
Field::Static(value.into())
|
2025-02-10 08:05:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-17 14:55:36 -05:00
|
|
|
impl From<Uuid> for Field {
|
|
|
|
fn from(value: Uuid) -> Self {
|
|
|
|
Field::Uuid(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-10 08:05:59 -05:00
|
|
|
#[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),
|
2025-02-17 14:55:36 -05:00
|
|
|
_ => unreachable!("shouuld have been a static field"),
|
2025-02-10 08:05:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn str_to_field() {
|
|
|
|
let entries = ["test1", "test2"];
|
|
|
|
for data in entries {
|
|
|
|
match data.into() {
|
|
|
|
Field::Static(result) => assert_eq!(result, data),
|
2025-02-17 14:55:36 -05:00
|
|
|
_ => unreachable!("shouuld have been a static field"),
|
2025-02-10 08:05:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-02-17 14:55:36 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_to_field() {
|
|
|
|
let id = Uuid::new_v4();
|
|
|
|
match id.into() {
|
|
|
|
Field::Uuid(result) => assert_eq!(result, id),
|
|
|
|
_ => unreachable!("should have been a uuid field"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_string_to_field() {
|
|
|
|
let id = Uuid::new_v4();
|
|
|
|
let id_string = id.to_string();
|
|
|
|
match id_string.into() {
|
|
|
|
Field::Uuid(result) => assert_eq!(result, id),
|
|
|
|
_ => unreachable!("should have been a uuid field"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_str_to_field() {
|
|
|
|
let id = Uuid::new_v4();
|
|
|
|
let id_string = id.to_string();
|
|
|
|
let id_str = id_string.as_str();
|
|
|
|
match id_str.into() {
|
|
|
|
Field::Uuid(result) => assert_eq!(result, id),
|
|
|
|
_ => unreachable!("should have been a uuid field"),
|
|
|
|
}
|
|
|
|
}
|
2025-02-10 08:05:59 -05:00
|
|
|
}
|
|
|
|
|
2025-02-22 10:53:05 -05:00
|
|
|
#[derive(Clone)]
|
2025-02-18 09:54:05 -05:00
|
|
|
struct Request {
|
|
|
|
id: Option<Field>,
|
2025-02-22 10:53:05 -05:00
|
|
|
tx: Sender<Response>,
|
2025-02-18 09:54:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Request {
|
2025-02-22 10:53:05 -05:00
|
|
|
fn new<F>(id: Option<F>) -> (Self, Receiver<Response>)
|
2025-02-18 09:54:05 -05:00
|
|
|
where
|
|
|
|
F: Into<Field>,
|
|
|
|
{
|
|
|
|
let result: Option<Field>;
|
|
|
|
match id {
|
|
|
|
Some(data) => {
|
|
|
|
result = Some(data.into());
|
|
|
|
}
|
|
|
|
None => result = None,
|
|
|
|
}
|
2025-02-22 10:53:05 -05:00
|
|
|
let (tx, rx) = channel();
|
|
|
|
(Self { id: result, tx: tx }, rx)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_session(&self) -> &Option<Field> {
|
|
|
|
return &self.id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod create_request {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
pub fn empty_request() -> (Request, Receiver<Response>) {
|
|
|
|
let id: Option<String> = None;
|
|
|
|
Request::new(id)
|
2025-02-18 09:54:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod requests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn create_request_no_id() {
|
|
|
|
let input: Option<String> = None;
|
2025-02-22 10:53:05 -05:00
|
|
|
let (req, _) = Request::new(input);
|
2025-02-18 09:54:05 -05:00
|
|
|
assert!(req.id.is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn create_request_with_uuid() {
|
|
|
|
let id = Uuid::new_v4();
|
2025-02-22 10:53:05 -05:00
|
|
|
let (req, _) = Request::new(Some(id));
|
2025-02-18 09:54:05 -05:00
|
|
|
match req.id {
|
|
|
|
Some(field) => match (field) {
|
|
|
|
Field::Uuid(data) => assert_eq!(data, id),
|
|
|
|
_ => unreachable!("Should have been a uuid"),
|
|
|
|
},
|
|
|
|
None => unreachable!("Should producer data"),
|
|
|
|
}
|
|
|
|
}
|
2025-02-22 10:53:05 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn return_session() {
|
|
|
|
let id = Uuid::new_v4();
|
|
|
|
let (req, _) = Request::new(Some(id));
|
|
|
|
match req.get_session() {
|
|
|
|
Some(result) => {
|
|
|
|
match result {
|
|
|
|
Field::Uuid(data) => assert_eq!(data, &id),
|
|
|
|
_ => unreachable!("should have returned a uuid field"),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
None => unreachable!("should have returned a uuid"),
|
|
|
|
}
|
|
|
|
}
|
2025-02-18 09:54:05 -05:00
|
|
|
}
|
|
|
|
|
2025-02-11 11:33:54 -05:00
|
|
|
struct Record {
|
|
|
|
data: HashMap<String, Field>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Record {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
data: HashMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add<S, F>(&mut self, name: S, data: F)
|
|
|
|
where
|
|
|
|
S: Into<String>,
|
|
|
|
F: Into<Field>,
|
|
|
|
{
|
|
|
|
self.data.insert(name.into(), data.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for Record {
|
|
|
|
type Target = HashMap<String, Field>;
|
|
|
|
|
|
|
|
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),
|
2025-02-17 14:55:36 -05:00
|
|
|
_ => unreachable!("Should have been static"),
|
2025-02-11 11:33:54 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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),
|
2025-02-17 14:55:36 -05:00
|
|
|
_ => unreachable!("should have been statis"),
|
2025-02-11 11:33:54 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-02-09 15:48:13 -05:00
|
|
|
|
2025-02-14 22:14:48 -05:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum ResponseError {
|
|
|
|
ColumnNumberMisMatch,
|
|
|
|
MissionColumn(String),
|
|
|
|
}
|
|
|
|
|
2025-02-09 15:48:13 -05:00
|
|
|
struct Response {
|
2025-02-11 11:33:54 -05:00
|
|
|
data: HashMap<String, Vec<Field>>,
|
2025-02-14 17:38:07 -05:00
|
|
|
counter: usize,
|
2025-02-09 15:48:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Response {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
2025-02-11 11:33:54 -05:00
|
|
|
data: HashMap::new(),
|
2025-02-14 17:38:07 -05:00
|
|
|
counter: 0,
|
2025-02-09 15:48:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-14 22:14:48 -05:00
|
|
|
fn add(&mut self, rec: Record) -> Result<(), ResponseError> {
|
2025-02-14 17:38:07 -05:00
|
|
|
if self.data.is_empty() {
|
|
|
|
for (key, value) in rec.iter() {
|
|
|
|
let mut store = Vec::new();
|
|
|
|
store.push(value.clone());
|
|
|
|
self.data.insert(key.to_string(), store);
|
|
|
|
}
|
|
|
|
} else {
|
2025-02-14 18:00:37 -05:00
|
|
|
if rec.len() != self.data.len() {
|
2025-02-14 22:14:48 -05:00
|
|
|
return Err(ResponseError::ColumnNumberMisMatch);
|
2025-02-14 18:00:37 -05:00
|
|
|
}
|
2025-02-14 17:38:07 -05:00
|
|
|
for (key, value) in rec.iter() {
|
|
|
|
match self.data.get_mut(key) {
|
|
|
|
Some(data) => data.push(value.clone()),
|
2025-02-14 22:14:48 -05:00
|
|
|
None => return Err(ResponseError::MissionColumn(key.to_string())),
|
2025-02-14 17:38:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for Response {
|
|
|
|
type Item = Record;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.data.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let mut rec = Record::new();
|
|
|
|
for (key, value) in self.data.iter() {
|
|
|
|
if self.counter >= value.len() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
rec.add(key, value[self.counter].clone());
|
|
|
|
}
|
|
|
|
self.counter += 1;
|
|
|
|
Some(rec)
|
2025-02-09 15:48:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod responses {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn create_response() {
|
2025-02-14 17:38:07 -05:00
|
|
|
let mut res = Response::new();
|
2025-02-11 11:33:54 -05:00
|
|
|
assert!(res.data.is_empty());
|
2025-02-14 17:38:07 -05:00
|
|
|
assert!(res.next().is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_records() {
|
|
|
|
let mut res = Response::new();
|
|
|
|
let columns = ["col1", "col2"];
|
|
|
|
let count = 3;
|
|
|
|
let field_cnt = &count * columns.len();
|
|
|
|
let mut fields = 0..field_cnt;
|
|
|
|
for _ in 0..count {
|
|
|
|
let mut rec = Record::new();
|
|
|
|
for col in columns {
|
|
|
|
rec.add(col, fields.next().unwrap().to_string());
|
|
|
|
}
|
|
|
|
res.add(rec);
|
|
|
|
}
|
|
|
|
fields = 0..field_cnt;
|
|
|
|
for _ in 0..count {
|
|
|
|
match res.next() {
|
|
|
|
Some(rec) => {
|
|
|
|
assert_eq!(rec.len(), columns.len());
|
|
|
|
for col in columns {
|
|
|
|
match rec.get(col).unwrap() {
|
|
|
|
Field::Static(txt) => {
|
|
|
|
assert_eq!(txt.clone(), fields.next().unwrap().to_string())
|
2025-02-18 09:54:05 -05:00
|
|
|
}
|
2025-02-17 14:55:36 -05:00
|
|
|
_ => unreachable!("should have been static"),
|
2025-02-14 17:38:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => unreachable!("Should have returned data"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert!(res.next().is_none(), "exceeded the correct of records");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_of_columns_mismatch() {
|
|
|
|
let mut res = Response::new();
|
|
|
|
let mut rec1 = Record::new();
|
|
|
|
let mut rec2 = Record::new();
|
|
|
|
rec1.add("one", "one");
|
|
|
|
rec2.add("one", "one");
|
|
|
|
rec2.add("two", "two");
|
|
|
|
res.add(rec1).unwrap();
|
|
|
|
match res.add(rec2) {
|
|
|
|
Ok(_) => unreachable!("Should not accept additional value"),
|
2025-02-14 22:14:48 -05:00
|
|
|
Err(err) => match err {
|
|
|
|
ResponseError::ColumnNumberMisMatch => {}
|
|
|
|
_ => unreachable!("should havee been a mismatch error"),
|
|
|
|
},
|
2025-02-14 17:38:07 -05:00
|
|
|
}
|
2025-02-09 15:48:13 -05:00
|
|
|
}
|
2025-02-14 18:00:37 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn missing_field_error() {
|
|
|
|
let mut res = Response::new();
|
|
|
|
let mut rec1 = Record::new();
|
|
|
|
let mut rec2 = Record::new();
|
|
|
|
rec1.add("one", "one");
|
|
|
|
rec2.add("one", "one");
|
|
|
|
rec2.add("two", "two");
|
|
|
|
res.add(rec2).unwrap();
|
|
|
|
match res.add(rec1) {
|
|
|
|
Ok(_) => unreachable!("Should not accept additional value"),
|
2025-02-14 22:14:48 -05:00
|
|
|
Err(err) => match err {
|
|
|
|
ResponseError::ColumnNumberMisMatch => {}
|
|
|
|
_ => unreachable!("should havee been a mismatch error"),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn wrong_column_name() {
|
|
|
|
let mut res = Response::new();
|
|
|
|
let mut rec1 = Record::new();
|
|
|
|
let mut rec2 = Record::new();
|
|
|
|
rec1.add("one", "one");
|
|
|
|
rec2.add("two", "two");
|
|
|
|
res.add(rec1).unwrap();
|
|
|
|
match res.add(rec2) {
|
|
|
|
Ok(_) => unreachable!("Should not accept additional value"),
|
|
|
|
Err(err) => match err {
|
|
|
|
ResponseError::MissionColumn(txt) => assert_eq!(txt, "two"),
|
|
|
|
_ => unreachable!("should have been missing cloumn"),
|
|
|
|
},
|
2025-02-14 18:00:37 -05:00
|
|
|
}
|
|
|
|
}
|
2025-02-09 15:48:13 -05:00
|
|
|
}
|
|
|
|
|
2024-11-06 21:05:52 -05:00
|
|
|
/// 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
|
2024-03-19 19:54:14 -04:00
|
|
|
pub struct MoreThanText {
|
2024-11-06 21:05:52 -05:00
|
|
|
session: Option<SessionData>,
|
|
|
|
tx: Sender<Message>,
|
2024-03-19 19:54:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl MoreThanText {
|
2024-05-12 14:10:36 -04:00
|
|
|
/// Create a MoreThanText database.
|
|
|
|
///
|
|
|
|
/// Example:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use morethantext::MoreThanText;
|
|
|
|
///
|
2024-11-06 21:05:52 -05:00
|
|
|
/// MoreThanText::new();
|
2024-05-12 14:10:36 -04:00
|
|
|
/// ```
|
2024-11-06 21:05:52 -05:00
|
|
|
pub fn new() -> Self {
|
2024-03-19 19:54:14 -04:00
|
|
|
let (tx, rx) = channel();
|
2024-11-06 21:05:52 -05:00
|
|
|
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,
|
|
|
|
}
|
2024-05-12 14:10:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Opens an existing or new session with the database.
|
|
|
|
///
|
|
|
|
/// If the string is None, incorrect, or expired,
|
2024-11-06 21:05:52 -05:00
|
|
|
/// a new session will be created.
|
2024-05-12 14:10:36 -04:00
|
|
|
///
|
|
|
|
/// Example:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use morethantext::MoreThanText;
|
|
|
|
///
|
2024-11-06 21:05:52 -05:00
|
|
|
/// let mut mtt = MoreThanText::new();
|
2024-05-12 14:10:36 -04:00
|
|
|
/// mtt.open_session(None);
|
|
|
|
/// mtt.open_session(Some("7b1ff340-7dfa-4f29-b144-601384e54423".to_string()));
|
|
|
|
/// ```
|
|
|
|
pub fn open_session(&mut self, id: Option<String>) {
|
|
|
|
let (tx, rx) = channel();
|
2024-11-06 21:05:52 -05:00
|
|
|
let req = ClientMsg::OpenSession(id, tx);
|
|
|
|
let msg = Message::new(&req);
|
|
|
|
self.tx.send(msg).unwrap();
|
|
|
|
match rx.recv().unwrap().get_message() {
|
2024-11-09 12:45:19 -05:00
|
|
|
MsgData::Session(data) => match data {
|
|
|
|
SessionMsg::Opened(sess) => self.session = Some(sess.clone()),
|
|
|
|
_ => {}
|
2024-11-06 21:05:52 -05:00
|
|
|
},
|
2024-11-09 12:45:19 -05:00
|
|
|
_ => {}
|
2024-11-06 21:05:52 -05:00
|
|
|
};
|
2024-03-19 19:54:14 -04:00
|
|
|
}
|
|
|
|
|
2024-05-12 14:10:36 -04:00
|
|
|
/// Get the session id
|
|
|
|
///
|
|
|
|
/// Example:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use morethantext::MoreThanText;
|
|
|
|
///
|
2024-11-06 21:05:52 -05:00
|
|
|
/// let mut mtt = MoreThanText::new();
|
|
|
|
/// let id = mtt.get_id();
|
2024-05-12 14:10:36 -04:00
|
|
|
/// ```
|
|
|
|
pub fn get_id(&self) -> String {
|
2024-11-06 21:05:52 -05:00
|
|
|
match &self.session {
|
|
|
|
Some(id) => id.to_string(),
|
|
|
|
None => "".to_string(),
|
2024-05-12 14:10:36 -04:00
|
|
|
}
|
2024-03-19 19:54:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-06 21:28:44 -05:00
|
|
|
impl Clone for MoreThanText {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
2024-11-09 12:45:19 -05:00
|
|
|
session: None,
|
|
|
|
tx: self.tx.clone(),
|
2024-11-06 21:28:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 19:54:14 -04:00
|
|
|
#[cfg(test)]
|
2024-05-12 14:10:36 -04:00
|
|
|
mod mtt_client {
|
2024-03-19 19:54:14 -04:00
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
2024-11-06 21:05:52 -05:00
|
|
|
fn default_values() {
|
|
|
|
let mtt = MoreThanText::new();
|
|
|
|
assert!(mtt.session.is_none());
|
2024-03-19 19:54:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-11-06 21:05:52 -05:00
|
|
|
fn new_session() {
|
|
|
|
let mut mtt = MoreThanText::new();
|
2024-05-12 14:10:36 -04:00
|
|
|
mtt.open_session(None);
|
2024-11-06 21:05:52 -05:00
|
|
|
assert!(mtt.session.is_some());
|
2024-03-19 19:54:14 -04:00
|
|
|
}
|
2024-05-05 23:18:42 -04:00
|
|
|
|
|
|
|
#[test]
|
2024-11-06 21:05:52 -05:00
|
|
|
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);
|
2024-05-05 23:18:42 -04:00
|
|
|
}
|
2024-11-06 21:28:44 -05:00
|
|
|
|
|
|
|
#[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());
|
|
|
|
}
|
2024-05-05 23:18:42 -04:00
|
|
|
}
|