Skip to content

Commit 8922ccd

Browse files
committed
typetag serde for StorageFactory
1 parent 3cedfe1 commit 8922ccd

File tree

8 files changed

+108
-7
lines changed

8 files changed

+108
-7
lines changed

crates/iceberg/src/io/file_io.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,16 @@ mod tests {
607607
}
608608
}
609609

610+
fn default_received_props() -> Arc<Mutex<HashMap<String, String>>> {
611+
Arc::new(Mutex::new(HashMap::new()))
612+
}
613+
610614
// Test storage factory
611-
#[derive(Debug)]
615+
#[derive(Debug, Serialize, Deserialize)]
612616
struct TestStorageFactory {
617+
#[serde(skip, default = "default_written")]
613618
written: Arc<Mutex<Vec<String>>>,
619+
#[serde(skip, default = "default_received_props")]
614620
received_props: Arc<Mutex<HashMap<String, String>>>,
615621
}
616622

@@ -624,6 +630,7 @@ mod tests {
624630
}
625631
}
626632

633+
#[typetag::serde]
627634
impl StorageFactory for TestStorageFactory {
628635
fn build(
629636
&self,

crates/iceberg/src/io/storage.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,19 @@ pub trait Storage: Debug + Send + Sync {
9393
/// properties and extensions. Each storage backend (S3, GCS, etc.) provides its own
9494
/// factory implementation.
9595
///
96+
/// The trait supports serialization via `typetag`, allowing factory instances to be
97+
/// serialized and deserialized across process boundaries.
98+
///
9699
/// # Example
97100
///
98101
/// ```rust,ignore
99102
/// use iceberg::io::{StorageFactory, Extensions};
100103
/// use std::collections::HashMap;
101104
///
105+
/// #[derive(Debug, Serialize, Deserialize)]
102106
/// struct MyStorageFactory;
103107
///
108+
/// #[typetag::serde]
104109
/// impl StorageFactory for MyStorageFactory {
105110
/// fn build(
106111
/// &self,
@@ -112,6 +117,7 @@ pub trait Storage: Debug + Send + Sync {
112117
/// }
113118
/// }
114119
/// ```
120+
#[typetag::serde(tag = "type")]
115121
pub trait StorageFactory: Debug + Send + Sync {
116122
/// Create a new storage instance with the given properties and extensions.
117123
///

crates/iceberg/src/io/storage_azdls.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,9 +688,10 @@ impl Storage for OpenDALAzdlsStorage {
688688
}
689689

690690
/// Factory for Azure Data Lake Storage
691-
#[derive(Debug)]
691+
#[derive(Debug, Serialize, Deserialize)]
692692
pub struct OpenDALAzdlsStorageFactory;
693693

694+
#[typetag::serde]
694695
impl StorageFactory for OpenDALAzdlsStorageFactory {
695696
fn build(
696697
&self,

crates/iceberg/src/io/storage_fs.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ impl Storage for OpenDALFsStorage {
123123
}
124124

125125
/// Factory for OpenDAL Filesystem storage
126-
#[derive(Debug)]
126+
#[derive(Debug, Serialize, Deserialize)]
127127
pub struct OpenDALFsStorageFactory;
128128

129+
#[typetag::serde]
129130
impl StorageFactory for OpenDALFsStorageFactory {
130131
fn build(
131132
&self,
@@ -158,4 +159,21 @@ mod tests {
158159
// Verify the type is correct
159160
assert!(format!("{:?}", deserialized).contains("OpenDALFsStorage"));
160161
}
162+
163+
#[test]
164+
fn test_fs_factory_serialization() {
165+
use crate::io::StorageFactory;
166+
167+
// Create a factory instance
168+
let factory: Box<dyn StorageFactory> = Box::new(OpenDALFsStorageFactory);
169+
170+
// Serialize the factory
171+
let serialized = serde_json::to_string(&factory).unwrap();
172+
173+
// Deserialize the factory
174+
let deserialized: Box<dyn StorageFactory> = serde_json::from_str(&serialized).unwrap();
175+
176+
// Verify the type is correct
177+
assert!(format!("{:?}", deserialized).contains("OpenDALFsStorageFactory"));
178+
}
161179
}

crates/iceberg/src/io/storage_gcs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,10 @@ impl Storage for OpenDALGcsStorage {
200200
}
201201

202202
/// Factory for OpenDAL GCS storage
203-
#[derive(Debug)]
203+
#[derive(Debug, Serialize, Deserialize)]
204204
pub struct OpenDALGcsStorageFactory;
205205

206+
#[typetag::serde]
206207
impl StorageFactory for OpenDALGcsStorageFactory {
207208
fn build(
208209
&self,

crates/iceberg/src/io/storage_memory.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,10 @@ impl Storage for OpenDALMemoryStorage {
141141
}
142142

143143
/// Factory for OpenDAL Memory storage
144-
#[derive(Debug)]
144+
#[derive(Debug, Serialize, Deserialize)]
145145
pub struct OpenDALMemoryStorageFactory;
146146

147+
#[typetag::serde]
147148
impl StorageFactory for OpenDALMemoryStorageFactory {
148149
fn build(
149150
&self,
@@ -176,4 +177,52 @@ mod tests {
176177
// Verify the type is correct
177178
assert!(format!("{:?}", deserialized).contains("OpenDALMemoryStorage"));
178179
}
180+
181+
#[test]
182+
fn test_memory_factory_serialization() {
183+
use crate::io::StorageFactory;
184+
185+
// Create a factory instance
186+
let factory: Box<dyn StorageFactory> = Box::new(OpenDALMemoryStorageFactory);
187+
188+
// Serialize the factory
189+
let serialized = serde_json::to_string(&factory).unwrap();
190+
191+
// Deserialize the factory
192+
let deserialized: Box<dyn StorageFactory> = serde_json::from_str(&serialized).unwrap();
193+
194+
// Verify the type is correct
195+
assert!(format!("{:?}", deserialized).contains("OpenDALMemoryStorageFactory"));
196+
}
197+
198+
#[test]
199+
fn test_memory_factory_to_storage_serialization() {
200+
use crate::io::{Extensions, StorageFactory};
201+
202+
// Create a factory and build storage
203+
let factory = OpenDALMemoryStorageFactory;
204+
let storage = factory
205+
.build(HashMap::new(), Extensions::default())
206+
.unwrap();
207+
208+
// Serialize the storage
209+
let storage_json = serde_json::to_string(&storage).unwrap();
210+
211+
// Deserialize the storage
212+
let deserialized_storage: Box<dyn Storage> = serde_json::from_str(&storage_json).unwrap();
213+
214+
// Verify storage type
215+
assert!(format!("{:?}", deserialized_storage).contains("OpenDALMemoryStorage"));
216+
217+
// Serialize the factory
218+
let factory_boxed: Box<dyn StorageFactory> = Box::new(factory);
219+
let factory_json = serde_json::to_string(&factory_boxed).unwrap();
220+
221+
// Deserialize the factory
222+
let deserialized_factory: Box<dyn StorageFactory> =
223+
serde_json::from_str(&factory_json).unwrap();
224+
225+
// Verify factory type
226+
assert!(format!("{:?}", deserialized_factory).contains("OpenDALMemoryStorageFactory"));
227+
}
179228
}

crates/iceberg/src/io/storage_oss.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,10 @@ impl Storage for OpenDALOssStorage {
160160
}
161161

162162
/// Factory for OpenDAL OSS storage
163-
#[derive(Debug)]
163+
#[derive(Debug, Serialize, Deserialize)]
164164
pub struct OpenDALOssStorageFactory;
165165

166+
#[typetag::serde]
166167
impl StorageFactory for OpenDALOssStorageFactory {
167168
fn build(
168169
&self,

crates/iceberg/src/io/storage_s3.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,10 @@ impl Storage for OpenDALS3Storage {
328328
}
329329

330330
/// Factory for S3 storage
331-
#[derive(Debug)]
331+
#[derive(Debug, Serialize, Deserialize)]
332332
pub struct OpenDALS3StorageFactory;
333333

334+
#[typetag::serde]
334335
impl StorageFactory for OpenDALS3StorageFactory {
335336
fn build(
336337
&self,
@@ -383,4 +384,21 @@ mod tests {
383384
// Verify the type is correct
384385
assert!(format!("{:?}", deserialized).contains("OpenDALS3Storage"));
385386
}
387+
388+
#[test]
389+
fn test_s3_factory_serialization() {
390+
use crate::io::StorageFactory;
391+
392+
// Create a factory instance
393+
let factory: Box<dyn StorageFactory> = Box::new(OpenDALS3StorageFactory);
394+
395+
// Serialize the factory
396+
let serialized = serde_json::to_string(&factory).unwrap();
397+
398+
// Deserialize the factory
399+
let deserialized: Box<dyn StorageFactory> = serde_json::from_str(&serialized).unwrap();
400+
401+
// Verify the type is correct
402+
assert!(format!("{:?}", deserialized).contains("OpenDALS3StorageFactory"));
403+
}
386404
}

0 commit comments

Comments
 (0)