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(_) => {
24 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 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 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}