databend_driver_core/value/format/
display.rs1use crate::_macro_internal::Value;
16use crate::value::base::{DAYS_FROM_CE, TIMESTAMP_FORMAT, TIMESTAMP_TIMEZONE_FORMAT};
17use crate::value::NumberValue;
18use chrono::NaiveDate;
19use ethnum::i256;
20use std::fmt::Write;
21
22impl std::fmt::Display for Value {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 self.display_value(f, true)
25 }
26}
27
28impl std::fmt::Display for NumberValue {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 NumberValue::Int8(i) => write!(f, "{i}"),
32 NumberValue::Int16(i) => write!(f, "{i}"),
33 NumberValue::Int32(i) => write!(f, "{i}"),
34 NumberValue::Int64(i) => write!(f, "{i}"),
35 NumberValue::UInt8(i) => write!(f, "{i}"),
36 NumberValue::UInt16(i) => write!(f, "{i}"),
37 NumberValue::UInt32(i) => write!(f, "{i}"),
38 NumberValue::UInt64(i) => write!(f, "{i}"),
39 NumberValue::Float32(i) => display_float(*i, f),
40 NumberValue::Float64(i) => display_float(*i, f),
41 NumberValue::Decimal64(v, s) => {
42 write!(f, "{}", display_decimal_128(*v as i128, s.scale))
43 }
44 NumberValue::Decimal128(v, s) => write!(f, "{}", display_decimal_128(*v, s.scale)),
45 NumberValue::Decimal256(v, s) => write!(f, "{}", display_decimal_256(*v, s.scale)),
46 }
47 }
48}
49
50impl Value {
51 pub fn display_value(&self, f: &mut std::fmt::Formatter<'_>, raw: bool) -> std::fmt::Result {
54 match self {
55 Value::Null => write!(f, "NULL"),
56 Value::EmptyArray => write!(f, "[]"),
57 Value::EmptyMap => write!(f, "{{}}"),
58 Value::Boolean(b) => {
59 if *b {
60 write!(f, "true")
61 } else {
62 write!(f, "false")
63 }
64 }
65 Value::Number(n) => write!(f, "{n}"),
66 Value::Binary(s) => write!(f, "{}", hex::encode_upper(s)),
67 Value::String(s) | Value::Bitmap(s) | Value::Interval(s) => {
68 if raw {
69 write!(f, "{s}")
70 } else {
71 write!(f, "\"{s}\"")
72 }
73 }
74 Value::Variant(s) => {
75 write!(f, "{s}")
76 }
77 Value::Geometry(s) | Value::Geography(s) => {
78 let s = s.to_string();
79 if raw || s.starts_with('{') {
80 write!(f, "{s}")
81 } else {
82 write!(f, "\"{s}\"")
83 }
84 }
85 Value::Timestamp(dt) => {
86 let formatted = dt.strftime(TIMESTAMP_FORMAT);
87 if raw {
88 write!(f, "{formatted}")
89 } else {
90 write!(f, "\"{formatted}\"")
91 }
92 }
93 Value::TimestampTz(dt) => {
94 let formatted = dt.strftime(TIMESTAMP_TIMEZONE_FORMAT);
95 if raw {
96 write!(f, "{formatted}")
97 } else {
98 write!(f, "\"{formatted}\"")
99 }
100 }
101 Value::Date(i) => {
102 let days = i + DAYS_FROM_CE;
103 let d = NaiveDate::from_num_days_from_ce_opt(days).unwrap_or_default();
104 if raw {
105 write!(f, "{d}")
106 } else {
107 write!(f, "\"{d}\"")
108 }
109 }
110 Value::Array(vals) => {
111 write!(f, "[")?;
112 for (i, val) in vals.iter().enumerate() {
113 if i > 0 {
114 write!(f, ",")?;
115 }
116 val.display_value(f, false)?;
117 }
118 write!(f, "]")?;
119 Ok(())
120 }
121 Value::Map(kvs) => {
122 write!(f, "{{")?;
123 for (i, (key, val)) in kvs.iter().enumerate() {
124 if i > 0 {
125 write!(f, ",")?;
126 }
127 key.display_value(f, false)?;
128 write!(f, ":")?;
129 val.display_value(f, false)?;
130 }
131 write!(f, "}}")?;
132 Ok(())
133 }
134 Value::Tuple(vals) => {
135 write!(f, "(")?;
136 for (i, val) in vals.iter().enumerate() {
137 if i > 0 {
138 write!(f, ",")?;
139 }
140 val.display_value(f, false)?;
141 }
142 write!(f, ")")?;
143 Ok(())
144 }
145 Value::Vector(vals) => {
146 write!(f, "[")?;
147 let mut buffer = zmij::Buffer::new();
148 for (i, val) in vals.iter().enumerate() {
149 if i > 0 {
150 write!(f, ",")?;
151 }
152 let s = buffer.format_finite(*val);
153 write!(f, "{s}")?;
154 }
155 write!(f, "]")?;
156 Ok(())
157 }
158 }
159 }
160}
161
162trait FloatForDisplay: Copy {
163 fn is_nan(self) -> bool;
164 fn is_infinite(self) -> bool;
165 fn is_sign_negative(self) -> bool;
166 fn write_with(self, buf: &mut zmij::Buffer) -> &str;
167}
168
169impl FloatForDisplay for f32 {
170 fn is_nan(self) -> bool {
171 f32::is_nan(self)
172 }
173 fn is_infinite(self) -> bool {
174 f32::is_infinite(self)
175 }
176 fn is_sign_negative(self) -> bool {
177 f32::is_sign_negative(self)
178 }
179 fn write_with(self, buf: &mut zmij::Buffer) -> &str {
180 buf.format_finite(self)
181 }
182}
183
184impl FloatForDisplay for f64 {
185 fn is_nan(self) -> bool {
186 f64::is_nan(self)
187 }
188 fn is_infinite(self) -> bool {
189 f64::is_infinite(self)
190 }
191 fn is_sign_negative(self) -> bool {
192 f64::is_sign_negative(self)
193 }
194 fn write_with(self, buf: &mut zmij::Buffer) -> &str {
195 buf.format_finite(self)
196 }
197}
198
199fn display_float<T: FloatForDisplay>(num: T, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 if num.is_nan() {
201 write!(f, "NaN")
202 } else if num.is_infinite() {
203 if num.is_sign_negative() {
204 write!(f, "-inf")
205 } else {
206 write!(f, "inf")
207 }
208 } else {
209 let mut buffer = zmij::Buffer::new();
210 write!(f, "{}", num.write_with(&mut buffer))
211 }
212}
213
214pub fn display_decimal_128(num: i128, scale: u8) -> String {
215 let mut buf = String::new();
216 if scale == 0 {
217 write!(buf, "{num}").unwrap();
218 } else {
219 let pow_scale = 10_i128.pow(scale as u32);
220 if num >= 0 {
221 write!(
222 buf,
223 "{}.{:0>width$}",
224 num / pow_scale,
225 (num % pow_scale).abs(),
226 width = scale as usize
227 )
228 .unwrap();
229 } else {
230 write!(
231 buf,
232 "-{}.{:0>width$}",
233 -num / pow_scale,
234 (num % pow_scale).abs(),
235 width = scale as usize
236 )
237 .unwrap();
238 }
239 }
240 buf
241}
242
243pub fn display_decimal_256(num: i256, scale: u8) -> String {
244 let mut buf = String::new();
245 if scale == 0 {
246 write!(buf, "{}", num).unwrap();
247 } else {
248 let pow_scale = i256::from(10).pow(scale as u32);
249 if !num.is_negative() {
251 write!(
252 buf,
253 "{}.{:0>width$}",
254 num / pow_scale,
255 (num % pow_scale).wrapping_abs(),
256 width = scale as usize
257 )
258 } else {
259 write!(
260 buf,
261 "-{}.{:0>width$}",
262 -num / pow_scale,
263 (num % pow_scale).wrapping_abs(),
264 width = scale as usize
265 )
266 }
267 .expect("display_decimal_256 should not fail");
268 }
269 String::from_utf8_lossy(buf.as_bytes()).to_string()
270}