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