1use std::fmt::{Debug, Formatter, Result, Write};
2
3use crate::array::Array;
4use crate::datatypes::{IntervalUnit, TimeUnit};
5use crate::types::{days_ms, i256, months_days_ns};
6
7use super::PrimitiveArray;
8use crate::array::fmt::write_vec;
9use crate::temporal_conversions;
10use crate::types::NativeType;
11
12macro_rules! dyn_primitive {
13 ($array:expr, $ty:ty, $expr:expr) => {{
14 let array = ($array as &dyn Array)
15 .as_any()
16 .downcast_ref::<PrimitiveArray<$ty>>()
17 .unwrap();
18 Box::new(move |f, index| write!(f, "{}", $expr(array.value(index))))
19 }};
20}
21
22pub fn get_write_value<'a, T: NativeType, F: Write>(
23 array: &'a PrimitiveArray<T>,
24) -> Box<dyn Fn(&mut F, usize) -> Result + 'a> {
25 use crate::datatypes::DataType::*;
26 match array.data_type().to_logical_type() {
27 Int8 => Box::new(|f, index| write!(f, "{}", array.value(index))),
28 Int16 => Box::new(|f, index| write!(f, "{}", array.value(index))),
29 Int32 => Box::new(|f, index| write!(f, "{}", array.value(index))),
30 Int64 => Box::new(|f, index| write!(f, "{}", array.value(index))),
31 UInt8 => Box::new(|f, index| write!(f, "{}", array.value(index))),
32 UInt16 => Box::new(|f, index| write!(f, "{}", array.value(index))),
33 UInt32 => Box::new(|f, index| write!(f, "{}", array.value(index))),
34 UInt64 => Box::new(|f, index| write!(f, "{}", array.value(index))),
35 Float16 => unreachable!(),
36 Float32 => Box::new(|f, index| write!(f, "{}", array.value(index))),
37 Float64 => Box::new(|f, index| write!(f, "{}", array.value(index))),
38 Date32 => {
39 dyn_primitive!(array, i32, temporal_conversions::date32_to_date)
40 }
41 Date64 => {
42 dyn_primitive!(array, i64, temporal_conversions::date64_to_date)
43 }
44 Time32(TimeUnit::Second) => {
45 dyn_primitive!(array, i32, temporal_conversions::time32s_to_time)
46 }
47 Time32(TimeUnit::Millisecond) => {
48 dyn_primitive!(array, i32, temporal_conversions::time32ms_to_time)
49 }
50 Time32(_) => unreachable!(), Time64(TimeUnit::Microsecond) => {
52 dyn_primitive!(array, i64, temporal_conversions::time64us_to_time)
53 }
54 Time64(TimeUnit::Nanosecond) => {
55 dyn_primitive!(array, i64, temporal_conversions::time64ns_to_time)
56 }
57 Time64(_) => unreachable!(), Timestamp(time_unit, tz) => {
59 if let Some(tz) = tz {
60 let timezone = temporal_conversions::parse_offset(tz);
61 match timezone {
62 Ok(timezone) => {
63 dyn_primitive!(array, i64, |time| {
64 temporal_conversions::timestamp_to_datetime(time, *time_unit, &timezone)
65 })
66 }
67 #[cfg(feature = "chrono-tz")]
68 Err(_) => {
69 let timezone = temporal_conversions::parse_offset_tz(tz);
70 match timezone {
71 Ok(timezone) => dyn_primitive!(array, i64, |time| {
72 temporal_conversions::timestamp_to_datetime(
73 time, *time_unit, &timezone,
74 )
75 }),
76 Err(_) => {
77 let tz = tz.clone();
78 Box::new(move |f, index| {
79 write!(f, "{} ({})", array.value(index), tz)
80 })
81 }
82 }
83 }
84 #[cfg(not(feature = "chrono-tz"))]
85 _ => {
86 let tz = tz.clone();
87 Box::new(move |f, index| write!(f, "{} ({})", array.value(index), tz))
88 }
89 }
90 } else {
91 dyn_primitive!(array, i64, |time| {
92 temporal_conversions::timestamp_to_naive_datetime(time, *time_unit)
93 })
94 }
95 }
96 Interval(IntervalUnit::YearMonth) => {
97 dyn_primitive!(array, i32, |x| format!("{x}m"))
98 }
99 Interval(IntervalUnit::DayTime) => {
100 dyn_primitive!(array, days_ms, |x: days_ms| format!(
101 "{}d{}ms",
102 x.days(),
103 x.milliseconds()
104 ))
105 }
106 Interval(IntervalUnit::MonthDayNano) => {
107 dyn_primitive!(array, months_days_ns, |x: months_days_ns| format!(
108 "{}m{}d{}ns",
109 x.months(),
110 x.days(),
111 x.ns()
112 ))
113 }
114 Duration(TimeUnit::Second) => dyn_primitive!(array, i64, |x| format!("{x}s")),
115 Duration(TimeUnit::Millisecond) => dyn_primitive!(array, i64, |x| format!("{x}ms")),
116 Duration(TimeUnit::Microsecond) => dyn_primitive!(array, i64, |x| format!("{x}us")),
117 Duration(TimeUnit::Nanosecond) => dyn_primitive!(array, i64, |x| format!("{x}ns")),
118 Decimal(_, scale) => {
119 let scale = *scale as u32;
121 let factor = 10i128.pow(scale);
122 let display = move |x: i128| {
123 let base = x / factor;
124 let decimals = (x - base * factor).abs();
125 format!("{base}.{decimals}")
126 };
127 dyn_primitive!(array, i128, display)
128 }
129 Decimal256(_, scale) => {
130 let scale = *scale as u32;
131 let factor = (ethnum::I256::ONE * 10).pow(scale);
132 let display = move |x: i256| {
133 let base = x.0 / factor;
134 let decimals = (x.0 - base * factor).abs();
135 format!("{base}.{decimals}")
136 };
137 dyn_primitive!(array, i256, display)
138 }
139 _ => unreachable!(),
140 }
141}
142
143impl<T: NativeType> Debug for PrimitiveArray<T> {
144 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
145 let writer = get_write_value(self);
146
147 write!(f, "{:?}", self.data_type())?;
148 write_vec(f, &*writer, self.validity(), self.len(), "None", false)
149 }
150}