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