Skip to main content

vortex_array/scalar/
display.rs

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