vrl/compiler/
expression_error.rs

1use ExpressionError::{Abort, Error, Fallible, Missing, Return};
2
3use crate::diagnostic::{Diagnostic, DiagnosticMessage, Label, Note, Severity, Span};
4use crate::value::Value;
5
6pub type Resolved = Result<Value, ExpressionError>;
7
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub enum ExpressionError {
10    Abort {
11        span: Span,
12        message: Option<String>,
13    },
14    Return {
15        span: Span,
16        value: Value,
17    },
18    Error {
19        message: String,
20        labels: Vec<Label>,
21        notes: Vec<Note>,
22    },
23
24    Fallible {
25        span: Span,
26    },
27
28    Missing {
29        span: Span,
30        feature: &'static str,
31    },
32}
33
34impl std::fmt::Display for ExpressionError {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        self.message().fmt(f)
37    }
38}
39
40impl std::error::Error for ExpressionError {
41    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
42        None
43    }
44}
45
46impl From<ExpressionError> for Diagnostic {
47    fn from(error: ExpressionError) -> Self {
48        Self {
49            severity: Severity::Error,
50            code: error.code(),
51            message: error.message(),
52            labels: error.labels(),
53            notes: error.notes(),
54        }
55    }
56}
57
58impl DiagnosticMessage for ExpressionError {
59    fn code(&self) -> usize {
60        match self {
61            Abort { .. } | Return { .. } | Error { .. } => 0,
62            Fallible { .. } => 100,
63            Missing { .. } => 900,
64        }
65    }
66
67    fn message(&self) -> String {
68        match self {
69            Abort { message, .. } => message.clone().unwrap_or_else(|| "aborted".to_owned()),
70            Return { .. } => "return".to_string(),
71            Error { message, .. } => message.clone(),
72            Fallible { .. } => "unhandled error".to_string(),
73            Missing { .. } => "expression type unavailable".to_string(),
74        }
75    }
76
77    fn labels(&self) -> Vec<Label> {
78        match self {
79            Abort { span, .. } => {
80                vec![Label::primary("aborted", span)]
81            }
82            Return { .. } => Vec::new(),
83            Error { labels, .. } => labels.clone(),
84            Fallible { span } => vec![
85                Label::primary("expression can result in runtime error", span),
86                Label::context("handle the error case to ensure runtime success", span),
87            ],
88            Missing { span, feature } => vec![
89                Label::primary("expression type is disabled in this version of vrl", span),
90                Label::context(
91                    format!("build vrl using the `{feature}` feature to enable it"),
92                    span,
93                ),
94            ],
95        }
96    }
97
98    fn notes(&self) -> Vec<Note> {
99        match self {
100            Return { .. } | Abort { .. } | Missing { .. } => vec![],
101            Error { notes, .. } => notes.clone(),
102            Fallible { .. } => vec![Note::SeeErrorDocs],
103        }
104    }
105}
106
107impl From<String> for ExpressionError {
108    fn from(message: String) -> Self {
109        ExpressionError::Error {
110            message,
111            labels: vec![],
112            notes: vec![],
113        }
114    }
115}
116
117impl From<&str> for ExpressionError {
118    fn from(message: &str) -> Self {
119        message.to_owned().into()
120    }
121}