From eca86a53b9e7570aaebc3d24d2d1a88dcebe78fb Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Sun, 8 Feb 2026 12:57:29 -0500 Subject: [PATCH] Moved operand into action. --- src/action.rs | 2 +- src/action/calculation.rs | 78 ++++++- src/action/query.rs | 2 +- src/document/create.rs | 5 +- src/document/definition.rs | 2 +- src/document/session.rs | 4 +- src/lib.rs | 4 +- src/message/wrapper.rs | 420 +------------------------------------ 8 files changed, 88 insertions(+), 429 deletions(-) diff --git a/src/action.rs b/src/action.rs index 79a41a6..3e20ad9 100644 --- a/src/action.rs +++ b/src/action.rs @@ -10,7 +10,7 @@ pub use crate::document::{ field::{Field, FieldType}, }; pub use action_type::Action; -pub use calculation::{CalcValue, Calculation}; +pub use calculation::{CalcValue, Calculation, Operand}; pub use message::MsgAction; pub use query::Query; use request_data::RequestData; diff --git a/src/action/calculation.rs b/src/action/calculation.rs index 464d10d..5b3ab6d 100644 --- a/src/action/calculation.rs +++ b/src/action/calculation.rs @@ -1,9 +1,85 @@ use super::{Field, FieldType}; -use crate::{message::wrapper::Operand, mtterror::MTTError}; +use crate::mtterror::MTTError; use chrono::{DateTime, Utc}; use std::time::Duration; use uuid::Uuid; +#[derive(Clone, Debug)] +pub enum Operand { + Add, + Equal, + GreaterThan, + GreaterThanEqual, + LessThan, + LessThanEqual, +} + +impl Operand { + pub fn validate(&self, x: &Field, y: &Field) -> bool { + match self { + Self::Equal => x == y, + Self::GreaterThan => x > y, + Self::GreaterThanEqual => x >= y, + Self::LessThan => x < y, + Self::LessThanEqual => x <= y, + _ => false, + } + } +} + +#[cfg(test)] +mod operands { + use super::*; + + #[test] + fn equals_true() { + let data: Field = Uuid::new_v4().into(); + assert!(Operand::Equal.validate(&data, &data)); + } + + #[test] + fn equals_false() { + let x: Field = Uuid::new_v4().into(); + let mut y: Field = Uuid::new_v4().into(); + while x == y { + y = Uuid::new_v4().into(); + } + assert!(!Operand::Equal.validate(&x, &y)); + } + + #[test] + fn does_greater() { + let data: Vec = vec![1.into(), 2.into(), 3.into()]; + assert!(!Operand::GreaterThan.validate(&data[0], &data[1])); + assert!(!Operand::GreaterThan.validate(&data[1], &data[1])); + assert!(Operand::GreaterThan.validate(&data[2], &data[1])); + } + + #[test] + fn does_greater_equal() { + let data: Vec = vec![1.into(), 2.into(), 3.into()]; + assert!(!Operand::GreaterThanEqual.validate(&data[0], &data[1])); + assert!(Operand::GreaterThanEqual.validate(&data[1], &data[1])); + assert!(Operand::GreaterThanEqual.validate(&data[2], &data[1])); + } + + #[test] + fn does_lesser() { + let data: Vec = vec![1.into(), 2.into(), 3.into()]; + assert!(Operand::LessThan.validate(&data[0], &data[1])); + assert!(!Operand::LessThan.validate(&data[1], &data[1])); + assert!(!Operand::LessThan.validate(&data[2], &data[1])); + } + + #[test] + fn does_lesser_equal() { + let data: Vec = vec![1.into(), 2.into(), 3.into()]; + assert!(Operand::LessThanEqual.validate(&data[0], &data[1])); + assert!(Operand::LessThanEqual.validate(&data[1], &data[1])); + assert!(!Operand::LessThanEqual.validate(&data[2], &data[1])); + } +} + #[derive(Clone, Debug)] pub enum CalcValue { Calculate(Calculation), diff --git a/src/action/query.rs b/src/action/query.rs index 582f6f1..861482a 100644 --- a/src/action/query.rs +++ b/src/action/query.rs @@ -45,7 +45,7 @@ impl Query { #[cfg(test)] mod queries { use super::*; - use crate::{document::field::Field, message::wrapper::Operand, name::Name}; + use crate::{action::{Field, Operand}, name::Name}; use uuid::Uuid; #[test] diff --git a/src/document/create.rs b/src/document/create.rs index 8306195..2fc3042 100644 --- a/src/document/create.rs +++ b/src/document/create.rs @@ -317,7 +317,7 @@ impl Indexes { #[cfg(test)] mod indexes { use super::*; - use crate::{document::field::FieldType, message::wrapper::Operand}; + use crate::action::{FieldType, Operand}; fn get_fields(count: usize) -> Vec { let mut output = Vec::new(); @@ -813,8 +813,9 @@ impl DocumentFile { mod document_files { use super::*; use crate::{ + action::Operand, document::field::FieldType, - message::wrapper::{Addition, Delete, Operand}, + message::wrapper::{Addition, Delete}, name::{Name, Names}, support_tests::TIMEOUT, }; diff --git a/src/document/definition.rs b/src/document/definition.rs index aa275c1..7595e90 100644 --- a/src/document/definition.rs +++ b/src/document/definition.rs @@ -72,7 +72,7 @@ impl FieldSetting { #[cfg(test)] mod fieldsettings { use super::*; - use crate::{action::Calculation, message::wrapper::Operand}; + use crate::{action::Calculation, Operand}; use chrono::Utc; use std::time::Duration; diff --git a/src/document/session.rs b/src/document/session.rs index 88687f7..5ed3869 100644 --- a/src/document/session.rs +++ b/src/document/session.rs @@ -1,11 +1,11 @@ use crate::{ - action::{Action, CalcValue, Calculation, FieldType, Query}, + action::{Action, CalcValue, Calculation, FieldType, Operand, Query}, document::{ clock::Clock, create::IndexType, definition::{DocDef, DocFuncType}, }, - message::wrapper::{Delete, Message, Operand, Update}, + message::wrapper::{Delete, Message, Update}, name::{Name, NameType}, queue::{ data_director::{Include, Path, RegMsg, Register}, diff --git a/src/lib.rs b/src/lib.rs index ef6ea60..e2169f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,9 +5,9 @@ mod mtterror; mod name; mod queue; -use action::{Action, CalcValue, Calculation, DocDef, Field, FieldType, MsgAction, Query, UserAction}; +use action::{Action, CalcValue, Calculation, DocDef, Field, FieldType, MsgAction, Operand, Query, UserAction}; use document::{clock::Clock, create::CreateDoc, session::Session}; -use message::wrapper::{Addition, Message, Operand}; +use message::wrapper::{Addition, Message}; pub use mtterror::MTTError; pub use name::{Name, NameType}; use queue::{ diff --git a/src/message/wrapper.rs b/src/message/wrapper.rs index 0ca57b0..d11f310 100644 --- a/src/message/wrapper.rs +++ b/src/message/wrapper.rs @@ -1,5 +1,5 @@ use crate::{ - action::{CalcValue, MsgAction, Query}, + action::{CalcValue, MsgAction, Operand, Query}, document::field::{Field, FieldType}, mtterror::MTTError, name::{NameType, Names}, @@ -330,424 +330,6 @@ mod additions { } } -#[derive(Clone, Debug)] -pub enum Operand { - Add, - Equal, - GreaterThan, - GreaterThanEqual, - LessThan, - LessThanEqual, -} - -impl Operand { - #[allow(dead_code)] - fn validate(&self, x: &Field, y: &Field) -> bool { - match self { - Self::Equal => x == y, - Self::GreaterThan => x > y, - Self::GreaterThanEqual => x >= y, - Self::LessThan => x < y, - Self::LessThanEqual => x <= y, - _ => false, - } - } -} - -#[cfg(test)] -mod operands { - use super::*; - - #[test] - fn equals_true() { - let data: Field = Uuid::new_v4().into(); - assert!(Operand::Equal.validate(&data, &data)); - } - - #[test] - fn equals_false() { - let x: Field = Uuid::new_v4().into(); - let mut y: Field = Uuid::new_v4().into(); - while x == y { - y = Uuid::new_v4().into(); - } - assert!(!Operand::Equal.validate(&x, &y)); - } - - #[test] - fn does_greater() { - let data: Vec = vec![1.into(), 2.into(), 3.into()]; - assert!(!Operand::GreaterThan.validate(&data[0], &data[1])); - assert!(!Operand::GreaterThan.validate(&data[1], &data[1])); - assert!(Operand::GreaterThan.validate(&data[2], &data[1])); - } - - #[test] - fn does_greater_equal() { - let data: Vec = vec![1.into(), 2.into(), 3.into()]; - assert!(!Operand::GreaterThanEqual.validate(&data[0], &data[1])); - assert!(Operand::GreaterThanEqual.validate(&data[1], &data[1])); - assert!(Operand::GreaterThanEqual.validate(&data[2], &data[1])); - } - - #[test] - fn does_lesser() { - let data: Vec = vec![1.into(), 2.into(), 3.into()]; - assert!(Operand::LessThan.validate(&data[0], &data[1])); - assert!(!Operand::LessThan.validate(&data[1], &data[1])); - assert!(!Operand::LessThan.validate(&data[2], &data[1])); - } - - #[test] - fn does_lesser_equal() { - let data: Vec = vec![1.into(), 2.into(), 3.into()]; - assert!(Operand::LessThanEqual.validate(&data[0], &data[1])); - assert!(Operand::LessThanEqual.validate(&data[1], &data[1])); - assert!(!Operand::LessThanEqual.validate(&data[2], &data[1])); - } -} - -/* -#[derive(Clone, Debug)] -pub struct Calculation { - operation: Operand, - values: Vec, -} - -impl Calculation { - pub fn new(operand: Operand) -> Self { - Self { - operation: operand, - values: Vec::new(), - } - } - - #[allow(dead_code)] - fn operation(&self) -> &Operand { - &self.operation - } - - #[allow(dead_code)] - fn get_fields(&self, existing: Field) -> Vec { - let mut output = Vec::new(); - for item in self.values.iter() { - output.push(item.get(&existing)); - } - output - } - - pub fn get_type(&self) -> FieldType { - if self.values.is_empty() { - FieldType::None - } else { - self.values[0].get_type() - } - } - - pub fn add_value(&mut self, data: CV) -> Result<(), MTTError> - where - CV: Into, - { - let holder: CalcValue = data.into(); - if self.values.is_empty() { - self.values.push(holder); - return Ok(()); - } - let mut base = self.get_type(); - match self.operation { - Operand::Add => match base { - FieldType::DateTime => base = FieldType::Duration, - _ => {} - }, - _ => {} - } - let ftype = holder.get_type(); - if base == ftype { - self.values.push(holder); - } else { - return Err(MTTError::DocumentFieldWrongDataType(base, ftype)); - } - Ok(()) - } - - #[allow(dead_code)] - fn validate_value(&self, value: CV) -> Result<(), MTTError> - where - CV: Into, - { - if self.values.is_empty() { - return Ok(()); - } - let holder = value.into(); - let mut base = self.get_type(); - match self.operation { - Operand::Add => { - if base == FieldType::DateTime { - base = FieldType::Duration; - } - } - _ => {} - } - let ftype = holder.get_type(); - if base == ftype { - Ok(()) - } else { - Err(MTTError::DocumentFieldWrongDataType(base, ftype)) - } - } - - pub fn calculate(&self, existing: &Field) -> Field { - let mut result = Field::None; - match self.operation { - Operand::Add => { - let mut first = true; - for value in self.values.iter() { - let data = value.get(existing); - if first { - result = data; - first = false; - } else { - result += data; - } - } - } - Operand::Equal => { - if self.values.len() >= 2 { - result = self.values[0] - .get(existing) - .equal(&self.values[1].get(existing)); - } - } - Operand::GreaterThan => { - if self.values.len() >= 2 { - result = self.values[0] - .get(existing) - .greater(&self.values[1].get(existing)); - } - } - Operand::GreaterThanEqual => { - if self.values.len() >= 2 { - result = self.values[0] - .get(existing) - .greater_equal(&self.values[1].get(existing)); - } - } - Operand::LessThan => { - if self.values.len() >= 2 { - result = self.values[0] - .get(existing) - .lesser(&self.values[1].get(existing)); - } - } - Operand::LessThanEqual => { - if self.values.len() >= 2 { - result = self.values[0] - .get(existing) - .lesser_equal(&self.values[1].get(existing)); - } - } - } - result - } -} - -#[cfg(test)] -mod calculations { - use super::*; - use rand::random; - - #[test] - fn errors_on_different_field_types() { - let mut calc = Calculation::new(Operand::Equal); - calc.add_value(Uuid::nil()).unwrap(); - match calc.add_value("other") { - Ok(_) => unreachable!("should have errored with wrong type"), - Err(err) => match err { - MTTError::DocumentFieldWrongDataType(expected, got) => { - assert_eq!(expected, FieldType::Uuid); - assert_eq!(got, FieldType::StaticString); - } - _ => unreachable!("got {:?}, expected wrong field type", err), - }, - } - } - - #[test] - fn returns_reference_to_operand() { - let calc = Calculation::new(Operand::Add); - match calc.operation() { - Operand::Add => {} - _ => unreachable!("got {:?}, shold have gotten assign", calc.operation()), - } - let calc = Calculation::new(Operand::Equal); - match calc.operation() { - Operand::Equal => {} - _ => unreachable!("got {:?}, shold have gotten assign", calc.operation()), - } - } - - #[test] - fn can_equal_true() { - let mut calc = Calculation::new(Operand::Equal); - let data: Field = Uuid::new_v4().into(); - calc.add_value(data.clone()).unwrap(); - calc.add_value(data.clone()).unwrap(); - let expected: Field = true.into(); - let result = calc.calculate(&Field::None); - assert_eq!(result, expected); - } - - #[test] - fn can_equal_false() { - let mut calc = Calculation::new(Operand::Equal); - let value1: Field = "fred".into(); - let value2: Field = "barney".into(); - calc.add_value(value1).unwrap(); - calc.add_value(value2).unwrap(); - let expected: Field = false.into(); - let result = calc.calculate(&Field::None); - assert_eq!(result, expected); - } - - #[test] - fn can_greater_than() { - let data: Vec<(Field, Field)> = vec![ - (0.into(), false.into()), - (1.into(), false.into()), - (2.into(), true.into()), - ]; - for (item, expected) in data.iter() { - let mut calc = Calculation::new(Operand::GreaterThan); - calc.add_value(item.clone()).unwrap(); - calc.add_value(data[1].0.clone()).unwrap(); - let result = calc.calculate(&Field::None); - assert_eq!(&result, expected); - } - } - - #[test] - fn can_greater_than_equal() { - let data: Vec<(Field, Field)> = vec![ - (0.into(), false.into()), - (1.into(), true.into()), - (2.into(), true.into()), - ]; - for (item, expected) in data.iter() { - let mut calc = Calculation::new(Operand::GreaterThanEqual); - calc.add_value(item.clone()).unwrap(); - calc.add_value(data[1].0.clone()).unwrap(); - let result = calc.calculate(&Field::None); - assert_eq!(&result, expected); - } - } - - #[test] - fn can_lesser_than() { - let data: Vec<(Field, Field)> = vec![ - (0.into(), true.into()), - (1.into(), false.into()), - (2.into(), false.into()), - ]; - for (item, expected) in data.iter() { - let mut calc = Calculation::new(Operand::LessThan); - calc.add_value(item.clone()).unwrap(); - calc.add_value(data[1].0.clone()).unwrap(); - let result = calc.calculate(&Field::None); - assert_eq!(&result, expected); - } - } - - #[test] - fn can_lesser_than_equal() { - let data: Vec<(Field, Field)> = vec![ - (0.into(), true.into()), - (1.into(), true.into()), - (2.into(), false.into()), - ]; - for (item, expected) in data.iter() { - let mut calc = Calculation::new(Operand::LessThanEqual); - calc.add_value(item.clone()).unwrap(); - calc.add_value(data[1].0.clone()).unwrap(); - let result = calc.calculate(&Field::None); - assert_eq!(&result, expected); - } - } - - #[test] - fn can_add_numbers() { - let mut calc = Calculation::new(Operand::Add); - 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(); - calc.add_value(value1.clone()).unwrap(); - calc.add_value(value2.clone()).unwrap(); - let result = calc.calculate(&Field::None); - assert_eq!( - result, expected, - "{:?} plus {:?} should equal {:?}", - value1, value2, expected - ); - } - - #[test] - fn can_use_existing_values() { - let mut calc = Calculation::new(Operand::Add); - 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(); - calc.add_value(value1.clone()).unwrap(); - calc.add_value(CalcValue::Existing(FieldType::Integer)) - .unwrap(); - let result = calc.calculate(&value2); - assert_eq!( - result, expected, - "{:?} plus {:?} should equal {:?}", - value1, value2, expected - ); - } - - #[test] - fn returns_error_on_mismatch() { - let mut calc = Calculation::new(Operand::Add); - calc.add_value(Uuid::nil()).unwrap(); - match calc.add_value("mismatch") { - Ok(_) => unreachable!("should have returned an error"), - Err(err) => match err { - MTTError::DocumentFieldWrongDataType(expected, got) => { - assert_eq!(got, FieldType::StaticString); - assert_eq!(expected, FieldType::Uuid); - } - _ => unreachable!("got {:?}, expected wrong field type", err), - }, - } - } - - #[test] - fn datetime_accepts_duration() { - let mut calc = Calculation::new(Operand::Add); - let duration = Duration::from_secs(3600); - let start = Utc::now() + duration; - calc.add_value(FieldType::DateTime).unwrap(); - match calc.add_value(duration.clone()) { - Ok(_) => {} - Err(err) => unreachable!("got {:?}, should have returned normally", err), - } - let result = calc.calculate(&Field::None); - let stop = Utc::now() + duration; - match result { - Field::DateTime(data) => { - assert!(data > start); - assert!(data < stop); - } - _ => unreachable!("got {:?}, should have been datetime", result), - } - } -} -*/ #[allow(dead_code)] #[derive(Clone, Debug)]