@@ -22,10 +22,12 @@ use std::cmp::Ordering;
2222use std:: collections:: HashMap ;
2323use std:: fmt:: { Display , Formatter } ;
2424use std:: hash:: Hash ;
25+ use std:: io:: Read as _;
2526use std:: sync:: Arc ;
2627
2728use _serde:: TableMetadataEnum ;
2829use chrono:: { DateTime , Utc } ;
30+ use flate2:: read:: GzDecoder ;
2931use serde:: { Deserialize , Serialize } ;
3032use serde_repr:: { Deserialize_repr , Serialize_repr } ;
3133use uuid:: Uuid ;
@@ -426,9 +428,30 @@ impl TableMetadata {
426428 file_io : & FileIO ,
427429 metadata_location : impl AsRef < str > ,
428430 ) -> Result < TableMetadata > {
431+ let metadata_location = metadata_location. as_ref ( ) ;
429432 let input_file = file_io. new_input ( metadata_location) ?;
430433 let metadata_content = input_file. read ( ) . await ?;
431- let metadata = serde_json:: from_slice :: < TableMetadata > ( & metadata_content) ?;
434+
435+ // Check if the file is compressed by looking for the gzip "magic number".
436+ let metadata = if metadata_content. len ( ) > 2
437+ && metadata_content[ 0 ] == 0x1F
438+ && metadata_content[ 1 ] == 0x8B
439+ {
440+ let mut decoder = GzDecoder :: new ( metadata_content. as_ref ( ) ) ;
441+ let mut decompressed_data = Vec :: new ( ) ;
442+ decoder. read_to_end ( & mut decompressed_data) . map_err ( |e| {
443+ Error :: new (
444+ ErrorKind :: DataInvalid ,
445+ "Trying to read compressed metadata file" ,
446+ )
447+ . with_context ( "file_path" , metadata_location)
448+ . with_source ( e)
449+ } ) ?;
450+ serde_json:: from_slice ( & decompressed_data) ?
451+ } else {
452+ serde_json:: from_slice ( & metadata_content) ?
453+ } ;
454+
432455 Ok ( metadata)
433456 }
434457
@@ -1516,6 +1539,7 @@ impl SnapshotLog {
15161539mod tests {
15171540 use std:: collections:: HashMap ;
15181541 use std:: fs;
1542+ use std:: io:: Write as _;
15191543 use std:: sync:: Arc ;
15201544
15211545 use anyhow:: Result ;
@@ -3524,6 +3548,30 @@ mod tests {
35243548 assert_eq ! ( read_metadata, original_metadata) ;
35253549 }
35263550
3551+ #[ tokio:: test]
3552+ async fn test_table_metadata_read_compressed ( ) {
3553+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
3554+ let metadata_location = temp_dir. path ( ) . join ( "v1.gz.metadata.json" ) ;
3555+
3556+ let original_metadata: TableMetadata = get_test_table_metadata ( "TableMetadataV2Valid.json" ) ;
3557+ let json = serde_json:: to_string ( & original_metadata) . unwrap ( ) ;
3558+
3559+ let mut encoder = flate2:: write:: GzEncoder :: new ( Vec :: new ( ) , flate2:: Compression :: default ( ) ) ;
3560+ encoder. write_all ( json. as_bytes ( ) ) . unwrap ( ) ;
3561+ std:: fs:: write ( & metadata_location, encoder. finish ( ) . unwrap ( ) )
3562+ . expect ( "failed to write metadata" ) ;
3563+
3564+ // Read the metadata back
3565+ let file_io = FileIOBuilder :: new_fs_io ( ) . build ( ) . unwrap ( ) ;
3566+ let metadata_location = metadata_location. to_str ( ) . unwrap ( ) ;
3567+ let read_metadata = TableMetadata :: read_from ( & file_io, metadata_location)
3568+ . await
3569+ . unwrap ( ) ;
3570+
3571+ // Verify the metadata matches
3572+ assert_eq ! ( read_metadata, original_metadata) ;
3573+ }
3574+
35273575 #[ tokio:: test]
35283576 async fn test_table_metadata_read_nonexistent_file ( ) {
35293577 // Create a FileIO instance
0 commit comments