1use std::fmt::{Display, Formatter};
2
3use vortex_dtype::DType;
4
5use crate::Scalar;
6
7impl Display for Scalar {
8 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
9 match self.dtype() {
10 DType::Null => write!(f, "null"),
11 DType::Bool(_) => write!(f, "{}", self.as_bool()),
12 DType::Primitive(..) => write!(f, "{}", self.as_primitive()),
13 DType::Utf8(_) => write!(f, "{}", self.as_utf8()),
14 DType::Binary(_) => write!(f, "{}", self.as_binary()),
15 DType::Struct(..) => write!(f, "{}", self.as_struct()),
16 DType::List(..) => write!(f, "{}", self.as_list()),
17 DType::Extension(_) => write!(f, "{}", self.as_extension()),
18 }
19 }
20}
21
22#[cfg(test)]
23mod tests {
24 use std::sync::Arc;
25
26 use vortex_buffer::ByteBuffer;
27 use vortex_dtype::Nullability::{NonNullable, Nullable};
28 use vortex_dtype::datetime::{DATE_ID, TIME_ID, TIMESTAMP_ID, TemporalMetadata, TimeUnit};
29 use vortex_dtype::{DType, ExtDType, ExtMetadata, PType, StructDType};
30
31 use crate::{InnerScalarValue, PValue, Scalar, ScalarValue};
32
33 const MINUTES: i32 = 60;
34 const HOURS: i32 = 60 * MINUTES;
35 const DAYS: i32 = 24 * HOURS;
36
37 #[test]
38 fn display_bool() {
39 assert_eq!(format!("{}", Scalar::from(false)), "false");
40 assert_eq!(format!("{}", Scalar::from(true)), "true");
41 assert_eq!(format!("{}", Scalar::null(DType::Bool(Nullable))), "null");
42 }
43
44 #[test]
45 fn display_primitive() {
46 assert_eq!(format!("{}", Scalar::from(0u8)), "0u8");
47 assert_eq!(format!("{}", Scalar::from(255u8)), "255u8");
48
49 assert_eq!(format!("{}", Scalar::from(0u16)), "0u16");
50 assert_eq!(format!("{}", Scalar::from(!0u16)), "65535u16");
51
52 assert_eq!(format!("{}", Scalar::from(0u32)), "0u32");
53 assert_eq!(format!("{}", Scalar::from(!0u32)), "4294967295u32");
54
55 assert_eq!(format!("{}", Scalar::from(0u64)), "0u64");
56 assert_eq!(
57 format!("{}", Scalar::from(!0u64)),
58 "18446744073709551615u64"
59 );
60
61 assert_eq!(
62 format!("{}", Scalar::null(DType::Primitive(PType::U8, Nullable))),
63 "null"
64 );
65 }
66
67 #[test]
68 fn display_utf8() {
69 assert_eq!(
70 format!("{}", Scalar::from("Hello World!")),
71 "\"Hello World!\""
72 );
73 assert_eq!(format!("{}", Scalar::null(DType::Utf8(Nullable))), "null");
74 }
75
76 #[test]
77 fn display_binary() {
78 assert_eq!(
79 format!(
80 "{}",
81 Scalar::binary(
82 ByteBuffer::from("Hello World!".as_bytes().to_vec()),
83 NonNullable
84 )
85 ),
86 "\"48 65 6c 6c 6f 20 57 6f 72 6c 64 21\""
87 );
88 assert_eq!(format!("{}", Scalar::null(DType::Binary(Nullable))), "null");
89 }
90
91 #[test]
92 fn display_empty_struct() {
93 fn dtype() -> DType {
94 DType::Struct(Arc::new(StructDType::new([].into(), vec![])), Nullable)
95 }
96
97 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
98
99 assert_eq!(format!("{}", Scalar::struct_(dtype(), vec![])), "{}");
100 }
101
102 #[test]
103 fn display_one_field_struct() {
104 fn dtype() -> DType {
105 DType::Struct(
106 Arc::new(StructDType::new(
107 [Arc::from("foo")].into(),
108 vec![DType::Primitive(PType::U32, Nullable)],
109 )),
110 Nullable,
111 )
112 }
113
114 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
115
116 assert_eq!(
117 format!(
118 "{}",
119 Scalar::struct_(dtype(), vec![Scalar::null_typed::<u32>()])
120 ),
121 "{foo: null}"
122 );
123
124 assert_eq!(
125 format!("{}", Scalar::struct_(dtype(), vec![Scalar::from(32_u32)])),
126 "{foo: 32u32}"
127 );
128 }
129
130 #[test]
131 fn display_two_field_struct() {
132 let f1 = DType::Bool(Nullable);
134 let f2 = DType::Primitive(PType::U32, Nullable);
135 let dtype = DType::Struct(
136 Arc::new(StructDType::new(
137 [Arc::from("foo"), Arc::from("bar")].into(),
138 vec![f1.clone(), f2.clone()],
139 )),
140 Nullable,
141 );
142 assert_eq!(format!("{}", Scalar::null(dtype.clone())), "null");
145
146 assert_eq!(
147 format!(
148 "{}",
149 Scalar::struct_(
150 dtype.clone(),
151 vec![Scalar::null(f1), Scalar::null(f2.clone())]
152 )
153 ),
154 "{foo: null, bar: null}"
155 );
156
157 assert_eq!(
158 format!(
159 "{}",
160 Scalar::struct_(dtype.clone(), vec![Scalar::from(true), Scalar::null(f2)])
161 ),
162 "{foo: true, bar: null}"
163 );
164
165 assert_eq!(
166 format!(
167 "{}",
168 Scalar::struct_(dtype, vec![Scalar::from(true), Scalar::from(32_u32)])
169 ),
170 "{foo: true, bar: 32u32}"
171 );
172 }
173
174 #[test]
175 fn display_time() {
176 fn dtype() -> DType {
177 DType::Extension(Arc::new(ExtDType::new(
178 TIME_ID.clone(),
179 Arc::new(DType::Primitive(PType::I32, Nullable)),
180 Some(ExtMetadata::from(TemporalMetadata::Time(TimeUnit::S))),
181 )))
182 }
183
184 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
185
186 assert_eq!(
187 format!(
188 "{}",
189 Scalar::new(
190 dtype(),
191 ScalarValue(InnerScalarValue::Primitive(PValue::I32(3 * MINUTES + 25)))
192 )
193 ),
194 "00:03:25"
195 );
196 }
197
198 #[test]
199 fn display_date() {
200 fn dtype() -> DType {
201 DType::Extension(Arc::new(ExtDType::new(
202 DATE_ID.clone(),
203 Arc::new(DType::Primitive(PType::I32, Nullable)),
204 Some(ExtMetadata::from(TemporalMetadata::Date(TimeUnit::D))),
205 )))
206 }
207
208 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
209
210 assert_eq!(
211 format!(
212 "{}",
213 Scalar::new(
214 dtype(),
215 ScalarValue(InnerScalarValue::Primitive(PValue::I32(25)))
216 )
217 ),
218 "1970-01-26"
219 );
220
221 assert_eq!(
222 format!(
223 "{}",
224 Scalar::new(
225 dtype(),
226 ScalarValue(InnerScalarValue::Primitive(PValue::I32(365)))
227 )
228 ),
229 "1971-01-01"
230 );
231
232 assert_eq!(
233 format!(
234 "{}",
235 Scalar::new(
236 dtype(),
237 ScalarValue(InnerScalarValue::Primitive(PValue::I32(365 * 4)))
238 )
239 ),
240 "1973-12-31"
241 );
242 }
243
244 #[test]
245 fn display_local_timestamp() {
246 fn dtype() -> DType {
247 DType::Extension(Arc::new(ExtDType::new(
248 TIMESTAMP_ID.clone(),
249 Arc::new(DType::Primitive(PType::I32, Nullable)),
250 Some(ExtMetadata::from(TemporalMetadata::Timestamp(
251 TimeUnit::S,
252 None,
253 ))),
254 )))
255 }
256
257 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
258
259 assert_eq!(
260 format!(
261 "{}",
262 Scalar::new(
263 dtype(),
264 ScalarValue(InnerScalarValue::Primitive(PValue::I32(
265 3 * DAYS + 2 * HOURS + 5 * MINUTES + 10
266 )))
267 )
268 ),
269 "1970-01-04T02:05:10Z"
270 );
271 }
272
273 #[cfg_attr(miri, ignore)]
274 #[test]
275 fn display_zoned_timestamp() {
276 fn dtype() -> DType {
277 DType::Extension(Arc::new(ExtDType::new(
278 TIMESTAMP_ID.clone(),
279 Arc::new(DType::Primitive(PType::I64, Nullable)),
280 Some(ExtMetadata::from(TemporalMetadata::Timestamp(
281 TimeUnit::S,
282 Some(String::from("Pacific/Guam")),
283 ))),
284 )))
285 }
286
287 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
288
289 assert_eq!(
290 format!(
291 "{}",
292 Scalar::new(
293 dtype(),
294 ScalarValue(InnerScalarValue::Primitive(PValue::I32(0)))
295 )
296 ),
297 "1970-01-01T10:00:00+10:00[Pacific/Guam]"
298 );
299
300 assert_eq!(
301 format!(
302 "{}",
303 Scalar::new(
304 dtype(),
305 ScalarValue(InnerScalarValue::Primitive(PValue::I32(
306 3 * DAYS + 2 * HOURS + 5 * MINUTES + 10
307 )))
308 )
309 ),
310 "1970-01-04T12:05:10+10:00[Pacific/Guam]"
311 );
312 }
313}