Skip to main content

geam_core/runtime/value/
inspection.rs

1mod bit_array;
2mod custom;
3mod function;
4mod list;
5mod tuple;
6
7use std::fmt::{self, Display, Formatter};
8
9use super::Value;
10
11pub struct ValueInspection<'value> {
12    value: &'value Value,
13}
14
15impl<'value> ValueInspection<'value> {
16    pub(super) fn new(value: &'value Value) -> Self {
17        Self { value }
18    }
19
20    pub(crate) fn write_to(&self, output: &mut String) {
21        write_value(output, self.value);
22    }
23}
24
25impl Display for ValueInspection<'_> {
26    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
27        let mut output = String::new();
28        self.write_to(&mut output);
29        formatter.write_str(&output)
30    }
31}
32
33fn write_value(output: &mut String, value: &Value) {
34    match value {
35        Value::Int(value) => output.push_str(&value.to_string()),
36        Value::Float(value) => output.push_str(&format!("{value:?}")),
37        Value::String(value) => output.push_str(&format!("{value:?}")),
38        Value::BitArray(value) => bit_array::write(output, value),
39        Value::UtfCodepoint(value) => output.push_str(&format!("{value:?}")),
40        Value::Custom(value) => custom::write(output, value),
41        Value::External(value) => output.push_str(value.inspection()),
42        Value::Bool(true) => output.push_str("True"),
43        Value::Bool(false) => output.push_str("False"),
44        Value::Nil => output.push_str("Nil"),
45        Value::Tuple(values) => tuple::write(output, values),
46        Value::List(value) => list::write(output, value),
47        Value::Function(value) => function::write(output, value),
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::super::Value;
54
55    #[test]
56    fn inspects_primitive_values() {
57        let cases = [
58            (Value::Int((-12).into()), "-12"),
59            (Value::Float(1.0), "1.0"),
60            (Value::Float(-0.0), "-0.0"),
61            (Value::Float(f64::INFINITY), "inf"),
62            (Value::Float(f64::NEG_INFINITY), "-inf"),
63            (Value::Float(f64::NAN), "NaN"),
64            (
65                Value::String("one\n\"two\"\\".into()),
66                r#""one\n\"two\"\\""#,
67            ),
68            (Value::UtfCodepoint('A'), "'A'"),
69            (Value::UtfCodepoint('\n'), "'\\n'"),
70            (Value::UtfCodepoint('\u{10ffff}'), "'\\u{10ffff}'"),
71            (Value::Bool(true), "True"),
72            (Value::Bool(false), "False"),
73            (Value::Nil, "Nil"),
74        ];
75
76        for (value, expected) in cases {
77            assert_eq!(value.inspect().to_string(), expected);
78        }
79    }
80}