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
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            // Semantic meaning can only be assigned to external fields.
79            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        // Reject assigning meaning to non-existing field.
112        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            // Disallow a single VRL program from assigning the same semantic meaning to two
132            // different fields.
133            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}