Skip to main content

parquet/record/
api.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5//! Contains Row enum that is used to represent record in Rust.
6
7use std::fmt;
8
9use chrono::{TimeZone, Utc};
10use half::f16;
11use num_bigint::{BigInt, Sign};
12use num_traits::Float;
13
14use crate::basic::{ConvertedType, LogicalType, Type as PhysicalType};
15use crate::data_type::{ByteArray, Decimal, Int96};
16use crate::errors::{ParquetError, Result};
17use crate::schema::types::ColumnDescPtr;
18
19#[cfg(any(feature = "json", test))]
20use serde_json::Value;
21
22/// Macro as a shortcut to generate 'not yet implemented' panic error.
23macro_rules! nyi {
24    ($column_descr:ident, $value:ident) => {{
25        unimplemented!(
26            "Conversion for physical type {}, converted type {}, value {:?}",
27            $column_descr.physical_type(),
28            $column_descr.converted_type(),
29            $value
30        );
31    }};
32}
33
34/// `Row` represents a nested Parquet record.
35#[derive(Clone, Debug, PartialEq)]
36pub struct Row {
37    fields: Vec<(String, Field)>,
38}
39
40#[expect(clippy::len_without_is_empty)]
41impl Row {
42    /// Constructs a `Row` from the list of `fields` and returns it.
43    pub fn new(fields: Vec<(String, Field)>) -> Row {
44        Row { fields }
45    }
46
47    /// Get the number of fields in this row.
48    pub fn len(&self) -> usize {
49        self.fields.len()
50    }
51
52    /// Move columns data out of the row. Useful to avoid internal data cloning.
53    ///
54    /// # Example
55    ///
56    /// ```no_run
57    /// use std::fs::File;
58    /// use parquet::record::Row;
59    /// use parquet::file::reader::{FileReader, SerializedFileReader};
60    ///
61    /// let file = File::open("/path/to/file").unwrap();
62    /// let reader = SerializedFileReader::new(file).unwrap();
63    /// let row: Row = reader.get_row_iter(None).unwrap().next().unwrap().unwrap();
64    /// let columns = row.into_columns();
65    /// println!("row columns: {:?}", columns);
66    ///
67    /// ```
68    pub fn into_columns(self) -> Vec<(String, Field)> {
69        self.fields
70    }
71
72    /// Get an iterator to go through all columns in the row.
73    ///
74    /// # Example
75    ///
76    /// ```no_run
77    /// use std::fs::File;
78    /// use parquet::record::Row;
79    /// use parquet::file::reader::{FileReader, SerializedFileReader};
80    ///
81    /// let file = File::open("/path/to/file").unwrap();
82    /// let reader = SerializedFileReader::new(file).unwrap();
83    /// let row: Row = reader.get_row_iter(None).unwrap().next().unwrap().unwrap();
84    /// for (idx, (name, field)) in row.get_column_iter().enumerate() {
85    ///     println!("column index: {}, column name: {}, column value: {}", idx, name, field);
86    /// }
87    /// ```
88    pub fn get_column_iter(&self) -> RowColumnIter<'_> {
89        RowColumnIter {
90            fields: &self.fields,
91            curr: 0,
92            count: self.fields.len(),
93        }
94    }
95
96    /// Converts the row into a JSON object.
97    #[cfg(any(feature = "json", test))]
98    pub fn to_json_value(&self) -> Value {
99        Value::Object(
100            self.fields
101                .iter()
102                .map(|(key, field)| (key.to_owned(), field.to_json_value()))
103                .collect(),
104        )
105    }
106}
107
108/// `RowColumnIter` represents an iterator over column names and values in a Row.
109pub struct RowColumnIter<'a> {
110    fields: &'a Vec<(String, Field)>,
111    curr: usize,
112    count: usize,
113}
114
115impl<'a> Iterator for RowColumnIter<'a> {
116    type Item = (&'a String, &'a Field);
117
118    fn next(&mut self) -> Option<Self::Item> {
119        let idx = self.curr;
120        if idx >= self.count {
121            return None;
122        }
123        self.curr += 1;
124        Some((&self.fields[idx].0, &self.fields[idx].1))
125    }
126}
127
128/// Trait for type-safe convenient access to fields within a Row.
129pub trait RowAccessor {
130    /// Check if the field at the index is null.
131    fn is_null(&self, i: usize) -> Result<bool>;
132    /// Try to get a boolean value at the given index.
133    fn get_bool(&self, i: usize) -> Result<bool>;
134    /// Try to get a byte value at the given index.
135    fn get_byte(&self, i: usize) -> Result<i8>;
136    /// Try to get a short value at the given index.
137    fn get_short(&self, i: usize) -> Result<i16>;
138    /// Try to get a int value at the given index.
139    fn get_int(&self, i: usize) -> Result<i32>;
140    /// Try to get a long value at the given index.
141    fn get_long(&self, i: usize) -> Result<i64>;
142    /// Try to get a ubyte value at the given index.
143    fn get_ubyte(&self, i: usize) -> Result<u8>;
144    /// Try to get a ushort value at the given index.
145    fn get_ushort(&self, i: usize) -> Result<u16>;
146    /// Try to get a uint value at the given index.
147    fn get_uint(&self, i: usize) -> Result<u32>;
148    /// Try to get a ulong value at the given index.
149    fn get_ulong(&self, i: usize) -> Result<u64>;
150    /// Try to get a float16 value at the given index.
151    fn get_float16(&self, i: usize) -> Result<f16>;
152    /// Try to get a float value at the given index.
153    fn get_float(&self, i: usize) -> Result<f32>;
154    /// Try to get a double value at the given index.
155    fn get_double(&self, i: usize) -> Result<f64>;
156    /// Try to get a date value at the given index.
157    fn get_timestamp_millis(&self, i: usize) -> Result<i64>;
158    /// Try to get a date value at the given index.
159    fn get_timestamp_micros(&self, i: usize) -> Result<i64>;
160    /// Try to get a decimal value at the given index.
161    fn get_decimal(&self, i: usize) -> Result<&Decimal>;
162    /// Try to get a string value at the given index.
163    fn get_string(&self, i: usize) -> Result<&String>;
164    /// Try to get a bytes value at the given index.
165    fn get_bytes(&self, i: usize) -> Result<&ByteArray>;
166    /// Try to get a group value at the given index.
167    fn get_group(&self, i: usize) -> Result<&Row>;
168    /// Try to get a list value at the given index.
169    fn get_list(&self, i: usize) -> Result<&List>;
170    /// Try to get a map value at the given index.
171    fn get_map(&self, i: usize) -> Result<&Map>;
172}
173
174/// Trait for formatting fields within a Row.
175///
176/// # Examples
177///
178/// ```
179/// use std::fs::File;
180/// use std::path::Path;
181/// use parquet::record::Row;
182/// use parquet::record::RowFormatter;
183/// use parquet::file::reader::{FileReader, SerializedFileReader};
184///
185/// if let Ok(file) = File::open(&Path::new("test.parquet")) {
186///     let reader = SerializedFileReader::new(file).unwrap();
187///     let row = reader.get_row_iter(None).unwrap().next().unwrap().unwrap();
188///     println!("column 0: {}, column 1: {}", row.fmt(0), row.fmt(1));
189/// }
190/// ```
191///
192pub trait RowFormatter {
193    /// The method to format a field at the given index.
194    fn fmt(&self, i: usize) -> &dyn fmt::Display;
195}
196
197/// Macro to generate type-safe get_xxx methods for primitive types,
198/// e.g. `get_bool`, `get_short`.
199macro_rules! row_primitive_accessor {
200    ($METHOD:ident, $VARIANT:ident, $TY:ty) => {
201        fn $METHOD(&self, i: usize) -> Result<$TY> {
202            match self.fields.get(i) {
203                Some((_, Field::$VARIANT(v))) => Ok(*v),
204                None => Err(ParquetError::IndexOutOfBound(i, self.fields.len())),
205                _ => Err(general_err!(
206                    "Cannot access {} as {}",
207                    self.fields[i].1.get_type_name(), // Safe access as None is
208                    stringify!($VARIANT)
209                )),
210            }
211        }
212    };
213}
214
215/// Macro to generate type-safe get_xxx methods for reference types,
216/// e.g. `get_list`, `get_map`.
217macro_rules! row_complex_accessor {
218    ($METHOD:ident, $VARIANT:ident, $TY:ty) => {
219        fn $METHOD(&self, i: usize) -> Result<&$TY> {
220            match self.fields.get(i) {
221                Some((_, Field::$VARIANT(v))) => Ok(v),
222                None => Err(ParquetError::IndexOutOfBound(i, self.fields.len())),
223                _ => Err(general_err!(
224                    "Cannot access {} as {}",
225                    self.fields[i].1.get_type_name(), // Safe access as None is
226                    // just checked.
227                    stringify!($VARIANT)
228                )),
229            }
230        }
231    };
232}
233
234impl RowFormatter for Row {
235    /// Get Display reference for a given field.
236    fn fmt(&self, i: usize) -> &dyn fmt::Display {
237        if let Some((_, v)) = self.fields.get(i) {
238            v
239        } else {
240            &"<IndexOutOfBound>"
241        }
242    }
243}
244
245impl RowAccessor for Row {
246    fn is_null(&self, i: usize) -> Result<bool> {
247        match self.fields.get(i) {
248            Some((_, Field::Null)) => Ok(true),
249            None => Err(ParquetError::IndexOutOfBound(i, self.len())),
250            _ => Ok(false),
251        }
252    }
253
254    row_primitive_accessor!(get_bool, Bool, bool);
255
256    row_primitive_accessor!(get_byte, Byte, i8);
257
258    row_primitive_accessor!(get_short, Short, i16);
259
260    row_primitive_accessor!(get_int, Int, i32);
261
262    row_primitive_accessor!(get_long, Long, i64);
263
264    row_primitive_accessor!(get_ubyte, UByte, u8);
265
266    row_primitive_accessor!(get_ushort, UShort, u16);
267
268    row_primitive_accessor!(get_uint, UInt, u32);
269
270    row_primitive_accessor!(get_ulong, ULong, u64);
271
272    row_primitive_accessor!(get_float16, Float16, f16);
273
274    row_primitive_accessor!(get_float, Float, f32);
275
276    row_primitive_accessor!(get_double, Double, f64);
277
278    row_primitive_accessor!(get_timestamp_millis, TimestampMillis, i64);
279
280    row_primitive_accessor!(get_timestamp_micros, TimestampMicros, i64);
281
282    row_complex_accessor!(get_decimal, Decimal, Decimal);
283
284    row_complex_accessor!(get_string, Str, String);
285
286    row_complex_accessor!(get_bytes, Bytes, ByteArray);
287
288    row_complex_accessor!(get_group, Group, Row);
289
290    row_complex_accessor!(get_list, ListInternal, List);
291
292    row_complex_accessor!(get_map, MapInternal, Map);
293}
294
295impl fmt::Display for Row {
296    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297        write!(f, "{{")?;
298        for (i, (key, value)) in self.fields.iter().enumerate() {
299            key.fmt(f)?;
300            write!(f, ": ")?;
301            value.fmt(f)?;
302            if i < self.fields.len() - 1 {
303                write!(f, ", ")?;
304            }
305        }
306        write!(f, "}}")
307    }
308}
309
310/// `List` represents a list which contains an array of elements.
311#[derive(Clone, Debug, PartialEq)]
312pub struct List {
313    elements: Vec<Field>,
314}
315
316#[expect(clippy::len_without_is_empty)]
317impl List {
318    /// Get the number of fields in this row
319    pub fn len(&self) -> usize {
320        self.elements.len()
321    }
322
323    /// Get the reference to the elements in this list
324    pub fn elements(&self) -> &[Field] {
325        self.elements.as_slice()
326    }
327}
328
329/// Constructs a `List` from the list of `fields` and returns it.
330#[inline]
331pub fn make_list(elements: Vec<Field>) -> List {
332    List { elements }
333}
334
335/// Trait for type-safe access of an index for a `List`.
336/// Note that the get_XXX methods do not do bound checking.
337pub trait ListAccessor {
338    /// Try getting a `boolean` value at the given index.
339    fn get_bool(&self, i: usize) -> Result<bool>;
340    /// Try getting a `byte` value at the given index.
341    fn get_byte(&self, i: usize) -> Result<i8>;
342    /// Try getting an `i16` value at the given index.
343    fn get_short(&self, i: usize) -> Result<i16>;
344    /// Try getting an `i32` value at the given index.
345    fn get_int(&self, i: usize) -> Result<i32>;
346    /// Try getting an `i64` value at the given index.
347    fn get_long(&self, i: usize) -> Result<i64>;
348    /// Try getting a `u8` value at the given index.
349    fn get_ubyte(&self, i: usize) -> Result<u8>;
350    /// Try getting a `u16` value at the given index.
351    fn get_ushort(&self, i: usize) -> Result<u16>;
352    /// Try getting a `u32` value at the given index.
353    fn get_uint(&self, i: usize) -> Result<u32>;
354    /// Try getting a `u64` value at the given index.
355    fn get_ulong(&self, i: usize) -> Result<u64>;
356    /// Try getting a `f16` value at the given index.
357    fn get_float16(&self, i: usize) -> Result<f16>;
358    /// Try getting a `f32` value at the given index.
359    fn get_float(&self, i: usize) -> Result<f32>;
360    /// Try getting a `f64` value at the given index.
361    fn get_double(&self, i: usize) -> Result<f64>;
362    /// Try getting a `timestamp` as milliseconds value
363    /// encoded as `i64` at the given index.
364    fn get_timestamp_millis(&self, i: usize) -> Result<i64>;
365    /// Try getting a `timestamp` as microseconds value
366    /// encoded as `i64` at the given index.
367    fn get_timestamp_micros(&self, i: usize) -> Result<i64>;
368    /// Try getting a `decimal` value at the given index.
369    fn get_decimal(&self, i: usize) -> Result<&Decimal>;
370    /// Try getting a `string` value at the given index.
371    fn get_string(&self, i: usize) -> Result<&String>;
372    /// Try getting a `bytes` value at the given index.
373    fn get_bytes(&self, i: usize) -> Result<&ByteArray>;
374    /// Try getting a `group` value at the given index.
375    fn get_group(&self, i: usize) -> Result<&Row>;
376    /// Try getting a `list` value at the given index.
377    fn get_list(&self, i: usize) -> Result<&List>;
378    /// Try getting a `map` value at the given index.
379    fn get_map(&self, i: usize) -> Result<&Map>;
380}
381
382/// Macro to generate type-safe get_xxx methods for primitive types,
383/// e.g. get_bool, get_short
384macro_rules! list_primitive_accessor {
385    ($METHOD:ident, $VARIANT:ident, $TY:ty) => {
386        fn $METHOD(&self, i: usize) -> Result<$TY> {
387            match self.elements[i] {
388                Field::$VARIANT(v) => Ok(v),
389                _ => Err(general_err!(
390                    "Cannot access {} as {}",
391                    self.elements[i].get_type_name(),
392                    stringify!($VARIANT)
393                )),
394            }
395        }
396    };
397}
398
399/// Macro to generate type-safe get_xxx methods for reference types
400/// e.g. get_list, get_map
401macro_rules! list_complex_accessor {
402    ($METHOD:ident, $VARIANT:ident, $TY:ty) => {
403        fn $METHOD(&self, i: usize) -> Result<&$TY> {
404            match &self.elements[i] {
405                Field::$VARIANT(v) => Ok(&v),
406                _ => Err(general_err!(
407                    "Cannot access {} as {}",
408                    self.elements[i].get_type_name(),
409                    stringify!($VARIANT)
410                )),
411            }
412        }
413    };
414}
415
416impl ListAccessor for List {
417    list_primitive_accessor!(get_bool, Bool, bool);
418
419    list_primitive_accessor!(get_byte, Byte, i8);
420
421    list_primitive_accessor!(get_short, Short, i16);
422
423    list_primitive_accessor!(get_int, Int, i32);
424
425    list_primitive_accessor!(get_long, Long, i64);
426
427    list_primitive_accessor!(get_ubyte, UByte, u8);
428
429    list_primitive_accessor!(get_ushort, UShort, u16);
430
431    list_primitive_accessor!(get_uint, UInt, u32);
432
433    list_primitive_accessor!(get_ulong, ULong, u64);
434
435    list_primitive_accessor!(get_float16, Float16, f16);
436
437    list_primitive_accessor!(get_float, Float, f32);
438
439    list_primitive_accessor!(get_double, Double, f64);
440
441    list_primitive_accessor!(get_timestamp_millis, TimestampMillis, i64);
442
443    list_primitive_accessor!(get_timestamp_micros, TimestampMicros, i64);
444
445    list_complex_accessor!(get_decimal, Decimal, Decimal);
446
447    list_complex_accessor!(get_string, Str, String);
448
449    list_complex_accessor!(get_bytes, Bytes, ByteArray);
450
451    list_complex_accessor!(get_group, Group, Row);
452
453    list_complex_accessor!(get_list, ListInternal, List);
454
455    list_complex_accessor!(get_map, MapInternal, Map);
456}
457
458/// `Map` represents a map which contains a list of key->value pairs.
459#[derive(Clone, Debug, PartialEq)]
460pub struct Map {
461    entries: Vec<(Field, Field)>,
462}
463
464#[expect(clippy::len_without_is_empty)]
465impl Map {
466    /// Get the number of fields in this row
467    pub fn len(&self) -> usize {
468        self.entries.len()
469    }
470
471    /// Get the reference to the key-value pairs in this map
472    pub fn entries(&self) -> &[(Field, Field)] {
473        self.entries.as_slice()
474    }
475}
476
477/// Constructs a `Map` from the list of `entries` and returns it.
478#[inline]
479pub fn make_map(entries: Vec<(Field, Field)>) -> Map {
480    Map { entries }
481}
482
483/// Trait for type-safe access of an index for a `Map`
484pub trait MapAccessor {
485    /// Get the keys of the map.
486    fn get_keys<'a>(&'a self) -> Box<dyn ListAccessor + 'a>;
487    /// Get the values of the map.
488    fn get_values<'a>(&'a self) -> Box<dyn ListAccessor + 'a>;
489}
490
491struct MapList<'a> {
492    elements: Vec<&'a Field>,
493}
494
495/// Macro to generate type-safe get_xxx methods for primitive types,
496/// e.g. get_bool, get_short
497macro_rules! map_list_primitive_accessor {
498    ($METHOD:ident, $VARIANT:ident, $TY:ty) => {
499        fn $METHOD(&self, i: usize) -> Result<$TY> {
500            match self.elements[i] {
501                Field::$VARIANT(v) => Ok(*v),
502                _ => Err(general_err!(
503                    "Cannot access {} as {}",
504                    self.elements[i].get_type_name(),
505                    stringify!($VARIANT)
506                )),
507            }
508        }
509    };
510}
511
512impl ListAccessor for MapList<'_> {
513    map_list_primitive_accessor!(get_bool, Bool, bool);
514
515    map_list_primitive_accessor!(get_byte, Byte, i8);
516
517    map_list_primitive_accessor!(get_short, Short, i16);
518
519    map_list_primitive_accessor!(get_int, Int, i32);
520
521    map_list_primitive_accessor!(get_long, Long, i64);
522
523    map_list_primitive_accessor!(get_ubyte, UByte, u8);
524
525    map_list_primitive_accessor!(get_ushort, UShort, u16);
526
527    map_list_primitive_accessor!(get_uint, UInt, u32);
528
529    map_list_primitive_accessor!(get_ulong, ULong, u64);
530
531    map_list_primitive_accessor!(get_float16, Float16, f16);
532
533    map_list_primitive_accessor!(get_float, Float, f32);
534
535    map_list_primitive_accessor!(get_double, Double, f64);
536
537    map_list_primitive_accessor!(get_timestamp_millis, TimestampMillis, i64);
538
539    map_list_primitive_accessor!(get_timestamp_micros, TimestampMicros, i64);
540
541    list_complex_accessor!(get_decimal, Decimal, Decimal);
542
543    list_complex_accessor!(get_string, Str, String);
544
545    list_complex_accessor!(get_bytes, Bytes, ByteArray);
546
547    list_complex_accessor!(get_group, Group, Row);
548
549    list_complex_accessor!(get_list, ListInternal, List);
550
551    list_complex_accessor!(get_map, MapInternal, Map);
552}
553
554impl MapAccessor for Map {
555    fn get_keys<'a>(&'a self) -> Box<dyn ListAccessor + 'a> {
556        let map_list = MapList {
557            elements: self.entries.iter().map(|v| &v.0).collect(),
558        };
559        Box::new(map_list)
560    }
561
562    fn get_values<'a>(&'a self) -> Box<dyn ListAccessor + 'a> {
563        let map_list = MapList {
564            elements: self.entries.iter().map(|v| &v.1).collect(),
565        };
566        Box::new(map_list)
567    }
568}
569
570/// API to represent a single field in a `Row`.
571#[derive(Clone, Debug, PartialEq)]
572pub enum Field {
573    // Primitive types
574    /// Null value.
575    Null,
576    /// Boolean value (`true`, `false`).
577    Bool(bool),
578    /// Signed integer INT_8.
579    Byte(i8),
580    /// Signed integer INT_16.
581    Short(i16),
582    /// Signed integer INT_32.
583    Int(i32),
584    /// Signed integer INT_64.
585    Long(i64),
586    /// Unsigned integer UINT_8.
587    UByte(u8),
588    /// Unsigned integer UINT_16.
589    UShort(u16),
590    /// Unsigned integer UINT_32.
591    UInt(u32),
592    /// Unsigned integer UINT_64.
593    ULong(u64),
594    /// IEEE 16-bit floating point value.
595    Float16(f16),
596    /// IEEE 32-bit floating point value.
597    Float(f32),
598    /// IEEE 64-bit floating point value.
599    Double(f64),
600    /// Decimal value.
601    Decimal(Decimal),
602    /// UTF-8 encoded character string.
603    Str(String),
604    /// General binary value.
605    Bytes(ByteArray),
606    /// Date without a time of day, stores the number of days from the
607    /// Unix epoch, 1 January 1970.
608    Date(i32),
609
610    /// The total number of milliseconds since midnight.
611    TimeMillis(i32),
612    /// The total number of microseconds since midnight.
613    TimeMicros(i64),
614
615    /// Milliseconds from the Unix epoch, 1 January 1970.
616    TimestampMillis(i64),
617    /// Microseconds from the Unix epoch, 1 January 1970.
618    TimestampMicros(i64),
619
620    // ----------------------------------------------------------------------
621    // Complex types
622    /// Struct, child elements are tuples of field-value pairs.
623    Group(Row),
624    /// List of elements.
625    ListInternal(List),
626    /// List of key-value pairs.
627    MapInternal(Map),
628}
629
630impl Field {
631    /// Get the type name.
632    fn get_type_name(&self) -> &'static str {
633        match *self {
634            Field::Null => "Null",
635            Field::Bool(_) => "Bool",
636            Field::Byte(_) => "Byte",
637            Field::Short(_) => "Short",
638            Field::Int(_) => "Int",
639            Field::Long(_) => "Long",
640            Field::UByte(_) => "UByte",
641            Field::UShort(_) => "UShort",
642            Field::UInt(_) => "UInt",
643            Field::ULong(_) => "ULong",
644            Field::Float16(_) => "Float16",
645            Field::Float(_) => "Float",
646            Field::Double(_) => "Double",
647            Field::Decimal(_) => "Decimal",
648            Field::Date(_) => "Date",
649            Field::Str(_) => "Str",
650            Field::Bytes(_) => "Bytes",
651            Field::TimeMillis(_) => "TimeMillis",
652            Field::TimeMicros(_) => "TimeMicros",
653            Field::TimestampMillis(_) => "TimestampMillis",
654            Field::TimestampMicros(_) => "TimestampMicros",
655            Field::Group(_) => "Group",
656            Field::ListInternal(_) => "ListInternal",
657            Field::MapInternal(_) => "MapInternal",
658        }
659    }
660
661    /// Determines if this Row represents a primitive value.
662    pub fn is_primitive(&self) -> bool {
663        !matches!(
664            *self,
665            Field::Group(_) | Field::ListInternal(_) | Field::MapInternal(_)
666        )
667    }
668
669    /// Converts Parquet BOOLEAN type with logical type into `bool` value.
670    #[inline]
671    pub fn convert_bool(_descr: &ColumnDescPtr, value: bool) -> Self {
672        Field::Bool(value)
673    }
674
675    /// Converts Parquet INT32 type with converted type into `i32` value.
676    #[inline]
677    pub fn convert_int32(descr: &ColumnDescPtr, value: i32) -> Self {
678        match descr.converted_type() {
679            ConvertedType::INT_8 => Field::Byte(value as i8),
680            ConvertedType::INT_16 => Field::Short(value as i16),
681            ConvertedType::INT_32 | ConvertedType::NONE => Field::Int(value),
682            ConvertedType::UINT_8 => Field::UByte(value as u8),
683            ConvertedType::UINT_16 => Field::UShort(value as u16),
684            ConvertedType::UINT_32 => Field::UInt(value as u32),
685            ConvertedType::DATE => Field::Date(value),
686            ConvertedType::TIME_MILLIS => Field::TimeMillis(value),
687            ConvertedType::DECIMAL => Field::Decimal(Decimal::from_i32(
688                value,
689                descr.type_precision(),
690                descr.type_scale(),
691            )),
692            _ => nyi!(descr, value),
693        }
694    }
695
696    /// Converts Parquet INT64 type with converted type into `i64` value.
697    #[inline]
698    pub fn convert_int64(descr: &ColumnDescPtr, value: i64) -> Self {
699        match descr.converted_type() {
700            ConvertedType::INT_64 | ConvertedType::NONE => Field::Long(value),
701            ConvertedType::UINT_64 => Field::ULong(value as u64),
702            ConvertedType::TIME_MICROS => Field::TimeMicros(value),
703            ConvertedType::TIMESTAMP_MILLIS => Field::TimestampMillis(value),
704            ConvertedType::TIMESTAMP_MICROS => Field::TimestampMicros(value),
705            ConvertedType::DECIMAL => Field::Decimal(Decimal::from_i64(
706                value,
707                descr.type_precision(),
708                descr.type_scale(),
709            )),
710            _ => nyi!(descr, value),
711        }
712    }
713
714    /// Converts Parquet INT96 (nanosecond timestamps) type and logical type into
715    /// `Timestamp` value.
716    #[inline]
717    pub fn convert_int96(_descr: &ColumnDescPtr, value: Int96) -> Self {
718        Field::TimestampMillis(value.to_millis())
719    }
720
721    /// Converts Parquet FLOAT type with logical type into `f32` value.
722    #[inline]
723    pub fn convert_float(_descr: &ColumnDescPtr, value: f32) -> Self {
724        Field::Float(value)
725    }
726
727    /// Converts Parquet DOUBLE type with converted type into `f64` value.
728    #[inline]
729    pub fn convert_double(_descr: &ColumnDescPtr, value: f64) -> Self {
730        Field::Double(value)
731    }
732
733    /// Converts Parquet BYTE_ARRAY type with converted type into a UTF8
734    /// string, decimal, float16, or an array of bytes.
735    #[inline]
736    pub fn convert_byte_array(descr: &ColumnDescPtr, value: ByteArray) -> Result<Self> {
737        let field = match descr.physical_type() {
738            PhysicalType::BYTE_ARRAY => match descr.converted_type() {
739                ConvertedType::UTF8 | ConvertedType::ENUM | ConvertedType::JSON => {
740                    let value = String::from_utf8(value.data().to_vec()).map_err(|e| {
741                        general_err!(
742                            "Error reading BYTE_ARRAY as String. Bytes: {:?} Error: {:?}",
743                            value.data(),
744                            e
745                        )
746                    })?;
747                    Field::Str(value)
748                }
749                ConvertedType::BSON | ConvertedType::NONE => Field::Bytes(value),
750                ConvertedType::DECIMAL => Field::Decimal(Decimal::from_bytes(
751                    value,
752                    descr.type_precision(),
753                    descr.type_scale(),
754                )),
755                _ => nyi!(descr, value),
756            },
757            PhysicalType::FIXED_LEN_BYTE_ARRAY => match descr.converted_type() {
758                ConvertedType::DECIMAL => Field::Decimal(Decimal::from_bytes(
759                    value,
760                    descr.type_precision(),
761                    descr.type_scale(),
762                )),
763                ConvertedType::NONE if descr.logical_type_ref() == Some(&LogicalType::Float16) => {
764                    if value.len() != 2 {
765                        return Err(general_err!(
766                            "Error reading FIXED_LEN_BYTE_ARRAY as FLOAT16. Length must be 2, got {}",
767                            value.len()
768                        ));
769                    }
770                    let bytes = [value.data()[0], value.data()[1]];
771                    Field::Float16(f16::from_le_bytes(bytes))
772                }
773                ConvertedType::NONE => Field::Bytes(value),
774                _ => nyi!(descr, value),
775            },
776            _ => nyi!(descr, value),
777        };
778        Ok(field)
779    }
780
781    /// Converts the Parquet field into a JSON [`Value`].
782    #[cfg(any(feature = "json", test))]
783    pub fn to_json_value(&self) -> Value {
784        use base64::Engine;
785        use base64::prelude::BASE64_STANDARD;
786
787        match &self {
788            Field::Null => Value::Null,
789            Field::Bool(b) => Value::Bool(*b),
790            Field::Byte(n) => Value::Number(serde_json::Number::from(*n)),
791            Field::Short(n) => Value::Number(serde_json::Number::from(*n)),
792            Field::Int(n) => Value::Number(serde_json::Number::from(*n)),
793            Field::Long(n) => Value::Number(serde_json::Number::from(*n)),
794            Field::UByte(n) => Value::Number(serde_json::Number::from(*n)),
795            Field::UShort(n) => Value::Number(serde_json::Number::from(*n)),
796            Field::UInt(n) => Value::Number(serde_json::Number::from(*n)),
797            Field::ULong(n) => Value::Number(serde_json::Number::from(*n)),
798            Field::Float16(n) => serde_json::Number::from_f64(f64::from(*n))
799                .map(Value::Number)
800                .unwrap_or(Value::Null),
801            Field::Float(n) => serde_json::Number::from_f64(f64::from(*n))
802                .map(Value::Number)
803                .unwrap_or(Value::Null),
804            Field::Double(n) => serde_json::Number::from_f64(*n)
805                .map(Value::Number)
806                .unwrap_or(Value::Null),
807            Field::Decimal(n) => Value::String(convert_decimal_to_string(n)),
808            Field::Str(s) => Value::String(s.to_owned()),
809            Field::Bytes(b) => Value::String(BASE64_STANDARD.encode(b.data())),
810            Field::Date(d) => Value::String(convert_date_to_string(*d)),
811            Field::TimeMillis(t) => Value::String(convert_time_millis_to_string(*t)),
812            Field::TimeMicros(t) => Value::String(convert_time_micros_to_string(*t)),
813            Field::TimestampMillis(ts) => Value::String(convert_timestamp_millis_to_string(*ts)),
814            Field::TimestampMicros(ts) => Value::String(convert_timestamp_micros_to_string(*ts)),
815            Field::Group(row) => row.to_json_value(),
816            Field::ListInternal(fields) => {
817                Value::Array(fields.elements.iter().map(|f| f.to_json_value()).collect())
818            }
819            Field::MapInternal(map) => Value::Object(
820                map.entries
821                    .iter()
822                    .map(|(key_field, value_field)| {
823                        let key_val = key_field.to_json_value();
824                        let key_str = key_val
825                            .as_str()
826                            .map(|s| s.to_owned())
827                            .unwrap_or_else(|| key_val.to_string());
828                        (key_str, value_field.to_json_value())
829                    })
830                    .collect(),
831            ),
832        }
833    }
834}
835
836impl fmt::Display for Field {
837    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
838        match *self {
839            Field::Null => write!(f, "null"),
840            Field::Bool(value) => write!(f, "{value}"),
841            Field::Byte(value) => write!(f, "{value}"),
842            Field::Short(value) => write!(f, "{value}"),
843            Field::Int(value) => write!(f, "{value}"),
844            Field::Long(value) => write!(f, "{value}"),
845            Field::UByte(value) => write!(f, "{value}"),
846            Field::UShort(value) => write!(f, "{value}"),
847            Field::UInt(value) => write!(f, "{value}"),
848            Field::ULong(value) => write!(f, "{value}"),
849            Field::Float16(value) => {
850                if !value.is_finite() {
851                    write!(f, "{value}")
852                } else if value.trunc() == value {
853                    write!(f, "{value}.0")
854                } else {
855                    write!(f, "{value}")
856                }
857            }
858            Field::Float(value) => {
859                if !(1e-15..=1e19).contains(&value) {
860                    write!(f, "{value:E}")
861                } else if value.trunc() == value {
862                    write!(f, "{value}.0")
863                } else {
864                    write!(f, "{value}")
865                }
866            }
867            Field::Double(value) => {
868                if !(1e-15..=1e19).contains(&value) {
869                    write!(f, "{value:E}")
870                } else if value.trunc() == value {
871                    write!(f, "{value}.0")
872                } else {
873                    write!(f, "{value}")
874                }
875            }
876            Field::Decimal(ref value) => {
877                write!(f, "{}", convert_decimal_to_string(value))
878            }
879            Field::Str(ref value) => write!(f, "\"{value}\""),
880            Field::Bytes(ref value) => write!(f, "{:?}", value.data()),
881            Field::Date(value) => write!(f, "{}", convert_date_to_string(value)),
882            Field::TimeMillis(value) => {
883                write!(f, "{}", convert_time_millis_to_string(value))
884            }
885            Field::TimeMicros(value) => {
886                write!(f, "{}", convert_time_micros_to_string(value))
887            }
888            Field::TimestampMillis(value) => {
889                write!(f, "{}", convert_timestamp_millis_to_string(value))
890            }
891            Field::TimestampMicros(value) => {
892                write!(f, "{}", convert_timestamp_micros_to_string(value))
893            }
894            Field::Group(ref fields) => write!(f, "{fields}"),
895            Field::ListInternal(ref list) => {
896                let elems = &list.elements;
897                write!(f, "[")?;
898                for (i, field) in elems.iter().enumerate() {
899                    field.fmt(f)?;
900                    if i < elems.len() - 1 {
901                        write!(f, ", ")?;
902                    }
903                }
904                write!(f, "]")
905            }
906            Field::MapInternal(ref map) => {
907                let entries = &map.entries;
908                write!(f, "{{")?;
909                for (i, (key, value)) in entries.iter().enumerate() {
910                    key.fmt(f)?;
911                    write!(f, " -> ")?;
912                    value.fmt(f)?;
913                    if i < entries.len() - 1 {
914                        write!(f, ", ")?;
915                    }
916                }
917                write!(f, "}}")
918            }
919        }
920    }
921}
922
923/// Helper method to convert Parquet date into a string.
924/// Input `value` is a number of days since the epoch in UTC.
925/// Date is displayed in local timezone.
926#[inline]
927fn convert_date_to_string(value: i32) -> String {
928    static NUM_SECONDS_IN_DAY: i64 = 60 * 60 * 24;
929    let dt = Utc
930        .timestamp_opt(value as i64 * NUM_SECONDS_IN_DAY, 0)
931        .unwrap();
932    format!("{}", dt.format("%Y-%m-%d"))
933}
934
935/// Helper method to convert Parquet timestamp into a string.
936/// Input `value` is a number of milliseconds since the epoch in UTC.
937/// Datetime is displayed in UTC timezone.
938#[inline]
939fn convert_timestamp_millis_to_string(value: i64) -> String {
940    let dt = Utc.timestamp_millis_opt(value).unwrap();
941    format!("{}", dt.format("%Y-%m-%d %H:%M:%S%.3f %:z"))
942}
943
944/// Helper method to convert Parquet timestamp into a string.
945/// Input `value` is a number of microseconds since the epoch in UTC.
946/// Datetime is displayed in UTC timezone.
947#[inline]
948fn convert_timestamp_micros_to_string(value: i64) -> String {
949    let dt = Utc.timestamp_micros(value).unwrap();
950    format!("{}", dt.format("%Y-%m-%d %H:%M:%S%.6f %:z"))
951}
952
953/// Helper method to convert Parquet time (milliseconds since midnight) into a string.
954/// Input `value` is a number of milliseconds since midnight.
955/// Time is displayed in HH:MM:SS.sss format.
956#[inline]
957fn convert_time_millis_to_string(value: i32) -> String {
958    let total_ms = value as u64;
959    let hours = total_ms / (60 * 60 * 1000);
960    let minutes = (total_ms % (60 * 60 * 1000)) / (60 * 1000);
961    let seconds = (total_ms % (60 * 1000)) / 1000;
962    let millis = total_ms % 1000;
963    format!("{hours:02}:{minutes:02}:{seconds:02}.{millis:03}")
964}
965
966/// Helper method to convert Parquet time (microseconds since midnight) into a string.
967/// Input `value` is a number of microseconds since midnight.
968/// Time is displayed in HH:MM:SS.ssssss format.
969#[inline]
970fn convert_time_micros_to_string(value: i64) -> String {
971    let total_us = value as u64;
972    let hours = total_us / (60 * 60 * 1000 * 1000);
973    let minutes = (total_us % (60 * 60 * 1000 * 1000)) / (60 * 1000 * 1000);
974    let seconds = (total_us % (60 * 1000 * 1000)) / (1000 * 1000);
975    let micros = total_us % (1000 * 1000);
976    format!("{hours:02}:{minutes:02}:{seconds:02}.{micros:06}")
977}
978
979/// Helper method to convert Parquet decimal into a string.
980/// We assert that `scale >= 0` and `precision >= scale`, which is enforced when
981/// constructing a Parquet schema.
982#[inline]
983fn convert_decimal_to_string(decimal: &Decimal) -> String {
984    assert!(decimal.scale() >= 0 && decimal.precision() >= decimal.scale());
985
986    // Specify as signed bytes to resolve sign as part of conversion.
987    let num = BigInt::from_signed_bytes_be(decimal.data());
988
989    // Offset of the first digit in a string.
990    let negative = i32::from(num.sign() == Sign::Minus);
991    let mut num_str = num.to_string();
992    let mut point = num_str.len() as i32 - decimal.scale() - negative;
993
994    // Convert to string form without scientific notation.
995    if point <= 0 {
996        // Zeros need to be prepended to the unscaled value.
997        while point < 0 {
998            num_str.insert(negative as usize, '0');
999            point += 1;
1000        }
1001        num_str.insert_str(negative as usize, "0.");
1002    } else {
1003        // No zeroes need to be prepended to the unscaled value, simply insert decimal
1004        // point.
1005        num_str.insert((point + negative) as usize, '.');
1006    }
1007
1008    num_str
1009}
1010
1011#[cfg(test)]
1012#[expect(clippy::many_single_char_names)]
1013mod tests {
1014    use super::*;
1015
1016    use std::f64::consts::PI;
1017    use std::sync::Arc;
1018
1019    use crate::schema::types::{ColumnDescriptor, ColumnPath, PrimitiveTypeBuilder};
1020
1021    /// Creates test column descriptor based on provided type parameters.
1022    macro_rules! make_column_descr {
1023        ($physical_type:expr, $logical_type:expr) => {{
1024            let type_ = PrimitiveTypeBuilder::new("col", $physical_type)
1025                .with_converted_type($logical_type)
1026                .build()
1027                .unwrap();
1028            Arc::new(ColumnDescriptor::new(
1029                Arc::new(type_),
1030                0,
1031                0,
1032                ColumnPath::from("col"),
1033            ))
1034        }};
1035        ($physical_type:expr, $logical_type:expr, $len:expr, $prec:expr, $scale:expr) => {{
1036            let type_ = PrimitiveTypeBuilder::new("col", $physical_type)
1037                .with_converted_type($logical_type)
1038                .with_length($len)
1039                .with_precision($prec)
1040                .with_scale($scale)
1041                .build()
1042                .unwrap();
1043            Arc::new(ColumnDescriptor::new(
1044                Arc::new(type_),
1045                0,
1046                0,
1047                ColumnPath::from("col"),
1048            ))
1049        }};
1050    }
1051
1052    #[test]
1053    fn test_row_convert_bool() {
1054        // BOOLEAN value does not depend on logical type
1055        let descr = make_column_descr![PhysicalType::BOOLEAN, ConvertedType::NONE];
1056
1057        let row = Field::convert_bool(&descr, true);
1058        assert_eq!(row, Field::Bool(true));
1059
1060        let row = Field::convert_bool(&descr, false);
1061        assert_eq!(row, Field::Bool(false));
1062    }
1063
1064    #[test]
1065    fn test_row_convert_int32() {
1066        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::INT_8];
1067        let row = Field::convert_int32(&descr, 111);
1068        assert_eq!(row, Field::Byte(111));
1069
1070        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::INT_16];
1071        let row = Field::convert_int32(&descr, 222);
1072        assert_eq!(row, Field::Short(222));
1073
1074        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::INT_32];
1075        let row = Field::convert_int32(&descr, 333);
1076        assert_eq!(row, Field::Int(333));
1077
1078        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::UINT_8];
1079        let row = Field::convert_int32(&descr, -1);
1080        assert_eq!(row, Field::UByte(255));
1081
1082        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::UINT_16];
1083        let row = Field::convert_int32(&descr, 256);
1084        assert_eq!(row, Field::UShort(256));
1085
1086        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::UINT_32];
1087        let row = Field::convert_int32(&descr, 1234);
1088        assert_eq!(row, Field::UInt(1234));
1089
1090        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::NONE];
1091        let row = Field::convert_int32(&descr, 444);
1092        assert_eq!(row, Field::Int(444));
1093
1094        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::DATE];
1095        let row = Field::convert_int32(&descr, 14611);
1096        assert_eq!(row, Field::Date(14611));
1097
1098        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::TIME_MILLIS];
1099        let row = Field::convert_int32(&descr, 14611);
1100        assert_eq!(row, Field::TimeMillis(14611));
1101
1102        let descr = make_column_descr![PhysicalType::INT32, ConvertedType::DECIMAL, 0, 8, 2];
1103        let row = Field::convert_int32(&descr, 444);
1104        assert_eq!(row, Field::Decimal(Decimal::from_i32(444, 8, 2)));
1105    }
1106
1107    #[test]
1108    fn test_row_convert_int64() {
1109        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::INT_64];
1110        let row = Field::convert_int64(&descr, 1111);
1111        assert_eq!(row, Field::Long(1111));
1112
1113        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::UINT_64];
1114        let row = Field::convert_int64(&descr, 78239823);
1115        assert_eq!(row, Field::ULong(78239823));
1116
1117        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::TIMESTAMP_MILLIS];
1118        let row = Field::convert_int64(&descr, 1541186529153);
1119        assert_eq!(row, Field::TimestampMillis(1541186529153));
1120
1121        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::TIMESTAMP_MICROS];
1122        let row = Field::convert_int64(&descr, 1541186529153123);
1123        assert_eq!(row, Field::TimestampMicros(1541186529153123));
1124
1125        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::TIME_MICROS];
1126        let row = Field::convert_int64(&descr, 47445123456);
1127        assert_eq!(row, Field::TimeMicros(47445123456));
1128
1129        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::NONE];
1130        let row = Field::convert_int64(&descr, 2222);
1131        assert_eq!(row, Field::Long(2222));
1132
1133        let descr = make_column_descr![PhysicalType::INT64, ConvertedType::DECIMAL, 0, 8, 2];
1134        let row = Field::convert_int64(&descr, 3333);
1135        assert_eq!(row, Field::Decimal(Decimal::from_i64(3333, 8, 2)));
1136    }
1137
1138    #[test]
1139    fn test_row_convert_int96() {
1140        // INT96 value does not depend on logical type
1141        let descr = make_column_descr![PhysicalType::INT96, ConvertedType::NONE];
1142
1143        let value = Int96::from(vec![0, 0, 2454923]);
1144        let row = Field::convert_int96(&descr, value);
1145        assert_eq!(row, Field::TimestampMillis(1238544000000));
1146
1147        let value = Int96::from(vec![4165425152, 13, 2454923]);
1148        let row = Field::convert_int96(&descr, value);
1149        assert_eq!(row, Field::TimestampMillis(1238544060000));
1150    }
1151
1152    #[test]
1153    fn test_row_convert_float() {
1154        // FLOAT value does not depend on logical type
1155        let descr = make_column_descr![PhysicalType::FLOAT, ConvertedType::NONE];
1156        let row = Field::convert_float(&descr, 2.31);
1157        assert_eq!(row, Field::Float(2.31));
1158    }
1159
1160    #[test]
1161    fn test_row_convert_double() {
1162        // DOUBLE value does not depend on logical type
1163        let descr = make_column_descr![PhysicalType::DOUBLE, ConvertedType::NONE];
1164        let row = Field::convert_double(&descr, 1.56);
1165        assert_eq!(row, Field::Double(1.56));
1166    }
1167
1168    #[test]
1169    fn test_row_convert_byte_array() {
1170        // UTF8
1171        let descr = make_column_descr![PhysicalType::BYTE_ARRAY, ConvertedType::UTF8];
1172        let value = ByteArray::from(vec![b'A', b'B', b'C', b'D']);
1173        let row = Field::convert_byte_array(&descr, value);
1174        assert_eq!(row.unwrap(), Field::Str("ABCD".to_string()));
1175
1176        // ENUM
1177        let descr = make_column_descr![PhysicalType::BYTE_ARRAY, ConvertedType::ENUM];
1178        let value = ByteArray::from(vec![b'1', b'2', b'3']);
1179        let row = Field::convert_byte_array(&descr, value);
1180        assert_eq!(row.unwrap(), Field::Str("123".to_string()));
1181
1182        // JSON
1183        let descr = make_column_descr![PhysicalType::BYTE_ARRAY, ConvertedType::JSON];
1184        let value = ByteArray::from(vec![b'{', b'"', b'a', b'"', b':', b'1', b'}']);
1185        let row = Field::convert_byte_array(&descr, value);
1186        assert_eq!(row.unwrap(), Field::Str("{\"a\":1}".to_string()));
1187
1188        // NONE
1189        let descr = make_column_descr![PhysicalType::BYTE_ARRAY, ConvertedType::NONE];
1190        let value = ByteArray::from(vec![1, 2, 3, 4, 5]);
1191        let row = Field::convert_byte_array(&descr, value.clone());
1192        assert_eq!(row.unwrap(), Field::Bytes(value));
1193
1194        // BSON
1195        let descr = make_column_descr![PhysicalType::BYTE_ARRAY, ConvertedType::BSON];
1196        let value = ByteArray::from(vec![1, 2, 3, 4, 5]);
1197        let row = Field::convert_byte_array(&descr, value.clone());
1198        assert_eq!(row.unwrap(), Field::Bytes(value));
1199
1200        // DECIMAL
1201        let descr = make_column_descr![PhysicalType::BYTE_ARRAY, ConvertedType::DECIMAL, 0, 8, 2];
1202        let value = ByteArray::from(vec![207, 200]);
1203        let row = Field::convert_byte_array(&descr, value.clone());
1204        assert_eq!(
1205            row.unwrap(),
1206            Field::Decimal(Decimal::from_bytes(value, 8, 2))
1207        );
1208
1209        // DECIMAL (FIXED_LEN_BYTE_ARRAY)
1210        let descr = make_column_descr![
1211            PhysicalType::FIXED_LEN_BYTE_ARRAY,
1212            ConvertedType::DECIMAL,
1213            8,
1214            17,
1215            5
1216        ];
1217        let value = ByteArray::from(vec![0, 0, 0, 0, 0, 4, 147, 224]);
1218        let row = Field::convert_byte_array(&descr, value.clone());
1219        assert_eq!(
1220            row.unwrap(),
1221            Field::Decimal(Decimal::from_bytes(value, 17, 5))
1222        );
1223
1224        // FLOAT16
1225        let descr = {
1226            let type_ = PrimitiveTypeBuilder::new("col", PhysicalType::FIXED_LEN_BYTE_ARRAY)
1227                .with_logical_type(Some(LogicalType::Float16))
1228                .with_length(2)
1229                .build()
1230                .unwrap();
1231            Arc::new(ColumnDescriptor::new(
1232                Arc::new(type_),
1233                0,
1234                0,
1235                ColumnPath::from("col"),
1236            ))
1237        };
1238        let value = ByteArray::from(f16::PI);
1239        let row = Field::convert_byte_array(&descr, value.clone());
1240        assert_eq!(row.unwrap(), Field::Float16(f16::PI));
1241
1242        // NONE (FIXED_LEN_BYTE_ARRAY)
1243        let descr = make_column_descr![
1244            PhysicalType::FIXED_LEN_BYTE_ARRAY,
1245            ConvertedType::NONE,
1246            6,
1247            0,
1248            0
1249        ];
1250        let value = ByteArray::from(vec![1, 2, 3, 4, 5, 6]);
1251        let row = Field::convert_byte_array(&descr, value.clone());
1252        assert_eq!(row.unwrap(), Field::Bytes(value));
1253    }
1254
1255    #[test]
1256    fn test_convert_date_to_string() {
1257        fn check_date_conversion(y: u32, m: u32, d: u32) {
1258            let datetime = chrono::NaiveDate::from_ymd_opt(y as i32, m, d)
1259                .unwrap()
1260                .and_hms_opt(0, 0, 0)
1261                .unwrap();
1262            let dt = Utc.from_utc_datetime(&datetime);
1263            let res = convert_date_to_string((dt.timestamp() / 60 / 60 / 24) as i32);
1264            let exp = format!("{}", dt.format("%Y-%m-%d"));
1265            assert_eq!(res, exp);
1266        }
1267
1268        check_date_conversion(1969, 12, 31);
1269        check_date_conversion(2010, 1, 2);
1270        check_date_conversion(2014, 5, 1);
1271        check_date_conversion(2016, 2, 29);
1272        check_date_conversion(2017, 9, 12);
1273        check_date_conversion(2018, 3, 31);
1274    }
1275
1276    #[test]
1277    fn test_convert_timestamp_millis_to_string() {
1278        fn check_datetime_conversion(
1279            (y, m, d, h, mi, s, milli): (u32, u32, u32, u32, u32, u32, u32),
1280            exp: &str,
1281        ) {
1282            let datetime = chrono::NaiveDate::from_ymd_opt(y as i32, m, d)
1283                .unwrap()
1284                .and_hms_milli_opt(h, mi, s, milli)
1285                .unwrap();
1286            let dt = Utc.from_utc_datetime(&datetime);
1287            let res = convert_timestamp_millis_to_string(dt.timestamp_millis());
1288            assert_eq!(res, exp);
1289        }
1290
1291        check_datetime_conversion((1969, 9, 10, 1, 2, 3, 4), "1969-09-10 01:02:03.004 +00:00");
1292        check_datetime_conversion(
1293            (2010, 1, 2, 13, 12, 54, 42),
1294            "2010-01-02 13:12:54.042 +00:00",
1295        );
1296        check_datetime_conversion((2011, 1, 3, 8, 23, 1, 27), "2011-01-03 08:23:01.027 +00:00");
1297        check_datetime_conversion((2012, 4, 5, 11, 6, 32, 0), "2012-04-05 11:06:32.000 +00:00");
1298        check_datetime_conversion(
1299            (2013, 5, 12, 16, 38, 0, 15),
1300            "2013-05-12 16:38:00.015 +00:00",
1301        );
1302        check_datetime_conversion(
1303            (2014, 11, 28, 21, 15, 12, 59),
1304            "2014-11-28 21:15:12.059 +00:00",
1305        );
1306    }
1307
1308    #[test]
1309    fn test_convert_timestamp_micros_to_string() {
1310        fn check_datetime_conversion(
1311            (y, m, d, h, mi, s, micro): (u32, u32, u32, u32, u32, u32, u32),
1312            exp: &str,
1313        ) {
1314            let datetime = chrono::NaiveDate::from_ymd_opt(y as i32, m, d)
1315                .unwrap()
1316                .and_hms_micro_opt(h, mi, s, micro)
1317                .unwrap();
1318            let dt = Utc.from_utc_datetime(&datetime);
1319            let res = convert_timestamp_micros_to_string(dt.timestamp_micros());
1320            assert_eq!(res, exp);
1321        }
1322
1323        check_datetime_conversion(
1324            (1969, 9, 10, 1, 2, 3, 4),
1325            "1969-09-10 01:02:03.000004 +00:00",
1326        );
1327        check_datetime_conversion(
1328            (2010, 1, 2, 13, 12, 54, 42),
1329            "2010-01-02 13:12:54.000042 +00:00",
1330        );
1331        check_datetime_conversion(
1332            (2011, 1, 3, 8, 23, 1, 27),
1333            "2011-01-03 08:23:01.000027 +00:00",
1334        );
1335        check_datetime_conversion(
1336            (2012, 4, 5, 11, 6, 32, 0),
1337            "2012-04-05 11:06:32.000000 +00:00",
1338        );
1339        check_datetime_conversion(
1340            (2013, 5, 12, 16, 38, 0, 15),
1341            "2013-05-12 16:38:00.000015 +00:00",
1342        );
1343        check_datetime_conversion(
1344            (2014, 11, 28, 21, 15, 12, 59),
1345            "2014-11-28 21:15:12.000059 +00:00",
1346        );
1347    }
1348
1349    #[test]
1350    #[cfg_attr(miri, ignore)] // inline assembly is not supported
1351    fn test_convert_float16_to_string() {
1352        assert_eq!(format!("{}", Field::Float16(f16::ONE)), "1.0");
1353        assert_eq!(format!("{}", Field::Float16(f16::PI)), "3.140625");
1354        assert_eq!(format!("{}", Field::Float16(f16::MAX)), "65504.0");
1355        assert_eq!(format!("{}", Field::Float16(f16::NAN)), "NaN");
1356        assert_eq!(format!("{}", Field::Float16(f16::INFINITY)), "inf");
1357        assert_eq!(format!("{}", Field::Float16(f16::NEG_INFINITY)), "-inf");
1358        assert_eq!(format!("{}", Field::Float16(f16::ZERO)), "0.0");
1359        assert_eq!(format!("{}", Field::Float16(f16::NEG_ZERO)), "-0.0");
1360    }
1361
1362    #[test]
1363    fn test_convert_float_to_string() {
1364        assert_eq!(format!("{}", Field::Float(1.0)), "1.0");
1365        assert_eq!(format!("{}", Field::Float(9.63)), "9.63");
1366        assert_eq!(format!("{}", Field::Float(1e-15)), "0.000000000000001");
1367        assert_eq!(format!("{}", Field::Float(1e-16)), "1E-16");
1368        assert_eq!(format!("{}", Field::Float(1e19)), "10000000000000000000.0");
1369        assert_eq!(format!("{}", Field::Float(1e20)), "1E20");
1370        assert_eq!(format!("{}", Field::Float(1.7976931E30)), "1.7976931E30");
1371        assert_eq!(format!("{}", Field::Float(-1.7976931E30)), "-1.7976931E30");
1372    }
1373
1374    #[test]
1375    fn test_convert_double_to_string() {
1376        assert_eq!(format!("{}", Field::Double(1.0)), "1.0");
1377        assert_eq!(format!("{}", Field::Double(9.63)), "9.63");
1378        assert_eq!(format!("{}", Field::Double(1e-15)), "0.000000000000001");
1379        assert_eq!(format!("{}", Field::Double(1e-16)), "1E-16");
1380        assert_eq!(format!("{}", Field::Double(1e19)), "10000000000000000000.0");
1381        assert_eq!(format!("{}", Field::Double(1e20)), "1E20");
1382        assert_eq!(
1383            format!("{}", Field::Double(1.79769313486E308)),
1384            "1.79769313486E308"
1385        );
1386        assert_eq!(
1387            format!("{}", Field::Double(-1.79769313486E308)),
1388            "-1.79769313486E308"
1389        );
1390    }
1391
1392    #[test]
1393    fn test_convert_decimal_to_string() {
1394        // Helper method to compare decimal
1395        fn check_decimal(bytes: Vec<u8>, precision: i32, scale: i32, res: &str) {
1396            let decimal = Decimal::from_bytes(ByteArray::from(bytes), precision, scale);
1397            assert_eq!(convert_decimal_to_string(&decimal), res);
1398        }
1399
1400        // This example previously used to fail in some engines
1401        check_decimal(
1402            vec![0, 0, 0, 0, 0, 0, 0, 0, 13, 224, 182, 179, 167, 100, 0, 0],
1403            38,
1404            18,
1405            "1.000000000000000000",
1406        );
1407        check_decimal(
1408            vec![
1409                249, 233, 247, 16, 185, 192, 202, 223, 215, 165, 192, 166, 67, 72,
1410            ],
1411            36,
1412            28,
1413            "-12344.0242342304923409234234293432",
1414        );
1415        check_decimal(vec![0, 0, 0, 0, 0, 4, 147, 224], 17, 5, "3.00000");
1416        check_decimal(vec![0, 0, 0, 0, 1, 201, 195, 140], 18, 2, "300000.12");
1417        check_decimal(vec![207, 200], 10, 2, "-123.44");
1418        check_decimal(vec![207, 200], 10, 8, "-0.00012344");
1419        check_decimal(vec![48, 57], 5, 5, "0.12345");
1420        check_decimal(vec![207, 199], 5, 5, "-0.12345");
1421        check_decimal(vec![45], 5, 5, "0.00045");
1422    }
1423
1424    #[test]
1425    #[cfg_attr(miri, ignore)] // inline assembly is not supported
1426    fn test_row_display() {
1427        // Primitive types
1428        assert_eq!(format!("{}", Field::Null), "null");
1429        assert_eq!(format!("{}", Field::Bool(true)), "true");
1430        assert_eq!(format!("{}", Field::Bool(false)), "false");
1431        assert_eq!(format!("{}", Field::Byte(1)), "1");
1432        assert_eq!(format!("{}", Field::Short(2)), "2");
1433        assert_eq!(format!("{}", Field::Int(3)), "3");
1434        assert_eq!(format!("{}", Field::Long(4)), "4");
1435        assert_eq!(format!("{}", Field::UByte(1)), "1");
1436        assert_eq!(format!("{}", Field::UShort(2)), "2");
1437        assert_eq!(format!("{}", Field::UInt(3)), "3");
1438        assert_eq!(format!("{}", Field::ULong(4)), "4");
1439        assert_eq!(format!("{}", Field::Float16(f16::E)), "2.71875");
1440        assert_eq!(format!("{}", Field::Float(5.0)), "5.0");
1441        assert_eq!(format!("{}", Field::Float(5.1234)), "5.1234");
1442        assert_eq!(format!("{}", Field::Double(6.0)), "6.0");
1443        assert_eq!(format!("{}", Field::Double(6.1234)), "6.1234");
1444        assert_eq!(format!("{}", Field::Str("abc".to_string())), "\"abc\"");
1445        assert_eq!(
1446            format!("{}", Field::Bytes(ByteArray::from(vec![1, 2, 3]))),
1447            "[1, 2, 3]"
1448        );
1449        assert_eq!(
1450            format!("{}", Field::Date(14611)),
1451            convert_date_to_string(14611)
1452        );
1453        assert_eq!(
1454            format!("{}", Field::TimestampMillis(1262391174000)),
1455            convert_timestamp_millis_to_string(1262391174000)
1456        );
1457        assert_eq!(
1458            format!("{}", Field::TimestampMicros(1262391174000000)),
1459            convert_timestamp_micros_to_string(1262391174000000)
1460        );
1461        assert_eq!(
1462            format!("{}", Field::Decimal(Decimal::from_i32(4, 8, 2))),
1463            convert_decimal_to_string(&Decimal::from_i32(4, 8, 2))
1464        );
1465
1466        // Complex types
1467        let fields = vec![
1468            ("x".to_string(), Field::Null),
1469            ("Y".to_string(), Field::Int(2)),
1470            ("z".to_string(), Field::Float(3.1)),
1471            ("a".to_string(), Field::Str("abc".to_string())),
1472        ];
1473        let row = Field::Group(Row::new(fields));
1474        assert_eq!(format!("{row}"), "{x: null, Y: 2, z: 3.1, a: \"abc\"}");
1475
1476        let row = Field::ListInternal(make_list(vec![
1477            Field::Int(2),
1478            Field::Int(1),
1479            Field::Null,
1480            Field::Int(12),
1481        ]));
1482        assert_eq!(format!("{row}"), "[2, 1, null, 12]");
1483
1484        let row = Field::MapInternal(make_map(vec![
1485            (Field::Int(1), Field::Float(1.2)),
1486            (Field::Int(2), Field::Float(4.5)),
1487            (Field::Int(3), Field::Float(2.3)),
1488        ]));
1489        assert_eq!(format!("{row}"), "{1 -> 1.2, 2 -> 4.5, 3 -> 2.3}");
1490    }
1491
1492    #[test]
1493    fn test_is_primitive() {
1494        // primitives
1495        assert!(Field::Null.is_primitive());
1496        assert!(Field::Bool(true).is_primitive());
1497        assert!(Field::Bool(false).is_primitive());
1498        assert!(Field::Byte(1).is_primitive());
1499        assert!(Field::Short(2).is_primitive());
1500        assert!(Field::Int(3).is_primitive());
1501        assert!(Field::Long(4).is_primitive());
1502        assert!(Field::UByte(1).is_primitive());
1503        assert!(Field::UShort(2).is_primitive());
1504        assert!(Field::UInt(3).is_primitive());
1505        assert!(Field::ULong(4).is_primitive());
1506        assert!(Field::Float16(f16::E).is_primitive());
1507        assert!(Field::Float(5.0).is_primitive());
1508        assert!(Field::Float(5.1234).is_primitive());
1509        assert!(Field::Double(6.0).is_primitive());
1510        assert!(Field::Double(6.1234).is_primitive());
1511        assert!(Field::Str("abc".to_string()).is_primitive());
1512        assert!(Field::Bytes(ByteArray::from(vec![1, 2, 3])).is_primitive());
1513        assert!(Field::TimestampMillis(12345678).is_primitive());
1514        assert!(Field::TimestampMicros(12345678901).is_primitive());
1515        assert!(Field::Decimal(Decimal::from_i32(4, 8, 2)).is_primitive());
1516
1517        // complex types
1518        assert!(
1519            !Field::Group(Row::new(vec![
1520                ("x".to_string(), Field::Null),
1521                ("Y".to_string(), Field::Int(2)),
1522                ("z".to_string(), Field::Float(3.1)),
1523                ("a".to_string(), Field::Str("abc".to_string()))
1524            ]))
1525            .is_primitive()
1526        );
1527
1528        assert!(
1529            !Field::ListInternal(make_list(vec![
1530                Field::Int(2),
1531                Field::Int(1),
1532                Field::Null,
1533                Field::Int(12)
1534            ]))
1535            .is_primitive()
1536        );
1537
1538        assert!(
1539            !Field::MapInternal(make_map(vec![
1540                (Field::Int(1), Field::Float(1.2)),
1541                (Field::Int(2), Field::Float(4.5)),
1542                (Field::Int(3), Field::Float(2.3))
1543            ]))
1544            .is_primitive()
1545        );
1546    }
1547
1548    #[test]
1549    #[cfg_attr(miri, ignore)] // inline assembly is not supported
1550    fn test_row_primitive_field_fmt() {
1551        // Primitives types
1552        let row = Row::new(vec![
1553            ("00".to_string(), Field::Null),
1554            ("01".to_string(), Field::Bool(false)),
1555            ("02".to_string(), Field::Byte(3)),
1556            ("03".to_string(), Field::Short(4)),
1557            ("04".to_string(), Field::Int(5)),
1558            ("05".to_string(), Field::Long(6)),
1559            ("06".to_string(), Field::UByte(7)),
1560            ("07".to_string(), Field::UShort(8)),
1561            ("08".to_string(), Field::UInt(9)),
1562            ("09".to_string(), Field::ULong(10)),
1563            ("10".to_string(), Field::Float(11.1)),
1564            ("11".to_string(), Field::Double(12.1)),
1565            ("12".to_string(), Field::Str("abc".to_string())),
1566            (
1567                "13".to_string(),
1568                Field::Bytes(ByteArray::from(vec![1, 2, 3, 4, 5])),
1569            ),
1570            ("14".to_string(), Field::Date(14611)),
1571            ("15".to_string(), Field::TimestampMillis(1262391174000)),
1572            ("16".to_string(), Field::TimestampMicros(1262391174000000)),
1573            ("17".to_string(), Field::Decimal(Decimal::from_i32(4, 7, 2))),
1574            ("18".to_string(), Field::Float16(f16::PI)),
1575        ]);
1576
1577        assert_eq!("null", format!("{}", row.fmt(0)));
1578        assert_eq!("false", format!("{}", row.fmt(1)));
1579        assert_eq!("3", format!("{}", row.fmt(2)));
1580        assert_eq!("4", format!("{}", row.fmt(3)));
1581        assert_eq!("5", format!("{}", row.fmt(4)));
1582        assert_eq!("6", format!("{}", row.fmt(5)));
1583        assert_eq!("7", format!("{}", row.fmt(6)));
1584        assert_eq!("8", format!("{}", row.fmt(7)));
1585        assert_eq!("9", format!("{}", row.fmt(8)));
1586        assert_eq!("10", format!("{}", row.fmt(9)));
1587        assert_eq!("11.1", format!("{}", row.fmt(10)));
1588        assert_eq!("12.1", format!("{}", row.fmt(11)));
1589        assert_eq!("\"abc\"", format!("{}", row.fmt(12)));
1590        assert_eq!("[1, 2, 3, 4, 5]", format!("{}", row.fmt(13)));
1591        assert_eq!(convert_date_to_string(14611), format!("{}", row.fmt(14)));
1592        assert_eq!(
1593            convert_timestamp_millis_to_string(1262391174000),
1594            format!("{}", row.fmt(15))
1595        );
1596        assert_eq!(
1597            convert_timestamp_micros_to_string(1262391174000000),
1598            format!("{}", row.fmt(16))
1599        );
1600        assert_eq!("0.04", format!("{}", row.fmt(17)));
1601        assert_eq!("3.140625", format!("{}", row.fmt(18)));
1602    }
1603
1604    #[test]
1605    fn test_row_complex_field_fmt() {
1606        // Complex types
1607        let row = Row::new(vec![
1608            (
1609                "00".to_string(),
1610                Field::Group(Row::new(vec![
1611                    ("x".to_string(), Field::Null),
1612                    ("Y".to_string(), Field::Int(2)),
1613                ])),
1614            ),
1615            (
1616                "01".to_string(),
1617                Field::ListInternal(make_list(vec![
1618                    Field::Int(2),
1619                    Field::Int(1),
1620                    Field::Null,
1621                    Field::Int(12),
1622                ])),
1623            ),
1624            (
1625                "02".to_string(),
1626                Field::MapInternal(make_map(vec![
1627                    (Field::Int(1), Field::Float(1.2)),
1628                    (Field::Int(2), Field::Float(4.5)),
1629                    (Field::Int(3), Field::Float(2.3)),
1630                ])),
1631            ),
1632        ]);
1633
1634        assert_eq!("{x: null, Y: 2}", format!("{}", row.fmt(0)));
1635        assert_eq!("[2, 1, null, 12]", format!("{}", row.fmt(1)));
1636        assert_eq!("{1 -> 1.2, 2 -> 4.5, 3 -> 2.3}", format!("{}", row.fmt(2)));
1637    }
1638
1639    #[test]
1640    #[cfg_attr(miri, ignore)] // inline assembly is not supported
1641    fn test_row_primitive_accessors() {
1642        // primitives
1643        let row = Row::new(vec![
1644            ("a".to_string(), Field::Null),
1645            ("b".to_string(), Field::Bool(false)),
1646            ("c".to_string(), Field::Byte(3)),
1647            ("d".to_string(), Field::Short(4)),
1648            ("e".to_string(), Field::Int(5)),
1649            ("f".to_string(), Field::Long(6)),
1650            ("g".to_string(), Field::UByte(3)),
1651            ("h".to_string(), Field::UShort(4)),
1652            ("i".to_string(), Field::UInt(5)),
1653            ("j".to_string(), Field::ULong(6)),
1654            ("k".to_string(), Field::Float(7.1)),
1655            ("l".to_string(), Field::Double(8.1)),
1656            ("m".to_string(), Field::Str("abc".to_string())),
1657            (
1658                "n".to_string(),
1659                Field::Bytes(ByteArray::from(vec![1, 2, 3, 4, 5])),
1660            ),
1661            ("o".to_string(), Field::Decimal(Decimal::from_i32(4, 7, 2))),
1662            ("p".to_string(), Field::Float16(f16::from_f32(9.1))),
1663        ]);
1664
1665        assert!(row.is_null(0).unwrap());
1666        assert!(!row.is_null(1).unwrap());
1667        assert!(!row.get_bool(1).unwrap());
1668        assert_eq!(3, row.get_byte(2).unwrap());
1669        assert_eq!(4, row.get_short(3).unwrap());
1670        assert_eq!(5, row.get_int(4).unwrap());
1671        assert_eq!(6, row.get_long(5).unwrap());
1672        assert_eq!(3, row.get_ubyte(6).unwrap());
1673        assert_eq!(4, row.get_ushort(7).unwrap());
1674        assert_eq!(5, row.get_uint(8).unwrap());
1675        assert_eq!(6, row.get_ulong(9).unwrap());
1676        assert!((7.1 - row.get_float(10).unwrap()).abs() < f32::EPSILON);
1677        assert!((8.1 - row.get_double(11).unwrap()).abs() < f64::EPSILON);
1678        assert_eq!("abc", row.get_string(12).unwrap());
1679        assert_eq!(5, row.get_bytes(13).unwrap().len());
1680        assert_eq!(7, row.get_decimal(14).unwrap().precision());
1681        assert!((f16::from_f32(9.1) - row.get_float16(15).unwrap()).abs() < f16::EPSILON);
1682
1683        assert!(matches!(
1684            row.is_null(16).unwrap_err(),
1685            ParquetError::IndexOutOfBound(16, 16),
1686        ));
1687        assert!(matches!(
1688            row.get_bool(16).unwrap_err(),
1689            ParquetError::IndexOutOfBound(16, 16),
1690        ));
1691        assert!(matches!(
1692            row.get_byte(16).unwrap_err(),
1693            ParquetError::IndexOutOfBound(16, 16),
1694        ));
1695        assert!(matches!(
1696            row.get_short(16).unwrap_err(),
1697            ParquetError::IndexOutOfBound(16, 16),
1698        ));
1699        assert!(matches!(
1700            row.get_int(16).unwrap_err(),
1701            ParquetError::IndexOutOfBound(16, 16),
1702        ));
1703        assert!(matches!(
1704            row.get_long(16).unwrap_err(),
1705            ParquetError::IndexOutOfBound(16, 16),
1706        ));
1707        assert!(matches!(
1708            row.get_ubyte(16).unwrap_err(),
1709            ParquetError::IndexOutOfBound(16, 16),
1710        ));
1711        assert!(matches!(
1712            row.get_ushort(16).unwrap_err(),
1713            ParquetError::IndexOutOfBound(16, 16),
1714        ));
1715        assert!(matches!(
1716            row.get_uint(16).unwrap_err(),
1717            ParquetError::IndexOutOfBound(16, 16),
1718        ));
1719        assert!(matches!(
1720            row.get_ulong(16).unwrap_err(),
1721            ParquetError::IndexOutOfBound(16, 16),
1722        ));
1723        assert!(matches!(
1724            row.get_float(16).unwrap_err(),
1725            ParquetError::IndexOutOfBound(16, 16),
1726        ));
1727        assert!(matches!(
1728            row.get_double(16).unwrap_err(),
1729            ParquetError::IndexOutOfBound(16, 16),
1730        ));
1731        assert!(matches!(
1732            row.get_string(16).unwrap_err(),
1733            ParquetError::IndexOutOfBound(16, 16),
1734        ));
1735        assert!(matches!(
1736            row.get_bytes(16).unwrap_err(),
1737            ParquetError::IndexOutOfBound(16, 16),
1738        ));
1739        assert!(matches!(
1740            row.get_decimal(16).unwrap_err(),
1741            ParquetError::IndexOutOfBound(16, 16),
1742        ));
1743        assert!(matches!(
1744            row.get_float16(16).unwrap_err(),
1745            ParquetError::IndexOutOfBound(16, 16),
1746        ));
1747    }
1748
1749    #[test]
1750    #[cfg_attr(miri, ignore)] // inline assembly is not supported
1751    fn test_row_primitive_invalid_accessors() {
1752        // primitives
1753        let row = Row::new(vec![
1754            ("a".to_string(), Field::Null),
1755            ("b".to_string(), Field::Bool(false)),
1756            ("c".to_string(), Field::Byte(3)),
1757            ("d".to_string(), Field::Short(4)),
1758            ("e".to_string(), Field::Int(5)),
1759            ("f".to_string(), Field::Long(6)),
1760            ("g".to_string(), Field::UByte(3)),
1761            ("h".to_string(), Field::UShort(4)),
1762            ("i".to_string(), Field::UInt(5)),
1763            ("j".to_string(), Field::ULong(6)),
1764            ("k".to_string(), Field::Float(7.1)),
1765            ("l".to_string(), Field::Double(8.1)),
1766            ("m".to_string(), Field::Str("abc".to_string())),
1767            (
1768                "n".to_string(),
1769                Field::Bytes(ByteArray::from(vec![1, 2, 3, 4, 5])),
1770            ),
1771            ("o".to_string(), Field::Decimal(Decimal::from_i32(4, 7, 2))),
1772            ("p".to_string(), Field::Float16(f16::from_f32(9.1))),
1773        ]);
1774
1775        for i in 0..row.len() {
1776            assert!(row.get_group(i).is_err());
1777        }
1778    }
1779
1780    #[test]
1781    fn test_row_complex_accessors() {
1782        let row = Row::new(vec![
1783            (
1784                "a".to_string(),
1785                Field::Group(Row::new(vec![
1786                    ("x".to_string(), Field::Null),
1787                    ("Y".to_string(), Field::Int(2)),
1788                ])),
1789            ),
1790            (
1791                "b".to_string(),
1792                Field::ListInternal(make_list(vec![
1793                    Field::Int(2),
1794                    Field::Int(1),
1795                    Field::Null,
1796                    Field::Int(12),
1797                ])),
1798            ),
1799            (
1800                "c".to_string(),
1801                Field::MapInternal(make_map(vec![
1802                    (Field::Int(1), Field::Float(1.2)),
1803                    (Field::Int(2), Field::Float(4.5)),
1804                    (Field::Int(3), Field::Float(2.3)),
1805                ])),
1806            ),
1807        ]);
1808
1809        assert_eq!(2, row.get_group(0).unwrap().len());
1810        assert_eq!(4, row.get_list(1).unwrap().len());
1811        assert_eq!(3, row.get_map(2).unwrap().len());
1812    }
1813
1814    #[test]
1815    fn test_row_complex_invalid_accessors() {
1816        let row = Row::new(vec![
1817            (
1818                "a".to_string(),
1819                Field::Group(Row::new(vec![
1820                    ("x".to_string(), Field::Null),
1821                    ("Y".to_string(), Field::Int(2)),
1822                ])),
1823            ),
1824            (
1825                "b".to_string(),
1826                Field::ListInternal(make_list(vec![
1827                    Field::Int(2),
1828                    Field::Int(1),
1829                    Field::Null,
1830                    Field::Int(12),
1831                ])),
1832            ),
1833            (
1834                "c".to_string(),
1835                Field::MapInternal(make_map(vec![
1836                    (Field::Int(1), Field::Float(1.2)),
1837                    (Field::Int(2), Field::Float(4.5)),
1838                    (Field::Int(3), Field::Float(2.3)),
1839                ])),
1840            ),
1841        ]);
1842
1843        assert_eq!(
1844            row.get_float(0).unwrap_err().to_string(),
1845            "Parquet error: Cannot access Group as Float"
1846        );
1847        assert_eq!(
1848            row.get_float(1).unwrap_err().to_string(),
1849            "Parquet error: Cannot access ListInternal as Float"
1850        );
1851        assert_eq!(
1852            row.get_float(2).unwrap_err().to_string(),
1853            "Parquet error: Cannot access MapInternal as Float",
1854        );
1855    }
1856
1857    #[test]
1858    #[cfg_attr(miri, ignore)] // inline assembly is not supported
1859    fn test_list_primitive_accessors() {
1860        // primitives
1861        let list = make_list(vec![Field::Bool(false)]);
1862        assert!(!list.get_bool(0).unwrap());
1863
1864        let list = make_list(vec![Field::Byte(3), Field::Byte(4)]);
1865        assert_eq!(4, list.get_byte(1).unwrap());
1866
1867        let list = make_list(vec![Field::Short(4), Field::Short(5), Field::Short(6)]);
1868        assert_eq!(6, list.get_short(2).unwrap());
1869
1870        let list = make_list(vec![Field::Int(5)]);
1871        assert_eq!(5, list.get_int(0).unwrap());
1872
1873        let list = make_list(vec![Field::Long(6), Field::Long(7)]);
1874        assert_eq!(7, list.get_long(1).unwrap());
1875
1876        let list = make_list(vec![Field::UByte(3), Field::UByte(4)]);
1877        assert_eq!(4, list.get_ubyte(1).unwrap());
1878
1879        let list = make_list(vec![Field::UShort(4), Field::UShort(5), Field::UShort(6)]);
1880        assert_eq!(6, list.get_ushort(2).unwrap());
1881
1882        let list = make_list(vec![Field::UInt(5)]);
1883        assert_eq!(5, list.get_uint(0).unwrap());
1884
1885        let list = make_list(vec![Field::ULong(6), Field::ULong(7)]);
1886        assert_eq!(7, list.get_ulong(1).unwrap());
1887
1888        let list = make_list(vec![Field::Float16(f16::PI)]);
1889        assert!((f16::PI - list.get_float16(0).unwrap()).abs() < f16::EPSILON);
1890
1891        let list = make_list(vec![
1892            Field::Float(8.1),
1893            Field::Float(9.2),
1894            Field::Float(10.3),
1895        ]);
1896        assert!((10.3 - list.get_float(2).unwrap()).abs() < f32::EPSILON);
1897
1898        let list = make_list(vec![Field::Double(PI)]);
1899        assert!((PI - list.get_double(0).unwrap()).abs() < f64::EPSILON);
1900
1901        let list = make_list(vec![Field::Str("abc".to_string())]);
1902        assert_eq!(&"abc".to_string(), list.get_string(0).unwrap());
1903
1904        let list = make_list(vec![Field::Bytes(ByteArray::from(vec![1, 2, 3, 4, 5]))]);
1905        assert_eq!(&[1, 2, 3, 4, 5], list.get_bytes(0).unwrap().data());
1906
1907        let list = make_list(vec![Field::Decimal(Decimal::from_i32(4, 5, 2))]);
1908        assert_eq!(&[0, 0, 0, 4], list.get_decimal(0).unwrap().data());
1909    }
1910
1911    #[test]
1912    fn test_list_primitive_invalid_accessors() {
1913        // primitives
1914        let list = make_list(vec![Field::Bool(false)]);
1915        assert!(list.get_byte(0).is_err());
1916
1917        let list = make_list(vec![Field::Byte(3), Field::Byte(4)]);
1918        assert!(list.get_short(1).is_err());
1919
1920        let list = make_list(vec![Field::Short(4), Field::Short(5), Field::Short(6)]);
1921        assert!(list.get_int(2).is_err());
1922
1923        let list = make_list(vec![Field::Int(5)]);
1924        assert!(list.get_long(0).is_err());
1925
1926        let list = make_list(vec![Field::Long(6), Field::Long(7)]);
1927        assert!(list.get_float(1).is_err());
1928
1929        let list = make_list(vec![Field::UByte(3), Field::UByte(4)]);
1930        assert!(list.get_short(1).is_err());
1931
1932        let list = make_list(vec![Field::UShort(4), Field::UShort(5), Field::UShort(6)]);
1933        assert!(list.get_int(2).is_err());
1934
1935        let list = make_list(vec![Field::UInt(5)]);
1936        assert!(list.get_long(0).is_err());
1937
1938        let list = make_list(vec![Field::ULong(6), Field::ULong(7)]);
1939        assert!(list.get_float(1).is_err());
1940
1941        let list = make_list(vec![Field::Float16(f16::PI)]);
1942        assert!(list.get_string(0).is_err());
1943
1944        let list = make_list(vec![
1945            Field::Float(8.1),
1946            Field::Float(9.2),
1947            Field::Float(10.3),
1948        ]);
1949        assert!(list.get_double(2).is_err());
1950
1951        let list = make_list(vec![Field::Double(PI)]);
1952        assert!(list.get_string(0).is_err());
1953
1954        let list = make_list(vec![Field::Str("abc".to_string())]);
1955        assert!(list.get_bytes(0).is_err());
1956
1957        let list = make_list(vec![Field::Bytes(ByteArray::from(vec![1, 2, 3, 4, 5]))]);
1958        assert!(list.get_bool(0).is_err());
1959
1960        let list = make_list(vec![Field::Decimal(Decimal::from_i32(4, 5, 2))]);
1961        assert!(list.get_bool(0).is_err());
1962    }
1963
1964    #[test]
1965    fn test_list_complex_accessors() {
1966        let list = make_list(vec![Field::Group(Row::new(vec![
1967            ("x".to_string(), Field::Null),
1968            ("Y".to_string(), Field::Int(2)),
1969        ]))]);
1970        assert_eq!(2, list.get_group(0).unwrap().len());
1971
1972        let list = make_list(vec![Field::ListInternal(make_list(vec![
1973            Field::Int(2),
1974            Field::Int(1),
1975            Field::Null,
1976            Field::Int(12),
1977        ]))]);
1978        assert_eq!(4, list.get_list(0).unwrap().len());
1979
1980        let list = make_list(vec![Field::MapInternal(make_map(vec![
1981            (Field::Int(1), Field::Float(1.2)),
1982            (Field::Int(2), Field::Float(4.5)),
1983            (Field::Int(3), Field::Float(2.3)),
1984        ]))]);
1985        assert_eq!(3, list.get_map(0).unwrap().len());
1986    }
1987
1988    #[test]
1989    fn test_list_complex_invalid_accessors() {
1990        let list = make_list(vec![Field::Group(Row::new(vec![
1991            ("x".to_string(), Field::Null),
1992            ("Y".to_string(), Field::Int(2)),
1993        ]))]);
1994        assert_eq!(
1995            list.get_float(0).unwrap_err().to_string(),
1996            "Parquet error: Cannot access Group as Float"
1997        );
1998
1999        let list = make_list(vec![Field::ListInternal(make_list(vec![
2000            Field::Int(2),
2001            Field::Int(1),
2002            Field::Null,
2003            Field::Int(12),
2004        ]))]);
2005        assert_eq!(
2006            list.get_float(0).unwrap_err().to_string(),
2007            "Parquet error: Cannot access ListInternal as Float"
2008        );
2009
2010        let list = make_list(vec![Field::MapInternal(make_map(vec![
2011            (Field::Int(1), Field::Float(1.2)),
2012            (Field::Int(2), Field::Float(4.5)),
2013            (Field::Int(3), Field::Float(2.3)),
2014        ]))]);
2015        assert_eq!(
2016            list.get_float(0).unwrap_err().to_string(),
2017            "Parquet error: Cannot access MapInternal as Float",
2018        );
2019    }
2020
2021    #[test]
2022    fn test_map_accessors() {
2023        // a map from int to string
2024        let map = make_map(vec![
2025            (Field::Int(1), Field::Str("a".to_string())),
2026            (Field::Int(2), Field::Str("b".to_string())),
2027            (Field::Int(3), Field::Str("c".to_string())),
2028            (Field::Int(4), Field::Str("d".to_string())),
2029            (Field::Int(5), Field::Str("e".to_string())),
2030        ]);
2031
2032        assert_eq!(5, map.len());
2033        for i in 0..5 {
2034            assert_eq!((i + 1) as i32, map.get_keys().get_int(i).unwrap());
2035            assert_eq!(
2036                &((i as u8 + b'a') as char).to_string(),
2037                map.get_values().get_string(i).unwrap()
2038            );
2039        }
2040    }
2041
2042    #[test]
2043    #[cfg_attr(miri, ignore)] // inline assembly is not supported
2044    fn test_to_json_value() {
2045        assert_eq!(Field::Null.to_json_value(), Value::Null);
2046        assert_eq!(Field::Bool(true).to_json_value(), Value::Bool(true));
2047        assert_eq!(Field::Bool(false).to_json_value(), Value::Bool(false));
2048        assert_eq!(
2049            Field::Byte(1).to_json_value(),
2050            Value::Number(serde_json::Number::from(1))
2051        );
2052        assert_eq!(
2053            Field::Short(2).to_json_value(),
2054            Value::Number(serde_json::Number::from(2))
2055        );
2056        assert_eq!(
2057            Field::Int(3).to_json_value(),
2058            Value::Number(serde_json::Number::from(3))
2059        );
2060        assert_eq!(
2061            Field::Long(4).to_json_value(),
2062            Value::Number(serde_json::Number::from(4))
2063        );
2064        assert_eq!(
2065            Field::UByte(1).to_json_value(),
2066            Value::Number(serde_json::Number::from(1))
2067        );
2068        assert_eq!(
2069            Field::UShort(2).to_json_value(),
2070            Value::Number(serde_json::Number::from(2))
2071        );
2072        assert_eq!(
2073            Field::UInt(3).to_json_value(),
2074            Value::Number(serde_json::Number::from(3))
2075        );
2076        assert_eq!(
2077            Field::ULong(4).to_json_value(),
2078            Value::Number(serde_json::Number::from(4))
2079        );
2080        assert_eq!(
2081            Field::Float16(f16::from_f32(5.0)).to_json_value(),
2082            Value::Number(serde_json::Number::from_f64(5.0).unwrap())
2083        );
2084        assert_eq!(
2085            Field::Float(5.0).to_json_value(),
2086            Value::Number(serde_json::Number::from_f64(5.0).unwrap())
2087        );
2088        assert_eq!(
2089            Field::Float(5.1234).to_json_value(),
2090            Value::Number(serde_json::Number::from_f64(5.1234_f32 as f64).unwrap())
2091        );
2092        assert_eq!(
2093            Field::Double(6.0).to_json_value(),
2094            Value::Number(serde_json::Number::from_f64(6.0).unwrap())
2095        );
2096        assert_eq!(
2097            Field::Double(6.1234).to_json_value(),
2098            Value::Number(serde_json::Number::from_f64(6.1234).unwrap())
2099        );
2100        assert_eq!(
2101            Field::Str("abc".to_string()).to_json_value(),
2102            Value::String(String::from("abc"))
2103        );
2104        assert_eq!(
2105            Field::Decimal(Decimal::from_i32(4, 8, 2)).to_json_value(),
2106            Value::String(String::from("0.04"))
2107        );
2108        assert_eq!(
2109            Field::Bytes(ByteArray::from(vec![1, 2, 3])).to_json_value(),
2110            Value::String(String::from("AQID"))
2111        );
2112        assert_eq!(
2113            Field::TimestampMillis(12345678).to_json_value(),
2114            Value::String("1970-01-01 03:25:45.678 +00:00".to_string())
2115        );
2116        assert_eq!(
2117            Field::TimestampMicros(12345678901).to_json_value(),
2118            Value::String("1970-01-01 03:25:45.678901 +00:00".to_string())
2119        );
2120        assert_eq!(
2121            Field::TimeMillis(47445123).to_json_value(),
2122            Value::String(String::from("13:10:45.123"))
2123        );
2124        assert_eq!(
2125            Field::TimeMicros(47445123456).to_json_value(),
2126            Value::String(String::from("13:10:45.123456"))
2127        );
2128
2129        let fields = vec![
2130            ("X".to_string(), Field::Int(1)),
2131            ("Y".to_string(), Field::Double(2.2)),
2132            ("Z".to_string(), Field::Str("abc".to_string())),
2133        ];
2134        let row = Field::Group(Row::new(fields));
2135        assert_eq!(
2136            row.to_json_value(),
2137            serde_json::json!({"X": 1, "Y": 2.2, "Z": "abc"})
2138        );
2139
2140        let row = Field::ListInternal(make_list(vec![Field::Int(1), Field::Int(12), Field::Null]));
2141        let array = vec![
2142            Value::Number(serde_json::Number::from(1)),
2143            Value::Number(serde_json::Number::from(12)),
2144            Value::Null,
2145        ];
2146        assert_eq!(row.to_json_value(), Value::Array(array));
2147
2148        let row = Field::MapInternal(make_map(vec![
2149            (Field::Str("k1".to_string()), Field::Double(1.2)),
2150            (Field::Str("k2".to_string()), Field::Double(3.4)),
2151            (Field::Str("k3".to_string()), Field::Double(4.5)),
2152        ]));
2153        assert_eq!(
2154            row.to_json_value(),
2155            serde_json::json!({"k1": 1.2, "k2": 3.4, "k3": 4.5})
2156        );
2157    }
2158}
2159
2160#[cfg(test)]
2161mod api_tests {
2162    use super::{Row, make_list, make_map};
2163    use crate::record::Field;
2164
2165    #[test]
2166    fn test_field_visibility() {
2167        let row = Row::new(vec![(
2168            "a".to_string(),
2169            Field::Group(Row::new(vec![
2170                ("x".to_string(), Field::Null),
2171                ("Y".to_string(), Field::Int(2)),
2172            ])),
2173        )]);
2174
2175        match row.get_column_iter().next() {
2176            Some(column) => {
2177                assert_eq!("a", column.0);
2178                match column.1 {
2179                    Field::Group(r) => {
2180                        assert_eq!(
2181                            &Row::new(vec![
2182                                ("x".to_string(), Field::Null),
2183                                ("Y".to_string(), Field::Int(2)),
2184                            ]),
2185                            r
2186                        );
2187                    }
2188                    _ => panic!("Expected the first column to be Field::Group"),
2189                }
2190            }
2191            None => panic!("Expected at least one column"),
2192        }
2193    }
2194
2195    #[test]
2196    fn test_list_element_access() {
2197        let expected = vec![
2198            Field::Int(1),
2199            Field::Group(Row::new(vec![
2200                ("x".to_string(), Field::Null),
2201                ("Y".to_string(), Field::Int(2)),
2202            ])),
2203        ];
2204
2205        let list = make_list(expected.clone());
2206        assert_eq!(expected.as_slice(), list.elements());
2207    }
2208
2209    #[test]
2210    fn test_map_entry_access() {
2211        let expected = vec![
2212            (Field::Str("one".to_owned()), Field::Int(1)),
2213            (Field::Str("two".to_owned()), Field::Int(2)),
2214        ];
2215
2216        let map = make_map(expected.clone());
2217        assert_eq!(expected.as_slice(), map.entries());
2218    }
2219}