This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch gh-pages
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git


The following commit(s) were added to refs/heads/gh-pages by this push:
     new ed4e55e2 deploy: e0b7f352ed8857cb401db2c8e3aa97e61fe4bd71
ed4e55e2 is described below

commit ed4e55e2f24166020e766caf00e1d690f17fff71
Author: liurenjie1024 <[email protected]>
AuthorDate: Mon Mar 31 13:12:50 2025 +0000

    deploy: e0b7f352ed8857cb401db2c8e3aa97e61fe4bd71
---
 api/help.html                               |   2 +-
 api/iceberg/spec/enum.FormatVersion.html    |  16 +-
 api/iceberg/spec/struct.MetadataLog.html    |  10 +-
 api/iceberg/spec/struct.SnapshotLog.html    |  14 +-
 api/iceberg/spec/struct.TableMetadata.html  |   2 +-
 api/settings.html                           |   2 +-
 api/src/iceberg/spec/table_metadata.rs.html | 362 +++++++++++++++++++++++-----
 7 files changed, 325 insertions(+), 83 deletions(-)

diff --git a/api/help.html b/api/help.html
index 886bccc7..21943ce1 100644
--- a/api/help.html
+++ b/api/help.html
@@ -1 +1 @@
-<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" 
content="Documentation for 
Rustdoc"><title>Help</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388.woff2,SourceCodePro-Regular-5
 [...]
\ No newline at end of file
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" 
content="Documentation for 
Rustdoc"><title>Help</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388.woff2,SourceCodePro-Regular-5
 [...]
\ No newline at end of file
diff --git a/api/iceberg/spec/enum.FormatVersion.html 
b/api/iceberg/spec/enum.FormatVersion.html
index 0664d450..4ad273b9 100644
--- a/api/iceberg/spec/enum.FormatVersion.html
+++ b/api/iceberg/spec/enum.FormatVersion.html
@@ -1,21 +1,21 @@
-<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="Iceberg 
format version"><title>FormatVersion in iceberg::spec - 
Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388
 [...]
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="Iceberg 
format version"><title>FormatVersion in iceberg::spec - 
Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388
 [...]
     V1 = 1,
     V2 = 2,
 }</code></pre><details class="toggle top-doc" open><summary 
class="hideme"><span>Expand description</span></summary><div 
class="docblock"><p>Iceberg format version</p>
 </div></details><h2 id="variants" class="variants section-header">Variants<a 
href="#variants" class="anchor">§</a></h2><div class="variants"><section 
id="variant.V1" class="variant"><a href="#variant.V1" class="anchor">§</a><h3 
class="code-header">V1 = 1</h3></section><div class="docblock"><p>Iceberg spec 
version 1</p>
 </div><section id="variant.V2" class="variant"><a href="#variant.V2" 
class="anchor">§</a><h3 class="code-header">V2 = 2</h3></section><div 
class="docblock"><p>Iceberg spec version 2</p>
-</div></div><h2 id="trait-implementations" class="section-header">Trait 
Implementations<a href="#trait-implementations" class="anchor">§</a></h2><div 
id="trait-implementations-list"><details class="toggle implementors-toggle" 
open><summary><section id="impl-Clone-for-FormatVersion" class="impl"><a 
class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1192">source</a><a 
href="#impl-Clone-for-FormatVersion" class="anchor">§</a><h3 
class="code-header">impl <a class="trai [...]
-    D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Display [...]
+</div></div><h2 id="trait-implementations" class="section-header">Trait 
Implementations<a href="#trait-implementations" class="anchor">§</a></h2><div 
id="trait-implementations-list"><details class="toggle implementors-toggle" 
open><summary><section id="impl-Clone-for-FormatVersion" class="impl"><a 
class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1215">source</a><a 
href="#impl-Clone-for-FormatVersion" class="anchor">§</a><h3 
class="code-header">impl <a class="trai [...]
+    D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Display [...]
     H: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html"; 
title="trait core::hash::Hasher">Hasher</a>,
-    Self: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h4></section></summary><div 
class='docblock'>Feeds a slice of this type into the given <a 
href="https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html"; 
title="trait core::hash::Hasher"><code>Hasher</code></a>. <a 
href="https://doc.rust-lang.org/nightly/core/hash/trait.Hash.html#method.hash_slice";>Read
 more</a></div></details></div></d [...]
+    Self: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h4></section></summary><div 
class='docblock'>Feeds a slice of this type into the given <a 
href="https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html"; 
title="trait core::hash::Hasher"><code>Hasher</code></a>. <a 
href="https://doc.rust-lang.org/nightly/core/hash/trait.Hash.html#method.hash_slice";>Read
 more</a></div></details></div></d [...]
     Self: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h4></section></summary><div 
class='docblock'>Compares and returns the maximum of two values. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html#method.max";>Read
 more</a></div></details><details class="toggle method-toggle" 
open><summary><section id="method.min" class="method trait-impl"><span 
class="rightside"><span class="si [...]
     Self: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h4></section></summary><div 
class='docblock'>Compares and returns the minimum of two values. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html#method.min";>Read
 more</a></div></details><details class="toggle method-toggle" 
open><summary><section id="method.clamp" class="method trait-impl"><span 
class="rightside"><span class=" [...]
-    Self: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a> + <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html"; 
title="trait 
core::cmp::PartialOrd">PartialOrd</a>,</div></h4></section></summary><div 
class='docblock'>Restrict a value to a certain interval. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html#method.clamp";>Read
 more</a></div></details></div> [...]
+    Self: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a> + <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html"; 
title="trait 
core::cmp::PartialOrd">PartialOrd</a>,</div></h4></section></summary><div 
class='docblock'>Restrict a value to a certain interval. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html#method.clamp";>Read
 more</a></div></details></div> [...]
 by <code>==</code>.</div></details><details class="toggle method-toggle" 
open><summary><section id="method.ne" class="method trait-impl"><span 
class="rightside"><span class="since" title="Stable since Rust version 
1.0.0">1.0.0</span> · <a class="src" 
href="https://doc.rust-lang.org/nightly/src/core/cmp.rs.html#263";>source</a></span><a
 href="#method.ne" class="anchor">§</a><h4 class="code-header">fn <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html#method.ne";
 class= [...]
-sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section 
id="impl-PartialOrd-for-FormatVersion" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1202-1206">source</a><a 
href="#impl-PartialOrd-for-FormatVersion" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd. [...]
+sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section 
id="impl-PartialOrd-for-FormatVersion" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1225-1229">source</a><a 
href="#impl-PartialOrd-for-FormatVersion" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd. [...]
 operator. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html#method.le";>Read
 more</a></div></details><details class="toggle method-toggle" 
open><summary><section id="method.gt" class="method trait-impl"><span 
class="rightside"><span class="since" title="Stable since Rust version 
1.0.0">1.0.0</span> · <a class="src" 
href="https://doc.rust-lang.org/nightly/src/core/cmp.rs.html#1215";>source</a></span><a
 href="#method.gt" class="anchor">§</a><h4 class="code-header">fn  [...]
-operator. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html#method.ge";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section 
id="impl-Serialize-for-FormatVersion" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1192">source</a><a 
href="#impl-Serialize-for-FormatVersion" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" href="https://docs.rs/serde/1.0 [...]
-    S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section 
id="impl-Copy-for-FormatVersion" class="impl"><a class="src rightside" 
href="../../src/iceberg/s [...]
+operator. <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html#method.ge";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section 
id="impl-Serialize-for-FormatVersion" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1215">source</a><a 
href="#impl-Serialize-for-FormatVersion" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" href="https://docs.rs/serde/1.0 [...]
+    S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section 
id="impl-Copy-for-FormatVersion" class="impl"><a class="src rightside" 
href="../../src/iceberg/s [...]
     T: 'static + ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.type_id" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#141";>source</a><a 
href="#method.type_id" class="anchor">§</a><h4 class="code-header">fn <a href 
[...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#210";>source</a><a
 href="#method.borrow" class="anchor">§</a><h4 class="code-header">fn <a 
href="https:/ [...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow_mut" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#217";>source</a><a
 href="#method.borrow_mut" class="anchor">§</a><h4 class="code-header">fn <a 
href= [...]
diff --git a/api/iceberg/spec/struct.MetadataLog.html 
b/api/iceberg/spec/struct.MetadataLog.html
index 7a4843cc..23733fe2 100644
--- a/api/iceberg/spec/struct.MetadataLog.html
+++ b/api/iceberg/spec/struct.MetadataLog.html
@@ -1,14 +1,14 @@
-<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="Encodes 
changes to the previous metadata files for the table"><title>MetadataLog in 
iceberg::spec - 
Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.wo
 [...]
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="Encodes 
changes to the previous metadata files for the table"><title>MetadataLog in 
iceberg::spec - 
Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.wo
 [...]
     pub metadata_file: <a class="struct" 
href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html"; 
title="struct alloc::string::String">String</a>,
     pub timestamp_ms: <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a>,
 }</code></pre><details class="toggle top-doc" open><summary 
class="hideme"><span>Expand description</span></summary><div 
class="docblock"><p>Encodes changes to the previous metadata files for the 
table</p>
 </div></details><h2 id="fields" class="fields section-header">Fields<a 
href="#fields" class="anchor">§</a></h2><span id="structfield.metadata_file" 
class="structfield section-header"><a href="#structfield.metadata_file" 
class="anchor field">§</a><code>metadata_file: <a class="struct" 
href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html"; 
title="struct alloc::string::String">String</a></code></span><div 
class="docblock"><p>The file for the log.</p>
 </div><span id="structfield.timestamp_ms" class="structfield 
section-header"><a href="#structfield.timestamp_ms" class="anchor 
field">§</a><code>timestamp_ms: <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a></code></span><div
 class="docblock"><p>Time new metadata was created</p>
-</div><h2 id="trait-implementations" class="section-header">Trait 
Implementations<a href="#trait-implementations" class="anchor">§</a></h2><div 
id="trait-implementations-list"><details class="toggle implementors-toggle" 
open><summary><section id="impl-Clone-for-MetadataLog" class="impl"><a 
class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1223">source</a><a 
href="#impl-Clone-for-MetadataLog" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" href="h [...]
-    __D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Parti [...]
+</div><h2 id="trait-implementations" class="section-header">Trait 
Implementations<a href="#trait-implementations" class="anchor">§</a></h2><div 
id="trait-implementations-list"><details class="toggle implementors-toggle" 
open><summary><section id="impl-Clone-for-MetadataLog" class="impl"><a 
class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1246">source</a><a 
href="#impl-Clone-for-MetadataLog" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" href="h [...]
+    __D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Parti [...]
 by <code>==</code>.</div></details><details class="toggle method-toggle" 
open><summary><section id="method.ne" class="method trait-impl"><span 
class="rightside"><span class="since" title="Stable since Rust version 
1.0.0">1.0.0</span> · <a class="src" 
href="https://doc.rust-lang.org/nightly/src/core/cmp.rs.html#263";>source</a></span><a
 href="#method.ne" class="anchor">§</a><h4 class="code-header">fn <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html#method.ne";
 class= [...]
-sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Serialize-for-MetadataLog" 
class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1223">source</a><a 
href="#impl-Serialize-for-MetadataLog" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html"; title="tr 
[...]
-    __S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section id="impl-Eq-for-MetadataLog" 
class="impl"><a class="src rightside" href="../../src/iceberg/spe [...]
+sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Serialize-for-MetadataLog" 
class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1246">source</a><a 
href="#impl-Serialize-for-MetadataLog" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html"; title="tr 
[...]
+    __S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section id="impl-Eq-for-MetadataLog" 
class="impl"><a class="src rightside" href="../../src/iceberg/spe [...]
     T: 'static + ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.type_id" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#141";>source</a><a 
href="#method.type_id" class="anchor">§</a><h4 class="code-header">fn <a href 
[...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#210";>source</a><a
 href="#method.borrow" class="anchor">§</a><h4 class="code-header">fn <a 
href="https:/ [...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow_mut" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#217";>source</a><a
 href="#method.borrow_mut" class="anchor">§</a><h4 class="code-header">fn <a 
href= [...]
diff --git a/api/iceberg/spec/struct.SnapshotLog.html 
b/api/iceberg/spec/struct.SnapshotLog.html
index 6e2980c7..0b100abc 100644
--- a/api/iceberg/spec/struct.SnapshotLog.html
+++ b/api/iceberg/spec/struct.SnapshotLog.html
@@ -1,16 +1,16 @@
-<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="A log of 
when each snapshot was made."><title>SnapshotLog in iceberg::spec - 
Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9
 [...]
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="A log of 
when each snapshot was made."><title>SnapshotLog in iceberg::spec - 
Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9
 [...]
     pub snapshot_id: <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a>,
     pub timestamp_ms: <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a>,
 }</code></pre><details class="toggle top-doc" open><summary 
class="hideme"><span>Expand description</span></summary><div 
class="docblock"><p>A log of when each snapshot was made.</p>
 </div></details><h2 id="fields" class="fields section-header">Fields<a 
href="#fields" class="anchor">§</a></h2><span id="structfield.snapshot_id" 
class="structfield section-header"><a href="#structfield.snapshot_id" 
class="anchor field">§</a><code>snapshot_id: <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a></code></span><div
 class="docblock"><p>Id of the snapshot.</p>
 </div><span id="structfield.timestamp_ms" class="structfield 
section-header"><a href="#structfield.timestamp_ms" class="anchor 
field">§</a><code>timestamp_ms: <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a></code></span><div
 class="docblock"><p>Last updated timestamp</p>
-</div><h2 id="implementations" class="section-header">Implementations<a 
href="#implementations" class="anchor">§</a></h2><div 
id="implementations-list"><details class="toggle implementors-toggle" 
open><summary><section id="impl-SnapshotLog" class="impl"><a class="src 
rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1243-1254">source</a><a 
href="#impl-SnapshotLog" class="anchor">§</a><h3 class="code-header">impl <a 
class="struct" href="struct.SnapshotLog.html" title="struct  [...]
-</div></details><details class="toggle method-toggle" open><summary><section 
id="method.timestamp_ms" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1251-1253">source</a><h4 
class="code-header">pub fn <a href="#method.timestamp_ms" 
class="fn">timestamp_ms</a>(&amp;self) -&gt; <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a></h4></section></summary><div
 class="docblock"><p>Returns the timestamp in mil [...]
-</div></details></div></details></div><h2 id="trait-implementations" 
class="section-header">Trait Implementations<a href="#trait-implementations" 
class="anchor">§</a></h2><div id="trait-implementations-list"><details 
class="toggle implementors-toggle" open><summary><section 
id="impl-Clone-for-SnapshotLog" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1233">source</a><a 
href="#impl-Clone-for-SnapshotLog" class="anchor">§</a><h3 class="code-heade 
[...]
-    __D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Parti [...]
+</div><h2 id="implementations" class="section-header">Implementations<a 
href="#implementations" class="anchor">§</a></h2><div 
id="implementations-list"><details class="toggle implementors-toggle" 
open><summary><section id="impl-SnapshotLog" class="impl"><a class="src 
rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1266-1277">source</a><a 
href="#impl-SnapshotLog" class="anchor">§</a><h3 class="code-header">impl <a 
class="struct" href="struct.SnapshotLog.html" title="struct  [...]
+</div></details><details class="toggle method-toggle" open><summary><section 
id="method.timestamp_ms" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1274-1276">source</a><h4 
class="code-header">pub fn <a href="#method.timestamp_ms" 
class="fn">timestamp_ms</a>(&amp;self) -&gt; <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.i64.html";>i64</a></h4></section></summary><div
 class="docblock"><p>Returns the timestamp in mil [...]
+</div></details></div></details></div><h2 id="trait-implementations" 
class="section-header">Trait Implementations<a href="#trait-implementations" 
class="anchor">§</a></h2><div id="trait-implementations-list"><details 
class="toggle implementors-toggle" open><summary><section 
id="impl-Clone-for-SnapshotLog" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1256">source</a><a 
href="#impl-Clone-for-SnapshotLog" class="anchor">§</a><h3 class="code-heade 
[...]
+    __D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Parti [...]
 by <code>==</code>.</div></details><details class="toggle method-toggle" 
open><summary><section id="method.ne" class="method trait-impl"><span 
class="rightside"><span class="since" title="Stable since Rust version 
1.0.0">1.0.0</span> · <a class="src" 
href="https://doc.rust-lang.org/nightly/src/core/cmp.rs.html#263";>source</a></span><a
 href="#method.ne" class="anchor">§</a><h4 class="code-header">fn <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html#method.ne";
 class= [...]
-sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Serialize-for-SnapshotLog" 
class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1233">source</a><a 
href="#impl-Serialize-for-SnapshotLog" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html"; title="tr 
[...]
-    __S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section id="impl-Eq-for-SnapshotLog" 
class="impl"><a class="src rightside" href="../../src/iceberg/spe [...]
+sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-Serialize-for-SnapshotLog" 
class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#1256">source</a><a 
href="#impl-Serialize-for-SnapshotLog" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html"; title="tr 
[...]
+    __S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section id="impl-Eq-for-SnapshotLog" 
class="impl"><a class="src rightside" href="../../src/iceberg/spe [...]
     T: 'static + ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.type_id" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#141";>source</a><a 
href="#method.type_id" class="anchor">§</a><h4 class="code-header">fn <a href 
[...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#210";>source</a><a
 href="#method.borrow" class="anchor">§</a><h4 class="code-header">fn <a 
href="https:/ [...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow_mut" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#217";>source</a><a
 href="#method.borrow_mut" class="anchor">§</a><h4 class="code-header">fn <a 
href= [...]
diff --git a/api/iceberg/spec/struct.TableMetadata.html 
b/api/iceberg/spec/struct.TableMetadata.html
index c9d19543..f325d7eb 100644
--- a/api/iceberg/spec/struct.TableMetadata.html
+++ b/api/iceberg/spec/struct.TableMetadata.html
@@ -57,7 +57,7 @@ Returns an option if the <code>ref_name</code> is not 
found</p>
 </div></details></div></details></div><h2 id="trait-implementations" 
class="section-header">Trait Implementations<a href="#trait-implementations" 
class="anchor">§</a></h2><div id="trait-implementations-list"><details 
class="toggle implementors-toggle" open><summary><section 
id="impl-Clone-for-TableMetadata" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#99">source</a><a 
href="#impl-Clone-for-TableMetadata" class="anchor">§</a><h3 class="code-hea 
[...]
     __D: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserializer.html"; 
title="trait 
serde::de::Deserializer">Deserializer</a>&lt;'de&gt;,</div></h4></section></summary><div
 class='docblock'>Deserialize this value from the given Serde deserializer. <a 
href="https://docs.rs/serde/1.0.217/serde/de/trait.Deserialize.html#tymethod.deserialize";>Read
 more</a></div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section id="impl-From% [...]
 by <code>==</code>.</div></details><details class="toggle method-toggle" 
open><summary><section id="method.ne" class="method trait-impl"><span 
class="rightside"><span class="since" title="Stable since Rust version 
1.0.0">1.0.0</span> · <a class="src" 
href="https://doc.rust-lang.org/nightly/src/core/cmp.rs.html#263";>source</a></span><a
 href="#method.ne" class="anchor">§</a><h4 class="code-header">fn <a 
href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html#method.ne";
 class= [...]
-sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section 
id="impl-Serialize-for-TableMetadata" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#734-743">source</a><a 
href="#impl-Serialize-for-TableMetadata" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html"; ti [...]
+sufficient, and should not be overridden without very good 
reason.</div></details></div></details><details class="toggle 
implementors-toggle" open><summary><section 
id="impl-Serialize-for-TableMetadata" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/table_metadata.rs.html#736-745">source</a><a 
href="#impl-Serialize-for-TableMetadata" class="anchor">§</a><h3 
class="code-header">impl <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html"; ti [...]
     S: <a class="trait" 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serializer.html"; 
title="trait 
serde::ser::Serializer">Serializer</a>,</div></h4></section></summary><div 
class='docblock'>Serialize this value into the given Serde serializer. <a 
href="https://docs.rs/serde/1.0.217/serde/ser/trait.Serialize.html#tymethod.serialize";>Read
 more</a></div></details></div></details><section 
id="impl-Eq-for-TableMetadata" class="impl"><a class="src rightside" 
href="../../src/iceberg/spe [...]
     T: 'static + ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.type_id" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/any.rs.html#141";>source</a><a 
href="#method.type_id" class="anchor">§</a><h4 class="code-header">fn <a href 
[...]
     T: ?<a class="trait" 
href="https://doc.rust-lang.org/nightly/core/marker/trait.Sized.html"; 
title="trait core::marker::Sized">Sized</a>,</div></h3></section></summary><div 
class="impl-items"><details class="toggle method-toggle" open><summary><section 
id="method.borrow" class="method trait-impl"><a class="src rightside" 
href="https://doc.rust-lang.org/nightly/src/core/borrow.rs.html#210";>source</a><a
 href="#method.borrow" class="anchor">§</a><h4 class="code-header">fn <a 
href="https:/ [...]
diff --git a/api/settings.html b/api/settings.html
index 430a9162..8bb04340 100644
--- a/api/settings.html
+++ b/api/settings.html
@@ -1 +1 @@
-<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="Settings 
of 
Rustdoc"><title>Settings</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388.woff2,SourceCodePro-Regular-562
 [...]
\ No newline at end of file
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta 
name="viewport" content="width=device-width, initial-scale=1.0"><meta 
name="generator" content="rustdoc"><meta name="description" content="Settings 
of 
Rustdoc"><title>Settings</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,FiraSans-Regular-018c141bf0843ffd.woff2,FiraSans-Medium-8f9a781e4970d388.woff2,SourceCodePro-Regular-562
 [...]
\ No newline at end of file
diff --git a/api/src/iceberg/spec/table_metadata.rs.html 
b/api/src/iceberg/spec/table_metadata.rs.html
index a7be57d7..42792384 100644
--- a/api/src/iceberg/spec/table_metadata.rs.html
+++ b/api/src/iceberg/spec/table_metadata.rs.html
@@ -2764,6 +2764,127 @@
 <a href="#2764" id="2764">2764</a>
 <a href="#2765" id="2765">2765</a>
 <a href="#2766" id="2766">2766</a>
+<a href="#2767" id="2767">2767</a>
+<a href="#2768" id="2768">2768</a>
+<a href="#2769" id="2769">2769</a>
+<a href="#2770" id="2770">2770</a>
+<a href="#2771" id="2771">2771</a>
+<a href="#2772" id="2772">2772</a>
+<a href="#2773" id="2773">2773</a>
+<a href="#2774" id="2774">2774</a>
+<a href="#2775" id="2775">2775</a>
+<a href="#2776" id="2776">2776</a>
+<a href="#2777" id="2777">2777</a>
+<a href="#2778" id="2778">2778</a>
+<a href="#2779" id="2779">2779</a>
+<a href="#2780" id="2780">2780</a>
+<a href="#2781" id="2781">2781</a>
+<a href="#2782" id="2782">2782</a>
+<a href="#2783" id="2783">2783</a>
+<a href="#2784" id="2784">2784</a>
+<a href="#2785" id="2785">2785</a>
+<a href="#2786" id="2786">2786</a>
+<a href="#2787" id="2787">2787</a>
+<a href="#2788" id="2788">2788</a>
+<a href="#2789" id="2789">2789</a>
+<a href="#2790" id="2790">2790</a>
+<a href="#2791" id="2791">2791</a>
+<a href="#2792" id="2792">2792</a>
+<a href="#2793" id="2793">2793</a>
+<a href="#2794" id="2794">2794</a>
+<a href="#2795" id="2795">2795</a>
+<a href="#2796" id="2796">2796</a>
+<a href="#2797" id="2797">2797</a>
+<a href="#2798" id="2798">2798</a>
+<a href="#2799" id="2799">2799</a>
+<a href="#2800" id="2800">2800</a>
+<a href="#2801" id="2801">2801</a>
+<a href="#2802" id="2802">2802</a>
+<a href="#2803" id="2803">2803</a>
+<a href="#2804" id="2804">2804</a>
+<a href="#2805" id="2805">2805</a>
+<a href="#2806" id="2806">2806</a>
+<a href="#2807" id="2807">2807</a>
+<a href="#2808" id="2808">2808</a>
+<a href="#2809" id="2809">2809</a>
+<a href="#2810" id="2810">2810</a>
+<a href="#2811" id="2811">2811</a>
+<a href="#2812" id="2812">2812</a>
+<a href="#2813" id="2813">2813</a>
+<a href="#2814" id="2814">2814</a>
+<a href="#2815" id="2815">2815</a>
+<a href="#2816" id="2816">2816</a>
+<a href="#2817" id="2817">2817</a>
+<a href="#2818" id="2818">2818</a>
+<a href="#2819" id="2819">2819</a>
+<a href="#2820" id="2820">2820</a>
+<a href="#2821" id="2821">2821</a>
+<a href="#2822" id="2822">2822</a>
+<a href="#2823" id="2823">2823</a>
+<a href="#2824" id="2824">2824</a>
+<a href="#2825" id="2825">2825</a>
+<a href="#2826" id="2826">2826</a>
+<a href="#2827" id="2827">2827</a>
+<a href="#2828" id="2828">2828</a>
+<a href="#2829" id="2829">2829</a>
+<a href="#2830" id="2830">2830</a>
+<a href="#2831" id="2831">2831</a>
+<a href="#2832" id="2832">2832</a>
+<a href="#2833" id="2833">2833</a>
+<a href="#2834" id="2834">2834</a>
+<a href="#2835" id="2835">2835</a>
+<a href="#2836" id="2836">2836</a>
+<a href="#2837" id="2837">2837</a>
+<a href="#2838" id="2838">2838</a>
+<a href="#2839" id="2839">2839</a>
+<a href="#2840" id="2840">2840</a>
+<a href="#2841" id="2841">2841</a>
+<a href="#2842" id="2842">2842</a>
+<a href="#2843" id="2843">2843</a>
+<a href="#2844" id="2844">2844</a>
+<a href="#2845" id="2845">2845</a>
+<a href="#2846" id="2846">2846</a>
+<a href="#2847" id="2847">2847</a>
+<a href="#2848" id="2848">2848</a>
+<a href="#2849" id="2849">2849</a>
+<a href="#2850" id="2850">2850</a>
+<a href="#2851" id="2851">2851</a>
+<a href="#2852" id="2852">2852</a>
+<a href="#2853" id="2853">2853</a>
+<a href="#2854" id="2854">2854</a>
+<a href="#2855" id="2855">2855</a>
+<a href="#2856" id="2856">2856</a>
+<a href="#2857" id="2857">2857</a>
+<a href="#2858" id="2858">2858</a>
+<a href="#2859" id="2859">2859</a>
+<a href="#2860" id="2860">2860</a>
+<a href="#2861" id="2861">2861</a>
+<a href="#2862" id="2862">2862</a>
+<a href="#2863" id="2863">2863</a>
+<a href="#2864" id="2864">2864</a>
+<a href="#2865" id="2865">2865</a>
+<a href="#2866" id="2866">2866</a>
+<a href="#2867" id="2867">2867</a>
+<a href="#2868" id="2868">2868</a>
+<a href="#2869" id="2869">2869</a>
+<a href="#2870" id="2870">2870</a>
+<a href="#2871" id="2871">2871</a>
+<a href="#2872" id="2872">2872</a>
+<a href="#2873" id="2873">2873</a>
+<a href="#2874" id="2874">2874</a>
+<a href="#2875" id="2875">2875</a>
+<a href="#2876" id="2876">2876</a>
+<a href="#2877" id="2877">2877</a>
+<a href="#2878" id="2878">2878</a>
+<a href="#2879" id="2879">2879</a>
+<a href="#2880" id="2880">2880</a>
+<a href="#2881" id="2881">2881</a>
+<a href="#2882" id="2882">2882</a>
+<a href="#2883" id="2883">2883</a>
+<a href="#2884" id="2884">2884</a>
+<a href="#2885" id="2885">2885</a>
+<a href="#2886" id="2886">2886</a>
+<a href="#2887" id="2887">2887</a>
 </pre></div><pre class="rust"><code><span class="comment">// Licensed to the 
Apache Software Foundation (ASF) under one
 // or more contributor license agreements.  See the NOTICE file
 // distributed with this work for additional information
@@ -3463,12 +3584,14 @@
         <span class="kw">pub </span>location: String,
         <span class="kw">pub </span>last_updated_ms: i64,
         <span class="kw">pub </span>last_column_id: i32,
-        <span class="kw">pub </span>schema: SchemaV1,
+        <span class="doccomment">/// `schema` is optional to prioritize 
`schemas` and `current-schema-id`, allowing liberal reading of V1 metadata.
+        </span><span class="kw">pub </span>schema: <span 
class="prelude-ty">Option</span>&lt;SchemaV1&gt;,
         <span class="attr">#[serde(skip_serializing_if = <span 
class="string">"Option::is_none"</span>)]
         </span><span class="kw">pub </span>schemas: <span 
class="prelude-ty">Option</span>&lt;Vec&lt;SchemaV1&gt;&gt;,
         <span class="attr">#[serde(skip_serializing_if = <span 
class="string">"Option::is_none"</span>)]
         </span><span class="kw">pub </span>current_schema_id: <span 
class="prelude-ty">Option</span>&lt;i32&gt;,
-        <span class="kw">pub </span>partition_spec: Vec&lt;PartitionField&gt;,
+        <span class="doccomment">/// `partition_spec` is optional to 
prioritize `partition_specs`, aligning with liberal reading of potentially 
invalid V1 metadata.
+        </span><span class="kw">pub </span>partition_spec: <span 
class="prelude-ty">Option</span>&lt;Vec&lt;PartitionField&gt;&gt;,
         <span class="attr">#[serde(skip_serializing_if = <span 
class="string">"Option::is_none"</span>)]
         </span><span class="kw">pub </span>partition_specs: <span 
class="prelude-ty">Option</span>&lt;Vec&lt;PartitionSpec&gt;&gt;,
         <span class="attr">#[serde(skip_serializing_if = <span 
class="string">"Option::is_none"</span>)]
@@ -3662,61 +3785,81 @@
                 value.current_snapshot_id
             };
 
-            <span class="kw">let </span>schemas = value
-                .schemas
-                .map(|schemas| {
-                    <span class="prelude-val">Ok</span>::&lt;<span 
class="kw">_</span>, Error&gt;(HashMap::from_iter(
-                        schemas
+            <span class="kw">let </span>(schemas, current_schema_id, 
current_schema) =
+                <span class="kw">if let </span>(<span 
class="prelude-val">Some</span>(schemas_vec), <span 
class="prelude-val">Some</span>(schema_id)) =
+                    (<span class="kw-2">&amp;</span>value.schemas, 
value.current_schema_id)
+                {
+                    <span class="comment">// Option 1: Use 'schemas' + 
'current_schema_id'
+                    </span><span class="kw">let </span>schema_map = 
HashMap::from_iter(
+                        schemas_vec
+                            .clone()
                             .into_iter()
-                            .enumerate()
-                            .map(|(i, schema)| {
-                                <span class="prelude-val">Ok</span>((
-                                    schema.schema_id.unwrap_or(i <span 
class="kw">as </span>i32),
-                                    Arc::new(schema.try_into()<span 
class="question-mark">?</span>),
-                                ))
+                            .map(|schema| {
+                                <span class="kw">let </span>schema: Schema = 
schema.try_into()<span class="question-mark">?</span>;
+                                <span 
class="prelude-val">Ok</span>((schema.schema_id(), Arc::new(schema)))
                             })
-                            .collect::&lt;<span 
class="prelude-ty">Result</span>&lt;Vec&lt;<span class="kw">_</span>&gt;, 
Error&gt;&gt;()<span class="question-mark">?
-                            </span>.into_iter(),
-                    ))
-                })
-                .or_else(|| {
-                    <span 
class="prelude-val">Some</span>(value.schema.try_into().map(|schema: Schema| {
-                        HashMap::from_iter(<span 
class="macro">vec!</span>[(schema.schema_id(), Arc::new(schema))])
-                    }))
-                })
-                .transpose()<span class="question-mark">?
-                </span>.unwrap_or_default();
-            <span class="kw">let </span>current_schema_id = value
-                .current_schema_id
-                .unwrap_or_else(|| 
schemas.keys().copied().max().unwrap_or_default());
-            <span class="kw">let </span>current_schema = schemas
-                .get(<span class="kw-2">&amp;</span>current_schema_id)
-                .ok_or_else(|| {
-                    Error::new(
+                            .collect::&lt;<span 
class="prelude-ty">Result</span>&lt;Vec&lt;<span class="kw">_</span>&gt;, 
Error&gt;&gt;()<span class="question-mark">?</span>,
+                    );
+
+                    <span class="kw">let </span>schema = schema_map
+                        .get(<span class="kw-2">&amp;</span>schema_id)
+                        .ok_or_else(|| {
+                            Error::new(
+                                ErrorKind::DataInvalid,
+                                <span class="macro">format!</span>(
+                                    <span class="string">"No schema exists 
with the current schema id {}."</span>,
+                                    schema_id
+                                ),
+                            )
+                        })<span class="question-mark">?
+                        </span>.clone();
+                    (schema_map, schema_id, schema)
+                } <span class="kw">else if let </span><span 
class="prelude-val">Some</span>(schema) = value.schema {
+                    <span class="comment">// Option 2: Fall back to `schema`
+                    </span><span class="kw">let </span>schema: Schema = 
schema.try_into()<span class="question-mark">?</span>;
+                    <span class="kw">let </span>schema_id = schema.schema_id();
+                    <span class="kw">let </span>schema_arc = Arc::new(schema);
+                    <span class="kw">let </span>schema_map = 
HashMap::from_iter(<span class="macro">vec!</span>[(schema_id, 
schema_arc.clone())]);
+                    (schema_map, schema_id, schema_arc)
+                } <span class="kw">else </span>{
+                    <span class="comment">// Option 3: No valid schema 
configuration found
+                    </span><span class="kw">return </span><span 
class="prelude-val">Err</span>(Error::new(
                         ErrorKind::DataInvalid,
-                        <span class="macro">format!</span>(
-                            <span class="string">"No schema exists with the 
current schema id {}."</span>,
-                            current_schema_id
-                        ),
-                    )
-                })<span class="question-mark">?
-                </span>.clone();
+                        <span class="string">"No valid schema configuration 
found in table metadata"</span>,
+                    ));
+                };
 
-            <span class="kw">let </span>partition_specs = <span 
class="kw">match </span>value.partition_specs {
-                <span class="prelude-val">Some</span>(partition_specs) =&gt; 
partition_specs,
-                <span class="prelude-val">None </span>=&gt; <span 
class="macro">vec!</span>[PartitionSpec::builder(current_schema.clone())
+            <span class="comment">// Prioritize 'partition_specs' over 
'partition_spec'
+            </span><span class="kw">let </span>partition_specs = <span 
class="kw">if let </span><span class="prelude-val">Some</span>(specs_vec) = 
value.partition_specs {
+                <span class="comment">// Option 1: Use 'partition_specs'
+                </span>specs_vec
+                    .into_iter()
+                    .map(|x| (x.spec_id(), Arc::new(x)))
+                    .collect::&lt;HashMap&lt;<span class="kw">_</span>, <span 
class="kw">_</span>&gt;&gt;()
+            } <span class="kw">else if let </span><span 
class="prelude-val">Some</span>(partition_spec) = value.partition_spec {
+                <span class="comment">// Option 2: Fall back to 
'partition_spec'
+                </span><span class="kw">let </span>spec = 
PartitionSpec::builder(current_schema.clone())
                     .with_spec_id(DEFAULT_PARTITION_SPEC_ID)
-                    
.add_unbound_fields(value.partition_spec.into_iter().map(|f| 
f.into_unbound()))<span class="question-mark">?
-                    </span>.build()<span class="question-mark">?</span>],
-            }
-            .into_iter()
-            .map(|x| (x.spec_id(), Arc::new(x)))
-            .collect::&lt;HashMap&lt;<span class="kw">_</span>, <span 
class="kw">_</span>&gt;&gt;();
+                    .add_unbound_fields(partition_spec.into_iter().map(|f| 
f.into_unbound()))<span class="question-mark">?
+                    </span>.build()<span class="question-mark">?</span>;
 
-            <span class="kw">let </span>default_spec_id = value
+                HashMap::from_iter(<span 
class="macro">vec!</span>[(DEFAULT_PARTITION_SPEC_ID, Arc::new(spec))])
+            } <span class="kw">else </span>{
+                <span class="comment">// Option 3: Create empty partition spec
+                </span><span class="kw">let </span>spec = 
PartitionSpec::builder(current_schema.clone())
+                    .with_spec_id(DEFAULT_PARTITION_SPEC_ID)
+                    .build()<span class="question-mark">?</span>;
+
+                HashMap::from_iter(<span 
class="macro">vec!</span>[(DEFAULT_PARTITION_SPEC_ID, Arc::new(spec))])
+            };
+
+            <span class="comment">// Get the default_spec_id, prioritizing the 
explicit value if provided
+            </span><span class="kw">let </span>default_spec_id = value
                 .default_spec_id
                 .unwrap_or_else(|| 
partition_specs.keys().copied().max().unwrap_or_default());
-            <span class="kw">let </span>default_spec: PartitionSpecRef = 
partition_specs
+
+            <span class="comment">// Get the default spec
+            </span><span class="kw">let </span>default_spec: PartitionSpecRef 
= partition_specs
                 .get(<span class="kw-2">&amp;</span>default_spec_id)
                 .map(|x| Arc::unwrap_or_clone(x.clone()))
                 .ok_or_else(|| {
@@ -3867,16 +4010,17 @@
                 location: v.location,
                 last_updated_ms: v.last_updated_ms,
                 last_column_id: v.last_column_id,
-                schema: v
-                    .schemas
-                    .get(<span class="kw-2">&amp;</span>v.current_schema_id)
-                    .ok_or(Error::new(
-                        ErrorKind::Unexpected,
-                        <span class="string">"current_schema_id not found in 
schemas"</span>,
-                    ))<span class="question-mark">?
-                    </span>.as_ref()
-                    .clone()
-                    .into(),
+                schema: <span class="prelude-val">Some</span>(
+                    v.schemas
+                        .get(<span 
class="kw-2">&amp;</span>v.current_schema_id)
+                        .ok_or(Error::new(
+                            ErrorKind::Unexpected,
+                            <span class="string">"current_schema_id not found 
in schemas"</span>,
+                        ))<span class="question-mark">?
+                        </span>.as_ref()
+                        .clone()
+                        .into(),
+                ),
                 schemas: <span class="prelude-val">Some</span>(
                     v.schemas
                         .into_values()
@@ -3888,7 +4032,7 @@
                         .collect(),
                 ),
                 current_schema_id: <span 
class="prelude-val">Some</span>(v.current_schema_id),
-                partition_spec: v.default_spec.fields().to_vec(),
+                partition_spec: <span 
class="prelude-val">Some</span>(v.default_spec.fields().to_vec()),
                 partition_specs: <span class="prelude-val">Some</span>(
                     v.partition_specs
                         .into_values()
@@ -5351,6 +5495,104 @@
         check_table_metadata_serde(<span class="kw-2">&amp;</span>metadata, 
expected);
     }
 
+    <span class="attr">#[test]
+    </span><span class="kw">fn </span>test_table_metadata_v1_compat() {
+        <span class="kw">let </span>metadata =
+            fs::read_to_string(<span 
class="string">"testdata/table_metadata/TableMetadataV1Compat.json"</span>).unwrap();
+
+        <span class="comment">// Deserialize the JSON to verify it works
+        </span><span class="kw">let </span>desered_type: TableMetadata = 
serde_json::from_str(<span class="kw-2">&amp;</span>metadata)
+            .expect(<span class="string">"Failed to deserialize 
TableMetadataV1Compat.json"</span>);
+
+        <span class="comment">// Verify some key fields match
+        </span><span 
class="macro">assert_eq!</span>(desered_type.format_version(), 
FormatVersion::V1);
+        <span class="macro">assert_eq!</span>(
+            desered_type.uuid(),
+            Uuid::parse_str(<span 
class="string">"3276010d-7b1d-488c-98d8-9025fc4fde6b"</span>).unwrap()
+        );
+        <span class="macro">assert_eq!</span>(
+            desered_type.location(),
+            <span 
class="string">"s3://bucket/warehouse/iceberg/glue.db/table_name"
+        </span>);
+        <span class="macro">assert_eq!</span>(desered_type.last_updated_ms(), 
<span class="number">1727773114005</span>);
+        <span 
class="macro">assert_eq!</span>(desered_type.current_schema_id(), <span 
class="number">0</span>);
+    }
+
+    <span class="attr">#[test]
+    </span><span class="kw">fn 
</span>test_table_metadata_v1_schemas_without_current_id() {
+        <span class="kw">let </span>metadata = fs::read_to_string(
+            <span 
class="string">"testdata/table_metadata/TableMetadataV1SchemasWithoutCurrentId.json"</span>,
+        )
+        .unwrap();
+
+        <span class="comment">// Deserialize the JSON - this should succeed by 
using the 'schema' field instead of 'schemas'
+        </span><span class="kw">let </span>desered_type: TableMetadata = 
serde_json::from_str(<span class="kw-2">&amp;</span>metadata)
+            .expect(<span class="string">"Failed to deserialize 
TableMetadataV1SchemasWithoutCurrentId.json"</span>);
+
+        <span class="comment">// Verify it used the 'schema' field
+        </span><span 
class="macro">assert_eq!</span>(desered_type.format_version(), 
FormatVersion::V1);
+        <span class="macro">assert_eq!</span>(
+            desered_type.uuid(),
+            Uuid::parse_str(<span 
class="string">"d20125c8-7284-442c-9aea-15fee620737c"</span>).unwrap()
+        );
+
+        <span class="comment">// Get the schema and verify it has the expected 
fields
+        </span><span class="kw">let </span>schema = 
desered_type.current_schema();
+        <span 
class="macro">assert_eq!</span>(schema.as_struct().fields().len(), <span 
class="number">3</span>);
+        <span 
class="macro">assert_eq!</span>(schema.as_struct().fields()[<span 
class="number">0</span>].name, <span class="string">"x"</span>);
+        <span 
class="macro">assert_eq!</span>(schema.as_struct().fields()[<span 
class="number">1</span>].name, <span class="string">"y"</span>);
+        <span 
class="macro">assert_eq!</span>(schema.as_struct().fields()[<span 
class="number">2</span>].name, <span class="string">"z"</span>);
+    }
+
+    <span class="attr">#[test]
+    </span><span class="kw">fn </span>test_table_metadata_v1_no_valid_schema() 
{
+        <span class="kw">let </span>metadata =
+            fs::read_to_string(<span 
class="string">"testdata/table_metadata/TableMetadataV1NoValidSchema.json"</span>)
+                .unwrap();
+
+        <span class="comment">// Deserialize the JSON - this should fail 
because neither schemas + current_schema_id nor schema is valid
+        </span><span class="kw">let </span>desered: <span 
class="prelude-ty">Result</span>&lt;TableMetadata, serde_json::Error&gt; = 
serde_json::from_str(<span class="kw-2">&amp;</span>metadata);
+
+        <span class="macro">assert!</span>(desered.is_err());
+        <span class="kw">let </span>error_message = 
desered.unwrap_err().to_string();
+        <span class="macro">assert!</span>(
+            error_message.contains(<span class="string">"No valid schema 
configuration found"</span>),
+            <span class="string">"Expected error about no valid schema 
configuration, got: {}"</span>,
+            error_message
+        );
+    }
+
+    <span class="attr">#[test]
+    </span><span class="kw">fn 
</span>test_table_metadata_v1_partition_specs_without_default_id() {
+        <span class="kw">let </span>metadata = fs::read_to_string(
+            <span 
class="string">"testdata/table_metadata/TableMetadataV1PartitionSpecsWithoutDefaultId.json"</span>,
+        )
+        .unwrap();
+
+        <span class="comment">// Deserialize the JSON - this should succeed by 
inferring default_spec_id as the max spec ID
+        </span><span class="kw">let </span>desered_type: TableMetadata = 
serde_json::from_str(<span class="kw-2">&amp;</span>metadata)
+            .expect(<span class="string">"Failed to deserialize 
TableMetadataV1PartitionSpecsWithoutDefaultId.json"</span>);
+
+        <span class="comment">// Verify basic metadata
+        </span><span 
class="macro">assert_eq!</span>(desered_type.format_version(), 
FormatVersion::V1);
+        <span class="macro">assert_eq!</span>(
+            desered_type.uuid(),
+            Uuid::parse_str(<span 
class="string">"d20125c8-7284-442c-9aea-15fee620737c"</span>).unwrap()
+        );
+
+        <span class="comment">// Verify partition specs
+        </span><span 
class="macro">assert_eq!</span>(desered_type.default_partition_spec_id(), <span 
class="number">2</span>); <span class="comment">// Should pick the largest spec 
ID (2)
+        </span><span 
class="macro">assert_eq!</span>(desered_type.partition_specs.len(), <span 
class="number">2</span>);
+
+        <span class="comment">// Verify the default spec has the expected 
fields
+        </span><span class="kw">let </span>default_spec = <span 
class="kw-2">&amp;</span>desered_type.default_spec;
+        <span class="macro">assert_eq!</span>(default_spec.spec_id(), <span 
class="number">2</span>);
+        <span class="macro">assert_eq!</span>(default_spec.fields().len(), 
<span class="number">1</span>);
+        <span class="macro">assert_eq!</span>(default_spec.fields()[<span 
class="number">0</span>].name, <span class="string">"y"</span>);
+        <span class="macro">assert_eq!</span>(default_spec.fields()[<span 
class="number">0</span>].transform, Transform::Identity);
+        <span class="macro">assert_eq!</span>(default_spec.fields()[<span 
class="number">0</span>].source_id, <span class="number">2</span>);
+    }
+
     <span class="attr">#[test]
     </span><span class="kw">fn 
</span>test_table_metadata_v2_schema_not_found() {
         <span class="kw">let </span>metadata =

Reply via email to