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