vector_vrl_functions/
set_semantic_meaning.rs1use std::{
2 collections::BTreeMap,
3 ops::{Deref, DerefMut},
4};
5
6use vrl::{
7 diagnostic::Label,
8 path::{OwnedTargetPath, PathPrefix},
9 prelude::*,
10};
11
12use indoc::indoc;
13
14#[derive(Debug, Default, Clone)]
15pub struct MeaningList(pub BTreeMap<String, OwnedTargetPath>);
16
17impl Deref for MeaningList {
18 type Target = BTreeMap<String, OwnedTargetPath>;
19
20 fn deref(&self) -> &Self::Target {
21 &self.0
22 }
23}
24
25impl DerefMut for MeaningList {
26 fn deref_mut(&mut self) -> &mut Self::Target {
27 &mut self.0
28 }
29}
30
31#[derive(Clone, Copy, Debug)]
32pub struct SetSemanticMeaning;
33
34impl Function for SetSemanticMeaning {
35 fn identifier(&self) -> &'static str {
36 "set_semantic_meaning"
37 }
38
39 fn usage(&self) -> &'static str {
40 indoc! {"
41 Sets a semantic meaning for an event. **Note**: This function assigns
42 meaning at startup, and has _no_ runtime behavior. It is suggested
43 to put all calls to this function at the beginning of a VRL function. The function
44 cannot be conditionally called. For example, using an if statement cannot stop the meaning
45 from being assigned.
46 "}
47 }
48
49 fn parameters(&self) -> &'static [Parameter] {
50 &[
51 Parameter {
52 keyword: "target",
53 kind: kind::ANY,
54 required: true,
55 },
56 Parameter {
57 keyword: "meaning",
58 kind: kind::BYTES,
59 required: true,
60 },
61 ]
62 }
63
64 fn examples(&self) -> &'static [Example] {
65 &[example!(
66 title: "Sets custom field semantic meaning",
67 source: r#"set_semantic_meaning(.foo, "bar")"#,
68 result: Ok("null"),
69 )]
70 }
71
72 fn compile(
73 &self,
74 state: &TypeState,
75 ctx: &mut FunctionCompileContext,
76 arguments: ArgumentList,
77 ) -> Compiled {
78 let span = ctx.span();
79 let query = arguments.required_query("target")?;
80
81 let meaning = arguments
82 .required_literal("meaning", state)?
83 .try_bytes_utf8_lossy()
84 .expect("meaning not bytes")
85 .into_owned();
86
87 let path = if let Some(path) = query.external_path() {
88 path
89 } else {
90 let mut labels = vec![Label::primary(
92 "this path must point to an event or metadata",
93 span,
94 )];
95
96 if let Some(variable) = query.as_variable() {
97 labels.push(Label::context(
98 format!(
99 "maybe you meant \".{}\" or \"%{}\"?",
100 variable.ident(),
101 variable.ident()
102 ),
103 span,
104 ));
105 }
106
107 let error = ExpressionError::Error {
108 message: "semantic meaning is not valid for local variables".to_owned(),
109 labels,
110 notes: vec![],
111 };
112
113 return Err(Box::new(error) as Box<dyn DiagnosticMessage>);
114 };
115
116 let exists = match path.prefix {
117 PathPrefix::Event => state.external.target_kind(),
118 PathPrefix::Metadata => state.external.metadata_kind(),
119 }
120 .at_path(&path.path)
121 .contains_any_defined();
122
123 if !exists {
125 let error = ExpressionError::Error {
126 message: "semantic meaning defined for non-existing field".to_owned(),
127 labels: vec![
128 Label::primary("cannot assign semantic meaning to non-existing field", span),
129 Label::context(
130 format!("field \".{}\" is not known to exist for all events", &path),
131 span,
132 ),
133 ],
134 notes: vec![],
135 };
136
137 return Err(Box::new(error) as Box<dyn DiagnosticMessage>);
138 }
139
140 if let Some(list) = ctx.get_external_context_mut::<MeaningList>() {
141 let duplicate = list.get(&meaning).filter(|&p| p != &path);
142
143 if let Some(duplicate) = duplicate {
146 let error = ExpressionError::Error {
147 message: "semantic meaning referencing two different fields".to_owned(),
148 labels: vec![
149 Label::primary(
150 format!(
151 "semantic meaning \"{}\" must reference a single field",
152 &meaning
153 ),
154 span,
155 ),
156 Label::context(
157 format!("already referencing field \".{}\"", &duplicate),
158 span,
159 ),
160 ],
161 notes: vec![],
162 };
163
164 return Err(Box::new(error) as Box<dyn DiagnosticMessage>);
165 }
166
167 list.insert(meaning, path);
168 };
169
170 Ok(SetSemanticMeaningFn.as_expr())
171 }
172}
173
174#[derive(Debug, Clone)]
175struct SetSemanticMeaningFn;
176
177impl FunctionExpression for SetSemanticMeaningFn {
178 fn resolve(&self, _ctx: &mut Context) -> Resolved {
179 Ok(Value::Null)
180 }
181
182 fn type_def(&self, _: &TypeState) -> TypeDef {
183 TypeDef::null().infallible().impure()
184 }
185}