laminar_connectors/lakehouse/iceberg_config/
modes.rs1use std::fmt;
2use std::str::FromStr;
3
4macro_rules! string_enum {
5 (
6 $(#[$meta:meta])*
7 pub enum $name:ident {
8 $($(#[$variant_meta:meta])* $variant:ident => [$canonical:literal $(, $alias:literal)*]),+ $(,)?
9 }
10 default $default:ident;
11 error $error:literal;
12 ) => {
13 $(#[$meta])*
14 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
15 pub enum $name {
16 $($(#[$variant_meta])* $variant),+
17 }
18
19 impl Default for $name {
20 fn default() -> Self {
21 Self::$default
22 }
23 }
24
25 impl FromStr for $name {
26 type Err = String;
27
28 fn from_str(value: &str) -> Result<Self, Self::Err> {
29 match value.trim().to_ascii_lowercase().as_str() {
30 $($canonical $(| $alias)* => Ok(Self::$variant),)+
31 other => Err(format!(concat!($error, ": '{}'"), other)),
32 }
33 }
34 }
35
36 impl fmt::Display for $name {
37 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 $(Self::$variant => formatter.write_str($canonical),)+
40 }
41 }
42 }
43 };
44}
45
46string_enum! {
47 pub enum IcebergReadMode {
49 Snapshot => ["snapshot"],
51 Append => ["append", "incremental"],
53 Changelog => ["changelog", "cdc"]
55 }
56 default Snapshot;
57 error "invalid Iceberg read.mode";
58}
59
60string_enum! {
61 pub enum IcebergReadBootstrap {
63 Initial => ["initial", "snapshot", "current"],
65 None => ["none", "skip"]
67 }
68 default Initial;
69 error "invalid Iceberg read.bootstrap";
70}
71
72string_enum! {
73 pub enum IcebergWriteMode {
75 Append => ["append"],
77 MergeOnRead => ["merge-on-read", "merge_on_read", "mor"],
79 CopyOnWrite => ["copy-on-write", "copy_on_write", "cow"]
81 }
82 default Append;
83 error "invalid Iceberg write.mode";
84}
85
86string_enum! {
87 pub enum IcebergWriteDistributionMode {
89 Clustered => ["clustered"],
91 Fanout => ["fanout", "hash"]
93 }
94 default Fanout;
95 error "invalid Iceberg write.distribution.mode";
96}
97
98string_enum! {
99 pub enum IcebergSchemaEvolutionMode {
101 Strict => ["strict", "none", "disabled"],
103 Safe => ["safe", "additive"]
105 }
106 default Strict;
107 error "invalid Iceberg schema.evolution.mode";
108}
109
110string_enum! {
111 pub enum IcebergCatalogType {
113 Rest => ["rest"],
115 Glue => ["glue"],
117 Hms => ["hms", "hive"],
119 S3Tables => ["s3tables", "s3-tables"],
121 Sql => ["sql"]
123 }
124 default Rest;
125 error "invalid Iceberg catalog.type";
126}
127
128string_enum! {
129 pub enum IcebergCatalogAuthType {
131 None => ["none"],
133 Bearer => ["bearer", "token"],
135 OAuth2 => ["oauth2", "oauth"]
137 }
138 default None;
139 error "invalid Iceberg catalog.auth.type";
140}
141
142string_enum! {
143 pub enum IcebergStorageType {
145 S3 => ["s3", "s3a"],
147 Gcs => ["gcs", "gs"],
149 Azure => ["azure", "azdls", "adls", "blob", "abfs", "abfss", "wasb", "wasbs"],
151 Fs => ["fs", "file", "filesystem"]
153 }
154 default S3;
155 error "invalid Iceberg storage.type";
156}
157
158string_enum! {
159 pub enum IcebergStorageEncryption {
161 None => ["none"],
163 Sse => ["sse", "sse-s3"],
165 Kms => ["kms", "sse-kms"]
167 }
168 default None;
169 error "invalid Iceberg storage.encryption";
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn aliases_parse_to_typed_modes() {
178 assert_eq!("incremental".parse(), Ok(IcebergReadMode::Append));
179 assert_eq!("mor".parse(), Ok(IcebergWriteMode::MergeOnRead));
180 assert_eq!("abfss".parse(), Ok(IcebergStorageType::Azure));
181 assert!("overwrite".parse::<IcebergWriteMode>().is_err());
182 }
183}