vector_vrl_functions/
set_semantic_meaning.rs

1use 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            // Semantic meaning can only be assigned to external fields.
91            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        // Reject assigning meaning to non-existing field.
124        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            // Disallow a single VRL program from assigning the same semantic meaning to two
144            // different fields.
145            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}