1- use std :: collections :: HashSet ;
2- use std :: sync :: LazyLock ;
3-
4- use serde :: { Deserialize , Serialize } ;
1+ use crate :: { DeltaResult , Error } ;
2+ use enumset :: { enum_set , EnumSet , EnumSetType } ;
3+ use serde :: { de :: DeserializeOwned , Deserialize , Serialize } ;
4+ use std :: fmt :: Display ;
55use strum:: { AsRefStr , Display as StrumDisplay , EnumString , VariantNames } ;
66
77pub ( crate ) use column_mapping:: column_mapping_mode;
@@ -18,14 +18,12 @@ mod column_mapping;
1818 Serialize ,
1919 Deserialize ,
2020 Debug ,
21- Clone ,
22- Eq ,
23- PartialEq ,
2421 EnumString ,
2522 StrumDisplay ,
2623 AsRefStr ,
2724 VariantNames ,
2825 Hash ,
26+ EnumSetType ,
2927) ]
3028#[ strum( serialize_all = "camelCase" ) ]
3129#[ serde( rename_all = "camelCase" ) ]
@@ -59,14 +57,12 @@ pub enum ReaderFeature {
5957 Serialize ,
6058 Deserialize ,
6159 Debug ,
62- Clone ,
63- Eq ,
64- PartialEq ,
6560 EnumString ,
6661 StrumDisplay ,
6762 AsRefStr ,
6863 VariantNames ,
6964 Hash ,
65+ EnumSetType ,
7066) ]
7167#[ strum( serialize_all = "camelCase" ) ]
7268#[ serde( rename_all = "camelCase" ) ]
@@ -123,30 +119,51 @@ impl From<WriterFeature> for String {
123119 }
124120}
125121
126- pub ( crate ) static SUPPORTED_READER_FEATURES : LazyLock < HashSet < ReaderFeature > > =
127- LazyLock :: new ( || {
128- HashSet :: from ( [
129- ReaderFeature :: ColumnMapping ,
130- ReaderFeature :: DeletionVectors ,
131- ReaderFeature :: TimestampWithoutTimezone ,
132- ReaderFeature :: TypeWidening ,
133- ReaderFeature :: TypeWideningPreview ,
134- ReaderFeature :: VacuumProtocolCheck ,
135- ReaderFeature :: V2Checkpoint ,
136- ] )
137- } ) ;
138-
139- pub ( crate ) static SUPPORTED_WRITER_FEATURES : LazyLock < HashSet < WriterFeature > > =
122+ pub ( crate ) static SUPPORTED_READER_FEATURES : EnumSet < ReaderFeature > = enum_set ! (
123+ ReaderFeature :: ColumnMapping
124+ | ReaderFeature :: DeletionVectors
125+ | ReaderFeature :: TimestampWithoutTimezone
126+ | ReaderFeature :: TypeWidening
127+ | ReaderFeature :: TypeWideningPreview
128+ | ReaderFeature :: VacuumProtocolCheck
129+ | ReaderFeature :: V2Checkpoint
130+ ) ;
131+
132+ pub ( crate ) static SUPPORTED_WRITER_FEATURES : EnumSet < WriterFeature > =
140133 // note: we 'support' Invariants, but only insofar as we check that they are not present.
141134 // we support writing to tables that have Invariants enabled but not used. similarly, we only
142135 // support DeletionVectors in that we never write them (no DML).
143- LazyLock :: new ( || {
144- HashSet :: from ( [
145- WriterFeature :: AppendOnly ,
146- WriterFeature :: DeletionVectors ,
147- WriterFeature :: Invariants ,
148- ] )
149- } ) ;
136+ enum_set ! (
137+ WriterFeature :: AppendOnly | WriterFeature :: DeletionVectors | WriterFeature :: Invariants
138+ ) ;
139+
140+ pub ( crate ) static CDF_SUPPORTED_READER_FEATURES : EnumSet < ReaderFeature > =
141+ enum_set ! ( ReaderFeature :: DeletionVectors ) ;
142+
143+ pub ( crate ) fn ensure_supported_features < F > (
144+ features : & [ String ] ,
145+ supported : & EnumSet < F > ,
146+ ) -> DeltaResult < ( ) >
147+ where
148+ F : DeserializeOwned + EnumSetType + Display ,
149+ {
150+ for feature_str in features {
151+ match serde_json:: from_str :: < F > ( feature_str) {
152+ Ok ( feature_enum) => {
153+ if !supported. contains ( feature_enum) {
154+ return Err ( Error :: Unsupported ( format ! (
155+ "Unsupported feature: {}" ,
156+ feature_enum
157+ ) ) ) ;
158+ }
159+ }
160+ Err ( err) => {
161+ return Err ( Error :: Unsupported ( format ! ( "Unknown feature: {}" , err) ) ) ;
162+ }
163+ }
164+ }
165+ Ok ( ( ) )
166+ }
150167
151168#[ cfg( test) ]
152169mod tests {
0 commit comments