Skip to main content

github_actions_expressions/
literal.rs

1//! Literal values.
2
3use std::borrow::Cow;
4
5use crate::Evaluation;
6
7/// Represents a literal value in a GitHub Actions expression.
8#[derive(Debug, PartialEq)]
9pub enum Literal<'src> {
10    /// A number literal.
11    Number(f64),
12    /// A string literal.
13    String(Cow<'src, str>),
14    /// A boolean literal.
15    Boolean(bool),
16    /// The `null` literal.
17    Null,
18}
19
20impl<'src> Literal<'src> {
21    /// Returns a string representation of the literal.
22    ///
23    /// This is not guaranteed to be an exact equivalent of the literal
24    /// as it appears in its source expression. For example, the string
25    /// representation of a floating point literal is subject to normalization,
26    /// and string literals are returned without surrounding quotes.
27    pub fn as_str(&self) -> Cow<'src, str> {
28        match self {
29            Literal::String(s) => s.clone(),
30            Literal::Number(n) => Cow::Owned(n.to_string()),
31            Literal::Boolean(b) => Cow::Owned(b.to_string()),
32            Literal::Null => Cow::Borrowed("null"),
33        }
34    }
35
36    /// Returns the trivial constant evaluation of the literal.
37    pub(crate) fn consteval(&self) -> Evaluation {
38        match self {
39            Literal::String(s) => Evaluation::String(s.to_string()),
40            Literal::Number(n) => Evaluation::Number(*n),
41            Literal::Boolean(b) => Evaluation::Boolean(*b),
42            Literal::Null => Evaluation::Null,
43        }
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use crate::{Error, Expr};
50
51    #[test]
52    fn test_evaluate_constant_literals() -> Result<(), Error> {
53        use crate::Evaluation;
54
55        let test_cases = &[
56            ("'hello'", Evaluation::String("hello".to_string())),
57            ("'world'", Evaluation::String("world".to_string())),
58            ("42", Evaluation::Number(42.0)),
59            ("3.14", Evaluation::Number(3.14)),
60            ("true", Evaluation::Boolean(true)),
61            ("false", Evaluation::Boolean(false)),
62            ("null", Evaluation::Null),
63            ("0xFF", Evaluation::Number(255.0)),
64            ("0o10", Evaluation::Number(8.0)),
65            ("1.5e2", Evaluation::Number(150.0)),
66            ("+42", Evaluation::Number(42.0)),
67            (".5", Evaluation::Number(0.5)),
68        ];
69
70        for (expr_str, expected) in test_cases {
71            let expr = Expr::parse(expr_str)?;
72            let result = expr.consteval().unwrap();
73            assert_eq!(result, *expected, "Failed for expression: {}", expr_str);
74        }
75
76        Ok(())
77    }
78}