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