1use std::fmt::Display;
7use std::fmt::Formatter;
8
9use crate::dtype::DType;
10use crate::scalar::Scalar;
11
12impl Display for Scalar {
13 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
14 match self.dtype() {
15 DType::Null => write!(f, "null"),
16 DType::Bool(_) => write!(f, "{}", self.as_bool()),
17 DType::Primitive(..) => write!(f, "{}", self.as_primitive()),
18 DType::Decimal(..) => write!(f, "{}", self.as_decimal()),
19 DType::Utf8(_) => write!(f, "{}", self.as_utf8()),
20 DType::Binary(_) => write!(f, "{}", self.as_binary()),
21 DType::List(..) | DType::FixedSizeList(..) => write!(f, "{}", self.as_list()),
22 DType::Map(..) => write!(f, "{}", self.as_map()),
23 DType::Struct(..) => write!(f, "{}", self.as_struct()),
24 DType::Union(..) => write!(f, "{}", self.as_union()),
25 DType::Variant(_) => write!(f, "{}", self.as_variant()),
26 DType::Extension(_) => write!(f, "{}", self.as_extension()),
27 }
28 }
29}
30
31#[cfg(test)]
32mod tests {
33 use vortex_buffer::ByteBuffer;
34 use vortex_error::VortexResult;
35
36 use crate::dtype::DType;
37 use crate::dtype::FieldName;
38 use crate::dtype::Nullability::NonNullable;
39 use crate::dtype::Nullability::Nullable;
40 use crate::dtype::PType;
41 use crate::dtype::StructFields;
42 use crate::dtype::UnionVariants;
43 use crate::extension::datetime::Date;
44 use crate::extension::datetime::Time;
45 use crate::extension::datetime::TimeUnit;
46 use crate::extension::datetime::Timestamp;
47 use crate::scalar::PValue;
48 use crate::scalar::Scalar;
49 use crate::scalar::ScalarValue;
50
51 const MINUTES: i32 = 60;
52 const HOURS: i32 = 60 * MINUTES;
53 const DAYS: i32 = 24 * HOURS;
54
55 #[test]
56 fn display_bool() {
57 assert_eq!(format!("{}", Scalar::from(false)), "false");
58 assert_eq!(format!("{}", Scalar::from(true)), "true");
59 assert_eq!(format!("{}", Scalar::null(DType::Bool(Nullable))), "null");
60 }
61
62 #[test]
63 fn display_primitive() {
64 assert_eq!(format!("{}", Scalar::from(0u8)), "0u8");
65 assert_eq!(format!("{}", Scalar::from(255u8)), "255u8");
66
67 assert_eq!(format!("{}", Scalar::from(0u16)), "0u16");
68 assert_eq!(format!("{}", Scalar::from(!0u16)), "65535u16");
69
70 assert_eq!(format!("{}", Scalar::from(0u32)), "0u32");
71 assert_eq!(format!("{}", Scalar::from(!0u32)), "4294967295u32");
72
73 assert_eq!(format!("{}", Scalar::from(0u64)), "0u64");
74 assert_eq!(
75 format!("{}", Scalar::from(!0u64)),
76 "18446744073709551615u64"
77 );
78
79 assert_eq!(
80 format!("{}", Scalar::null(DType::Primitive(PType::U8, Nullable))),
81 "null"
82 );
83 }
84
85 #[test]
86 fn display_union() -> VortexResult<()> {
87 let variants = UnionVariants::new(
88 ["int", "string"].into(),
89 vec![
90 DType::Primitive(PType::I32, Nullable),
91 DType::Utf8(NonNullable),
92 ],
93 )?;
94
95 let scalar = Scalar::union(
96 variants.clone(),
97 0,
98 Scalar::primitive(42_i32, Nullable),
99 Nullable,
100 )?;
101
102 assert_eq!(format!("{scalar}"), "int(42i32)");
103 let inner_null = Scalar::union(
104 variants.clone(),
105 0,
106 Scalar::null(DType::Primitive(PType::I32, Nullable)),
107 Nullable,
108 )?;
109 assert_eq!(format!("{inner_null}"), "int(null)");
110 assert_eq!(
111 format!("{}", Scalar::null(DType::Union(variants, Nullable))),
112 "null"
113 );
114
115 let struct_dtype = DType::struct_(
116 [("field", DType::Primitive(PType::I32, NonNullable))],
117 NonNullable,
118 );
119 let struct_scalar = Scalar::struct_(
120 struct_dtype.clone(),
121 [Scalar::primitive(42_i32, NonNullable)],
122 );
123 let struct_variants = UnionVariants::new(["record"].into(), vec![struct_dtype])?;
124 let struct_union = Scalar::union(struct_variants, 0, struct_scalar, NonNullable)?;
125 assert_eq!(format!("{struct_union}"), "record({field: 42i32})");
126
127 Ok(())
128 }
129
130 #[test]
131 fn display_utf8() {
132 assert_eq!(
133 format!("{}", Scalar::from("Hello World!")),
134 "\"Hello World!\""
135 );
136 assert_eq!(format!("{}", Scalar::null(DType::Utf8(Nullable))), "null");
137 }
138
139 #[test]
140 fn display_binary() {
141 assert_eq!(
142 format!(
143 "{}",
144 Scalar::binary(
145 ByteBuffer::from("Hello World!".as_bytes().to_vec()),
146 NonNullable
147 )
148 ),
149 "\"48 65 6c 6c 6f 20 57 6f 72 6c 64 21\""
150 );
151 assert_eq!(format!("{}", Scalar::null(DType::Binary(Nullable))), "null");
152 }
153
154 #[test]
155 fn display_empty_struct() {
156 fn dtype() -> DType {
157 DType::Struct(StructFields::new(Default::default(), vec![]), Nullable)
158 }
159
160 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
161
162 assert_eq!(format!("{}", Scalar::struct_(dtype(), vec![])), "{}");
163 }
164
165 #[test]
166 fn display_one_field_struct() {
167 fn dtype() -> DType {
168 DType::Struct(
169 StructFields::new(
170 [FieldName::from("foo")].into(),
171 vec![DType::Primitive(PType::U32, Nullable)],
172 ),
173 Nullable,
174 )
175 }
176
177 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
178
179 assert_eq!(
180 format!(
181 "{}",
182 Scalar::struct_(dtype(), vec![Scalar::null_native::<u32>()])
183 ),
184 "{foo: null}"
185 );
186
187 assert_eq!(
188 format!(
189 "{}",
190 Scalar::struct_(dtype(), vec![Scalar::from(Some(32_u32))])
191 ),
192 "{foo: 32u32}"
193 );
194 }
195
196 #[test]
197 fn display_two_field_struct() {
198 let f1 = DType::Bool(Nullable);
200 let f2 = DType::Primitive(PType::U32, Nullable);
201 let dtype = DType::Struct(
202 StructFields::new(
203 [FieldName::from("foo"), FieldName::from("bar")].into(),
204 vec![f1.clone(), f2.clone()],
205 ),
206 Nullable,
207 );
208 assert_eq!(format!("{}", Scalar::null(dtype.clone())), "null");
211
212 assert_eq!(
213 format!(
214 "{}",
215 Scalar::struct_(
216 dtype.clone(),
217 vec![Scalar::null(f1), Scalar::null(f2.clone())]
218 )
219 ),
220 "{foo: null, bar: null}"
221 );
222
223 assert_eq!(
224 format!(
225 "{}",
226 Scalar::struct_(dtype.clone(), vec![Some(true).into(), Scalar::null(f2)])
227 ),
228 "{foo: true, bar: null}"
229 );
230
231 assert_eq!(
232 format!(
233 "{}",
234 Scalar::struct_(dtype, vec![Some(true).into(), Some(32_u32).into()])
235 ),
236 "{foo: true, bar: 32u32}"
237 );
238 }
239
240 #[test]
241 fn display_time() {
242 fn dtype() -> DType {
243 DType::Extension(Time::new(TimeUnit::Seconds, Nullable).erased())
244 }
245
246 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
247
248 assert_eq!(
249 format!(
250 "{}",
251 Scalar::new(
252 dtype(),
253 Some(ScalarValue::Primitive(PValue::I32(3 * MINUTES + 25)))
254 )
255 ),
256 "00:03:25"
257 );
258 }
259
260 #[test]
261 fn display_date() {
262 fn dtype() -> DType {
263 DType::Extension(Date::new(TimeUnit::Days, Nullable).erased())
264 }
265
266 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
267
268 assert_eq!(
269 format!(
270 "{}",
271 Scalar::new(dtype(), Some(ScalarValue::Primitive(PValue::I32(25))))
272 ),
273 "1970-01-26"
274 );
275
276 assert_eq!(
277 format!(
278 "{}",
279 Scalar::new(dtype(), Some(ScalarValue::Primitive(PValue::I32(365))))
280 ),
281 "1971-01-01"
282 );
283
284 assert_eq!(
285 format!(
286 "{}",
287 Scalar::new(dtype(), Some(ScalarValue::Primitive(PValue::I32(365 * 4))))
288 ),
289 "1973-12-31"
290 );
291 }
292
293 #[test]
294 fn display_variant_values() {
295 assert_eq!(
296 format!("{}", Scalar::null(DType::Variant(Nullable))),
297 "null"
298 );
299 assert_eq!(
300 format!("{}", Scalar::variant(Scalar::null(DType::Null))),
301 "variant(null)"
302 );
303 assert_eq!(
304 format!("{}", Scalar::variant(Scalar::from(42_u32))),
305 "variant(42u32)"
306 );
307 }
308
309 #[test]
310 fn display_local_timestamp() {
311 fn dtype() -> DType {
312 DType::Extension(Timestamp::new(TimeUnit::Seconds, Nullable).erased())
313 }
314
315 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
316
317 assert_eq!(
318 format!(
319 "{}",
320 Scalar::new(
321 dtype(),
322 Some(ScalarValue::Primitive(PValue::I64(
323 (3 * DAYS + 2 * HOURS + 5 * MINUTES + 10) as i64
324 )))
325 )
326 ),
327 "1970-01-04T02:05:10Z"
328 );
329 }
330
331 #[cfg_attr(miri, ignore)]
332 #[test]
333 fn display_zoned_timestamp() {
334 fn dtype() -> DType {
335 DType::Extension(
336 Timestamp::new_with_tz(TimeUnit::Seconds, Some("Pacific/Guam".into()), Nullable)
337 .erased(),
338 )
339 }
340
341 assert_eq!(format!("{}", Scalar::null(dtype())), "null");
342
343 assert_eq!(
344 format!(
345 "{}",
346 Scalar::new(dtype(), Some(ScalarValue::Primitive(PValue::I64(0i64))))
347 ),
348 "1970-01-01T10:00:00+10:00[Pacific/Guam]"
349 );
350
351 assert_eq!(
352 format!(
353 "{}",
354 Scalar::new(
355 dtype(),
356 Some(ScalarValue::Primitive(PValue::I64(
357 (3 * DAYS + 2 * HOURS + 5 * MINUTES + 10) as i64
358 )))
359 )
360 ),
361 "1970-01-04T12:05:10+10:00[Pacific/Guam]"
362 );
363 }
364}