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