vrl/value/value/
display.rs

1use std::{fmt, string::ToString};
2
3use chrono::SecondsFormat;
4
5use super::Value;
6
7impl fmt::Display for Value {
8    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9        match self {
10            Self::Bytes(val) => write!(
11                f,
12                r#""{}""#,
13                String::from_utf8_lossy(val)
14                    .replace('\\', r"\\")
15                    .replace('"', r#"\""#)
16                    .replace('\n', r"\n")
17            ),
18            Self::Integer(val) => write!(f, "{val}"),
19            Self::Float(val) => write!(f, "{val}"),
20            Self::Boolean(val) => write!(f, "{val}"),
21            Self::Object(map) => {
22                let joined = map
23                    .iter()
24                    .map(|(key, val)| format!(r#""{key}": {val}"#))
25                    .collect::<Vec<_>>()
26                    .join(", ");
27                write!(f, "{{ {joined} }}")
28            }
29            Self::Array(array) => {
30                let joined = array
31                    .iter()
32                    .map(ToString::to_string)
33                    .collect::<Vec<_>>()
34                    .join(", ");
35                write!(f, "[{joined}]")
36            }
37            Self::Timestamp(val) => {
38                write!(f, "t'{}'", val.to_rfc3339_opts(SecondsFormat::AutoSi, true))
39            }
40            Self::Regex(regex) => write!(f, "r'{}'", **regex),
41            Self::Null => write!(f, "null"),
42        }
43    }
44}
45
46#[cfg(test)]
47mod test {
48    use bytes::Bytes;
49    use chrono::DateTime;
50    use indoc::indoc;
51    use ordered_float::NotNan;
52    use regex::Regex;
53
54    use super::Value;
55
56    #[test]
57    fn test_display_string() {
58        assert_eq!(
59            Value::Bytes(Bytes::from("Hello, world!")).to_string(),
60            r#""Hello, world!""#
61        );
62    }
63
64    #[test]
65    fn test_display_string_with_backslashes() {
66        assert_eq!(
67            Value::Bytes(Bytes::from(r"foo \ bar \ baz")).to_string(),
68            r#""foo \\ bar \\ baz""#
69        );
70    }
71
72    #[test]
73    fn test_display_string_with_quotes() {
74        assert_eq!(
75            Value::Bytes(Bytes::from(r#""Hello, world!""#)).to_string(),
76            r#""\"Hello, world!\"""#
77        );
78    }
79
80    #[test]
81    fn test_display_string_with_newlines() {
82        assert_eq!(
83            Value::Bytes(Bytes::from(indoc! {"
84                Some
85                new
86                lines
87            "}))
88            .to_string(),
89            r#""Some\nnew\nlines\n""#
90        );
91    }
92
93    #[test]
94    fn test_display_integer() {
95        assert_eq!(Value::Integer(123).to_string(), "123");
96    }
97
98    #[test]
99    fn test_display_float() {
100        assert_eq!(
101            Value::Float(NotNan::new(123.45).unwrap()).to_string(),
102            "123.45"
103        );
104    }
105
106    #[test]
107    fn test_display_boolean() {
108        assert_eq!(Value::Boolean(true).to_string(), "true");
109    }
110
111    #[test]
112    fn test_display_object() {
113        assert_eq!(
114            Value::Object([("foo".into(), "bar".into())].into()).to_string(),
115            r#"{ "foo": "bar" }"#
116        );
117    }
118
119    #[test]
120    fn test_display_array() {
121        assert_eq!(
122            Value::Array(
123                vec!["foo", "bar"]
124                    .into_iter()
125                    .map(std::convert::Into::into)
126                    .collect()
127            )
128            .to_string(),
129            r#"["foo", "bar"]"#
130        );
131    }
132
133    #[test]
134    fn test_display_timestamp() {
135        assert_eq!(
136            Value::Timestamp(
137                DateTime::parse_from_rfc3339("2000-10-10T20:55:36Z")
138                    .unwrap()
139                    .into()
140            )
141            .to_string(),
142            "t'2000-10-10T20:55:36Z'"
143        );
144    }
145
146    #[test]
147    fn test_display_regex() {
148        assert_eq!(
149            Value::Regex(Regex::new(".*").unwrap().into()).to_string(),
150            "r'.*'"
151        );
152    }
153
154    #[test]
155    fn test_display_null() {
156        assert_eq!(Value::Null.to_string(), "null");
157    }
158}