1use 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 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 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 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}