vortex_scalar/
display.rs

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