vrl/compiler/value/
kind.rs1use crate::value::Value;
2use chrono::{TimeZone, Utc};
3use ordered_float::NotNan;
4use regex::Regex;
5
6use crate::value;
7
8pub const BYTES: u16 = 1 << 1;
9pub const INTEGER: u16 = 1 << 2;
10pub const FLOAT: u16 = 1 << 3;
11pub const BOOLEAN: u16 = 1 << 4;
12pub const OBJECT: u16 = 1 << 5;
13pub const ARRAY: u16 = 1 << 6;
14pub const TIMESTAMP: u16 = 1 << 7;
15pub const REGEX: u16 = 1 << 8;
16pub const NULL: u16 = 1 << 9;
17pub const UNDEFINED: u16 = 1 << 10;
18
19pub const ANY: u16 =
20 BYTES | INTEGER | FLOAT | BOOLEAN | OBJECT | ARRAY | TIMESTAMP | REGEX | NULL | UNDEFINED;
21pub const SCALAR: u16 = BYTES | INTEGER | FLOAT | BOOLEAN | TIMESTAMP | REGEX | NULL;
22pub const CONTAINER: u16 = OBJECT | ARRAY;
23
24pub use crate::value::{
25 Kind,
26 kind::{Collection, Field, Index, get, insert, merge, remove},
27};
28
29pub trait DefaultValue {
30 fn default_value(&self) -> Value;
40}
41
42impl DefaultValue for Kind {
43 fn default_value(&self) -> Value {
44 if self.is_bytes() {
45 return value!("");
46 }
47
48 if self.is_integer() {
49 return value!(0_i64);
50 }
51
52 if self.is_float() {
53 return value!(NotNan::new(0.0).unwrap());
54 }
55
56 if self.is_boolean() {
57 return value!(false);
58 }
59
60 if self.is_timestamp() {
61 return Utc
62 .timestamp_opt(0, 0)
63 .single()
64 .expect("invalid timestamp")
65 .into();
66 }
67
68 if self.is_regex() {
69 #[allow(clippy::trivial_regex)]
70 return Regex::new("").unwrap().into();
71 }
72
73 if self.is_array() {
74 return value!([]);
75 }
76
77 if self.is_object() {
78 return value!({});
79 }
80
81 Value::Null
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use std::collections::{BTreeMap, HashMap};
88
89 use super::*;
90
91 #[test]
92 fn test_from_value() {
93 struct TestCase {
94 value: Value,
95 want: Kind,
96 }
97
98 for (title, TestCase { value, want }) in HashMap::from([
99 (
100 "bytes",
101 TestCase {
102 value: value!("foo"),
103 want: Kind::bytes(),
104 },
105 ),
106 (
107 "integer",
108 TestCase {
109 value: value!(3_i64),
110 want: Kind::integer(),
111 },
112 ),
113 (
114 "float",
115 TestCase {
116 value: value!(NotNan::new(3.3).unwrap()),
117 want: Kind::float(),
118 },
119 ),
120 (
121 "boolean",
122 TestCase {
123 value: value!(true),
124 want: Kind::boolean(),
125 },
126 ),
127 (
128 "timestamp",
129 TestCase {
130 value: Utc::now().into(),
131 want: Kind::timestamp(),
132 },
133 ),
134 (
135 "regex",
136 TestCase {
137 value: Regex::new("").unwrap().into(),
138 want: Kind::regex(),
139 },
140 ),
141 (
142 "null",
143 TestCase {
144 value: value!(null),
145 want: Kind::null(),
146 },
147 ),
148 (
149 "object",
150 TestCase {
151 value: value!({ "foo": { "bar": 12_i64 }, "baz": true }),
152 want: Kind::object(BTreeMap::from([
153 (
154 "foo".into(),
155 Kind::object(BTreeMap::from([("bar".into(), Kind::integer())])),
156 ),
157 ("baz".into(), Kind::boolean()),
158 ])),
159 },
160 ),
161 (
162 "array",
163 TestCase {
164 value: value!([12_i64, true, "foo", { "bar": null }]),
165 want: Kind::array(BTreeMap::from([
166 (0.into(), Kind::integer()),
167 (1.into(), Kind::boolean()),
168 (2.into(), Kind::bytes()),
169 (
170 3.into(),
171 Kind::object(BTreeMap::from([("bar".into(), Kind::null())])),
172 ),
173 ])),
174 },
175 ),
176 ]) {
177 assert_eq!(Kind::from(value), want, "{title}");
178 }
179 }
180}