pub enum DataValue<'a> {
Null,
Bool(bool),
Number(NumberValue),
String(&'a str),
Array(&'a [DataValue<'a>]),
Object(&'a [(&'a str, DataValue<'a>)]),
DateTime(DateTime<Utc>),
Duration(Duration),
}Expand description
A memory-efficient value type that leverages arena allocation.
This replaces the direct dependency on serde_json::Value with a custom
implementation optimized for rule evaluation.
Variants§
Null
Represents a null value
Bool(bool)
Represents a boolean value
Number(NumberValue)
Represents a numeric value (integer or floating point)
String(&'a str)
Represents a string value (arena-allocated)
Array(&'a [DataValue<'a>])
Represents an array of values (arena-allocated)
Object(&'a [(&'a str, DataValue<'a>)])
Represents an object with key-value pairs (arena-allocated)
DateTime(DateTime<Utc>)
Represents a datetime value
Duration(Duration)
Represents a duration value
Implementations§
Source§impl<'a> DataValue<'a>
impl<'a> DataValue<'a>
Sourcepub fn string(arena: &'a DataArena, value: &str) -> Self
pub fn string(arena: &'a DataArena, value: &str) -> Self
Creates a string value.
If the string is empty, returns a string value with the preallocated empty string.
Sourcepub fn datetime(value: DateTime<Utc>) -> Self
pub fn datetime(value: DateTime<Utc>) -> Self
Creates a datetime value from a chrono::DateTime<Utc>.
Sourcepub fn array(arena: &'a DataArena, values: &[DataValue<'a>]) -> Self
pub fn array(arena: &'a DataArena, values: &[DataValue<'a>]) -> Self
Creates an array value.
If the array is empty, returns a value with the preallocated empty array. For small arrays (up to 8 elements), uses an optimized allocation method.
Sourcepub fn object(
arena: &'a DataArena,
entries: &[(&'a str, DataValue<'a>)],
) -> Self
pub fn object( arena: &'a DataArena, entries: &[(&'a str, DataValue<'a>)], ) -> Self
Creates an object value.
If the entries array is empty, returns an object with an empty entries array.
Sourcepub fn is_array(&self) -> bool
pub fn is_array(&self) -> bool
Returns true if the value is an array.
Examples found in repository?
40 fn evaluate<'a>(
41 &self,
42 args: &'a [DataValue<'a>],
43 arena: &'a DataArena,
44 ) -> Result<&'a DataValue<'a>> {
45 // Collect all numeric values
46 let mut numbers = Vec::new();
47
48 // Handle the case where a single array is passed
49 if args.len() == 1 && args[0].is_array() {
50 if let Some(items) = args[0].as_array() {
51 for item in items {
52 if let Some(n) = item.as_f64() {
53 numbers.push(n);
54 }
55 }
56 }
57 } else {
58 // Handle the case where multiple arguments are passed
59 for arg in args {
60 if let Some(n) = arg.as_f64() {
61 numbers.push(n);
62 }
63 }
64 }
65
66 // Return 0 for empty arrays
67 if numbers.is_empty() {
68 return Ok(arena.alloc(DataValue::Number(NumberValue::from_i64(0))));
69 }
70
71 // Sort the numbers
72 numbers.sort_by(|a, b| a.partial_cmp(b).unwrap());
73
74 // Calculate the median
75 let median = if numbers.len() % 2 == 0 {
76 // Even number of elements - average the middle two
77 let mid = numbers.len() / 2;
78 (numbers[mid - 1] + numbers[mid]) / 2.0
79 } else {
80 // Odd number of elements - take the middle one
81 numbers[numbers.len() / 2]
82 };
83
84 // Return the result
85 Ok(arena.alloc(DataValue::Number(NumberValue::from_f64(median))))
86 }Sourcepub fn is_datetime(&self) -> bool
pub fn is_datetime(&self) -> bool
Returns true if the value is a datetime.
Sourcepub fn is_duration(&self) -> bool
pub fn is_duration(&self) -> bool
Returns true if the value is a duration.
Sourcepub fn as_i64(&self) -> Option<i64>
pub fn as_i64(&self) -> Option<i64>
Returns the value as an i64, if it is a number that can be represented as an i64.
Sourcepub fn as_f64(&self) -> Option<f64>
pub fn as_f64(&self) -> Option<f64>
Returns the value as an f64, if it is a number.
Examples found in repository?
More examples
12 fn evaluate<'a>(
13 &self,
14 args: &'a [DataValue<'a>],
15 arena: &'a DataArena,
16 ) -> Result<&'a DataValue<'a>> {
17 // Default to 1 if no arguments provided
18 if args.is_empty() {
19 return Ok(arena.alloc(DataValue::Number(NumberValue::from_i64(1))));
20 }
21
22 // Calculate product of all numeric values
23 let mut product = 1.0;
24 for arg in args {
25 if let Some(n) = arg.as_f64() {
26 product *= n;
27 }
28 }
29
30 // Return the result
31 Ok(arena.alloc(DataValue::Number(NumberValue::from_f64(product))))
32 }
33}
34
35// Define a custom operator that returns the median of a set of numbers
36#[derive(Debug)]
37struct Median;
38
39impl CustomOperator for Median {
40 fn evaluate<'a>(
41 &self,
42 args: &'a [DataValue<'a>],
43 arena: &'a DataArena,
44 ) -> Result<&'a DataValue<'a>> {
45 // Collect all numeric values
46 let mut numbers = Vec::new();
47
48 // Handle the case where a single array is passed
49 if args.len() == 1 && args[0].is_array() {
50 if let Some(items) = args[0].as_array() {
51 for item in items {
52 if let Some(n) = item.as_f64() {
53 numbers.push(n);
54 }
55 }
56 }
57 } else {
58 // Handle the case where multiple arguments are passed
59 for arg in args {
60 if let Some(n) = arg.as_f64() {
61 numbers.push(n);
62 }
63 }
64 }
65
66 // Return 0 for empty arrays
67 if numbers.is_empty() {
68 return Ok(arena.alloc(DataValue::Number(NumberValue::from_i64(0))));
69 }
70
71 // Sort the numbers
72 numbers.sort_by(|a, b| a.partial_cmp(b).unwrap());
73
74 // Calculate the median
75 let median = if numbers.len() % 2 == 0 {
76 // Even number of elements - average the middle two
77 let mid = numbers.len() / 2;
78 (numbers[mid - 1] + numbers[mid]) / 2.0
79 } else {
80 // Odd number of elements - take the middle one
81 numbers[numbers.len() / 2]
82 };
83
84 // Return the result
85 Ok(arena.alloc(DataValue::Number(NumberValue::from_f64(median))))
86 }Sourcepub fn as_str(&self) -> Option<&str>
pub fn as_str(&self) -> Option<&str>
Returns the value as a string slice, if it is a string.
Examples found in repository?
21fn to_uppercase(args: Vec<DataValue>) -> std::result::Result<DataValue, String> {
22 if args.is_empty() {
23 return Err("to_uppercase requires a string argument".to_string());
24 }
25
26 if let Some(s) = args[0].as_str() {
27 // Use Box::leak to create a static string
28 let upper = s.to_uppercase();
29 let upper_str = Box::leak(upper.into_boxed_str());
30 return Ok(DataValue::String(upper_str));
31 }
32
33 Err("Argument must be a string".to_string())
34}Sourcepub fn as_array(&self) -> Option<&[DataValue<'a>]>
pub fn as_array(&self) -> Option<&[DataValue<'a>]>
Returns the value as an array slice, if it is an array.
Examples found in repository?
40 fn evaluate<'a>(
41 &self,
42 args: &'a [DataValue<'a>],
43 arena: &'a DataArena,
44 ) -> Result<&'a DataValue<'a>> {
45 // Collect all numeric values
46 let mut numbers = Vec::new();
47
48 // Handle the case where a single array is passed
49 if args.len() == 1 && args[0].is_array() {
50 if let Some(items) = args[0].as_array() {
51 for item in items {
52 if let Some(n) = item.as_f64() {
53 numbers.push(n);
54 }
55 }
56 }
57 } else {
58 // Handle the case where multiple arguments are passed
59 for arg in args {
60 if let Some(n) = arg.as_f64() {
61 numbers.push(n);
62 }
63 }
64 }
65
66 // Return 0 for empty arrays
67 if numbers.is_empty() {
68 return Ok(arena.alloc(DataValue::Number(NumberValue::from_i64(0))));
69 }
70
71 // Sort the numbers
72 numbers.sort_by(|a, b| a.partial_cmp(b).unwrap());
73
74 // Calculate the median
75 let median = if numbers.len() % 2 == 0 {
76 // Even number of elements - average the middle two
77 let mid = numbers.len() / 2;
78 (numbers[mid - 1] + numbers[mid]) / 2.0
79 } else {
80 // Odd number of elements - take the middle one
81 numbers[numbers.len() / 2]
82 };
83
84 // Return the result
85 Ok(arena.alloc(DataValue::Number(NumberValue::from_f64(median))))
86 }Sourcepub fn as_datetime(&self) -> Option<&DateTime<Utc>>
pub fn as_datetime(&self) -> Option<&DateTime<Utc>>
Returns the value as a datetime, if it is a datetime.
Sourcepub fn as_duration(&self) -> Option<&Duration>
pub fn as_duration(&self) -> Option<&Duration>
Returns the value as a duration, if it is a duration.
Sourcepub fn as_object(&self) -> Option<&[(&'a str, DataValue<'a>)]>
pub fn as_object(&self) -> Option<&[(&'a str, DataValue<'a>)]>
Returns the value as an object slice, if it is an object.
Sourcepub fn coerce_to_bool(&self) -> bool
pub fn coerce_to_bool(&self) -> bool
Coerces the value to a boolean.
The coercion follows JSON Logic rules:
nullisfalsefalseisfalse- Empty string is
false - Empty array is
false - Empty object is
false 0isfalse- Everything else is
true
Sourcepub fn coerce_to_number(&self) -> Option<NumberValue>
pub fn coerce_to_number(&self) -> Option<NumberValue>
Coerces the value to a number according to JSONLogic rules.
Sourcepub fn coerce_to_string(&self, arena: &'a DataArena) -> DataValue<'a>
pub fn coerce_to_string(&self, arena: &'a DataArena) -> DataValue<'a>
Coerces the value to a string according to JSONLogic rules.
Sourcepub fn get_index(&self, index: usize) -> Option<&DataValue<'a>>
pub fn get_index(&self, index: usize) -> Option<&DataValue<'a>>
Gets a value from an array by index.
Sourcepub fn type_name(&self) -> &'static str
pub fn type_name(&self) -> &'static str
Returns a string representation of the type of this value.
Sourcepub fn equals(&self, other: &DataValue<'a>) -> bool
pub fn equals(&self, other: &DataValue<'a>) -> bool
Checks if this value equals another value, with type coercion.
Sourcepub fn strict_equals(&self, other: &DataValue<'a>) -> bool
pub fn strict_equals(&self, other: &DataValue<'a>) -> bool
Checks if this value strictly equals another value, without type coercion.