1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use super::{Collection, Field, Index, Kind};
impl Kind {
/// Get the inner object collection.
///
/// This returns `None` if the type is not known to be an object.
#[must_use]
pub const fn as_object(&self) -> Option<&Collection<Field>> {
self.object.as_ref()
}
/// Get a mutable reference to the inner object collection.
///
/// This returns `None` if the type is not known to be an object.
#[must_use]
pub fn as_object_mut(&mut self) -> Option<&mut Collection<Field>> {
self.object.as_mut()
}
/// Take an object `Collection` type out of the `Kind`.
///
/// This returns `None` if the type is not known to be an object.
#[must_use]
pub fn into_object(self) -> Option<Collection<Field>> {
self.object
}
/// Get the inner array collection.
///
/// This returns `None` if the type is not known to be an array.
#[must_use]
pub const fn as_array(&self) -> Option<&Collection<Index>> {
self.array.as_ref()
}
/// Get a mutable reference to the inner array collection.
///
/// This returns `None` if the type is not known to be an array.
#[must_use]
pub fn as_array_mut(&mut self) -> Option<&mut Collection<Index>> {
self.array.as_mut()
}
/// Take an array `Collection` type out of the `Kind`.
///
/// This returns `None` if the type is not known to be an array.
#[must_use]
pub fn into_array(self) -> Option<Collection<Index>> {
self.array
}
/// Returns `Kind`, with non-primitive states removed.
///
/// That is, it returns `self,` but removes the `object` and `array` states.
#[must_use]
pub fn to_primitives(mut self) -> Self {
self.remove_array();
self.remove_object();
self
}
/// VRL has an interesting property where accessing an undefined value "upgrades"
/// it to a "null" value.
/// This should be used in places those implicit upgrades can occur.
// see: https://github.com/vectordotdev/vector/issues/13594
#[must_use]
pub fn upgrade_undefined(mut self) -> Self {
if self.is_never() {
return self;
}
if self.contains_undefined() {
self = self.without_undefined().or_null();
}
self
}
}
impl From<Collection<Field>> for Kind {
fn from(collection: Collection<Field>) -> Self {
Self::object(collection)
}
}
impl From<Collection<Index>> for Kind {
fn from(collection: Collection<Index>) -> Self {
Self::array(collection)
}
}
#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, HashMap};
use super::*;
#[test]
fn test_to_primitive() {
struct TestCase {
kind: Kind,
want: Kind,
}
for (title, TestCase { kind, want }) in HashMap::from([
(
"single primitive",
TestCase {
kind: Kind::bytes(),
want: Kind::bytes(),
},
),
(
"multiple primitives",
TestCase {
kind: Kind::integer().or_regex(),
want: Kind::integer().or_regex(),
},
),
(
"array only",
TestCase {
kind: Kind::array(BTreeMap::default()),
want: Kind::never(),
},
),
(
"object only",
TestCase {
kind: Kind::object(BTreeMap::default()),
want: Kind::never(),
},
),
(
"collections removed",
TestCase {
kind: Kind::timestamp()
.or_integer()
.or_object(BTreeMap::default())
.or_array(BTreeMap::default()),
want: Kind::timestamp().or_integer(),
},
),
]) {
assert_eq!(kind.to_primitives(), want, "{title}");
}
}
}