packages feed

dataframe-1.3.0.0: src/DataFrame/IO/Parquet/Thrift.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeFamilies #-}

module DataFrame.IO.Parquet.Thrift where

import Data.ByteString (ByteString)
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Text (Text)
import GHC.Generics (Generic)
import GHC.TypeLits (KnownNat)
import Pinch (Enumeration, Field, Pinchable (..))
import qualified Pinch

-- Primitive Parquet Types
-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L32
data ThriftType
    = BOOLEAN (Enumeration 0)
    | INT32 (Enumeration 1)
    | INT64 (Enumeration 2)
    | INT96 (Enumeration 3)
    | FLOAT (Enumeration 4)
    | DOUBLE (Enumeration 5)
    | BYTE_ARRAY (Enumeration 6)
    | FIXED_LEN_BYTE_ARRAY (Enumeration 7)
    deriving (Eq, Show, Generic)

instance Pinchable ThriftType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L183
data FieldRepetitionType
    = REQUIRED (Enumeration 0)
    | OPTIONAL (Enumeration 1)
    | REPEATED (Enumeration 2)
    deriving (Eq, Show, Generic)

instance Pinchable FieldRepetitionType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L203
data Encoding
    = PLAIN (Enumeration 0)
    | -- GROUP_VAR_INT Encoding was never used
      -- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L578
      PLAIN_DICTIONARY (Enumeration 2)
    | RLE (Enumeration 3)
    | BIT_PACKED (Enumeration 4)
    | DELTA_BINARY_PACKED (Enumeration 5)
    | DELTA_LENGTH_BYTE_ARRAY (Enumeration 6)
    | DELTA_BYTE_ARRAY (Enumeration 7)
    | RLE_DICTIONARY (Enumeration 8)
    | BYTE_STREAM_SPLIT (Enumeration 9)
    deriving (Eq, Show, Generic)

instance Pinchable Encoding

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L244
data CompressionCodec
    = UNCOMPRESSED (Enumeration 0)
    | SNAPPY (Enumeration 1)
    | GZIP (Enumeration 2)
    | LZO (Enumeration 3)
    | BROTLI (Enumeration 4)
    | LZ4 (Enumeration 5)
    | ZSTD (Enumeration 6)
    | LZ4_RAW (Enumeration 7)
    deriving (Eq, Show, Generic)

instance Pinchable CompressionCodec

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L261
data PageType
    = DATA_PAGE (Enumeration 0)
    | INDEX_PAGE (Enumeration 1)
    | DICTIONARY_PAGE (Enumeration 2)
    | DATA_PAGE_V2 (Enumeration 3)
    deriving (Eq, Show, Generic)

instance Pinchable PageType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L271
data BoundaryOrder
    = UNORDERED (Enumeration 0)
    | ASCENDING (Enumeration 1)
    | DESCENDING (Enumeration 2)
    deriving (Eq, Show, Generic)

instance Pinchable BoundaryOrder

-- Logical type annotations
-- Empty structs can't use deriving Generic with Pinch, so we use a unit-like workaround.
-- We represent empty structs as a newtype over () with a manual Pinchable instance.

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L283
-- struct StringType {}
data StringType = StringType deriving (Eq, Show)
instance Pinchable StringType where
    type Tag StringType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure StringType

data UUIDType = UUIDType deriving (Eq, Show)
instance Pinchable UUIDType where
    type Tag UUIDType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure UUIDType

data MapType = MapType deriving (Eq, Show)
instance Pinchable MapType where
    type Tag MapType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure MapType

data ListType = ListType deriving (Eq, Show)
instance Pinchable ListType where
    type Tag ListType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure ListType

data EnumType = EnumType deriving (Eq, Show)
instance Pinchable EnumType where
    type Tag EnumType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure EnumType

data DateType = DateType deriving (Eq, Show)
instance Pinchable DateType where
    type Tag DateType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure DateType

data Float16Type = Float16Type deriving (Eq, Show)
instance Pinchable Float16Type where
    type Tag Float16Type = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure Float16Type

data NullType = NullType deriving (Eq, Show)
instance Pinchable NullType where
    type Tag NullType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure NullType

data JsonType = JsonType deriving (Eq, Show)
instance Pinchable JsonType where
    type Tag JsonType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure JsonType

data BsonType = BsonType deriving (Eq, Show)
instance Pinchable BsonType where
    type Tag BsonType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure BsonType

data VariantType = VariantType deriving (Eq, Show)
instance Pinchable VariantType where
    type Tag VariantType = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure VariantType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L290
data TimeUnit
    = MILLIS (Field 1 MilliSeconds)
    | MICROS (Field 2 MicroSeconds)
    | NANOS (Field 3 NanoSeconds)
    deriving (Eq, Show, Generic)

instance Pinchable TimeUnit

data MilliSeconds = MilliSeconds deriving (Eq, Show)
instance Pinchable MilliSeconds where
    type Tag MilliSeconds = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure MilliSeconds

data MicroSeconds = MicroSeconds deriving (Eq, Show)
instance Pinchable MicroSeconds where
    type Tag MicroSeconds = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure MicroSeconds

data NanoSeconds = NanoSeconds deriving (Eq, Show)
instance Pinchable NanoSeconds where
    type Tag NanoSeconds = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure NanoSeconds

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L317
data DecimalType
    = DecimalType
    { decimal_scale :: Field 1 Int32
    , decimal_precision :: Field 2 Int32
    }
    deriving (Eq, Show, Generic)

instance Pinchable DecimalType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L328
data IntType
    = IntType
    { int_bitWidth :: Field 1 Int8
    , int_isSigned :: Field 2 Bool
    }
    deriving (Eq, Show, Generic)

instance Pinchable IntType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L338
data TimeType
    = TimeType
    { time_isAdjustedToUTC :: Field 1 Bool
    , time_unit :: Field 2 TimeUnit
    }
    deriving (Eq, Show, Generic)

instance Pinchable TimeType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L349
data TimestampType
    = TimestampType
    { timestamp_isAdjustedToUTC :: Field 1 Bool
    , timestamp_unit :: Field 2 TimeUnit
    }
    deriving (Eq, Show, Generic)

instance Pinchable TimestampType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L360
-- union LogicalType
data LogicalType
    = LT_STRING (Field 1 StringType)
    | LT_MAP (Field 2 MapType)
    | LT_LIST (Field 3 ListType)
    | LT_ENUM (Field 4 EnumType)
    | LT_DECIMAL (Field 5 DecimalType)
    | LT_DATE (Field 6 DateType)
    | LT_TIME (Field 7 TimeType)
    | LT_TIMESTAMP (Field 8 TimestampType)
    | LT_INTEGER (Field 10 IntType)
    | LT_NULL (Field 11 NullType)
    | LT_JSON (Field 12 JsonType)
    | LT_BSON (Field 13 BsonType)
    | LT_UUID (Field 14 UUIDType)
    | LT_FLOAT16 (Field 15 Float16Type)
    | LT_VARIANT (Field 16 VariantType)
    deriving (Eq, Show, Generic)

instance Pinchable LogicalType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L270
data ConvertedType
    = UTF8 (Enumeration 0)
    | MAP (Enumeration 1)
    | MAP_KEY_VALUE (Enumeration 2)
    | LIST (Enumeration 3)
    | ENUM (Enumeration 4)
    | DECIMAL (Enumeration 5)
    | DATE (Enumeration 6)
    | TIME_MILLIS (Enumeration 7)
    | TIME_MICROS (Enumeration 8)
    | TIMESTAMP_MILLIS (Enumeration 9)
    | TIMESTAMP_MICROS (Enumeration 10)
    | UINT_8 (Enumeration 11)
    | UINT_16 (Enumeration 12)
    | UINT_32 (Enumeration 13)
    | UINT_64 (Enumeration 14)
    | INT_8 (Enumeration 15)
    | INT_16 (Enumeration 16)
    | INT_32 (Enumeration 17)
    | INT_64 (Enumeration 18)
    | JSON (Enumeration 19)
    | BSON (Enumeration 20)
    | INTERVAL (Enumeration 21)
    deriving (Eq, Show, Generic)

instance Pinchable ConvertedType

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L505
data SchemaElement
    = SchemaElement
    { schematype :: Field 1 (Maybe ThriftType) -- called just type in parquet.thrift
    , type_length :: Field 2 (Maybe Int32)
    , repetition_type :: Field 3 (Maybe FieldRepetitionType)
    , name :: Field 4 Text
    , num_children :: Field 5 (Maybe Int32)
    , converted_type :: Field 6 (Maybe ConvertedType)
    , scale :: Field 7 (Maybe Int32)
    , precision :: Field 8 (Maybe Int32)
    , field_id :: Field 9 (Maybe Int32)
    , logicalType :: Field 10 (Maybe LogicalType)
    }
    deriving (Eq, Show, Generic)

instance Pinchable SchemaElement

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L560
data Statistics
    = Statistics
    { stats_max :: Field 1 (Maybe ByteString)
    , stats_min :: Field 2 (Maybe ByteString)
    , stats_null_count :: Field 3 (Maybe Int64)
    , stats_distinct_count :: Field 4 (Maybe Int64)
    , stats_max_value :: Field 5 (Maybe ByteString)
    , stats_min_value :: Field 6 (Maybe ByteString)
    , stats_is_max_value_exact :: Field 7 (Maybe Bool)
    , stats_is_min_value_exact :: Field 8 (Maybe Bool)
    }
    deriving (Eq, Show, Generic)

instance Pinchable Statistics

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L600
data PageEncodingStats
    = PageEncodingStats
    { pes_page_type :: Field 1 PageType
    , pes_encoding :: Field 2 Encoding
    , pes_count :: Field 3 Int32
    }
    deriving (Eq, Show, Generic)

instance Pinchable PageEncodingStats

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L614
data ColumnMetaData
    = ColumnMetaData
    { cmd_type :: Field 1 ThriftType
    , cmd_encodings :: Field 2 [Encoding]
    , cmd_path_in_schema :: Field 3 [Text]
    , cmd_codec :: Field 4 CompressionCodec
    , cmd_num_values :: Field 5 Int64
    , cmd_total_uncompressed_size :: Field 6 Int64
    , cmd_total_compressed_size :: Field 7 Int64
    , cmd_key_value_metadata :: Field 8 (Maybe [KeyValue])
    , cmd_data_page_offset :: Field 9 Int64
    , cmd_index_page_offset :: Field 10 (Maybe Int64)
    , cmd_dictionary_page_offset :: Field 11 (Maybe Int64)
    , cmd_statistics :: Field 12 (Maybe Statistics)
    , cmd_encoding_stats :: Field 13 (Maybe [PageEncodingStats])
    , cmd_bloom_filter_offset :: Field 14 (Maybe Int64)
    , cmd_bloom_filter_length :: Field 15 (Maybe Int32)
    }
    deriving (Eq, Show, Generic)

instance Pinchable ColumnMetaData

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L875
data EncryptionWithFooterKey = EncryptionWithFooterKey deriving (Eq, Show)
instance Pinchable EncryptionWithFooterKey where
    type Tag EncryptionWithFooterKey = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure EncryptionWithFooterKey

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L883
data EncryptionWithColumnKey
    = EncryptionWithColumnKey
    { ewck_path_in_schema :: Field 1 [Text]
    , ewck_key_metadata :: Field 2 (Maybe ByteString)
    }
    deriving (Eq, Show, Generic)

instance Pinchable EncryptionWithColumnKey

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L893
-- union ColumnCryptoMetaData
data ColumnCryptoMetaData
    = CCM_ENCRYPTION_WITH_FOOTER_KEY (Field 1 EncryptionWithFooterKey)
    | CCM_ENCRYPTION_WITH_COLUMN_KEY (Field 2 EncryptionWithColumnKey)
    deriving (Eq, Show, Generic)

instance Pinchable ColumnCryptoMetaData

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L899
data ColumnChunk
    = ColumnChunk
    { cc_file_path :: Field 1 (Maybe Text)
    , cc_file_offset :: Field 2 Int64
    , cc_meta_data :: Field 3 (Maybe ColumnMetaData)
    , cc_offset_index_offset :: Field 4 (Maybe Int64)
    , cc_offset_index_length :: Field 5 (Maybe Int32)
    , cc_column_index_offset :: Field 6 (Maybe Int64)
    , cc_column_index_length :: Field 7 (Maybe Int32)
    , cc_crypto_metadata :: Field 8 (Maybe ColumnCryptoMetaData)
    , cc_encrypted_column_metadata :: Field 9 (Maybe ByteString)
    }
    deriving (Eq, Show, Generic)

instance Pinchable ColumnChunk

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L940
data SortingColumn
    = SortingColumn
    { sc_column_idx :: Field 1 Int32
    , sc_descending :: Field 2 Bool
    , sc_nulls_first :: Field 3 Bool
    }
    deriving (Eq, Show, Generic)

instance Pinchable SortingColumn

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L958
data RowGroup
    = RowGroup
    { rg_columns :: Field 1 [ColumnChunk]
    , rg_total_byte_size :: Field 2 Int64
    , rg_num_rows :: Field 3 Int64
    , rg_sorting_columns :: Field 4 (Maybe [SortingColumn])
    , rg_file_offset :: Field 5 (Maybe Int64)
    , rg_total_compressed_size :: Field 6 (Maybe Int64)
    , rg_ordinal :: Field 7 (Maybe Int16)
    }
    deriving (Eq, Show, Generic)

instance Pinchable RowGroup

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L980
data KeyValue
    = KeyValue
    { kv_key :: Field 1 Text
    , kv_value :: Field 2 (Maybe Text)
    }
    deriving (Eq, Show, Generic)

instance Pinchable KeyValue

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L990
-- union ColumnOrder
newtype ColumnOrder
    = TYPE_ORDER (Field 1 TypeDefinedOrder)
    deriving (Eq, Show, Generic)

instance Pinchable ColumnOrder

-- Empty struct for TYPE_ORDER
data TypeDefinedOrder = TypeDefinedOrder deriving (Eq, Show)
instance Pinchable TypeDefinedOrder where
    type Tag TypeDefinedOrder = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure TypeDefinedOrder

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1094
data AesGcmV1
    = AesGcmV1
    { aes_gcm_v1_aad_prefix :: Field 1 (Maybe ByteString)
    , aes_gcm_v1_aad_file_unique :: Field 2 (Maybe ByteString)
    , aes_gcm_v1_supply_aad_prefix :: Field 3 (Maybe Bool)
    }
    deriving (Eq, Show, Generic)

instance Pinchable AesGcmV1

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1107
data AesGcmCtrV1
    = AesGcmCtrV1
    { aes_gcm_ctr_v1_aad_prefix :: Field 1 (Maybe ByteString)
    , aes_gcm_ctr_v1_aad_file_unique :: Field 2 (Maybe ByteString)
    , aes_gcm_ctr_v1_supply_aad_prefix :: Field 3 (Maybe Bool)
    }
    deriving (Eq, Show, Generic)

instance Pinchable AesGcmCtrV1

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1118
-- union EncryptionAlgorithm
data EncryptionAlgorithm
    = AES_GCM_V1 (Field 1 AesGcmV1)
    | AES_GCM_CTR_V1 (Field 2 AesGcmCtrV1)
    deriving (Eq, Show, Generic)

instance Pinchable EncryptionAlgorithm

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1001
data PageLocation
    = PageLocation
    { pl_offset :: Field 1 Int64
    , pl_compressed_page_size :: Field 2 Int32
    , pl_first_row_index :: Field 3 Int64
    }
    deriving (Eq, Show, Generic)

instance Pinchable PageLocation

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1017
data OffsetIndex
    = OffsetIndex
    { oi_page_locations :: Field 1 [PageLocation]
    , oi_unencoded_byte_array_data_bytes :: Field 2 (Maybe [Int64])
    }
    deriving (Eq, Show, Generic)

instance Pinchable OffsetIndex

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1033
data ColumnIndex
    = ColumnIndex
    { ci_null_pages :: Field 1 [Bool]
    , ci_min_values :: Field 2 [ByteString]
    , ci_max_values :: Field 3 [ByteString]
    , ci_boundary_order :: Field 4 BoundaryOrder
    , ci_null_counts :: Field 5 (Maybe [Int64])
    , ci_repetition_level_histograms :: Field 6 (Maybe [Int64])
    , ci_definition_level_histograms :: Field 7 (Maybe [Int64])
    }
    deriving (Eq, Show, Generic)

instance Pinchable ColumnIndex

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1248
data DataPageHeader
    = DataPageHeader
    { dph_num_values :: Field 1 Int32
    , dph_encoding :: Field 2 Encoding
    , dph_definition_level_encoding :: Field 3 Encoding
    , dph_repetition_level_encoding :: Field 4 Encoding
    , dph_statistics :: Field 5 (Maybe Statistics)
    }
    deriving (Eq, Show, Generic)

instance Pinchable DataPageHeader

data IndexPageHeader = IndexPageHeader deriving (Eq, Show)
instance Pinchable IndexPageHeader where
    type Tag IndexPageHeader = Pinch.TStruct
    pinch _ = Pinch.struct []
    unpinch _ = pure IndexPageHeader

data DictionaryPageHeader
    = DictionaryPageHeader
    { diph_num_values :: Field 1 Int32
    , diph_encoding :: Field 2 Encoding
    , diph_is_sorted :: Field 3 (Maybe Bool)
    }
    deriving (Eq, Show, Generic)

instance Pinchable DictionaryPageHeader

data DataPageHeaderV2
    = DataPageHeaderV2
    { dph2_num_values :: Field 1 Int32
    , dph2_num_nulls :: Field 2 Int32
    , dph2_num_rows :: Field 3 Int32
    , dph2_encoding :: Field 4 Encoding
    , dph2_definition_levels_byte_length :: Field 5 Int32
    , dph2_repetition_levels_byte_length :: Field 6 Int32
    , dph2_is_compressed :: Field 7 (Maybe Bool)
    , dph2_statistics :: Field 8 (Maybe Statistics)
    }
    deriving (Eq, Show, Generic)

instance Pinchable DataPageHeaderV2

data PageHeader
    = PageHeader
    { ph_type :: Field 1 PageType
    , ph_uncompressed_page_size :: Field 2 Int32
    , ph_compressed_page_size :: Field 3 Int32
    , ph_crc :: Field 4 (Maybe Int32)
    , ph_data_page_header :: Field 5 (Maybe DataPageHeader)
    , ph_index_page_header :: Field 6 (Maybe IndexPageHeader)
    , ph_dictionary_page_header :: Field 7 (Maybe DictionaryPageHeader)
    , ph_data_page_header_v2 :: Field 8 (Maybe DataPageHeaderV2)
    }
    deriving (Eq, Show, Generic)

instance Pinchable PageHeader

-- https://github.com/apache/parquet-format/blob/master/src/main/thrift/parquet.thrift#L1277
data FileMetadata
    = FileMetadata
    { version :: Field 1 Int32
    , schema :: Field 2 [SchemaElement]
    , num_rows :: Field 3 Int64
    , row_groups :: Field 4 [RowGroup]
    , key_value_metadata :: Field 5 (Maybe [KeyValue])
    , created_by :: Field 6 (Maybe Text)
    , column_orders :: Field 7 (Maybe [ColumnOrder])
    , encryption_algorithm :: Field 8 (Maybe EncryptionAlgorithm)
    , footer_signing_key_metadata :: Field 9 (Maybe ByteString)
    }
    deriving (Eq, Show, Generic)

instance Pinchable FileMetadata

unField :: (KnownNat n) => Field n a -> a
unField (Pinch.Field a) = a