ddb_core/functions/
mod.rs1pub mod aggregate;
3pub mod math;
4pub mod string;
5pub mod conversion;
6pub mod datetime;
7pub mod system;
8pub mod conditional;
9pub mod utility;
10pub mod registry;
11
12use crate::error::{DdbError, Result};
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub enum Value {
18 Null,
19 Boolean(bool),
20 Integer(i64),
21 Float(f64),
22 String(String),
23 Date(chrono::NaiveDate),
24 DateTime(chrono::NaiveDateTime),
25 Time(chrono::NaiveTime),
26}
27
28impl Value {
29 pub fn to_string(&self) -> String {
31 match self {
32 Value::Null => "NULL".to_string(),
33 Value::Boolean(b) => b.to_string(),
34 Value::Integer(i) => i.to_string(),
35 Value::Float(f) => f.to_string(),
36 Value::String(s) => s.clone(),
37 Value::Date(d) => d.format("%Y-%m-%d").to_string(),
38 Value::DateTime(dt) => dt.format("%Y-%m-%d %H:%M:%S").to_string(),
39 Value::Time(t) => t.format("%H:%M:%S").to_string(),
40 }
41 }
42
43 pub fn as_i64(&self) -> Result<i64> {
45 match self {
46 Value::Integer(i) => Ok(*i),
47 Value::Float(f) => Ok(*f as i64),
48 Value::String(s) => s.parse().map_err(|_| {
49 DdbError::TypeError(format!("Cannot convert '{}' to integer", s))
50 }),
51 Value::Boolean(b) => Ok(if *b { 1 } else { 0 }),
52 _ => Err(DdbError::TypeError(format!(
53 "Cannot convert {:?} to integer",
54 self
55 ))),
56 }
57 }
58
59 pub fn as_f64(&self) -> Result<f64> {
61 match self {
62 Value::Float(f) => Ok(*f),
63 Value::Integer(i) => Ok(*i as f64),
64 Value::String(s) => s.parse().map_err(|_| {
65 DdbError::TypeError(format!("Cannot convert '{}' to float", s))
66 }),
67 _ => Err(DdbError::TypeError(format!(
68 "Cannot convert {:?} to float",
69 self
70 ))),
71 }
72 }
73
74 pub fn is_null(&self) -> bool {
76 matches!(self, Value::Null)
77 }
78
79 pub fn from_str(s: &str) -> Self {
81 if s.eq_ignore_ascii_case("null") || s.is_empty() {
83 return Value::Null;
84 }
85
86 if s.eq_ignore_ascii_case("true") {
87 return Value::Boolean(true);
88 }
89
90 if s.eq_ignore_ascii_case("false") {
91 return Value::Boolean(false);
92 }
93
94 if let Ok(i) = s.parse::<i64>() {
96 return Value::Integer(i);
97 }
98
99 if let Ok(f) = s.parse::<f64>() {
101 return Value::Float(f);
102 }
103
104 Value::String(s.to_string())
106 }
107}
108
109impl std::fmt::Display for Value {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 write!(f, "{}", self.to_string())
112 }
113}
114
115impl From<&str> for Value {
116 fn from(s: &str) -> Self {
117 Value::String(s.to_string())
118 }
119}
120
121impl From<String> for Value {
122 fn from(s: String) -> Self {
123 Value::String(s)
124 }
125}
126
127impl From<i64> for Value {
128 fn from(i: i64) -> Self {
129 Value::Integer(i)
130 }
131}
132
133impl From<f64> for Value {
134 fn from(f: f64) -> Self {
135 Value::Float(f)
136 }
137}
138
139impl From<bool> for Value {
140 fn from(b: bool) -> Self {
141 Value::Boolean(b)
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_value_conversions() {
151 assert_eq!(Value::from_str("123"), Value::Integer(123));
152 assert_eq!(Value::from_str("12.5"), Value::Float(12.5));
153 assert_eq!(Value::from_str("true"), Value::Boolean(true));
154 assert_eq!(Value::from_str("null"), Value::Null);
155 assert_eq!(Value::from_str("hello"), Value::String("hello".to_string()));
156 }
157
158 #[test]
159 fn test_value_to_string() {
160 assert_eq!(Value::Integer(42).to_string(), "42");
161 assert_eq!(Value::Float(3.14).to_string(), "3.14");
162 assert_eq!(Value::Boolean(true).to_string(), "true");
163 assert_eq!(Value::Null.to_string(), "NULL");
164 }
165}