Started to add the functionality to allow default functions.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
This commit is contained in:
370
src/message.rs
370
src/message.rs
@@ -6,6 +6,7 @@ use std::{
|
||||
Arc, RwLock,
|
||||
},
|
||||
thread::spawn,
|
||||
time::Duration,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -951,7 +952,10 @@ impl CreateDoc {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum FieldType {
|
||||
Boolean,
|
||||
DateTime,
|
||||
Duration,
|
||||
Integer,
|
||||
None,
|
||||
StaticString,
|
||||
Uuid,
|
||||
@@ -960,7 +964,10 @@ enum FieldType {
|
||||
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(),
|
||||
@@ -971,7 +978,10 @@ impl FieldType {
|
||||
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,
|
||||
@@ -1017,7 +1027,10 @@ mod fieldtypes {
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
enum Field {
|
||||
Boolean(bool),
|
||||
DateTime(DateTime<Utc>),
|
||||
Duration(Duration),
|
||||
Integer(u128),
|
||||
None,
|
||||
StaticString(String),
|
||||
Uuid(Uuid),
|
||||
@@ -1029,12 +1042,24 @@ impl Field {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Field {
|
||||
fn from(value: bool) -> Self {
|
||||
Self::Boolean(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateTime<Utc>> for Field {
|
||||
fn from(value: DateTime<Utc>) -> Self {
|
||||
Self::DateTime(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Duration> for Field {
|
||||
fn from(value: Duration) -> Self {
|
||||
Self::Duration(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Field {
|
||||
fn from(value: String) -> Self {
|
||||
Self::StaticString(value)
|
||||
@@ -1053,6 +1078,12 @@ impl From<Uuid> for Field {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for Field {
|
||||
fn from(value: u128) -> Self {
|
||||
Self::Integer(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fields {
|
||||
use super::*;
|
||||
@@ -1091,6 +1122,17 @@ mod fields {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -1212,6 +1254,31 @@ mod fieldsettings {
|
||||
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
|
||||
}
|
||||
}
|
||||
|
||||
//#[test]
|
||||
fn can_default_be_calculated() {
|
||||
let mut fset = FieldSetting::new(FieldType::DateTime);
|
||||
fset.set_default(None);
|
||||
let duration = Duration::from_secs(3600);
|
||||
let start = Utc::now() + duration;
|
||||
let result = match fset.validate(None).unwrap() {
|
||||
Field::DateTime(data) => data,
|
||||
_ => unreachable!("should return datetime"),
|
||||
};
|
||||
let stop = Utc::now() + duration;
|
||||
assert!(
|
||||
result > start,
|
||||
"{:?} should have been greater than {:?}",
|
||||
result,
|
||||
start
|
||||
);
|
||||
assert!(
|
||||
result > stop,
|
||||
"{:?} should have been less than {:?}",
|
||||
result,
|
||||
stop
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -1476,6 +1543,8 @@ mod docdefs {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum Operand {
|
||||
Add,
|
||||
Assign,
|
||||
Equal,
|
||||
}
|
||||
|
||||
@@ -1483,6 +1552,7 @@ impl Operand {
|
||||
fn validate(&self, x: &Field, y: &Field) -> bool {
|
||||
match self {
|
||||
Self::Equal => x == y,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1508,6 +1578,306 @@ mod operands {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum CalcValue {
|
||||
FType(FieldType),
|
||||
Value(Field),
|
||||
}
|
||||
|
||||
impl CalcValue {
|
||||
fn get(&self) -> Field {
|
||||
match self {
|
||||
Self::FType(ftype) => ftype.get_default(),
|
||||
Self::Value(field) => field.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Field> for CalcValue {
|
||||
fn from(value: Field) -> Self {
|
||||
Self::Value(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FieldType> for CalcValue {
|
||||
fn from(value: FieldType) -> Self {
|
||||
Self::FType(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for CalcValue {
|
||||
fn from(value: bool) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateTime<Utc>> for CalcValue {
|
||||
fn from(value: DateTime<Utc>) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Duration> for CalcValue {
|
||||
fn from(value: Duration) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for CalcValue {
|
||||
fn from(value: u128) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for CalcValue {
|
||||
fn from(value: &str) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for CalcValue {
|
||||
fn from(value: String) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uuid> for CalcValue {
|
||||
fn from(value: Uuid) -> Self {
|
||||
let output: Field = value.into();
|
||||
Self::from(output).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod calcvalues {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_uuid() {
|
||||
let value = Uuid::new_v4();
|
||||
let expected: Field = value.into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
let value = "something";
|
||||
let expected: Field = value.into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_string() {
|
||||
let value = "data".to_string();
|
||||
let expected: Field = value.clone().into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_boolean() {
|
||||
let value = true;
|
||||
let expected: Field = value.clone().into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_datetime() {
|
||||
let value = Utc::now();
|
||||
let expected: Field = value.clone().into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_duration() {
|
||||
let value = Duration::from_secs(5);
|
||||
let expected: Field = value.clone().into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_integer() {
|
||||
let value: u128 = 5;
|
||||
let expected: Field = value.clone().into();
|
||||
let result: CalcValue = value.into();
|
||||
match result {
|
||||
CalcValue::FType(_) => unreachable!("got {:?}, should have gotten a field", result),
|
||||
CalcValue::Value(data) => assert_eq!(data, expected),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Calculation {
|
||||
operation: Operand,
|
||||
values: Vec<CalcValue>,
|
||||
}
|
||||
|
||||
impl Calculation {
|
||||
fn new(operand: Operand) -> Self {
|
||||
Self {
|
||||
operation: operand,
|
||||
values: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fields(&self) -> Vec<Field> {
|
||||
let mut output = Vec::new();
|
||||
for item in self.values.iter() {
|
||||
output.push(item.get());
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn add_value<CV>(&mut self, data: CV) -> Result<(), MTTError>
|
||||
where
|
||||
CV: Into<CalcValue>,
|
||||
{
|
||||
let holder: CalcValue = data.into();
|
||||
if self.values.len() == 0 {
|
||||
self.values.push(holder);
|
||||
} else {
|
||||
match self.operation {
|
||||
Operand::Add => {
|
||||
if self.values[0].get().get_type() == holder.get().get_type() {
|
||||
self.values.push(holder);
|
||||
} else {
|
||||
return Err(MTTError::DocumentFieldWrongDataType(
|
||||
FieldType::None,
|
||||
FieldType::None,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => self.values.push(holder),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn calculate(&self) -> Field {
|
||||
match self.operation {
|
||||
Operand::Add => {
|
||||
let values = self.get_fields();
|
||||
match values[0].get_type() {
|
||||
FieldType::Integer => {
|
||||
let mut output: u128 = 0;
|
||||
for item in values.iter() {
|
||||
match item {
|
||||
Field::Integer(data) => output += data,
|
||||
_ => unreachable! {"got {:?} expected Integer", item},
|
||||
}
|
||||
}
|
||||
output.into()
|
||||
}
|
||||
_ => unreachable!("{:?} does not handle addition", values[0].get_type()),
|
||||
}
|
||||
}
|
||||
Operand::Assign => self.values[0].get(),
|
||||
Operand::Equal => { self.values[0].get() == self.values[1].get() }.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod calculations {
|
||||
use super::*;
|
||||
use rand::random;
|
||||
|
||||
#[test]
|
||||
fn can_assign_value() {
|
||||
let mut calc = Calculation::new(Operand::Assign);
|
||||
let data: Field = Uuid::new_v4().into();
|
||||
calc.add_value(data.clone());
|
||||
let result = calc.calculate();
|
||||
assert_eq!(result, data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_assign_default_function() {
|
||||
let mut calc = Calculation::new(Operand::Assign);
|
||||
calc.add_value(FieldType::Uuid);
|
||||
let result1 = calc.calculate();
|
||||
let result2 = calc.calculate();
|
||||
assert_ne!(result1, result2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_equal_true() {
|
||||
let mut calc = Calculation::new(Operand::Equal);
|
||||
let data: Field = Uuid::new_v4().into();
|
||||
calc.add_value(data.clone());
|
||||
calc.add_value(data.clone());
|
||||
let expected: Field = true.into();
|
||||
let result = calc.calculate();
|
||||
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);
|
||||
calc.add_value(value2);
|
||||
let expected: Field = false.into();
|
||||
let result = calc.calculate();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_add_numbers() {
|
||||
let mut calc = Calculation::new(Operand::Add);
|
||||
let value1: u128 = random::<u8>().into();
|
||||
let value2: u128 = random::<u8>().into();
|
||||
let expected: Field = { value1 + value2 }.into();
|
||||
let value1: Field = value1.into();
|
||||
let value2: Field = value2.into();
|
||||
calc.add_value(value1);
|
||||
calc.add_value(value2);
|
||||
let result = calc.calculate();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_error_on_mismatch() {
|
||||
let mut calc = Calculation::new(Operand::Add);
|
||||
calc.add_value(Uuid::nil());
|
||||
match calc.add_value("mismatch") {
|
||||
Ok(_) => unreachable!("should have returned an error"),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Operation {
|
||||
field_name: String,
|
||||
|
||||
Reference in New Issue
Block a user