1use std::io::Write;
11use std::str::FromStr;
12use std::{fmt, str};
13
14pub use crate::compression::{BrotliLevel, GzipLevel, ZstdLevel};
15use crate::file::metadata::HeapSize;
16use crate::parquet_thrift::{
17 ElementType, FieldType, ReadThrift, ThriftCompactInputProtocol, ThriftCompactOutputProtocol,
18 WriteThrift, WriteThriftField, validate_list_type,
19};
20use crate::{
21 thrift_enum, thrift_struct, thrift_union_all_empty, thrift_union_with_unknown,
22 write_thrift_field,
23};
24
25use crate::errors::{ParquetError, Result};
26
27thrift_enum!(
34enum Type {
41 BOOLEAN = 0;
42 INT32 = 1;
43 INT64 = 2;
44 INT96 = 3; FLOAT = 4;
46 DOUBLE = 5;
47 BYTE_ARRAY = 6;
48 FIXED_LEN_BYTE_ARRAY = 7;
49}
50);
51
52thrift_enum!(
58enum ConvertedType {
66 NONE = -1;
68
69 UTF8 = 0;
71
72 MAP = 1;
74
75 MAP_KEY_VALUE = 2;
77
78 LIST = 3;
81
82 ENUM = 4;
84
85 DECIMAL = 5;
98
99 DATE = 6;
101
102 TIME_MILLIS = 7;
105
106 TIME_MICROS = 8;
109
110 TIMESTAMP_MILLIS = 9;
113
114 TIMESTAMP_MICROS = 10;
117
118 UINT_8 = 11;
120
121 UINT_16 = 12;
123
124 UINT_32 = 13;
126
127 UINT_64 = 14;
129
130 INT_8 = 15;
132
133 INT_16 = 16;
135
136 INT_32 = 17;
138
139 INT_64 = 18;
141
142 JSON = 19;
144
145 BSON = 20;
147
148 INTERVAL = 21;
158}
159);
160
161thrift_union_all_empty!(
165union TimeUnit {
167 1: MilliSeconds MILLIS
168 2: MicroSeconds MICROS
169 3: NanoSeconds NANOS
170}
171);
172
173thrift_struct!(
177pub struct DecimalType {
178 1: required i32 scale
180 2: required i32 precision
182}
183);
184
185thrift_struct!(
186pub struct TimestampType {
187 1: required bool is_adjusted_to_u_t_c
189 2: required TimeUnit unit
191}
192);
193
194pub use TimestampType as TimeType;
196
197thrift_struct!(
198pub struct IntType {
199 1: required i8 bit_width
201 2: required bool is_signed
203}
204);
205
206thrift_struct!(
207pub struct VariantType {
208 1: optional i8 specification_version
211}
212);
213
214thrift_struct!(
215pub struct GeometryType {
216 1: optional string crs;
219}
220);
221
222thrift_struct!(
223pub struct GeographyType {
224 1: optional string crs;
226 2: optional EdgeInterpolationAlgorithm algorithm;
229}
230);
231
232impl GeographyType {
233 pub fn algorithm(&self) -> Option<EdgeInterpolationAlgorithm> {
239 Some(self.algorithm.unwrap_or_default())
240 }
241}
242
243thrift_union_with_unknown!(
244union LogicalType {
250 1: String
252 2: Map
254 3: List
256 4: Enum
258 5: (DecimalType) Decimal
260 6: Date
262 7: (TimeType) Time
264 8: (TimestampType) Timestamp
266 10: (IntType) Integer
269 11: Unknown
271 12: Json
273 13: Bson
275 14: Uuid
277 15: Float16
279 16: (VariantType) Variant
281 17: (GeometryType) Geometry
283 18: (GeographyType) Geography
285 19: File
287}
288);
289
290impl LogicalType {
291 pub fn integer(bit_width: i8, is_signed: bool) -> Self {
293 Self::Integer(IntType {
294 bit_width,
295 is_signed,
296 })
297 }
298
299 pub fn decimal(scale: i32, precision: i32) -> Self {
301 Self::Decimal(DecimalType { scale, precision })
302 }
303
304 pub fn time(is_adjusted_to_u_t_c: bool, unit: TimeUnit) -> Self {
306 Self::Time(TimeType {
307 is_adjusted_to_u_t_c,
308 unit,
309 })
310 }
311
312 pub fn timestamp(is_adjusted_to_u_t_c: bool, unit: TimeUnit) -> Self {
314 Self::Timestamp(TimestampType {
315 is_adjusted_to_u_t_c,
316 unit,
317 })
318 }
319
320 pub fn variant(specification_version: Option<i8>) -> Self {
322 Self::Variant(VariantType {
323 specification_version,
324 })
325 }
326
327 pub fn geometry(crs: Option<String>) -> Self {
329 Self::Geometry(GeometryType { crs })
330 }
331
332 pub fn geography(crs: Option<String>, algorithm: Option<EdgeInterpolationAlgorithm>) -> Self {
334 Self::Geography(GeographyType { crs, algorithm })
335 }
336}
337
338thrift_enum!(
343enum FieldRepetitionType {
345 REQUIRED = 0;
347 OPTIONAL = 1;
349 REPEATED = 2;
351}
352);
353
354pub type Repetition = FieldRepetitionType;
356
357thrift_enum!(
361enum Encoding {
378 PLAIN = 0;
387 PLAIN_DICTIONARY = 2;
394 RLE = 3;
398 #[deprecated(
411 since = "51.0.0",
412 note = "Please see documentation for compatibility issues and use the RLE/bit-packing hybrid encoding instead"
413 )]
414 BIT_PACKED = 4;
415 DELTA_BINARY_PACKED = 5;
419 DELTA_LENGTH_BYTE_ARRAY = 6;
423 DELTA_BYTE_ARRAY = 7;
428 RLE_DICTIONARY = 8;
432 BYTE_STREAM_SPLIT = 9;
441 ALP = 10;
445}
446);
447
448impl FromStr for Encoding {
449 type Err = ParquetError;
450
451 fn from_str(s: &str) -> Result<Self, Self::Err> {
452 match s {
453 "PLAIN" | "plain" => Ok(Encoding::PLAIN),
454 "PLAIN_DICTIONARY" | "plain_dictionary" => Ok(Encoding::PLAIN_DICTIONARY),
455 "RLE" | "rle" => Ok(Encoding::RLE),
456 #[expect(deprecated)]
457 "BIT_PACKED" | "bit_packed" => Ok(Encoding::BIT_PACKED),
458 "DELTA_BINARY_PACKED" | "delta_binary_packed" => Ok(Encoding::DELTA_BINARY_PACKED),
459 "DELTA_LENGTH_BYTE_ARRAY" | "delta_length_byte_array" => {
460 Ok(Encoding::DELTA_LENGTH_BYTE_ARRAY)
461 }
462 "DELTA_BYTE_ARRAY" | "delta_byte_array" => Ok(Encoding::DELTA_BYTE_ARRAY),
463 "RLE_DICTIONARY" | "rle_dictionary" => Ok(Encoding::RLE_DICTIONARY),
464 "BYTE_STREAM_SPLIT" | "byte_stream_split" => Ok(Encoding::BYTE_STREAM_SPLIT),
465 "ALP" | "alp" => Ok(Encoding::ALP),
466 _ => Err(general_err!("unknown encoding: {}", s)),
467 }
468 }
469}
470
471#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
505pub struct EncodingMask(i32);
506
507impl EncodingMask {
508 const MAX_ENCODING: i32 = Encoding::MAX_DISCRIMINANT;
510 const ALLOWED_MASK: u32 =
513 !(1u32 << (EncodingMask::MAX_ENCODING as u32 + 1)).wrapping_sub(1) | (1 << 1);
514
515 pub fn try_new(val: i32) -> Result<Self> {
519 if val as u32 & Self::ALLOWED_MASK != 0 {
520 return Err(general_err!("Attempt to create invalid mask: 0x{:x}", val));
521 }
522 Ok(Self(val))
523 }
524
525 pub fn as_i32(&self) -> i32 {
527 self.0
528 }
529
530 pub fn new_from_encodings<'a>(encodings: impl Iterator<Item = &'a Encoding>) -> Self {
532 let mut mask = 0;
533 for &e in encodings {
534 mask |= 1 << (e as i32);
535 }
536 Self(mask)
537 }
538
539 pub fn insert(&mut self, val: Encoding) {
541 self.0 |= 1 << (val as i32);
542 }
543
544 pub fn is_set(&self, val: Encoding) -> bool {
546 self.0 & (1 << (val as i32)) != 0
547 }
548
549 pub fn is_only(&self, val: Encoding) -> bool {
551 self.0 == (1 << (val as i32))
552 }
553
554 pub fn all_set<'a>(&self, mut encodings: impl Iterator<Item = &'a Encoding>) -> bool {
556 encodings.all(|&e| self.is_set(e))
557 }
558
559 pub fn encodings(&self) -> impl Iterator<Item = Encoding> {
561 Self::mask_to_encodings_iter(self.0)
562 }
563
564 fn mask_to_encodings_iter(mask: i32) -> impl Iterator<Item = Encoding> {
565 (0..=Self::MAX_ENCODING)
566 .filter(move |i| mask & (1 << i) != 0)
567 .map(i32_to_encoding)
568 }
569}
570
571impl HeapSize for EncodingMask {
572 fn heap_size(&self) -> usize {
573 0 }
575}
576
577impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EncodingMask {
578 fn read_thrift(prot: &mut R) -> Result<Self> {
579 let mut mask = 0;
580
581 let list_ident = prot.read_list_begin()?;
583 validate_list_type(ElementType::I32, &list_ident)?;
585 for _ in 0..list_ident.size {
586 let val = Encoding::read_thrift(prot)?;
587 mask |= 1 << val as i32;
588 }
589 Ok(Self(mask))
590 }
591}
592
593#[expect(deprecated)]
594fn i32_to_encoding(val: i32) -> Encoding {
595 match val {
596 0 => Encoding::PLAIN,
597 2 => Encoding::PLAIN_DICTIONARY,
598 3 => Encoding::RLE,
599 4 => Encoding::BIT_PACKED,
600 5 => Encoding::DELTA_BINARY_PACKED,
601 6 => Encoding::DELTA_LENGTH_BYTE_ARRAY,
602 7 => Encoding::DELTA_BYTE_ARRAY,
603 8 => Encoding::RLE_DICTIONARY,
604 9 => Encoding::BYTE_STREAM_SPLIT,
605 10 => Encoding::ALP,
606 _ => panic!("Impossible encoding {val}"),
607 }
608}
609
610thrift_enum!(
614enum CompressionCodec {
624 UNCOMPRESSED = 0;
625 SNAPPY = 1;
626 GZIP = 2;
627 LZO = 3;
628 BROTLI = 4; LZ4 = 5; ZSTD = 6; LZ4_RAW = 7; }
633);
634
635#[derive(Debug, Clone, Copy, PartialEq, Eq)]
656#[expect(non_camel_case_types)]
657pub enum Compression {
658 UNCOMPRESSED,
660 SNAPPY,
662 GZIP(GzipLevel),
664 LZO,
666 BROTLI(BrotliLevel),
668 LZ4,
670 ZSTD(ZstdLevel),
672 LZ4_RAW,
674}
675
676impl From<CompressionCodec> for Compression {
677 fn from(value: CompressionCodec) -> Self {
678 match value {
679 CompressionCodec::UNCOMPRESSED => Compression::UNCOMPRESSED,
680 CompressionCodec::SNAPPY => Compression::SNAPPY,
681 CompressionCodec::GZIP => Compression::GZIP(Default::default()),
682 CompressionCodec::LZO => Compression::LZO,
683 CompressionCodec::BROTLI => Compression::BROTLI(Default::default()),
684 CompressionCodec::LZ4 => Compression::LZ4,
685 CompressionCodec::ZSTD => Compression::ZSTD(Default::default()),
686 CompressionCodec::LZ4_RAW => Compression::LZ4_RAW,
687 }
688 }
689}
690
691impl From<Compression> for CompressionCodec {
692 fn from(value: Compression) -> Self {
693 match value {
694 Compression::UNCOMPRESSED => CompressionCodec::UNCOMPRESSED,
695 Compression::SNAPPY => CompressionCodec::SNAPPY,
696 Compression::GZIP(_) => CompressionCodec::GZIP,
697 Compression::LZO => CompressionCodec::LZO,
698 Compression::BROTLI(_) => CompressionCodec::BROTLI,
699 Compression::LZ4 => CompressionCodec::LZ4,
700 Compression::ZSTD(_) => CompressionCodec::ZSTD,
701 Compression::LZ4_RAW => CompressionCodec::LZ4_RAW,
702 }
703 }
704}
705
706fn split_compression_string(str_setting: &str) -> Result<(&str, Option<i32>), ParquetError> {
707 let split_setting = str_setting.split_once('(');
708
709 match split_setting {
710 Some((codec, level_str)) => {
711 let level = &level_str[..level_str.len() - 1]
712 .parse::<i32>()
713 .map_err(|_| {
714 ParquetError::General(format!("invalid compression level: {level_str}"))
715 })?;
716 Ok((codec, Some(*level)))
717 }
718 None => Ok((str_setting, None)),
719 }
720}
721
722fn check_level_is_none(level: Option<i32>) -> Result<(), ParquetError> {
723 if level.is_some() {
724 return Err(ParquetError::General(
725 "compression level is not supported".to_string(),
726 ));
727 }
728
729 Ok(())
730}
731
732fn require_level(codec: &str, level: Option<i32>) -> Result<i32, ParquetError> {
733 level.ok_or(ParquetError::General(format!(
734 "{codec} requires a compression level",
735 )))
736}
737
738impl FromStr for Compression {
739 type Err = ParquetError;
740
741 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
742 let (codec, level) = split_compression_string(s)?;
743
744 let c = match codec {
745 "UNCOMPRESSED" | "uncompressed" => {
746 check_level_is_none(level)?;
747 Compression::UNCOMPRESSED
748 }
749 "SNAPPY" | "snappy" => {
750 check_level_is_none(level)?;
751 Compression::SNAPPY
752 }
753 "GZIP" | "gzip" => {
754 let level = require_level(codec, level)?;
755 Compression::GZIP(GzipLevel::try_new(level.try_into()?)?)
756 }
757 "LZO" | "lzo" => {
758 check_level_is_none(level)?;
759 Compression::LZO
760 }
761 "BROTLI" | "brotli" => {
762 let level = require_level(codec, level)?;
763 Compression::BROTLI(BrotliLevel::try_new(level.try_into()?)?)
764 }
765 "LZ4" | "lz4" => {
766 check_level_is_none(level)?;
767 Compression::LZ4
768 }
769 "ZSTD" | "zstd" => {
770 let level = require_level(codec, level)?;
771 Compression::ZSTD(ZstdLevel::try_new(level)?)
772 }
773 "LZ4_RAW" | "lz4_raw" => {
774 check_level_is_none(level)?;
775 Compression::LZ4_RAW
776 }
777 _ => {
778 return Err(ParquetError::General(format!(
779 "unsupported compression {codec}"
780 )));
781 }
782 };
783
784 Ok(c)
785 }
786}
787
788thrift_enum!(
792enum PageType {
795 DATA_PAGE = 0;
796 INDEX_PAGE = 1;
797 DICTIONARY_PAGE = 2;
798 DATA_PAGE_V2 = 3;
799}
800);
801
802thrift_enum!(
806enum BoundaryOrder {
809 UNORDERED = 0;
810 ASCENDING = 1;
811 DESCENDING = 2;
812}
813);
814
815#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
822#[repr(i32)]
823#[derive(Default)]
824pub enum EdgeInterpolationAlgorithm {
825 #[default]
827 SPHERICAL = 0,
828 VINCENTY = 1,
830 THOMAS = 2,
832 ANDOYER = 3,
834 KARNEY = 4,
836 _Unknown(i32),
838}
839
840#[cfg(feature = "geospatial")]
841impl EdgeInterpolationAlgorithm {
842 pub fn try_as_edges(&self) -> Result<parquet_geospatial::WkbEdges> {
848 match &self {
849 Self::SPHERICAL => Ok(parquet_geospatial::WkbEdges::Spherical),
850 Self::VINCENTY => Ok(parquet_geospatial::WkbEdges::Vincenty),
851 Self::THOMAS => Ok(parquet_geospatial::WkbEdges::Thomas),
852 Self::ANDOYER => Ok(parquet_geospatial::WkbEdges::Andoyer),
853 Self::KARNEY => Ok(parquet_geospatial::WkbEdges::Karney),
854 unknown @ Self::_Unknown(_) => Err(general_err!(
855 "Unknown edge interpolation algorithm: {}",
856 unknown
857 )),
858 }
859 }
860}
861
862impl fmt::Display for EdgeInterpolationAlgorithm {
863 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
864 f.write_fmt(format_args!("{self:?}"))
865 }
866}
867
868#[cfg(feature = "geospatial")]
869impl From<parquet_geospatial::WkbEdges> for EdgeInterpolationAlgorithm {
870 fn from(value: parquet_geospatial::WkbEdges) -> Self {
871 match value {
872 parquet_geospatial::WkbEdges::Spherical => Self::SPHERICAL,
873 parquet_geospatial::WkbEdges::Vincenty => Self::VINCENTY,
874 parquet_geospatial::WkbEdges::Thomas => Self::THOMAS,
875 parquet_geospatial::WkbEdges::Andoyer => Self::ANDOYER,
876 parquet_geospatial::WkbEdges::Karney => Self::KARNEY,
877 }
878 }
879}
880
881impl FromStr for EdgeInterpolationAlgorithm {
882 type Err = ParquetError;
883
884 fn from_str(s: &str) -> Result<Self> {
885 match s.to_ascii_uppercase().as_str() {
886 "SPHERICAL" => Ok(EdgeInterpolationAlgorithm::SPHERICAL),
887 "VINCENTY" => Ok(EdgeInterpolationAlgorithm::VINCENTY),
888 "THOMAS" => Ok(EdgeInterpolationAlgorithm::THOMAS),
889 "ANDOYER" => Ok(EdgeInterpolationAlgorithm::ANDOYER),
890 "KARNEY" => Ok(EdgeInterpolationAlgorithm::KARNEY),
891 unknown => Err(general_err!(
892 "Unknown edge interpolation algorithm: {}",
893 unknown
894 )),
895 }
896 }
897}
898
899impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for EdgeInterpolationAlgorithm {
900 fn read_thrift(prot: &mut R) -> Result<Self> {
901 let val = prot.read_i32()?;
902 match val {
903 0 => Ok(Self::SPHERICAL),
904 1 => Ok(Self::VINCENTY),
905 2 => Ok(Self::THOMAS),
906 3 => Ok(Self::ANDOYER),
907 4 => Ok(Self::KARNEY),
908 _ => Ok(Self::_Unknown(val)),
909 }
910 }
911}
912
913impl WriteThrift for EdgeInterpolationAlgorithm {
914 const ELEMENT_TYPE: ElementType = ElementType::I32;
915 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
916 let val: i32 = match *self {
917 Self::SPHERICAL => 0,
918 Self::VINCENTY => 1,
919 Self::THOMAS => 2,
920 Self::ANDOYER => 3,
921 Self::KARNEY => 4,
922 Self::_Unknown(i) => i,
923 };
924 writer.write_i32(val)
925 }
926}
927
928write_thrift_field!(EdgeInterpolationAlgorithm, FieldType::I32);
929
930thrift_union_all_empty!(
934union BloomFilterAlgorithm {
936 1: SplitBlockAlgorithm BLOCK;
938}
939);
940
941thrift_union_all_empty!(
945union BloomFilterHash {
948 1: XxHash XXHASH;
950}
951);
952
953thrift_union_all_empty!(
957union BloomFilterCompression {
959 1: Uncompressed UNCOMPRESSED;
960}
961);
962
963#[derive(Debug, Clone, Copy, PartialEq, Eq)]
974#[expect(non_camel_case_types)]
975pub enum SortOrder {
976 SIGNED,
978 UNSIGNED,
980 UNDEFINED,
982 TOTAL_ORDER,
984 INT96_TIMESTAMP,
989}
990
991impl SortOrder {
992 pub fn is_signed(&self) -> bool {
994 matches!(self, Self::SIGNED)
995 }
996}
997
998#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1019#[expect(non_camel_case_types)]
1020pub enum ColumnOrder {
1021 TYPE_DEFINED_ORDER(SortOrder),
1024 IEEE_754_TOTAL_ORDER,
1026 INT96_TIMESTAMP_ORDER,
1028 UNDEFINED,
1032 UNKNOWN,
1035}
1036
1037impl ColumnOrder {
1038 pub fn column_order_for_type(
1040 logical_type: Option<&LogicalType>,
1041 converted_type: ConvertedType,
1042 physical_type: Type,
1043 ) -> ColumnOrder {
1044 if Some(&LogicalType::Float16) == logical_type
1045 || matches!(physical_type, Type::FLOAT | Type::DOUBLE)
1046 {
1047 ColumnOrder::IEEE_754_TOTAL_ORDER
1048 } else if matches!(physical_type, Type::INT96) {
1049 ColumnOrder::INT96_TIMESTAMP_ORDER
1050 } else {
1051 let sort_order =
1052 Self::get_sort_order_for_type(logical_type, converted_type, physical_type, true);
1053 ColumnOrder::TYPE_DEFINED_ORDER(sort_order)
1054 }
1055 }
1056
1057 #[deprecated(since = "60.0.0", note = "use `ColumnOrder::sort_order` instead")]
1064 pub fn sort_order_for_type(
1065 logical_type: Option<&LogicalType>,
1066 converted_type: ConvertedType,
1067 physical_type: Type,
1068 is_type_defined: bool,
1069 ) -> SortOrder {
1070 ColumnOrder::get_sort_order_for_type(
1071 logical_type,
1072 converted_type,
1073 physical_type,
1074 is_type_defined,
1075 )
1076 }
1077
1078 pub(crate) fn get_sort_order_for_type(
1081 logical_type: Option<&LogicalType>,
1082 converted_type: ConvertedType,
1083 physical_type: Type,
1084 is_type_defined: bool,
1085 ) -> SortOrder {
1086 match logical_type {
1087 Some(logical) => match logical {
1088 LogicalType::String | LogicalType::Enum | LogicalType::Json | LogicalType::Bson => {
1089 SortOrder::UNSIGNED
1090 }
1091 LogicalType::Integer(int) => match int.is_signed {
1092 true => SortOrder::SIGNED,
1093 false => SortOrder::UNSIGNED,
1094 },
1095 LogicalType::Map | LogicalType::List => SortOrder::UNDEFINED,
1096 LogicalType::Decimal(_) => SortOrder::SIGNED,
1097 LogicalType::Date => SortOrder::SIGNED,
1098 LogicalType::Time(_) => SortOrder::SIGNED,
1099 LogicalType::Timestamp(_) => SortOrder::SIGNED,
1100 LogicalType::Unknown => SortOrder::UNDEFINED,
1101 LogicalType::Uuid => SortOrder::UNSIGNED,
1102 LogicalType::Float16 => {
1103 if is_type_defined {
1104 SortOrder::SIGNED
1105 } else {
1106 SortOrder::TOTAL_ORDER
1107 }
1108 }
1109 LogicalType::Variant(_)
1110 | LogicalType::Geometry(_)
1111 | LogicalType::Geography(_)
1112 | LogicalType::File
1113 | LogicalType::_Unknown { .. } => SortOrder::UNDEFINED,
1114 },
1115 None => Self::get_converted_sort_order(converted_type, physical_type, is_type_defined),
1117 }
1118 }
1119
1120 fn get_converted_sort_order(
1121 converted_type: ConvertedType,
1122 physical_type: Type,
1123 is_type_defined: bool,
1124 ) -> SortOrder {
1125 match converted_type {
1126 ConvertedType::UTF8
1128 | ConvertedType::JSON
1129 | ConvertedType::BSON
1130 | ConvertedType::ENUM => SortOrder::UNSIGNED,
1131
1132 ConvertedType::INT_8
1133 | ConvertedType::INT_16
1134 | ConvertedType::INT_32
1135 | ConvertedType::INT_64 => SortOrder::SIGNED,
1136
1137 ConvertedType::UINT_8
1138 | ConvertedType::UINT_16
1139 | ConvertedType::UINT_32
1140 | ConvertedType::UINT_64 => SortOrder::UNSIGNED,
1141
1142 ConvertedType::DECIMAL => SortOrder::SIGNED,
1144
1145 ConvertedType::DATE => SortOrder::SIGNED,
1146
1147 ConvertedType::TIME_MILLIS
1148 | ConvertedType::TIME_MICROS
1149 | ConvertedType::TIMESTAMP_MILLIS
1150 | ConvertedType::TIMESTAMP_MICROS => SortOrder::SIGNED,
1151
1152 ConvertedType::INTERVAL => SortOrder::UNDEFINED,
1153
1154 ConvertedType::LIST | ConvertedType::MAP | ConvertedType::MAP_KEY_VALUE => {
1155 SortOrder::UNDEFINED
1156 }
1157
1158 ConvertedType::NONE => Self::get_default_sort_order(physical_type, is_type_defined),
1160 }
1161 }
1162
1163 fn get_default_sort_order(physical_type: Type, is_type_defined: bool) -> SortOrder {
1165 match physical_type {
1166 Type::BOOLEAN => SortOrder::UNSIGNED,
1168 Type::INT32 | Type::INT64 => SortOrder::SIGNED,
1169 Type::INT96 => {
1170 if is_type_defined {
1171 SortOrder::UNDEFINED
1172 } else {
1173 SortOrder::INT96_TIMESTAMP
1174 }
1175 }
1176 Type::FLOAT | Type::DOUBLE => {
1188 if is_type_defined {
1189 SortOrder::SIGNED
1190 } else {
1191 SortOrder::TOTAL_ORDER
1192 }
1193 }
1194 Type::BYTE_ARRAY | Type::FIXED_LEN_BYTE_ARRAY => SortOrder::UNSIGNED,
1196 }
1197 }
1198
1199 pub fn sort_order(&self) -> SortOrder {
1201 match *self {
1202 ColumnOrder::TYPE_DEFINED_ORDER(order) => order,
1203 ColumnOrder::IEEE_754_TOTAL_ORDER => SortOrder::TOTAL_ORDER,
1204 ColumnOrder::INT96_TIMESTAMP_ORDER => SortOrder::INT96_TIMESTAMP,
1205 ColumnOrder::UNDEFINED => SortOrder::SIGNED,
1206 ColumnOrder::UNKNOWN => SortOrder::UNDEFINED,
1207 }
1208 }
1209}
1210
1211impl<'a, R: ThriftCompactInputProtocol<'a>> ReadThrift<'a, R> for ColumnOrder {
1212 fn read_thrift(prot: &mut R) -> Result<Self> {
1213 let field_ident = prot.read_field_begin(0)?;
1214 if field_ident.field_type == FieldType::Stop {
1215 return Err(general_err!("Received empty union from remote ColumnOrder"));
1216 }
1217 let ret = match field_ident.id {
1218 1 => {
1219 prot.skip_empty_struct()?;
1221 Self::TYPE_DEFINED_ORDER(SortOrder::SIGNED)
1222 }
1223 2 => {
1224 prot.skip_empty_struct()?;
1225 Self::IEEE_754_TOTAL_ORDER
1226 }
1227 3 => {
1228 prot.skip_empty_struct()?;
1229 Self::INT96_TIMESTAMP_ORDER
1230 }
1231 _ => {
1232 prot.skip(field_ident.field_type)?;
1233 Self::UNKNOWN
1234 }
1235 };
1236 let field_ident = prot.read_field_begin(field_ident.id)?;
1237 if field_ident.field_type != FieldType::Stop {
1238 return Err(general_err!(
1239 "Received multiple fields for union from remote ColumnOrder"
1240 ));
1241 }
1242 Ok(ret)
1243 }
1244}
1245
1246impl WriteThrift for ColumnOrder {
1247 const ELEMENT_TYPE: ElementType = ElementType::Struct;
1248
1249 fn write_thrift<W: Write>(&self, writer: &mut ThriftCompactOutputProtocol<W>) -> Result<()> {
1250 match *self {
1251 Self::TYPE_DEFINED_ORDER(_) => {
1252 writer.write_field_begin(FieldType::Struct, 1, 0)?;
1253 writer.write_struct_end()?;
1254 }
1255 Self::IEEE_754_TOTAL_ORDER => {
1256 writer.write_field_begin(FieldType::Struct, 2, 0)?;
1257 writer.write_struct_end()?;
1258 }
1259 Self::INT96_TIMESTAMP_ORDER => {
1260 writer.write_field_begin(FieldType::Struct, 3, 0)?;
1261 writer.write_struct_end()?;
1262 }
1263 _ => return Err(general_err!("Attempt to write undefined ColumnOrder")),
1264 }
1265 writer.write_struct_end()
1267 }
1268}
1269
1270impl fmt::Display for Compression {
1274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1275 write!(f, "{self:?}")
1276 }
1277}
1278
1279impl fmt::Display for SortOrder {
1280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1281 write!(f, "{self:?}")
1282 }
1283}
1284
1285impl fmt::Display for ColumnOrder {
1286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1287 write!(f, "{self:?}")
1288 }
1289}
1290
1291impl From<Option<LogicalType>> for ConvertedType {
1301 fn from(value: Option<LogicalType>) -> Self {
1302 match value {
1303 Some(value) => match value {
1304 LogicalType::String => ConvertedType::UTF8,
1305 LogicalType::Map => ConvertedType::MAP,
1306 LogicalType::List => ConvertedType::LIST,
1307 LogicalType::Enum => ConvertedType::ENUM,
1308 LogicalType::Decimal { .. } => ConvertedType::DECIMAL,
1309 LogicalType::Date => ConvertedType::DATE,
1310 LogicalType::Time(time) => match time.unit {
1311 TimeUnit::MILLIS => ConvertedType::TIME_MILLIS,
1312 TimeUnit::MICROS => ConvertedType::TIME_MICROS,
1313 TimeUnit::NANOS => ConvertedType::NONE,
1314 },
1315 LogicalType::Timestamp(time) => match time.unit {
1316 TimeUnit::MILLIS => ConvertedType::TIMESTAMP_MILLIS,
1317 TimeUnit::MICROS => ConvertedType::TIMESTAMP_MICROS,
1318 TimeUnit::NANOS => ConvertedType::NONE,
1319 },
1320 LogicalType::Integer(int_type) => match (int_type.bit_width, int_type.is_signed) {
1321 (8, true) => ConvertedType::INT_8,
1322 (16, true) => ConvertedType::INT_16,
1323 (32, true) => ConvertedType::INT_32,
1324 (64, true) => ConvertedType::INT_64,
1325 (8, false) => ConvertedType::UINT_8,
1326 (16, false) => ConvertedType::UINT_16,
1327 (32, false) => ConvertedType::UINT_32,
1328 (64, false) => ConvertedType::UINT_64,
1329 (bit_width, is_signed) => panic!(
1330 "Integer type bit_width={bit_width}, signed={is_signed} is not supported"
1331 ),
1332 },
1333 LogicalType::Json => ConvertedType::JSON,
1334 LogicalType::Bson => ConvertedType::BSON,
1335 LogicalType::Uuid
1336 | LogicalType::Float16
1337 | LogicalType::Variant(_)
1338 | LogicalType::Geometry(_)
1339 | LogicalType::Geography(_)
1340 | LogicalType::File
1341 | LogicalType::_Unknown { .. }
1342 | LogicalType::Unknown => ConvertedType::NONE,
1343 },
1344 None => ConvertedType::NONE,
1345 }
1346 }
1347}
1348
1349impl str::FromStr for Repetition {
1353 type Err = ParquetError;
1354
1355 fn from_str(s: &str) -> Result<Self> {
1356 match s {
1357 "REQUIRED" => Ok(Repetition::REQUIRED),
1358 "OPTIONAL" => Ok(Repetition::OPTIONAL),
1359 "REPEATED" => Ok(Repetition::REPEATED),
1360 other => Err(general_err!("Invalid parquet repetition {}", other)),
1361 }
1362 }
1363}
1364
1365impl str::FromStr for Type {
1366 type Err = ParquetError;
1367
1368 fn from_str(s: &str) -> Result<Self> {
1369 match s {
1370 "BOOLEAN" => Ok(Type::BOOLEAN),
1371 "INT32" => Ok(Type::INT32),
1372 "INT64" => Ok(Type::INT64),
1373 "INT96" => Ok(Type::INT96),
1374 "FLOAT" => Ok(Type::FLOAT),
1375 "DOUBLE" => Ok(Type::DOUBLE),
1376 "BYTE_ARRAY" | "BINARY" => Ok(Type::BYTE_ARRAY),
1377 "FIXED_LEN_BYTE_ARRAY" => Ok(Type::FIXED_LEN_BYTE_ARRAY),
1378 other => Err(general_err!("Invalid parquet type {}", other)),
1379 }
1380 }
1381}
1382
1383impl str::FromStr for ConvertedType {
1384 type Err = ParquetError;
1385
1386 fn from_str(s: &str) -> Result<Self> {
1387 match s {
1388 "NONE" => Ok(ConvertedType::NONE),
1389 "UTF8" => Ok(ConvertedType::UTF8),
1390 "MAP" => Ok(ConvertedType::MAP),
1391 "MAP_KEY_VALUE" => Ok(ConvertedType::MAP_KEY_VALUE),
1392 "LIST" => Ok(ConvertedType::LIST),
1393 "ENUM" => Ok(ConvertedType::ENUM),
1394 "DECIMAL" => Ok(ConvertedType::DECIMAL),
1395 "DATE" => Ok(ConvertedType::DATE),
1396 "TIME_MILLIS" => Ok(ConvertedType::TIME_MILLIS),
1397 "TIME_MICROS" => Ok(ConvertedType::TIME_MICROS),
1398 "TIMESTAMP_MILLIS" => Ok(ConvertedType::TIMESTAMP_MILLIS),
1399 "TIMESTAMP_MICROS" => Ok(ConvertedType::TIMESTAMP_MICROS),
1400 "UINT_8" => Ok(ConvertedType::UINT_8),
1401 "UINT_16" => Ok(ConvertedType::UINT_16),
1402 "UINT_32" => Ok(ConvertedType::UINT_32),
1403 "UINT_64" => Ok(ConvertedType::UINT_64),
1404 "INT_8" => Ok(ConvertedType::INT_8),
1405 "INT_16" => Ok(ConvertedType::INT_16),
1406 "INT_32" => Ok(ConvertedType::INT_32),
1407 "INT_64" => Ok(ConvertedType::INT_64),
1408 "JSON" => Ok(ConvertedType::JSON),
1409 "BSON" => Ok(ConvertedType::BSON),
1410 "INTERVAL" => Ok(ConvertedType::INTERVAL),
1411 other => Err(general_err!("Invalid parquet converted type {}", other)),
1412 }
1413 }
1414}
1415
1416impl str::FromStr for LogicalType {
1417 type Err = ParquetError;
1418
1419 fn from_str(s: &str) -> Result<Self> {
1420 match s {
1421 "INTEGER" => Ok(LogicalType::integer(8, false)),
1423 "MAP" => Ok(LogicalType::Map),
1424 "LIST" => Ok(LogicalType::List),
1425 "ENUM" => Ok(LogicalType::Enum),
1426 "DECIMAL" => Ok(LogicalType::decimal(-1, -1)),
1427 "DATE" => Ok(LogicalType::Date),
1428 "TIME" => Ok(LogicalType::time(false, TimeUnit::MILLIS)),
1429 "TIMESTAMP" => Ok(LogicalType::timestamp(false, TimeUnit::MILLIS)),
1430 "STRING" => Ok(LogicalType::String),
1431 "JSON" => Ok(LogicalType::Json),
1432 "BSON" => Ok(LogicalType::Bson),
1433 "UUID" => Ok(LogicalType::Uuid),
1434 "UNKNOWN" => Ok(LogicalType::Unknown),
1435 "INTERVAL" => Err(general_err!(
1436 "Interval parquet logical type not yet supported"
1437 )),
1438 "FLOAT16" => Ok(LogicalType::Float16),
1439 "VARIANT" => Ok(LogicalType::variant(None)),
1440 "FILE" => Ok(LogicalType::File),
1441 "GEOMETRY" => Ok(LogicalType::geometry(None)),
1442 "GEOGRAPHY" => Ok(LogicalType::geography(
1443 None,
1444 Some(EdgeInterpolationAlgorithm::SPHERICAL),
1445 )),
1446 other => Err(general_err!("Invalid parquet logical type {}", other)),
1447 }
1448 }
1449}
1450
1451#[cfg(test)]
1452#[expect(deprecated)] mod tests {
1454 use super::*;
1455 use crate::parquet_thrift::{ThriftSliceInputProtocol, tests::test_roundtrip};
1456
1457 #[test]
1458 fn test_display_type() {
1459 assert_eq!(Type::BOOLEAN.to_string(), "BOOLEAN");
1460 assert_eq!(Type::INT32.to_string(), "INT32");
1461 assert_eq!(Type::INT64.to_string(), "INT64");
1462 assert_eq!(Type::INT96.to_string(), "INT96");
1463 assert_eq!(Type::FLOAT.to_string(), "FLOAT");
1464 assert_eq!(Type::DOUBLE.to_string(), "DOUBLE");
1465 assert_eq!(Type::BYTE_ARRAY.to_string(), "BYTE_ARRAY");
1466 assert_eq!(
1467 Type::FIXED_LEN_BYTE_ARRAY.to_string(),
1468 "FIXED_LEN_BYTE_ARRAY"
1469 );
1470 }
1471
1472 #[test]
1473 fn test_from_string_into_type() {
1474 assert_eq!(
1475 Type::BOOLEAN.to_string().parse::<Type>().unwrap(),
1476 Type::BOOLEAN
1477 );
1478 assert_eq!(
1479 Type::INT32.to_string().parse::<Type>().unwrap(),
1480 Type::INT32
1481 );
1482 assert_eq!(
1483 Type::INT64.to_string().parse::<Type>().unwrap(),
1484 Type::INT64
1485 );
1486 assert_eq!(
1487 Type::INT96.to_string().parse::<Type>().unwrap(),
1488 Type::INT96
1489 );
1490 assert_eq!(
1491 Type::FLOAT.to_string().parse::<Type>().unwrap(),
1492 Type::FLOAT
1493 );
1494 assert_eq!(
1495 Type::DOUBLE.to_string().parse::<Type>().unwrap(),
1496 Type::DOUBLE
1497 );
1498 assert_eq!(
1499 Type::BYTE_ARRAY.to_string().parse::<Type>().unwrap(),
1500 Type::BYTE_ARRAY
1501 );
1502 assert_eq!("BINARY".parse::<Type>().unwrap(), Type::BYTE_ARRAY);
1503 assert_eq!(
1504 Type::FIXED_LEN_BYTE_ARRAY
1505 .to_string()
1506 .parse::<Type>()
1507 .unwrap(),
1508 Type::FIXED_LEN_BYTE_ARRAY
1509 );
1510 }
1511
1512 #[test]
1513 fn test_converted_type_roundtrip() {
1514 test_roundtrip(ConvertedType::UTF8);
1515 test_roundtrip(ConvertedType::MAP);
1516 test_roundtrip(ConvertedType::MAP_KEY_VALUE);
1517 test_roundtrip(ConvertedType::LIST);
1518 test_roundtrip(ConvertedType::ENUM);
1519 test_roundtrip(ConvertedType::DECIMAL);
1520 test_roundtrip(ConvertedType::DATE);
1521 test_roundtrip(ConvertedType::TIME_MILLIS);
1522 test_roundtrip(ConvertedType::TIME_MICROS);
1523 test_roundtrip(ConvertedType::TIMESTAMP_MILLIS);
1524 test_roundtrip(ConvertedType::TIMESTAMP_MICROS);
1525 test_roundtrip(ConvertedType::UINT_8);
1526 test_roundtrip(ConvertedType::UINT_16);
1527 test_roundtrip(ConvertedType::UINT_32);
1528 test_roundtrip(ConvertedType::UINT_64);
1529 test_roundtrip(ConvertedType::INT_8);
1530 test_roundtrip(ConvertedType::INT_16);
1531 test_roundtrip(ConvertedType::INT_32);
1532 test_roundtrip(ConvertedType::INT_64);
1533 test_roundtrip(ConvertedType::JSON);
1534 test_roundtrip(ConvertedType::BSON);
1535 test_roundtrip(ConvertedType::INTERVAL);
1536 }
1537
1538 #[test]
1539 fn test_read_invalid_converted_type() {
1540 let mut prot = ThriftSliceInputProtocol::new(&[0x7eu8]);
1541 let res = ConvertedType::read_thrift(&mut prot);
1542 assert!(res.is_err());
1543 assert_eq!(
1544 res.unwrap_err().to_string(),
1545 "Parquet error: Unexpected ConvertedType 63"
1546 );
1547 }
1548
1549 #[test]
1550 fn test_display_converted_type() {
1551 assert_eq!(ConvertedType::NONE.to_string(), "NONE");
1552 assert_eq!(ConvertedType::UTF8.to_string(), "UTF8");
1553 assert_eq!(ConvertedType::MAP.to_string(), "MAP");
1554 assert_eq!(ConvertedType::MAP_KEY_VALUE.to_string(), "MAP_KEY_VALUE");
1555 assert_eq!(ConvertedType::LIST.to_string(), "LIST");
1556 assert_eq!(ConvertedType::ENUM.to_string(), "ENUM");
1557 assert_eq!(ConvertedType::DECIMAL.to_string(), "DECIMAL");
1558 assert_eq!(ConvertedType::DATE.to_string(), "DATE");
1559 assert_eq!(ConvertedType::TIME_MILLIS.to_string(), "TIME_MILLIS");
1560 assert_eq!(ConvertedType::DATE.to_string(), "DATE");
1561 assert_eq!(ConvertedType::TIME_MICROS.to_string(), "TIME_MICROS");
1562 assert_eq!(
1563 ConvertedType::TIMESTAMP_MILLIS.to_string(),
1564 "TIMESTAMP_MILLIS"
1565 );
1566 assert_eq!(
1567 ConvertedType::TIMESTAMP_MICROS.to_string(),
1568 "TIMESTAMP_MICROS"
1569 );
1570 assert_eq!(ConvertedType::UINT_8.to_string(), "UINT_8");
1571 assert_eq!(ConvertedType::UINT_16.to_string(), "UINT_16");
1572 assert_eq!(ConvertedType::UINT_32.to_string(), "UINT_32");
1573 assert_eq!(ConvertedType::UINT_64.to_string(), "UINT_64");
1574 assert_eq!(ConvertedType::INT_8.to_string(), "INT_8");
1575 assert_eq!(ConvertedType::INT_16.to_string(), "INT_16");
1576 assert_eq!(ConvertedType::INT_32.to_string(), "INT_32");
1577 assert_eq!(ConvertedType::INT_64.to_string(), "INT_64");
1578 assert_eq!(ConvertedType::JSON.to_string(), "JSON");
1579 assert_eq!(ConvertedType::BSON.to_string(), "BSON");
1580 assert_eq!(ConvertedType::INTERVAL.to_string(), "INTERVAL");
1581 assert_eq!(ConvertedType::DECIMAL.to_string(), "DECIMAL")
1582 }
1583
1584 #[test]
1585 fn test_from_string_into_converted_type() {
1586 assert_eq!(
1587 ConvertedType::NONE
1588 .to_string()
1589 .parse::<ConvertedType>()
1590 .unwrap(),
1591 ConvertedType::NONE
1592 );
1593 assert_eq!(
1594 ConvertedType::UTF8
1595 .to_string()
1596 .parse::<ConvertedType>()
1597 .unwrap(),
1598 ConvertedType::UTF8
1599 );
1600 assert_eq!(
1601 ConvertedType::MAP
1602 .to_string()
1603 .parse::<ConvertedType>()
1604 .unwrap(),
1605 ConvertedType::MAP
1606 );
1607 assert_eq!(
1608 ConvertedType::MAP_KEY_VALUE
1609 .to_string()
1610 .parse::<ConvertedType>()
1611 .unwrap(),
1612 ConvertedType::MAP_KEY_VALUE
1613 );
1614 assert_eq!(
1615 ConvertedType::LIST
1616 .to_string()
1617 .parse::<ConvertedType>()
1618 .unwrap(),
1619 ConvertedType::LIST
1620 );
1621 assert_eq!(
1622 ConvertedType::ENUM
1623 .to_string()
1624 .parse::<ConvertedType>()
1625 .unwrap(),
1626 ConvertedType::ENUM
1627 );
1628 assert_eq!(
1629 ConvertedType::DECIMAL
1630 .to_string()
1631 .parse::<ConvertedType>()
1632 .unwrap(),
1633 ConvertedType::DECIMAL
1634 );
1635 assert_eq!(
1636 ConvertedType::DATE
1637 .to_string()
1638 .parse::<ConvertedType>()
1639 .unwrap(),
1640 ConvertedType::DATE
1641 );
1642 assert_eq!(
1643 ConvertedType::TIME_MILLIS
1644 .to_string()
1645 .parse::<ConvertedType>()
1646 .unwrap(),
1647 ConvertedType::TIME_MILLIS
1648 );
1649 assert_eq!(
1650 ConvertedType::TIME_MICROS
1651 .to_string()
1652 .parse::<ConvertedType>()
1653 .unwrap(),
1654 ConvertedType::TIME_MICROS
1655 );
1656 assert_eq!(
1657 ConvertedType::TIMESTAMP_MILLIS
1658 .to_string()
1659 .parse::<ConvertedType>()
1660 .unwrap(),
1661 ConvertedType::TIMESTAMP_MILLIS
1662 );
1663 assert_eq!(
1664 ConvertedType::TIMESTAMP_MICROS
1665 .to_string()
1666 .parse::<ConvertedType>()
1667 .unwrap(),
1668 ConvertedType::TIMESTAMP_MICROS
1669 );
1670 assert_eq!(
1671 ConvertedType::UINT_8
1672 .to_string()
1673 .parse::<ConvertedType>()
1674 .unwrap(),
1675 ConvertedType::UINT_8
1676 );
1677 assert_eq!(
1678 ConvertedType::UINT_16
1679 .to_string()
1680 .parse::<ConvertedType>()
1681 .unwrap(),
1682 ConvertedType::UINT_16
1683 );
1684 assert_eq!(
1685 ConvertedType::UINT_32
1686 .to_string()
1687 .parse::<ConvertedType>()
1688 .unwrap(),
1689 ConvertedType::UINT_32
1690 );
1691 assert_eq!(
1692 ConvertedType::UINT_64
1693 .to_string()
1694 .parse::<ConvertedType>()
1695 .unwrap(),
1696 ConvertedType::UINT_64
1697 );
1698 assert_eq!(
1699 ConvertedType::INT_8
1700 .to_string()
1701 .parse::<ConvertedType>()
1702 .unwrap(),
1703 ConvertedType::INT_8
1704 );
1705 assert_eq!(
1706 ConvertedType::INT_16
1707 .to_string()
1708 .parse::<ConvertedType>()
1709 .unwrap(),
1710 ConvertedType::INT_16
1711 );
1712 assert_eq!(
1713 ConvertedType::INT_32
1714 .to_string()
1715 .parse::<ConvertedType>()
1716 .unwrap(),
1717 ConvertedType::INT_32
1718 );
1719 assert_eq!(
1720 ConvertedType::INT_64
1721 .to_string()
1722 .parse::<ConvertedType>()
1723 .unwrap(),
1724 ConvertedType::INT_64
1725 );
1726 assert_eq!(
1727 ConvertedType::JSON
1728 .to_string()
1729 .parse::<ConvertedType>()
1730 .unwrap(),
1731 ConvertedType::JSON
1732 );
1733 assert_eq!(
1734 ConvertedType::BSON
1735 .to_string()
1736 .parse::<ConvertedType>()
1737 .unwrap(),
1738 ConvertedType::BSON
1739 );
1740 assert_eq!(
1741 ConvertedType::INTERVAL
1742 .to_string()
1743 .parse::<ConvertedType>()
1744 .unwrap(),
1745 ConvertedType::INTERVAL
1746 );
1747 assert_eq!(
1748 ConvertedType::DECIMAL
1749 .to_string()
1750 .parse::<ConvertedType>()
1751 .unwrap(),
1752 ConvertedType::DECIMAL
1753 )
1754 }
1755
1756 #[test]
1757 fn test_logical_to_converted_type() {
1758 let logical_none: Option<LogicalType> = None;
1759 assert_eq!(ConvertedType::from(logical_none), ConvertedType::NONE);
1760 assert_eq!(
1761 ConvertedType::from(Some(LogicalType::decimal(5, 20))),
1762 ConvertedType::DECIMAL
1763 );
1764 assert_eq!(
1765 ConvertedType::from(Some(LogicalType::Bson)),
1766 ConvertedType::BSON
1767 );
1768 assert_eq!(
1769 ConvertedType::from(Some(LogicalType::Json)),
1770 ConvertedType::JSON
1771 );
1772 assert_eq!(
1773 ConvertedType::from(Some(LogicalType::String)),
1774 ConvertedType::UTF8
1775 );
1776 assert_eq!(
1777 ConvertedType::from(Some(LogicalType::Date)),
1778 ConvertedType::DATE
1779 );
1780 assert_eq!(
1781 ConvertedType::from(Some(LogicalType::time(true, TimeUnit::MILLIS))),
1782 ConvertedType::TIME_MILLIS
1783 );
1784 assert_eq!(
1785 ConvertedType::from(Some(LogicalType::time(true, TimeUnit::MICROS))),
1786 ConvertedType::TIME_MICROS
1787 );
1788 assert_eq!(
1789 ConvertedType::from(Some(LogicalType::time(false, TimeUnit::NANOS))),
1790 ConvertedType::NONE
1791 );
1792 assert_eq!(
1793 ConvertedType::from(Some(LogicalType::timestamp(true, TimeUnit::MILLIS))),
1794 ConvertedType::TIMESTAMP_MILLIS
1795 );
1796 assert_eq!(
1797 ConvertedType::from(Some(LogicalType::timestamp(false, TimeUnit::MICROS))),
1798 ConvertedType::TIMESTAMP_MICROS
1799 );
1800 assert_eq!(
1801 ConvertedType::from(Some(LogicalType::timestamp(false, TimeUnit::NANOS))),
1802 ConvertedType::NONE
1803 );
1804 assert_eq!(
1805 ConvertedType::from(Some(LogicalType::integer(8, false))),
1806 ConvertedType::UINT_8
1807 );
1808 assert_eq!(
1809 ConvertedType::from(Some(LogicalType::integer(8, true))),
1810 ConvertedType::INT_8
1811 );
1812 assert_eq!(
1813 ConvertedType::from(Some(LogicalType::integer(16, false))),
1814 ConvertedType::UINT_16
1815 );
1816 assert_eq!(
1817 ConvertedType::from(Some(LogicalType::integer(16, true))),
1818 ConvertedType::INT_16
1819 );
1820 assert_eq!(
1821 ConvertedType::from(Some(LogicalType::integer(32, false))),
1822 ConvertedType::UINT_32
1823 );
1824 assert_eq!(
1825 ConvertedType::from(Some(LogicalType::integer(32, true))),
1826 ConvertedType::INT_32
1827 );
1828 assert_eq!(
1829 ConvertedType::from(Some(LogicalType::integer(64, false))),
1830 ConvertedType::UINT_64
1831 );
1832 assert_eq!(
1833 ConvertedType::from(Some(LogicalType::integer(64, true))),
1834 ConvertedType::INT_64
1835 );
1836 assert_eq!(
1837 ConvertedType::from(Some(LogicalType::List)),
1838 ConvertedType::LIST
1839 );
1840 assert_eq!(
1841 ConvertedType::from(Some(LogicalType::Map)),
1842 ConvertedType::MAP
1843 );
1844 assert_eq!(
1845 ConvertedType::from(Some(LogicalType::Uuid)),
1846 ConvertedType::NONE
1847 );
1848 assert_eq!(
1849 ConvertedType::from(Some(LogicalType::Enum)),
1850 ConvertedType::ENUM
1851 );
1852 assert_eq!(
1853 ConvertedType::from(Some(LogicalType::Float16)),
1854 ConvertedType::NONE
1855 );
1856 assert_eq!(
1857 ConvertedType::from(Some(LogicalType::variant(None))),
1858 ConvertedType::NONE
1859 );
1860 assert_eq!(
1861 ConvertedType::from(Some(LogicalType::geometry(None))),
1862 ConvertedType::NONE
1863 );
1864 assert_eq!(
1865 ConvertedType::from(Some(LogicalType::geography(None, Some(Default::default())))),
1866 ConvertedType::NONE
1867 );
1868 assert_eq!(
1869 ConvertedType::from(Some(LogicalType::Unknown)),
1870 ConvertedType::NONE
1871 );
1872 }
1873
1874 #[test]
1875 fn test_logical_type_roundtrip() {
1876 test_roundtrip(LogicalType::String);
1877 test_roundtrip(LogicalType::Map);
1878 test_roundtrip(LogicalType::List);
1879 test_roundtrip(LogicalType::Enum);
1880 test_roundtrip(LogicalType::decimal(0, 20));
1881 test_roundtrip(LogicalType::Date);
1882 test_roundtrip(LogicalType::time(true, TimeUnit::MICROS));
1883 test_roundtrip(LogicalType::time(false, TimeUnit::MILLIS));
1884 test_roundtrip(LogicalType::time(false, TimeUnit::NANOS));
1885 test_roundtrip(LogicalType::timestamp(false, TimeUnit::MICROS));
1886 test_roundtrip(LogicalType::timestamp(true, TimeUnit::MILLIS));
1887 test_roundtrip(LogicalType::timestamp(true, TimeUnit::NANOS));
1888 test_roundtrip(LogicalType::integer(8, true));
1889 test_roundtrip(LogicalType::integer(16, false));
1890 test_roundtrip(LogicalType::integer(32, true));
1891 test_roundtrip(LogicalType::integer(64, false));
1892 test_roundtrip(LogicalType::Json);
1893 test_roundtrip(LogicalType::Bson);
1894 test_roundtrip(LogicalType::Uuid);
1895 test_roundtrip(LogicalType::Float16);
1896 test_roundtrip(LogicalType::variant(Some(1)));
1897 test_roundtrip(LogicalType::variant(None));
1898 test_roundtrip(LogicalType::geometry(Some("foo".to_owned())));
1899 test_roundtrip(LogicalType::geometry(None));
1900 test_roundtrip(LogicalType::geography(
1901 Some("foo".to_owned()),
1902 Some(EdgeInterpolationAlgorithm::ANDOYER),
1903 ));
1904 test_roundtrip(LogicalType::geography(
1905 None,
1906 Some(EdgeInterpolationAlgorithm::KARNEY),
1907 ));
1908 test_roundtrip(LogicalType::geography(
1909 Some("foo".to_owned()),
1910 Some(EdgeInterpolationAlgorithm::SPHERICAL),
1911 ));
1912 test_roundtrip(LogicalType::geography(
1913 None,
1914 Some(EdgeInterpolationAlgorithm::SPHERICAL),
1915 ));
1916 }
1917
1918 #[test]
1919 fn test_display_repetition() {
1920 assert_eq!(Repetition::REQUIRED.to_string(), "REQUIRED");
1921 assert_eq!(Repetition::OPTIONAL.to_string(), "OPTIONAL");
1922 assert_eq!(Repetition::REPEATED.to_string(), "REPEATED");
1923 }
1924
1925 #[test]
1926 fn test_from_string_into_repetition() {
1927 assert_eq!(
1928 Repetition::REQUIRED
1929 .to_string()
1930 .parse::<Repetition>()
1931 .unwrap(),
1932 Repetition::REQUIRED
1933 );
1934 assert_eq!(
1935 Repetition::OPTIONAL
1936 .to_string()
1937 .parse::<Repetition>()
1938 .unwrap(),
1939 Repetition::OPTIONAL
1940 );
1941 assert_eq!(
1942 Repetition::REPEATED
1943 .to_string()
1944 .parse::<Repetition>()
1945 .unwrap(),
1946 Repetition::REPEATED
1947 );
1948 }
1949
1950 #[test]
1951 fn test_display_encoding() {
1952 assert_eq!(Encoding::PLAIN.to_string(), "PLAIN");
1953 assert_eq!(Encoding::PLAIN_DICTIONARY.to_string(), "PLAIN_DICTIONARY");
1954 assert_eq!(Encoding::RLE.to_string(), "RLE");
1955 assert_eq!(Encoding::BIT_PACKED.to_string(), "BIT_PACKED");
1956 assert_eq!(
1957 Encoding::DELTA_BINARY_PACKED.to_string(),
1958 "DELTA_BINARY_PACKED"
1959 );
1960 assert_eq!(
1961 Encoding::DELTA_LENGTH_BYTE_ARRAY.to_string(),
1962 "DELTA_LENGTH_BYTE_ARRAY"
1963 );
1964 assert_eq!(Encoding::DELTA_BYTE_ARRAY.to_string(), "DELTA_BYTE_ARRAY");
1965 assert_eq!(Encoding::RLE_DICTIONARY.to_string(), "RLE_DICTIONARY");
1966 assert_eq!(Encoding::ALP.to_string(), "ALP");
1967 }
1968
1969 #[test]
1970 fn test_compression_conversion() {
1971 assert_eq!(
1972 CompressionCodec::from(Compression::UNCOMPRESSED),
1973 CompressionCodec::UNCOMPRESSED
1974 );
1975 assert_eq!(
1976 CompressionCodec::from(Compression::SNAPPY),
1977 CompressionCodec::SNAPPY
1978 );
1979 assert_eq!(
1980 CompressionCodec::from(Compression::GZIP(Default::default())),
1981 CompressionCodec::GZIP
1982 );
1983 assert_eq!(
1984 CompressionCodec::from(Compression::LZO),
1985 CompressionCodec::LZO
1986 );
1987 assert_eq!(
1988 CompressionCodec::from(Compression::BROTLI(Default::default())),
1989 CompressionCodec::BROTLI
1990 );
1991 assert_eq!(
1992 CompressionCodec::from(Compression::LZ4),
1993 CompressionCodec::LZ4
1994 );
1995 assert_eq!(
1996 CompressionCodec::from(Compression::ZSTD(Default::default())),
1997 CompressionCodec::ZSTD
1998 );
1999 assert_eq!(
2000 CompressionCodec::from(Compression::LZ4_RAW),
2001 CompressionCodec::LZ4_RAW
2002 );
2003
2004 assert_eq!(
2005 Compression::from(CompressionCodec::UNCOMPRESSED),
2006 Compression::UNCOMPRESSED
2007 );
2008 assert_eq!(
2009 Compression::from(CompressionCodec::SNAPPY),
2010 Compression::SNAPPY
2011 );
2012 assert_eq!(
2013 Compression::from(CompressionCodec::GZIP),
2014 Compression::GZIP(Default::default())
2015 );
2016 assert_eq!(Compression::from(CompressionCodec::LZO), Compression::LZO);
2017 assert_eq!(
2018 Compression::from(CompressionCodec::BROTLI),
2019 Compression::BROTLI(Default::default())
2020 );
2021 assert_eq!(Compression::from(CompressionCodec::LZ4), Compression::LZ4);
2022 assert_eq!(
2023 Compression::from(CompressionCodec::ZSTD),
2024 Compression::ZSTD(Default::default())
2025 );
2026 assert_eq!(
2027 Compression::from(CompressionCodec::LZ4_RAW),
2028 Compression::LZ4_RAW
2029 );
2030 }
2031
2032 #[test]
2033 fn test_display_compression() {
2034 assert_eq!(Compression::UNCOMPRESSED.to_string(), "UNCOMPRESSED");
2035 assert_eq!(Compression::SNAPPY.to_string(), "SNAPPY");
2036 assert_eq!(
2037 Compression::GZIP(Default::default()).to_string(),
2038 "GZIP(GzipLevel(6))"
2039 );
2040 assert_eq!(Compression::LZO.to_string(), "LZO");
2041 assert_eq!(
2042 Compression::BROTLI(Default::default()).to_string(),
2043 "BROTLI(BrotliLevel(1))"
2044 );
2045 assert_eq!(Compression::LZ4.to_string(), "LZ4");
2046 assert_eq!(
2047 Compression::ZSTD(Default::default()).to_string(),
2048 "ZSTD(ZstdLevel(1))"
2049 );
2050 }
2051
2052 #[test]
2053 fn test_display_page_type() {
2054 assert_eq!(PageType::DATA_PAGE.to_string(), "DATA_PAGE");
2055 assert_eq!(PageType::INDEX_PAGE.to_string(), "INDEX_PAGE");
2056 assert_eq!(PageType::DICTIONARY_PAGE.to_string(), "DICTIONARY_PAGE");
2057 assert_eq!(PageType::DATA_PAGE_V2.to_string(), "DATA_PAGE_V2");
2058 }
2059
2060 #[test]
2061 fn test_display_sort_order() {
2062 assert_eq!(SortOrder::SIGNED.to_string(), "SIGNED");
2063 assert_eq!(SortOrder::UNSIGNED.to_string(), "UNSIGNED");
2064 assert_eq!(SortOrder::UNDEFINED.to_string(), "UNDEFINED");
2065 assert_eq!(SortOrder::TOTAL_ORDER.to_string(), "TOTAL_ORDER");
2066 assert_eq!(SortOrder::INT96_TIMESTAMP.to_string(), "INT96_TIMESTAMP");
2067 }
2068
2069 #[test]
2070 fn test_display_column_order() {
2071 assert_eq!(
2072 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED).to_string(),
2073 "TYPE_DEFINED_ORDER(SIGNED)"
2074 );
2075 assert_eq!(
2076 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNSIGNED).to_string(),
2077 "TYPE_DEFINED_ORDER(UNSIGNED)"
2078 );
2079 assert_eq!(
2080 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNDEFINED).to_string(),
2081 "TYPE_DEFINED_ORDER(UNDEFINED)"
2082 );
2083 assert_eq!(
2084 ColumnOrder::IEEE_754_TOTAL_ORDER.to_string(),
2085 "IEEE_754_TOTAL_ORDER"
2086 );
2087 assert_eq!(
2088 ColumnOrder::INT96_TIMESTAMP_ORDER.to_string(),
2089 "INT96_TIMESTAMP_ORDER"
2090 );
2091 assert_eq!(ColumnOrder::UNDEFINED.to_string(), "UNDEFINED");
2092 }
2093
2094 #[test]
2095 fn test_column_order_roundtrip() {
2096 test_roundtrip(ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED))
2098 }
2099
2100 #[test]
2101 fn test_column_order_get_logical_type_sort_order() {
2102 fn check_sort_order(types: Vec<LogicalType>, expected_order: SortOrder) {
2105 for type_ in types {
2106 assert_eq!(
2107 ColumnOrder::column_order_for_type(
2108 Some(&type_),
2109 ConvertedType::NONE,
2110 Type::BYTE_ARRAY
2111 )
2112 .sort_order(),
2113 expected_order
2114 );
2115 }
2116 }
2117
2118 let unsigned = vec![
2120 LogicalType::String,
2121 LogicalType::Json,
2122 LogicalType::Bson,
2123 LogicalType::Enum,
2124 LogicalType::Uuid,
2125 LogicalType::integer(8, false),
2126 LogicalType::integer(16, false),
2127 LogicalType::integer(32, false),
2128 LogicalType::integer(64, false),
2129 ];
2130 check_sort_order(unsigned, SortOrder::UNSIGNED);
2131
2132 let signed = vec![
2134 LogicalType::integer(8, true),
2135 LogicalType::integer(16, true),
2136 LogicalType::integer(32, true),
2137 LogicalType::integer(64, true),
2138 LogicalType::decimal(20, 4),
2139 LogicalType::Date,
2140 LogicalType::time(false, TimeUnit::MILLIS),
2141 LogicalType::time(false, TimeUnit::MICROS),
2142 LogicalType::time(true, TimeUnit::NANOS),
2143 LogicalType::timestamp(false, TimeUnit::MILLIS),
2144 LogicalType::timestamp(false, TimeUnit::MICROS),
2145 LogicalType::timestamp(true, TimeUnit::NANOS),
2146 ];
2147 check_sort_order(signed, SortOrder::SIGNED);
2148
2149 let float = vec![LogicalType::Float16];
2150 check_sort_order(float, SortOrder::TOTAL_ORDER);
2151
2152 let undefined = vec![
2154 LogicalType::List,
2155 LogicalType::Map,
2156 LogicalType::variant(None),
2157 LogicalType::geometry(None),
2158 LogicalType::geography(None, Some(Default::default())),
2159 ];
2160 check_sort_order(undefined, SortOrder::UNDEFINED);
2161 }
2162
2163 #[test]
2164 fn test_column_order_get_converted_type_sort_order() {
2165 fn check_sort_order(types: Vec<ConvertedType>, expected_order: SortOrder) {
2168 for type_ in types {
2169 assert_eq!(
2170 ColumnOrder::column_order_for_type(None, type_, Type::BYTE_ARRAY).sort_order(),
2171 expected_order
2172 );
2173 }
2174 }
2175
2176 let unsigned = vec![
2178 ConvertedType::UTF8,
2179 ConvertedType::JSON,
2180 ConvertedType::BSON,
2181 ConvertedType::ENUM,
2182 ConvertedType::UINT_8,
2183 ConvertedType::UINT_16,
2184 ConvertedType::UINT_32,
2185 ConvertedType::UINT_64,
2186 ];
2187 check_sort_order(unsigned, SortOrder::UNSIGNED);
2188
2189 let signed = vec![
2191 ConvertedType::INT_8,
2192 ConvertedType::INT_16,
2193 ConvertedType::INT_32,
2194 ConvertedType::INT_64,
2195 ConvertedType::DECIMAL,
2196 ConvertedType::DATE,
2197 ConvertedType::TIME_MILLIS,
2198 ConvertedType::TIME_MICROS,
2199 ConvertedType::TIMESTAMP_MILLIS,
2200 ConvertedType::TIMESTAMP_MICROS,
2201 ];
2202 check_sort_order(signed, SortOrder::SIGNED);
2203
2204 let undefined = vec![
2206 ConvertedType::LIST,
2207 ConvertedType::MAP,
2208 ConvertedType::MAP_KEY_VALUE,
2209 ConvertedType::INTERVAL,
2210 ];
2211 check_sort_order(undefined, SortOrder::UNDEFINED);
2212
2213 check_sort_order(vec![ConvertedType::NONE], SortOrder::UNSIGNED);
2216 }
2217
2218 #[test]
2219 fn test_column_order_get_default_sort_order() {
2220 assert_eq!(
2222 ColumnOrder::get_default_sort_order(Type::BOOLEAN, true),
2223 SortOrder::UNSIGNED
2224 );
2225 assert_eq!(
2226 ColumnOrder::get_default_sort_order(Type::INT32, true),
2227 SortOrder::SIGNED
2228 );
2229 assert_eq!(
2230 ColumnOrder::get_default_sort_order(Type::INT64, true),
2231 SortOrder::SIGNED
2232 );
2233 assert_eq!(
2234 ColumnOrder::get_default_sort_order(Type::INT96, true),
2235 SortOrder::UNDEFINED
2236 );
2237 assert_eq!(
2238 ColumnOrder::get_default_sort_order(Type::INT96, false),
2239 SortOrder::INT96_TIMESTAMP
2240 );
2241 assert_eq!(
2242 ColumnOrder::get_default_sort_order(Type::FLOAT, false),
2243 SortOrder::TOTAL_ORDER
2244 );
2245 assert_eq!(
2246 ColumnOrder::get_default_sort_order(Type::DOUBLE, false),
2247 SortOrder::TOTAL_ORDER
2248 );
2249 assert_eq!(
2250 ColumnOrder::get_default_sort_order(Type::FLOAT, true),
2251 SortOrder::SIGNED
2252 );
2253 assert_eq!(
2254 ColumnOrder::get_default_sort_order(Type::DOUBLE, true),
2255 SortOrder::SIGNED
2256 );
2257 assert_eq!(
2258 ColumnOrder::get_default_sort_order(Type::BYTE_ARRAY, true),
2259 SortOrder::UNSIGNED
2260 );
2261 assert_eq!(
2262 ColumnOrder::get_default_sort_order(Type::FIXED_LEN_BYTE_ARRAY, true),
2263 SortOrder::UNSIGNED
2264 );
2265 }
2266
2267 #[test]
2268 fn test_column_order_sort_order() {
2269 assert_eq!(
2270 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED).sort_order(),
2271 SortOrder::SIGNED
2272 );
2273 assert_eq!(
2274 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNSIGNED).sort_order(),
2275 SortOrder::UNSIGNED
2276 );
2277 assert_eq!(
2278 ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNDEFINED).sort_order(),
2279 SortOrder::UNDEFINED
2280 );
2281 assert_eq!(
2282 ColumnOrder::IEEE_754_TOTAL_ORDER.sort_order(),
2283 SortOrder::TOTAL_ORDER
2284 );
2285 assert_eq!(
2286 ColumnOrder::INT96_TIMESTAMP_ORDER.sort_order(),
2287 SortOrder::INT96_TIMESTAMP
2288 );
2289 assert_eq!(ColumnOrder::UNDEFINED.sort_order(), SortOrder::SIGNED);
2290 }
2291
2292 #[test]
2293 fn test_parse_encoding() {
2294 let mut encoding: Encoding = "PLAIN".parse().unwrap();
2295 assert_eq!(encoding, Encoding::PLAIN);
2296 encoding = "PLAIN_DICTIONARY".parse().unwrap();
2297 assert_eq!(encoding, Encoding::PLAIN_DICTIONARY);
2298 encoding = "RLE".parse().unwrap();
2299 assert_eq!(encoding, Encoding::RLE);
2300 encoding = "BIT_PACKED".parse().unwrap();
2301 assert_eq!(encoding, Encoding::BIT_PACKED);
2302 encoding = "DELTA_BINARY_PACKED".parse().unwrap();
2303 assert_eq!(encoding, Encoding::DELTA_BINARY_PACKED);
2304 encoding = "DELTA_LENGTH_BYTE_ARRAY".parse().unwrap();
2305 assert_eq!(encoding, Encoding::DELTA_LENGTH_BYTE_ARRAY);
2306 encoding = "DELTA_BYTE_ARRAY".parse().unwrap();
2307 assert_eq!(encoding, Encoding::DELTA_BYTE_ARRAY);
2308 encoding = "RLE_DICTIONARY".parse().unwrap();
2309 assert_eq!(encoding, Encoding::RLE_DICTIONARY);
2310 encoding = "BYTE_STREAM_SPLIT".parse().unwrap();
2311 assert_eq!(encoding, Encoding::BYTE_STREAM_SPLIT);
2312 encoding = "alp".parse().unwrap();
2313 assert_eq!(encoding, Encoding::ALP);
2314
2315 encoding = "byte_stream_split".parse().unwrap();
2317 assert_eq!(encoding, Encoding::BYTE_STREAM_SPLIT);
2318
2319 match "plain_xxx".parse::<Encoding>() {
2321 Ok(e) => {
2322 panic!("Should not be able to parse {e:?}");
2323 }
2324 Err(e) => {
2325 assert_eq!(e.to_string(), "Parquet error: unknown encoding: plain_xxx");
2326 }
2327 }
2328 }
2329
2330 #[test]
2331 fn test_parse_compression() {
2332 let mut compress: Compression = "snappy".parse().unwrap();
2333 assert_eq!(compress, Compression::SNAPPY);
2334 compress = "lzo".parse().unwrap();
2335 assert_eq!(compress, Compression::LZO);
2336 compress = "zstd(3)".parse().unwrap();
2337 assert_eq!(compress, Compression::ZSTD(ZstdLevel::try_new(3).unwrap()));
2338 compress = "zstd(-3)".parse().unwrap();
2339 assert_eq!(compress, Compression::ZSTD(ZstdLevel::try_new(-3).unwrap()));
2340 compress = "LZ4_RAW".parse().unwrap();
2341 assert_eq!(compress, Compression::LZ4_RAW);
2342 compress = "uncompressed".parse().unwrap();
2343 assert_eq!(compress, Compression::UNCOMPRESSED);
2344 compress = "snappy".parse().unwrap();
2345 assert_eq!(compress, Compression::SNAPPY);
2346 compress = "gzip(9)".parse().unwrap();
2347 assert_eq!(compress, Compression::GZIP(GzipLevel::try_new(9).unwrap()));
2348 compress = "lzo".parse().unwrap();
2349 assert_eq!(compress, Compression::LZO);
2350 compress = "brotli(3)".parse().unwrap();
2351 assert_eq!(
2352 compress,
2353 Compression::BROTLI(BrotliLevel::try_new(3).unwrap())
2354 );
2355 compress = "lz4".parse().unwrap();
2356 assert_eq!(compress, Compression::LZ4);
2357
2358 let mut err = "plain_xxx".parse::<Encoding>().unwrap_err();
2360 assert_eq!(
2361 err.to_string(),
2362 "Parquet error: unknown encoding: plain_xxx"
2363 );
2364
2365 err = "gzip(-10)".parse::<Encoding>().unwrap_err();
2367 assert_eq!(
2368 err.to_string(),
2369 "Parquet error: unknown encoding: gzip(-10)"
2370 );
2371 }
2372
2373 #[test]
2374 fn test_display_boundary_order() {
2375 assert_eq!(BoundaryOrder::ASCENDING.to_string(), "ASCENDING");
2376 assert_eq!(BoundaryOrder::DESCENDING.to_string(), "DESCENDING");
2377 assert_eq!(BoundaryOrder::UNORDERED.to_string(), "UNORDERED");
2378 }
2379
2380 #[test]
2381 fn test_display_edge_algo() {
2382 assert_eq!(
2383 EdgeInterpolationAlgorithm::SPHERICAL.to_string(),
2384 "SPHERICAL"
2385 );
2386 assert_eq!(EdgeInterpolationAlgorithm::VINCENTY.to_string(), "VINCENTY");
2387 assert_eq!(EdgeInterpolationAlgorithm::THOMAS.to_string(), "THOMAS");
2388 assert_eq!(EdgeInterpolationAlgorithm::ANDOYER.to_string(), "ANDOYER");
2389 assert_eq!(EdgeInterpolationAlgorithm::KARNEY.to_string(), "KARNEY");
2390 }
2391
2392 #[test]
2393 fn test_from_str_edge_algo() {
2394 assert_eq!(
2395 "spHErical".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2396 EdgeInterpolationAlgorithm::SPHERICAL
2397 );
2398 assert_eq!(
2399 "vinceNTY".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2400 EdgeInterpolationAlgorithm::VINCENTY
2401 );
2402 assert_eq!(
2403 "tHOmas".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2404 EdgeInterpolationAlgorithm::THOMAS
2405 );
2406 assert_eq!(
2407 "anDOYEr".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2408 EdgeInterpolationAlgorithm::ANDOYER
2409 );
2410 assert_eq!(
2411 "kaRNey".parse::<EdgeInterpolationAlgorithm>().unwrap(),
2412 EdgeInterpolationAlgorithm::KARNEY
2413 );
2414 assert!(
2415 "does not exist"
2416 .parse::<EdgeInterpolationAlgorithm>()
2417 .is_err()
2418 );
2419 }
2420
2421 fn encodings_roundtrip(mut encodings: Vec<Encoding>) {
2422 encodings.sort();
2423 let mask = EncodingMask::new_from_encodings(encodings.iter());
2424 assert!(mask.all_set(encodings.iter()));
2425 let v = mask.encodings().collect::<Vec<_>>();
2426 assert_eq!(v, encodings);
2427 }
2428
2429 #[test]
2430 fn test_encoding_roundtrip() {
2431 encodings_roundtrip(
2432 [
2433 Encoding::RLE,
2434 Encoding::PLAIN,
2435 Encoding::DELTA_BINARY_PACKED,
2436 ]
2437 .into(),
2438 );
2439 encodings_roundtrip([Encoding::RLE_DICTIONARY, Encoding::PLAIN_DICTIONARY].into());
2440 encodings_roundtrip([].into());
2441 let encodings = [
2442 Encoding::PLAIN,
2443 Encoding::BIT_PACKED,
2444 Encoding::RLE,
2445 Encoding::DELTA_BINARY_PACKED,
2446 Encoding::DELTA_BYTE_ARRAY,
2447 Encoding::DELTA_LENGTH_BYTE_ARRAY,
2448 Encoding::PLAIN_DICTIONARY,
2449 Encoding::RLE_DICTIONARY,
2450 Encoding::BYTE_STREAM_SPLIT,
2451 Encoding::ALP,
2452 ];
2453 encodings_roundtrip(encodings.into());
2454 }
2455
2456 #[test]
2457 fn test_invalid_encoding_mask() {
2458 let res = EncodingMask::try_new(-1);
2460 assert!(res.is_err());
2461 let err = res.unwrap_err();
2462 assert_eq!(
2463 err.to_string(),
2464 "Parquet error: Attempt to create invalid mask: 0xffffffff"
2465 );
2466
2467 let res = EncodingMask::try_new(2);
2469 assert!(res.is_err());
2470 let err = res.unwrap_err();
2471 assert_eq!(
2472 err.to_string(),
2473 "Parquet error: Attempt to create invalid mask: 0x2"
2474 );
2475 }
2476
2477 #[test]
2478 fn test_encoding_mask_is_only() {
2479 let mask = EncodingMask::new_from_encodings([Encoding::PLAIN].iter());
2480 assert!(mask.is_only(Encoding::PLAIN));
2481
2482 let mask =
2483 EncodingMask::new_from_encodings([Encoding::PLAIN, Encoding::PLAIN_DICTIONARY].iter());
2484 assert!(!mask.is_only(Encoding::PLAIN));
2485 }
2486}