From 6fd240634130de5f28d3cb622264ada0ada919d3 Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Tue, 6 Jan 2026 16:19:15 -0500 Subject: [PATCH] Moved fields into separate module. --- src/field.rs | 419 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 +- src/message.rs | 418 +---------------------------------------------- src/mtterror.rs | 6 +- 4 files changed, 428 insertions(+), 421 deletions(-) create mode 100644 src/field.rs diff --git a/src/field.rs b/src/field.rs new file mode 100644 index 0000000..d315415 --- /dev/null +++ b/src/field.rs @@ -0,0 +1,419 @@ +use chrono::prelude::*; +use std::{ + ops::{Add, AddAssign}, + time::Duration, +}; +use uuid::Uuid; + +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum Field { + Boolean(bool), + DateTime(DateTime), + Duration(Duration), + Integer(i128), + None, + StaticString(String), + Uuid(Uuid), +} + +impl Field { + pub fn get_type(&self) -> FieldType { + self.into() + } + + pub fn equal(&self, other: &Field) -> Field { + if self.get_type() == other.get_type() { + { self == other }.into() + } else { + Field::None + } + } + + pub fn not_equal(&self, other: &Field) -> Field { + if self.get_type() == other.get_type() { + { self != other }.into() + } else { + Field::None + } + } + + pub fn greater(&self, other: &Self) -> Field { + if self.get_type() == other.get_type() { + { self > other }.into() + } else { + Field::None + } + } + + pub fn greater_equal(&self, other: &Self) -> Field { + if self.get_type() == other.get_type() { + { self >= other }.into() + } else { + Field::None + } + } + + pub fn lesser(&self, other: &Self) -> Field { + if self.get_type() == other.get_type() { + { self < other }.into() + } else { + Field::None + } + } + + pub fn lesser_equal(&self, other: &Self) -> Field { + if self.get_type() == other.get_type() { + { self <= other }.into() + } else { + Field::None + } + } +} + +impl Add for Field { + type Output = Self; + + fn add(self, other: Self) -> Self { + match self { + Field::DateTime(value1) => match other { + Field::Duration(value2) => { value1 + value2 }.into(), + _ => Field::None, + }, + Field::Duration(value1) => match other { + Field::Duration(value2) => { value1 + value2 }.into(), + _ => Field::None, + }, + Field::Integer(value1) => match other { + Field::Integer(value2) => { value1 + value2 }.into(), + _ => Field::None, + }, + _ => Self::None, + } + } +} + +impl AddAssign for Field { + fn add_assign(&mut self, other: Self) { + *self = self.clone().add(other); + } +} + +impl From for Field { + fn from(value: bool) -> Self { + Self::Boolean(value) + } +} + +impl From> for Field { + fn from(value: DateTime) -> Self { + Self::DateTime(value) + } +} + +impl From for Field { + fn from(value: Duration) -> Self { + Self::Duration(value) + } +} + +impl From for Field { + fn from(value: String) -> Self { + Self::StaticString(value) + } +} + +impl From<&str> for Field { + fn from(value: &str) -> Self { + Self::from(value.to_string()) + } +} + +impl From for Field { + fn from(value: Uuid) -> Self { + Self::Uuid(value) + } +} + +impl From for Field { + fn from(value: i128) -> Self { + Self::Integer(value) + } +} + +impl From for Field { + fn from(value: isize) -> Self { + let data: i128 = value.try_into().unwrap(); + Self::from(data) + } +} + +impl From for Field { + fn from(value: i32) -> Self { + let data: i128 = value.into(); + Self::from(data) + } +} + +#[cfg(test)] +mod fields { + use super::*; + use rand::random; + + #[test] + fn can_create_static_string() { + let data = Uuid::new_v4().to_string(); + let result: Field = data.clone().into(); + match result.clone() { + Field::StaticString(output) => assert_eq!(output, data), + _ => unreachable!("got {:?}: should have been static string", result), + } + assert_eq!(result.get_type(), FieldType::StaticString); + } + + #[test] + fn can_create_from_str() { + let holder = ["one", "two"]; + for data in holder.into_iter() { + let result: Field = data.into(); + match result.clone() { + Field::StaticString(output) => assert_eq!(output, data), + _ => unreachable!("got {:?}: should have been static string", result), + } + assert_eq!(result.get_type(), FieldType::StaticString); + } + } + + #[test] + fn create_from_uuid() { + let data = Uuid::new_v4(); + let result: Field = data.clone().into(); + match result.clone() { + Field::Uuid(output) => assert_eq!(output, data), + _ => unreachable!("got {:?}: should have been uuid", result), + } + assert_eq!(result.get_type(), FieldType::Uuid); + } + + #[test] + fn create_from_datatime() { + let data = Utc::now(); + let result: Field = data.into(); + match result.clone() { + Field::DateTime(output) => assert_eq!(output, data), + _ => unreachable!("got {:?}: should have been uuid", result), + } + assert_eq!(result.get_type(), FieldType::DateTime); + } + + #[test] + fn does_adding_return_none_for_things_that_cannot_add() { + let value1: Field = Uuid::new_v4().into(); + let value2: Field = Uuid::new_v4().into(); + assert_eq!(value1 + value2, Field::None); + } + + #[test] + fn can_integers_be_added() { + let value1: i128 = random::().into(); + let value2: i128 = random::().into(); + let expected: Field = { value1 + value2 }.into(); + let value1: Field = value1.into(); + let value2: Field = value2.into(); + assert_eq!(value1 + value2, expected); + } + + #[test] + fn can_integer_add_mismatch_returns_none() { + let value1: Field = 5.into(); + let value2: Field = "nope".into(); + assert_eq!(value1 + value2, Field::None); + } + + #[test] + fn can_durations_be_added() { + let data1: u64 = random::().into(); + let data2: u64 = random::().into(); + let value1: Field = Duration::from_secs(data1).into(); + let value2: Field = Duration::from_secs(data2).into(); + let expected: Field = Duration::from_secs(data1 + data2).into(); + assert_eq!(value1 + value2, expected); + } + + #[test] + fn does_duration_mismatch_return_none() { + let value1: Field = Duration::from_secs(20).into(); + let value2: Field = "nope".into(); + assert_eq!(value1 + value2, Field::None); + } + + #[test] + fn can_durations_be_added_to_datetimes() { + let timestamp = Utc::now(); + let data: u64 = random::().into(); + let duration = Duration::from_secs(data); + let expected: Field = { timestamp + duration }.into(); + let value1: Field = timestamp.into(); + let value2: Field = duration.into(); + assert_eq!(value1 + value2, expected); + } + + #[test] + fn does_datetime_mismatch_return_none() { + let value1: Field = Utc::now().into(); + let value2: Field = "nope".into(); + assert_eq!(value1 + value2, Field::None); + } + + #[test] + fn does_field_equal_return_properly() { + let mut values: Vec = Vec::new(); + let count = 2; + while values.len() < count { + let value: Field = Uuid::new_v4().into(); + if !values.contains(&value) { + values.push(value); + } + } + assert_eq!(values[0].equal(&values[0]), true.into()); + assert_eq!(values[0].equal(&values[1]), false.into()); + assert_eq!(values[0].equal(&"nope".into()), Field::None); + } + + #[test] + fn does_field_not_equal_return_properly() { + let mut values: Vec = Vec::new(); + let count = 2; + while values.len() < count { + let value: Field = Uuid::new_v4().into(); + if !values.contains(&value) { + values.push(value); + } + } + assert_eq!(values[0].not_equal(&values[0]), false.into()); + assert_eq!(values[0].not_equal(&values[1]), true.into()); + assert_eq!(values[0].not_equal(&"nope".into()), Field::None); + } + + #[test] + fn can_field_have_greater_value() { + let value1: Field = 1.into(); + let value2: Field = 2.into(); + let value3: Field = 3.into(); + let mismatch: Field = "bad".into(); + assert_eq!(value2.greater(&value1), true.into()); + assert_eq!(value2.greater(&value2), false.into()); + assert_eq!(value2.greater(&value3), false.into()); + assert_eq!(value2.greater(&mismatch), Field::None); + } + + #[test] + fn can_field_have_greater_or_equal_value() { + let value1: Field = 1.into(); + let value2: Field = 2.into(); + let value3: Field = 3.into(); + let mismatch: Field = "bad".into(); + assert_eq!(value2.greater_equal(&value1), true.into()); + assert_eq!(value2.greater_equal(&value2), true.into()); + assert_eq!(value2.greater_equal(&value3), false.into()); + assert_eq!(value2.greater_equal(&mismatch), Field::None); + } + + #[test] + fn can_field_have_lesser_value() { + let value1: Field = 1.into(); + let value2: Field = 2.into(); + let value3: Field = 3.into(); + let mismatch: Field = "bad".into(); + assert_eq!(value2.lesser(&value1), false.into()); + assert_eq!(value2.lesser(&value2), false.into()); + assert_eq!(value2.lesser(&value3), true.into()); + assert_eq!(value2.lesser(&mismatch), Field::None); + } + + #[test] + fn can_field_have_lesser_or_equal_value() { + let value1: Field = 1.into(); + let value2: Field = 2.into(); + let value3: Field = 3.into(); + let mismatch: Field = "bad".into(); + assert_eq!(value2.lesser_equal(&value1), false.into()); + assert_eq!(value2.lesser_equal(&value2), true.into()); + assert_eq!(value2.lesser_equal(&value3), true.into()); + assert_eq!(value2.lesser_equal(&mismatch), Field::None); + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum FieldType { + Boolean, + DateTime, + Duration, + Integer, + None, + StaticString, + Uuid, +} + +impl FieldType { + pub fn get_default(&self) -> Field { + match self { + FieldType::Boolean => false.into(), + FieldType::DateTime => Utc::now().into(), + FieldType::Duration => Duration::from_secs(0).into(), + FieldType::Integer => 0.into(), + FieldType::None => Field::None, + FieldType::StaticString => "".into(), + FieldType::Uuid => Uuid::new_v4().into(), + } + } +} + +impl From<&Field> for FieldType { + fn from(value: &Field) -> Self { + match value { + Field::Boolean(_) => Self::Boolean, + Field::DateTime(_) => Self::DateTime, + Field::Duration(_) => Self::Duration, + Field::Integer(_) => Self::Integer, + Field::None => Self::None, + Field::StaticString(_) => Self::StaticString, + Field::Uuid(_) => Self::Uuid, + } + } +} + +#[cfg(test)] +mod fieldtypes { + use super::*; + + #[test] + fn can_get_defaults_for_uuid() { + let ftype = FieldType::Uuid; + let mut ids: Vec = Vec::new(); + for _ in 0..5 { + let result = ftype.get_default(); + match result { + Field::Uuid(data) => { + assert!( + !ids.contains(&data), + "found duplicate id {:?} in {:?}", + data, + ids + ); + ids.push(data.clone()); + } + _ => unreachable!("got {:?}: should have been uuid", result), + } + } + } + + #[test] + fn can_get_defaults_for_static_string() { + let ftype = FieldType::StaticString; + let result = ftype.get_default(); + match result { + Field::StaticString(data) => assert_eq!(data, ""), + _ => unreachable!("got {:?}: should have been static string", result), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index fba49e2..7a90edf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,16 +1,16 @@ mod data_director; +mod field; mod message; mod mtterror; mod name; mod router; use data_director::{Include, Path, RegMsg, Register}; +use field::{Field, FieldType}; use message::{ - Action, Addition, CalcValue, Calculation, Clock, CreateDoc, Field, FieldType, Message, Operand, - Session, + Action, Addition, CalcValue, Calculation, Clock, CreateDoc, Message, Operand, Session, }; pub use message::{MsgAction, Query}; -use mtterror::MTTError; use name::{Name, NameType}; use router::Queue; use std::sync::mpsc::{channel, Receiver}; diff --git a/src/message.rs b/src/message.rs index 3c42337..4e73053 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,13 +1,13 @@ -use super::MTTError; use crate::{ data_director::{Include, Path, RegMsg, Register, Route, RouteID}, + field::{Field, FieldType}, + mtterror::MTTError, name::{Name, NameType, Names}, router::Queue, }; use chrono::prelude::*; use std::{ collections::{HashMap, HashSet}, - ops::{Add, AddAssign}, sync::mpsc::{channel, Receiver}, thread::{sleep, spawn}, time::Duration, @@ -475,420 +475,6 @@ impl CreateDoc { } } -#[derive(Clone, Debug, PartialEq)] -pub enum FieldType { - Boolean, - DateTime, - Duration, - Integer, - None, - StaticString, - Uuid, -} - -impl FieldType { - fn get_default(&self) -> Field { - match self { - FieldType::Boolean => false.into(), - FieldType::DateTime => Utc::now().into(), - FieldType::Duration => Duration::from_secs(0).into(), - FieldType::Integer => 0.into(), - FieldType::None => Field::None, - FieldType::StaticString => "".into(), - FieldType::Uuid => Uuid::new_v4().into(), - } - } -} - -impl From<&Field> for FieldType { - fn from(value: &Field) -> Self { - match value { - Field::Boolean(_) => Self::Boolean, - Field::DateTime(_) => Self::DateTime, - Field::Duration(_) => Self::Duration, - Field::Integer(_) => Self::Integer, - Field::None => Self::None, - Field::StaticString(_) => Self::StaticString, - Field::Uuid(_) => Self::Uuid, - } - } -} - -#[cfg(test)] -mod fieldtypes { - use super::*; - - #[test] - fn can_get_defaults_for_uuid() { - let ftype = FieldType::Uuid; - let mut ids: Vec = Vec::new(); - for _ in 0..5 { - let result = ftype.get_default(); - match result { - Field::Uuid(data) => { - assert!( - !ids.contains(&data), - "found duplicate id {:?} in {:?}", - data, - ids - ); - ids.push(data.clone()); - } - _ => unreachable!("got {:?}: should have been uuid", result), - } - } - } - - #[test] - fn can_get_defaults_for_static_string() { - let ftype = FieldType::StaticString; - let result = ftype.get_default(); - match result { - Field::StaticString(data) => assert_eq!(data, ""), - _ => unreachable!("got {:?}: should have been static string", result), - } - } -} - -#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub enum Field { - Boolean(bool), - DateTime(DateTime), - Duration(Duration), - Integer(i128), - None, - StaticString(String), - Uuid(Uuid), -} - -impl Field { - fn get_type(&self) -> FieldType { - self.into() - } - - fn equal(&self, other: &Field) -> Field { - if self.get_type() == other.get_type() { - { self == other }.into() - } else { - Field::None - } - } - - #[allow(dead_code)] - fn not_equal(&self, other: &Field) -> Field { - if self.get_type() == other.get_type() { - { self != other }.into() - } else { - Field::None - } - } - - fn greater(&self, other: &Self) -> Field { - if self.get_type() == other.get_type() { - { self > other }.into() - } else { - Field::None - } - } - - fn greater_equal(&self, other: &Self) -> Field { - if self.get_type() == other.get_type() { - { self >= other }.into() - } else { - Field::None - } - } - - fn lesser(&self, other: &Self) -> Field { - if self.get_type() == other.get_type() { - { self < other }.into() - } else { - Field::None - } - } - - fn lesser_equal(&self, other: &Self) -> Field { - if self.get_type() == other.get_type() { - { self <= other }.into() - } else { - Field::None - } - } -} - -impl Add for Field { - type Output = Self; - - fn add(self, other: Self) -> Self { - match self { - Field::DateTime(value1) => match other { - Field::Duration(value2) => { value1 + value2 }.into(), - _ => Field::None, - }, - Field::Duration(value1) => match other { - Field::Duration(value2) => { value1 + value2 }.into(), - _ => Field::None, - }, - Field::Integer(value1) => match other { - Field::Integer(value2) => { value1 + value2 }.into(), - _ => Field::None, - }, - _ => Self::None, - } - } -} - -impl AddAssign for Field { - fn add_assign(&mut self, other: Self) { - *self = self.clone().add(other); - } -} - -impl From for Field { - fn from(value: bool) -> Self { - Self::Boolean(value) - } -} - -impl From> for Field { - fn from(value: DateTime) -> Self { - Self::DateTime(value) - } -} - -impl From for Field { - fn from(value: Duration) -> Self { - Self::Duration(value) - } -} - -impl From for Field { - fn from(value: String) -> Self { - Self::StaticString(value) - } -} - -impl From<&str> for Field { - fn from(value: &str) -> Self { - Self::from(value.to_string()) - } -} - -impl From for Field { - fn from(value: Uuid) -> Self { - Self::Uuid(value) - } -} - -impl From for Field { - fn from(value: i128) -> Self { - Self::Integer(value) - } -} - -impl From for Field { - fn from(value: isize) -> Self { - let data: i128 = value.try_into().unwrap(); - Self::from(data) - } -} - -impl From for Field { - fn from(value: i32) -> Self { - let data: i128 = value.into(); - Self::from(data) - } -} - -#[cfg(test)] -mod fields { - use super::*; - use rand::random; - - #[test] - fn can_create_static_string() { - let data = Uuid::new_v4().to_string(); - let result: Field = data.clone().into(); - match result.clone() { - Field::StaticString(output) => assert_eq!(output, data), - _ => unreachable!("got {:?}: should have been static string", result), - } - assert_eq!(result.get_type(), FieldType::StaticString); - } - - #[test] - fn can_create_from_str() { - let holder = ["one", "two"]; - for data in holder.into_iter() { - let result: Field = data.into(); - match result.clone() { - Field::StaticString(output) => assert_eq!(output, data), - _ => unreachable!("got {:?}: should have been static string", result), - } - assert_eq!(result.get_type(), FieldType::StaticString); - } - } - - #[test] - fn create_from_uuid() { - let data = Uuid::new_v4(); - let result: Field = data.clone().into(); - match result.clone() { - Field::Uuid(output) => assert_eq!(output, data), - _ => unreachable!("got {:?}: should have been uuid", result), - } - assert_eq!(result.get_type(), FieldType::Uuid); - } - - #[test] - fn create_from_datatime() { - let data = Utc::now(); - let result: Field = data.into(); - match result.clone() { - Field::DateTime(output) => assert_eq!(output, data), - _ => unreachable!("got {:?}: should have been uuid", result), - } - assert_eq!(result.get_type(), FieldType::DateTime); - } - - #[test] - fn does_adding_return_none_for_things_that_cannot_add() { - let value1: Field = Uuid::new_v4().into(); - let value2: Field = Uuid::new_v4().into(); - assert_eq!(value1 + value2, Field::None); - } - - #[test] - fn can_integers_be_added() { - let value1: i128 = random::().into(); - let value2: i128 = random::().into(); - let expected: Field = { value1 + value2 }.into(); - let value1: Field = value1.into(); - let value2: Field = value2.into(); - assert_eq!(value1 + value2, expected); - } - - #[test] - fn can_integer_add_mismatch_returns_none() { - let value1: Field = 5.into(); - let value2: Field = "nope".into(); - assert_eq!(value1 + value2, Field::None); - } - - #[test] - fn can_durations_be_added() { - let data1: u64 = random::().into(); - let data2: u64 = random::().into(); - let value1: Field = Duration::from_secs(data1).into(); - let value2: Field = Duration::from_secs(data2).into(); - let expected: Field = Duration::from_secs(data1 + data2).into(); - assert_eq!(value1 + value2, expected); - } - - #[test] - fn does_duration_mismatch_return_none() { - let value1: Field = Duration::from_secs(20).into(); - let value2: Field = "nope".into(); - assert_eq!(value1 + value2, Field::None); - } - - #[test] - fn can_durations_be_added_to_datetimes() { - let timestamp = Utc::now(); - let data: u64 = random::().into(); - let duration = Duration::from_secs(data); - let expected: Field = { timestamp + duration }.into(); - let value1: Field = timestamp.into(); - let value2: Field = duration.into(); - assert_eq!(value1 + value2, expected); - } - - #[test] - fn does_datetime_mismatch_return_none() { - let value1: Field = Utc::now().into(); - let value2: Field = "nope".into(); - assert_eq!(value1 + value2, Field::None); - } - - #[test] - fn does_field_equal_return_properly() { - let mut values: Vec = Vec::new(); - let count = 2; - while values.len() < count { - let value: Field = Uuid::new_v4().into(); - if !values.contains(&value) { - values.push(value); - } - } - assert_eq!(values[0].equal(&values[0]), true.into()); - assert_eq!(values[0].equal(&values[1]), false.into()); - assert_eq!(values[0].equal(&"nope".into()), Field::None); - } - - #[test] - fn does_field_not_equal_return_properly() { - let mut values: Vec = Vec::new(); - let count = 2; - while values.len() < count { - let value: Field = Uuid::new_v4().into(); - if !values.contains(&value) { - values.push(value); - } - } - assert_eq!(values[0].not_equal(&values[0]), false.into()); - assert_eq!(values[0].not_equal(&values[1]), true.into()); - assert_eq!(values[0].not_equal(&"nope".into()), Field::None); - } - - #[test] - fn can_field_have_greater_value() { - let value1: Field = 1.into(); - let value2: Field = 2.into(); - let value3: Field = 3.into(); - let mismatch: Field = "bad".into(); - assert_eq!(value2.greater(&value1), true.into()); - assert_eq!(value2.greater(&value2), false.into()); - assert_eq!(value2.greater(&value3), false.into()); - assert_eq!(value2.greater(&mismatch), Field::None); - } - - #[test] - fn can_field_have_greater_or_equal_value() { - let value1: Field = 1.into(); - let value2: Field = 2.into(); - let value3: Field = 3.into(); - let mismatch: Field = "bad".into(); - assert_eq!(value2.greater_equal(&value1), true.into()); - assert_eq!(value2.greater_equal(&value2), true.into()); - assert_eq!(value2.greater_equal(&value3), false.into()); - assert_eq!(value2.greater_equal(&mismatch), Field::None); - } - - #[test] - fn can_field_have_lesser_value() { - let value1: Field = 1.into(); - let value2: Field = 2.into(); - let value3: Field = 3.into(); - let mismatch: Field = "bad".into(); - assert_eq!(value2.lesser(&value1), false.into()); - assert_eq!(value2.lesser(&value2), false.into()); - assert_eq!(value2.lesser(&value3), true.into()); - assert_eq!(value2.lesser(&mismatch), Field::None); - } - - #[test] - fn can_field_have_lesser_or_equal_value() { - let value1: Field = 1.into(); - let value2: Field = 2.into(); - let value3: Field = 3.into(); - let mismatch: Field = "bad".into(); - assert_eq!(value2.lesser_equal(&value1), false.into()); - assert_eq!(value2.lesser_equal(&value2), true.into()); - assert_eq!(value2.lesser_equal(&value3), true.into()); - assert_eq!(value2.lesser_equal(&mismatch), Field::None); - } -} - #[derive(Clone, Debug)] struct FieldSetting { fieldtype: FieldType, diff --git a/src/mtterror.rs b/src/mtterror.rs index 0e4bab7..e74c23e 100644 --- a/src/mtterror.rs +++ b/src/mtterror.rs @@ -1,5 +1,7 @@ -use super::message::{Field, FieldType}; -use crate::name::Name; +use crate::{ + field::{Field, FieldType}, + name::Name, +}; use isolang::Language; use uuid::Uuid;