sqlite_diff_rs/encoding/serial/
display.rs1use super::Value;
4
5impl<S: AsRef<str>, B: AsRef<[u8]>> core::fmt::Display for Value<S, B> {
6 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8 match self {
9 Value::Integer(v) => write!(f, "{v}"),
10 Value::Real(v) => {
11 if v.is_nan() {
12 write!(f, "NULL")
13 } else if v.is_infinite() {
14 if v.is_sign_positive() {
15 write!(f, "9e999") } else {
17 write!(f, "-9e999")
18 }
19 } else {
20 write!(f, "{v}")
21 }
22 }
23 Value::Text(s) => {
24 write!(f, "'")?;
26 for c in s.as_ref().chars() {
27 if c == '\'' {
28 write!(f, "''")?;
29 } else {
30 core::fmt::Write::write_char(f, c)?;
31 }
32 }
33 write!(f, "'")
34 }
35 Value::Blob(b) => {
36 write!(f, "X'")?;
37 for byte in b.as_ref() {
38 write!(f, "{byte:02X}")?;
39 }
40 write!(f, "'")
41 }
42 Value::Null => write!(f, "NULL"),
43 }
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::Value;
50 use alloc::format;
51 use alloc::string::String;
52 use alloc::vec;
53 use alloc::vec::Vec;
54
55 type TestValue = Value<String, Vec<u8>>;
56
57 #[test]
58 fn test_display_null() {
59 let v: TestValue = Value::Null;
60 assert_eq!(format!("{v}"), "NULL");
61 }
62
63 #[test]
64 fn test_display_integer() {
65 let v: TestValue = Value::Integer(42);
66 assert_eq!(format!("{v}"), "42");
67
68 let v: TestValue = Value::Integer(-1);
69 assert_eq!(format!("{v}"), "-1");
70
71 let v: TestValue = Value::Integer(i64::MAX);
72 assert_eq!(format!("{v}"), "9223372036854775807");
73
74 let v: TestValue = Value::Integer(i64::MIN);
75 assert_eq!(format!("{v}"), "-9223372036854775808");
76 }
77
78 #[test]
79 #[allow(clippy::approx_constant)]
80 fn test_display_real_finite() {
81 let v: TestValue = Value::Real(3.14);
82 assert_eq!(format!("{v}"), "3.14");
83
84 let v: TestValue = Value::Real(-0.0);
85 let s = format!("{v}");
86 assert!(s == "-0" || s == "0", "got {s}");
87 }
88
89 #[test]
90 fn test_display_real_nan_becomes_null() {
91 let v: TestValue = Value::Real(f64::NAN);
92 assert_eq!(format!("{v}"), "NULL");
93 }
94
95 #[test]
96 fn test_display_real_positive_infinity() {
97 let v: TestValue = Value::Real(f64::INFINITY);
98 assert_eq!(format!("{v}"), "9e999");
99 }
100
101 #[test]
102 fn test_display_real_negative_infinity() {
103 let v: TestValue = Value::Real(f64::NEG_INFINITY);
104 assert_eq!(format!("{v}"), "-9e999");
105 }
106
107 #[test]
108 fn test_display_text_plain() {
109 let v: TestValue = Value::Text("hello".into());
110 assert_eq!(format!("{v}"), "'hello'");
111 }
112
113 #[test]
114 fn test_display_text_empty() {
115 let v: TestValue = Value::Text(String::new());
116 assert_eq!(format!("{v}"), "''");
117 }
118
119 #[test]
120 fn test_display_text_escapes_single_quote() {
121 let v: TestValue = Value::Text("it's".into());
122 assert_eq!(format!("{v}"), "'it''s'");
123 }
124
125 #[test]
126 fn test_display_text_escapes_multiple_quotes() {
127 let v: TestValue = Value::Text("''".into());
128 assert_eq!(format!("{v}"), "''''''");
129 }
130
131 #[test]
132 fn test_display_blob_uppercase_hex() {
133 let v: TestValue = Value::Blob(vec![0x01, 0xAB, 0xFF]);
134 assert_eq!(format!("{v}"), "X'01ABFF'");
135 }
136
137 #[test]
138 fn test_display_blob_empty() {
139 let v: TestValue = Value::Blob(Vec::new());
140 assert_eq!(format!("{v}"), "X''");
141 }
142}