1use std::{collections::HashMap, fmt};
19
20use crate::DataType;
21
22impl fmt::Display for DataType {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 fn format_metadata(metadata: &HashMap<String, String>) -> String {
25 if metadata.is_empty() {
26 String::new()
27 } else {
28 format!(", metadata: {metadata:?}")
29 }
30 }
31
32 match &self {
39 Self::Null => write!(f, "Null"),
40 Self::Boolean => write!(f, "Boolean"),
41 Self::Int8 => write!(f, "Int8"),
42 Self::Int16 => write!(f, "Int16"),
43 Self::Int32 => write!(f, "Int32"),
44 Self::Int64 => write!(f, "Int64"),
45 Self::UInt8 => write!(f, "UInt8"),
46 Self::UInt16 => write!(f, "UInt16"),
47 Self::UInt32 => write!(f, "UInt32"),
48 Self::UInt64 => write!(f, "UInt64"),
49 Self::Float16 => write!(f, "Float16"),
50 Self::Float32 => write!(f, "Float32"),
51 Self::Float64 => write!(f, "Float64"),
52 Self::Timestamp(time_unit, timezone) => {
53 if let Some(timezone) = timezone {
54 write!(f, "Timestamp({time_unit}, {timezone:?})")
55 } else {
56 write!(f, "Timestamp({time_unit})")
57 }
58 }
59 Self::Date32 => write!(f, "Date32"),
60 Self::Date64 => write!(f, "Date64"),
61 Self::Time32(time_unit) => write!(f, "Time32({time_unit})"),
62 Self::Time64(time_unit) => write!(f, "Time64({time_unit})"),
63 Self::Duration(time_unit) => write!(f, "Duration({time_unit})"),
64 Self::Interval(interval_unit) => write!(f, "Interval({interval_unit:?})"),
65 Self::Binary => write!(f, "Binary"),
66 Self::FixedSizeBinary(bytes_per_value) => {
67 write!(f, "FixedSizeBinary({bytes_per_value:?})")
68 }
69 Self::LargeBinary => write!(f, "LargeBinary"),
70 Self::BinaryView => write!(f, "BinaryView"),
71 Self::Utf8 => write!(f, "Utf8"),
72 Self::LargeUtf8 => write!(f, "LargeUtf8"),
73 Self::Utf8View => write!(f, "Utf8View"),
74 Self::ListView(field) => write!(f, "ListView({field})"), Self::LargeListView(field) => write!(f, "LargeListView({field})"), Self::List(field) | Self::LargeList(field) => {
77 let type_name = if matches!(self, Self::List(_)) {
78 "List"
79 } else {
80 "LargeList"
81 };
82
83 let name = field.name();
84 let maybe_nullable = if field.is_nullable() { "nullable " } else { "" };
85 let data_type = field.data_type();
86 let field_name_str = if name == "item" {
87 String::default()
88 } else {
89 format!(", field: '{name}'")
90 };
91 let metadata_str = format_metadata(field.metadata());
92
93 write!(
95 f,
96 "{type_name}({maybe_nullable}{data_type}{field_name_str}{metadata_str})"
97 )
98 }
99 Self::FixedSizeList(field, size) => {
100 let name = field.name();
101 let maybe_nullable = if field.is_nullable() { "nullable " } else { "" };
102 let data_type = field.data_type();
103 let field_name_str = if name == "item" {
104 String::default()
105 } else {
106 format!(", field: '{name}'")
107 };
108 let metadata_str = format_metadata(field.metadata());
109
110 write!(
111 f,
112 "FixedSizeList({size} x {maybe_nullable}{data_type}{field_name_str}{metadata_str})",
113 )
114 }
115 Self::Struct(fields) => {
116 write!(f, "Struct(")?;
117 if !fields.is_empty() {
118 let fields_str = fields
119 .iter()
120 .map(|field| {
121 let name = field.name();
122 let maybe_nullable = if field.is_nullable() { "nullable " } else { "" };
123 let data_type = field.data_type();
124 let metadata_str = format_metadata(field.metadata());
125 format!("{name:?}: {maybe_nullable}{data_type}{metadata_str}")
126 })
127 .collect::<Vec<_>>()
128 .join(", ");
129 write!(f, "{fields_str}")?;
130 }
131 write!(f, ")")?;
132 Ok(())
133 }
134 Self::Union(union_fields, union_mode) => {
135 write!(f, "Union({union_fields:?}, {union_mode:?})")
136 }
137 Self::Dictionary(data_type, data_type1) => {
138 write!(f, "Dictionary({data_type}, {data_type1})")
139 }
140 Self::Decimal32(precision, scale) => write!(f, "Decimal32({precision}, {scale})"),
141 Self::Decimal64(precision, scale) => write!(f, "Decimal64({precision}, {scale})"),
142 Self::Decimal128(precision, scale) => write!(f, "Decimal128({precision}, {scale})"),
143 Self::Decimal256(precision, scale) => write!(f, "Decimal256({precision}, {scale})"),
144 Self::Map(field, keys_are_sorted) => write!(f, "Map({field}, {keys_are_sorted})"),
145 Self::RunEndEncoded(run_ends_field, values_field) => {
146 write!(f, "RunEndEncoded({run_ends_field}, {values_field})")
147 }
148 }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154
155 use std::sync::Arc;
156
157 use crate::Field;
158
159 use super::*;
160
161 #[test]
162 fn test_display_list() {
163 let list_data_type = DataType::List(Arc::new(Field::new_list_field(DataType::Int32, true)));
164 let list_data_type_string = list_data_type.to_string();
165 let expected_string = "List(nullable Int32)";
166 assert_eq!(list_data_type_string, expected_string);
167 }
168
169 #[test]
170 fn test_display_list_with_named_field() {
171 let list_data_type = DataType::List(Arc::new(Field::new("foo", DataType::UInt64, false)));
172 let list_data_type_string = list_data_type.to_string();
173 let expected_string = "List(UInt64, field: 'foo')";
174 assert_eq!(list_data_type_string, expected_string);
175 }
176
177 #[test]
178 fn test_display_nested_list() {
179 let nested_data_type = DataType::List(Arc::new(Field::new_list_field(
180 DataType::List(Arc::new(Field::new_list_field(DataType::UInt64, false))),
181 false,
182 )));
183 let nested_data_type_string = nested_data_type.to_string();
184 let nested_expected_string = "List(List(UInt64))";
185 assert_eq!(nested_data_type_string, nested_expected_string);
186 }
187
188 #[test]
189 fn test_display_list_with_metadata() {
190 let mut field = Field::new_list_field(DataType::Int32, true);
191 let metadata = HashMap::from([("foo1".to_string(), "value1".to_string())]);
192 field.set_metadata(metadata);
193 let list_data_type = DataType::List(Arc::new(field));
194 let list_data_type_string = list_data_type.to_string();
195 let expected_string = "List(nullable Int32, metadata: {\"foo1\": \"value1\"})";
196
197 assert_eq!(list_data_type_string, expected_string);
198 }
199
200 #[test]
201 fn test_display_large_list() {
202 let large_list_data_type =
203 DataType::LargeList(Arc::new(Field::new_list_field(DataType::Int32, true)));
204 let large_list_data_type_string = large_list_data_type.to_string();
205 let expected_string = "LargeList(nullable Int32)";
206 assert_eq!(large_list_data_type_string, expected_string);
207
208 let large_list_named =
210 DataType::LargeList(Arc::new(Field::new("bar", DataType::UInt64, false)));
211 let large_list_named_string = large_list_named.to_string();
212 let expected_named_string = "LargeList(UInt64, field: 'bar')";
213 assert_eq!(large_list_named_string, expected_named_string);
214
215 let mut field = Field::new_list_field(DataType::Int32, true);
217 let metadata = HashMap::from([("key1".to_string(), "value1".to_string())]);
218 field.set_metadata(metadata);
219 let large_list_metadata = DataType::LargeList(Arc::new(field));
220 let large_list_metadata_string = large_list_metadata.to_string();
221 let expected_metadata_string =
222 "LargeList(nullable Int32, metadata: {\"key1\": \"value1\"})";
223 assert_eq!(large_list_metadata_string, expected_metadata_string);
224 }
225
226 #[test]
227 fn test_display_fixed_size_list() {
228 let fixed_size_list =
229 DataType::FixedSizeList(Arc::new(Field::new_list_field(DataType::Int32, true)), 5);
230 let fixed_size_list_string = fixed_size_list.to_string();
231 let expected_string = "FixedSizeList(5 x nullable Int32)";
232 assert_eq!(fixed_size_list_string, expected_string);
233
234 let fixed_size_named =
236 DataType::FixedSizeList(Arc::new(Field::new("baz", DataType::UInt64, false)), 3);
237 let fixed_size_named_string = fixed_size_named.to_string();
238 let expected_named_string = "FixedSizeList(3 x UInt64, field: 'baz')";
239 assert_eq!(fixed_size_named_string, expected_named_string);
240
241 let mut field = Field::new_list_field(DataType::Int32, true);
243 let metadata = HashMap::from([("key2".to_string(), "value2".to_string())]);
244 field.set_metadata(metadata);
245 let fixed_size_metadata = DataType::FixedSizeList(Arc::new(field), 4);
246 let fixed_size_metadata_string = fixed_size_metadata.to_string();
247 let expected_metadata_string =
248 "FixedSizeList(4 x nullable Int32, metadata: {\"key2\": \"value2\"})";
249 assert_eq!(fixed_size_metadata_string, expected_metadata_string);
250 }
251}