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 anyhow::Result;
50
51    use crate::Expr;
52
53    #[test]
54    fn test_evaluate_constant_literals() -> Result<()> {
55        use crate::Evaluation;
56
57        let test_cases = &[
58            ("'hello'", Evaluation::String("hello".to_string())),
59            ("'world'", Evaluation::String("world".to_string())),
60            ("42", Evaluation::Number(42.0)),
61            ("3.14", Evaluation::Number(3.14)),
62            ("true", Evaluation::Boolean(true)),
63            ("false", Evaluation::Boolean(false)),
64            ("null", Evaluation::Null),
65        ];
66
67        for (expr_str, expected) in test_cases {
68            let expr = Expr::parse(expr_str)?;
69            let result = expr.consteval().unwrap();
70            assert_eq!(result, *expected, "Failed for expression: {}", expr_str);
71        }
72
73        Ok(())
74    }
75}