Started to add the functionality to allow default functions.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s

This commit is contained in:
2025-09-18 13:30:20 -04:00
parent a157d5cc67
commit 85e12e20d4
3 changed files with 431 additions and 1 deletions

View File

@@ -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,