1use std::sync::Arc;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum TimeUnit {
9 Second,
11 Millisecond,
13 Microsecond,
15 #[default]
17 Nanosecond,
18}
19
20impl From<TimeUnit> for arrow_schema::TimeUnit {
21 fn from(value: TimeUnit) -> Self {
22 match value {
23 TimeUnit::Second => arrow_schema::TimeUnit::Second,
24 TimeUnit::Millisecond => arrow_schema::TimeUnit::Millisecond,
25 TimeUnit::Microsecond => arrow_schema::TimeUnit::Microsecond,
26 TimeUnit::Nanosecond => arrow_schema::TimeUnit::Nanosecond,
27 }
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
33pub enum EnumRepr {
34 #[default]
36 Int32,
37 String,
39 Binary,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
45pub enum ConfluentWirePolicy {
46 #[default]
48 Raw,
49 Standard,
52 Protobuf,
55}
56
57#[derive(Debug, Clone)]
62pub struct PtarsConfig {
63 pub timestamp_tz: Option<Arc<str>>,
66
67 pub timestamp_unit: TimeUnit,
69
70 pub time_unit: TimeUnit,
72
73 pub duration_unit: TimeUnit,
75
76 pub list_value_name: Arc<str>,
78
79 pub map_value_name: Arc<str>,
81
82 pub list_nullable: bool,
84
85 pub map_nullable: bool,
87
88 pub list_value_nullable: bool,
90
91 pub map_value_nullable: bool,
93
94 pub use_large_string: bool,
96
97 pub use_large_binary: bool,
99
100 pub use_large_list: bool,
102
103 pub enum_repr: EnumRepr,
107
108 pub confluent_wire_policy: ConfluentWirePolicy,
110}
111
112impl Default for PtarsConfig {
113 fn default() -> Self {
114 Self {
115 timestamp_tz: Some(Arc::from("UTC")),
116 timestamp_unit: TimeUnit::Nanosecond,
117 time_unit: TimeUnit::Nanosecond,
118 duration_unit: TimeUnit::Nanosecond,
119 list_value_name: Arc::from("item"),
120 map_value_name: Arc::from("value"),
121 list_nullable: false,
122 map_nullable: false,
123 list_value_nullable: false,
124 map_value_nullable: false,
125 use_large_string: false,
126 use_large_binary: false,
127 use_large_list: false,
128 enum_repr: EnumRepr::default(),
129 confluent_wire_policy: ConfluentWirePolicy::default(),
130 }
131 }
132}
133
134impl PtarsConfig {
135 pub fn new() -> Self {
137 Self::default()
138 }
139
140 pub fn with_timestamp_tz(mut self, tz: Option<&str>) -> Self {
142 self.timestamp_tz = tz.map(Arc::from);
143 self
144 }
145
146 pub fn with_timestamp_unit(mut self, unit: TimeUnit) -> Self {
148 self.timestamp_unit = unit;
149 self
150 }
151
152 pub fn with_time_unit(mut self, unit: TimeUnit) -> Self {
154 self.time_unit = unit;
155 self
156 }
157
158 pub fn with_duration_unit(mut self, unit: TimeUnit) -> Self {
160 self.duration_unit = unit;
161 self
162 }
163
164 pub fn with_list_value_name(mut self, name: &str) -> Self {
166 self.list_value_name = Arc::from(name);
167 self
168 }
169
170 pub fn with_map_value_name(mut self, name: &str) -> Self {
172 self.map_value_name = Arc::from(name);
173 self
174 }
175
176 pub fn with_list_nullable(mut self, nullable: bool) -> Self {
178 self.list_nullable = nullable;
179 self
180 }
181
182 pub fn with_map_nullable(mut self, nullable: bool) -> Self {
184 self.map_nullable = nullable;
185 self
186 }
187
188 pub fn with_list_value_nullable(mut self, nullable: bool) -> Self {
190 self.list_value_nullable = nullable;
191 self
192 }
193
194 pub fn with_map_value_nullable(mut self, nullable: bool) -> Self {
196 self.map_value_nullable = nullable;
197 self
198 }
199
200 pub fn with_use_large_string(mut self, use_large: bool) -> Self {
202 self.use_large_string = use_large;
203 self
204 }
205
206 pub fn with_use_large_binary(mut self, use_large: bool) -> Self {
208 self.use_large_binary = use_large;
209 self
210 }
211
212 pub fn with_use_large_list(mut self, use_large: bool) -> Self {
214 self.use_large_list = use_large;
215 self
216 }
217
218 pub fn with_enum_repr(mut self, repr: EnumRepr) -> Self {
220 self.enum_repr = repr;
221 self
222 }
223
224 pub fn with_confluent_wire_policy(mut self, policy: ConfluentWirePolicy) -> Self {
226 self.confluent_wire_policy = policy;
227 self
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234
235 #[test]
236 fn test_default_config() {
237 let config = PtarsConfig::default();
238 assert_eq!(config.timestamp_tz, Some(Arc::from("UTC")));
239 assert_eq!(config.timestamp_unit, TimeUnit::Nanosecond);
240 assert_eq!(config.time_unit, TimeUnit::Nanosecond);
241 assert_eq!(config.duration_unit, TimeUnit::Nanosecond);
242 assert_eq!(config.list_value_name.as_ref(), "item");
243 assert_eq!(config.map_value_name.as_ref(), "value");
244 assert!(!config.list_nullable);
245 assert!(!config.map_nullable);
246 assert!(!config.list_value_nullable);
247 assert!(!config.map_value_nullable);
248 assert!(!config.use_large_string);
249 assert!(!config.use_large_binary);
250 assert!(!config.use_large_list);
251 assert_eq!(config.enum_repr, EnumRepr::Int32);
252 assert_eq!(config.confluent_wire_policy, ConfluentWirePolicy::Raw);
253 }
254
255 #[test]
256 fn test_new_config() {
257 let config = PtarsConfig::new();
258 assert_eq!(config.timestamp_tz, Some(Arc::from("UTC")));
259 }
260
261 #[test]
262 fn test_with_timestamp_tz() {
263 let config = PtarsConfig::new().with_timestamp_tz(Some("America/New_York"));
264 assert_eq!(config.timestamp_tz, Some(Arc::from("America/New_York")));
265
266 let config = PtarsConfig::new().with_timestamp_tz(None);
267 assert_eq!(config.timestamp_tz, None);
268 }
269
270 #[test]
271 fn test_with_timestamp_unit() {
272 let config = PtarsConfig::new().with_timestamp_unit(TimeUnit::Microsecond);
273 assert_eq!(config.timestamp_unit, TimeUnit::Microsecond);
274 }
275
276 #[test]
277 fn test_with_time_unit() {
278 let config = PtarsConfig::new().with_time_unit(TimeUnit::Millisecond);
279 assert_eq!(config.time_unit, TimeUnit::Millisecond);
280 }
281
282 #[test]
283 fn test_with_duration_unit() {
284 let config = PtarsConfig::new().with_duration_unit(TimeUnit::Second);
285 assert_eq!(config.duration_unit, TimeUnit::Second);
286 }
287
288 #[test]
289 fn test_with_list_value_name() {
290 let config = PtarsConfig::new().with_list_value_name("element");
291 assert_eq!(config.list_value_name.as_ref(), "element");
292 }
293
294 #[test]
295 fn test_with_map_value_name() {
296 let config = PtarsConfig::new().with_map_value_name("val");
297 assert_eq!(config.map_value_name.as_ref(), "val");
298 }
299
300 #[test]
301 fn test_with_list_nullable() {
302 let config = PtarsConfig::new().with_list_nullable(true);
303 assert!(config.list_nullable);
304 }
305
306 #[test]
307 fn test_with_map_nullable() {
308 let config = PtarsConfig::new().with_map_nullable(true);
309 assert!(config.map_nullable);
310 }
311
312 #[test]
313 fn test_with_list_value_nullable() {
314 let config = PtarsConfig::new().with_list_value_nullable(true);
315 assert!(config.list_value_nullable);
316 }
317
318 #[test]
319 fn test_with_map_value_nullable() {
320 let config = PtarsConfig::new().with_map_value_nullable(true);
321 assert!(config.map_value_nullable);
322 }
323
324 #[test]
325 fn test_with_use_large_string() {
326 let config = PtarsConfig::new().with_use_large_string(true);
327 assert!(config.use_large_string);
328 }
329
330 #[test]
331 fn test_with_use_large_binary() {
332 let config = PtarsConfig::new().with_use_large_binary(true);
333 assert!(config.use_large_binary);
334 }
335
336 #[test]
337 fn test_with_use_large_list() {
338 let config = PtarsConfig::new().with_use_large_list(true);
339 assert!(config.use_large_list);
340 }
341
342 #[test]
343 fn test_builder_chaining() {
344 let config = PtarsConfig::new()
345 .with_timestamp_tz(Some("Europe/London"))
346 .with_timestamp_unit(TimeUnit::Millisecond)
347 .with_time_unit(TimeUnit::Microsecond)
348 .with_duration_unit(TimeUnit::Second)
349 .with_list_value_name("elem")
350 .with_map_value_name("v")
351 .with_list_nullable(true)
352 .with_map_nullable(true)
353 .with_list_value_nullable(true)
354 .with_map_value_nullable(true)
355 .with_use_large_string(true)
356 .with_use_large_binary(true)
357 .with_use_large_list(true)
358 .with_enum_repr(EnumRepr::String)
359 .with_confluent_wire_policy(ConfluentWirePolicy::Protobuf);
360
361 assert_eq!(config.timestamp_tz, Some(Arc::from("Europe/London")));
362 assert_eq!(config.timestamp_unit, TimeUnit::Millisecond);
363 assert_eq!(config.time_unit, TimeUnit::Microsecond);
364 assert_eq!(config.duration_unit, TimeUnit::Second);
365 assert_eq!(config.list_value_name.as_ref(), "elem");
366 assert_eq!(config.map_value_name.as_ref(), "v");
367 assert!(config.list_nullable);
368 assert!(config.map_nullable);
369 assert!(config.list_value_nullable);
370 assert!(config.map_value_nullable);
371 assert!(config.use_large_string);
372 assert!(config.use_large_binary);
373 assert!(config.use_large_list);
374 assert_eq!(config.enum_repr, EnumRepr::String);
375 assert_eq!(config.confluent_wire_policy, ConfluentWirePolicy::Protobuf);
376 }
377}