vector_vrl_functions/
set_semantic_meaning.rs

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