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

github-actions[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 73a415b99 deploy: e6b2ed4fb9cd51ba772074ff874f0b8cb7b6bef8
73a415b99 is described below

commit 73a415b998978f372be49259e687d5c973b17ebb
Author: github-merge-queue[bot] 
<github-merge-queue[bot]@users.noreply.github.com>
AuthorDate: Thu Oct 15 08:49:31 2026 +0000

    deploy: e6b2ed4fb9cd51ba772074ff874f0b8cb7b6bef8
---
 api/iceberg/spec/struct.Datum.html        |   6 +-
 api/src/iceberg/spec/partition.rs.html    | 338 ++++++++++++++++--------------
 api/src/iceberg/spec/values/datum.rs.html |  73 ++++++-
 3 files changed, 250 insertions(+), 167 deletions(-)

diff --git a/api/iceberg/spec/struct.Datum.html 
b/api/iceberg/spec/struct.Datum.html
index b12e10e0f..a8b068591 100644
--- a/api/iceberg/spec/struct.Datum.html
+++ b/api/iceberg/spec/struct.Datum.html
@@ -2,7 +2,7 @@
 guaranteed to be correct when used.</p>
 <p>By default, we decouple the type and value of a literal, so we can use 
avoid the cost of storing extra type info
 for each literal. But associate type with literal can be useful in some cases, 
for example, in unbound expression.</p>
-</div></details><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-Datum" class="impl"><a 
class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#360-1236">Source</a><a 
href="#impl-Datum" class="anchor">§</a><h3 class="code-header">impl <a 
class="struct" href="struct.Datum.html" title="struct iceberg::sp [...]
+</div></details><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-Datum" class="impl"><a 
class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#360-1240">Source</a><a 
href="#impl-Datum" class="anchor">§</a><h3 class="code-header">impl <a 
class="struct" href="struct.Datum.html" title="struct iceberg::sp [...]
 <p>See <a 
href="https://iceberg.apache.org/spec/#binary-single-value-serialization";>this 
spec</a> for reference.</p>
 </div></details><details class="toggle method-toggle" open><summary><section 
id="method.to_bytes" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#439-487">Source</a><h4 
class="code-header">pub fn <a href="#method.to_bytes" 
class="fn">to_bytes</a>(&amp;self) -&gt; <a class="type" 
href="../type.Result.html" title="type iceberg::Result">Result</a>&lt;<a 
class="struct" href="struct.ByteBuf.html" title="struct 
iceberg::spec::ByteBuf">ByteBuf</a>&gt;</ [...]
 <p>See <a 
href="https://iceberg.apache.org/spec/#binary-single-value-serialization";>this 
spec</a> for reference.</p>
@@ -239,8 +239,10 @@ Use <a href="struct.Datum.html#method.decimal" 
title="associated function iceber
 </div></details><details class="toggle method-toggle" open><summary><section 
id="method.data_type" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#1212-1214">Source</a><h4 
class="code-header">pub fn <a href="#method.data_type" 
class="fn">data_type</a>(&amp;self) -&gt; &amp;<a class="enum" 
href="enum.PrimitiveType.html" title="enum 
iceberg::spec::PrimitiveType">PrimitiveType</a></h4></section></summary><div 
class="docblock"><p>Get the primitive ty [...]
 </div></details><details class="toggle method-toggle" open><summary><section 
id="method.is_nan" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#1218-1224">Source</a><h4 
class="code-header">pub fn <a href="#method.is_nan" 
class="fn">is_nan</a>(&amp;self) -&gt; <a class="primitive" 
href="https://doc.rust-lang.org/nightly/std/primitive.bool.html";>bool</a></h4></section></summary><div
 class="docblock"><p>Returns true if the Literal represents a primi [...]
 that can be a NaN, and that it’s value is NaN</p>
-</div></details><details class="toggle method-toggle" open><summary><section 
id="method.to_human_string" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#1230-1235">Source</a><h4 
class="code-header">pub fn <a href="#method.to_human_string" 
class="fn">to_human_string</a>(&amp;self) -&gt; <a class="struct" 
href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html"; 
title="struct alloc::string::String">String</a></h4></section></summary> [...]
+</div></details><details class="toggle method-toggle" open><summary><section 
id="method.to_human_string" class="method"><a class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#1232-1239">Source</a><h4 
class="code-header">pub fn <a href="#method.to_human_string" 
class="fn">to_human_string</a>(&amp;self) -&gt; <a class="struct" 
href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html"; 
title="struct alloc::string::String">String</a></h4></section></summary> [...]
 <p>For string literals, this returns the raw string value without quotes.
+Float and double literals are formatted like Java’s 
<code>Float.toString</code> /
+<code>Double.toString</code> (JDK 19+).
 For all other literals, it falls back to <a 
href="https://doc.rust-lang.org/nightly/alloc/string/trait.ToString.html#tymethod.to_string";
 title="method 
alloc::string::ToString::to_string"><code>to_string()</code></a>.</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-Datum" class="impl"><a class="src rightside" 
href="../../src/iceberg/spec/values/datum.rs.html#57">Source</a><a 
href="#impl-Clone-for-Datum" class="anchor">§</a><h3 class="code-header">impl 
<a class [...]
     H: <a class="trait" 
href="https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html"; 
title="trait core::hash::Hasher">Hasher</a>,
diff --git a/api/src/iceberg/spec/partition.rs.html 
b/api/src/iceberg/spec/partition.rs.html
index 2f13849fb..75f58bf39 100644
--- a/api/src/iceberg/spec/partition.rs.html
+++ b/api/src/iceberg/spec/partition.rs.html
@@ -1952,163 +1952,189 @@
 <a href=#1952 id=1952 data-nosnippet>1952</a>    }
 <a href=#1953 id=1953 data-nosnippet>1953</a>
 <a href=#1954 id=1954 data-nosnippet>1954</a>    <span class="attr">#[test]
-<a href=#1955 id=1955 data-nosnippet>1955</a>    </span><span class="kw">fn 
</span>test_partition_to_path_escaped_strings() {
+<a href=#1955 id=1955 data-nosnippet>1955</a>    </span><span class="kw">fn 
</span>test_partition_to_path_float_matches_java() {
 <a href=#1956 id=1956 data-nosnippet>1956</a>        <span class="kw">let 
</span>schema = Schema::builder()
 <a href=#1957 id=1957 data-nosnippet>1957</a>            .with_fields(<span 
class="macro">vec!</span>[
-<a href=#1958 id=1958 data-nosnippet>1958</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"\"esc\"#1"</span>, Type::Primitive(PrimitiveType::String))
-<a href=#1959 id=1959 data-nosnippet>1959</a>                    .into(),
-<a href=#1960 id=1960 data-nosnippet>1960</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"data"</span>, Type::Primitive(PrimitiveType::String)).into(),
-<a href=#1961 id=1961 data-nosnippet>1961</a>            ])
-<a href=#1962 id=1962 data-nosnippet>1962</a>            .build()
-<a href=#1963 id=1963 data-nosnippet>1963</a>            .unwrap();
-<a href=#1964 id=1964 data-nosnippet>1964</a>
-<a href=#1965 id=1965 data-nosnippet>1965</a>        <span class="kw">let 
</span>spec = PartitionSpec::builder(schema.clone())
-<a href=#1966 id=1966 data-nosnippet>1966</a>            
.add_partition_field(<span class="string">"\"esc\"#1"</span>, <span 
class="string">"\"esc\"#1"</span>, Transform::Identity)
-<a href=#1967 id=1967 data-nosnippet>1967</a>            .unwrap()
-<a href=#1968 id=1968 data-nosnippet>1968</a>            .build()
-<a href=#1969 id=1969 data-nosnippet>1969</a>            .unwrap();
-<a href=#1970 id=1970 data-nosnippet>1970</a>
-<a href=#1971 id=1971 data-nosnippet>1971</a>        <span class="kw">let 
</span>data = Struct::from_iter([
-<a href=#1972 id=1972 data-nosnippet>1972</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"a/b/c/d"</span>)),
-<a href=#1973 id=1973 data-nosnippet>1973</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"val#1"</span>)),
-<a href=#1974 id=1974 data-nosnippet>1974</a>        ]);
-<a href=#1975 id=1975 data-nosnippet>1975</a>
-<a href=#1976 id=1976 data-nosnippet>1976</a>        <span 
class="macro">assert_eq!</span>(
-<a href=#1977 id=1977 data-nosnippet>1977</a>            
spec.partition_to_path(<span class="kw-2">&amp;</span>data, schema.into()),
-<a href=#1978 id=1978 data-nosnippet>1978</a>            <span 
class="string">"%22esc%22%231=a%2Fb%2Fc%2Fd"
-<a href=#1979 id=1979 data-nosnippet>1979</a>        </span>);
-<a href=#1980 id=1980 data-nosnippet>1980</a>    }
-<a href=#1981 id=1981 data-nosnippet>1981</a>
-<a href=#1982 id=1982 data-nosnippet>1982</a>    <span class="attr">#[test]
-<a href=#1983 id=1983 data-nosnippet>1983</a>    </span><span class="kw">fn 
</span>test_partition_to_path_escaped_field_name() {
-<a href=#1984 id=1984 data-nosnippet>1984</a>        <span class="kw">let 
</span>schema = Schema::builder()
-<a href=#1985 id=1985 data-nosnippet>1985</a>            .with_fields(<span 
class="macro">vec!</span>[
-<a href=#1986 id=1986 data-nosnippet>1986</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"\"esc\"#1"</span>, Type::Primitive(PrimitiveType::String))
-<a href=#1987 id=1987 data-nosnippet>1987</a>                    .into(),
-<a href=#1988 id=1988 data-nosnippet>1988</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"data"</span>, Type::Primitive(PrimitiveType::String)).into(),
-<a href=#1989 id=1989 data-nosnippet>1989</a>            ])
-<a href=#1990 id=1990 data-nosnippet>1990</a>            .build()
-<a href=#1991 id=1991 data-nosnippet>1991</a>            .unwrap();
-<a href=#1992 id=1992 data-nosnippet>1992</a>
-<a href=#1993 id=1993 data-nosnippet>1993</a>        <span class="kw">let 
</span>spec = PartitionSpec::builder(schema.clone())
-<a href=#1994 id=1994 data-nosnippet>1994</a>            
.add_partition_field(<span class="string">"data"</span>, <span 
class="string">"data"</span>, Transform::Identity)
-<a href=#1995 id=1995 data-nosnippet>1995</a>            .unwrap()
-<a href=#1996 id=1996 data-nosnippet>1996</a>            
.add_partition_field(<span class="string">"data"</span>, <span 
class="string">"data_truc_10"</span>, Transform::Truncate(<span 
class="number">10</span>))
-<a href=#1997 id=1997 data-nosnippet>1997</a>            .unwrap()
-<a href=#1998 id=1998 data-nosnippet>1998</a>            .build()
-<a href=#1999 id=1999 data-nosnippet>1999</a>            .unwrap();
-<a href=#2000 id=2000 data-nosnippet>2000</a>
-<a href=#2001 id=2001 data-nosnippet>2001</a>        <span class="kw">let 
</span>data = Struct::from_iter([
-<a href=#2002 id=2002 data-nosnippet>2002</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"a/b/c/d"</span>)),
-<a href=#2003 id=2003 data-nosnippet>2003</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"a/b/c/d"</span>)),
-<a href=#2004 id=2004 data-nosnippet>2004</a>        ]);
-<a href=#2005 id=2005 data-nosnippet>2005</a>
-<a href=#2006 id=2006 data-nosnippet>2006</a>        <span 
class="macro">assert_eq!</span>(
-<a href=#2007 id=2007 data-nosnippet>2007</a>            
spec.partition_to_path(<span class="kw-2">&amp;</span>data, schema.into()),
-<a href=#2008 id=2008 data-nosnippet>2008</a>            <span 
class="string">"data=a%2Fb%2Fc%2Fd/data_truc_10=a%2Fb%2Fc%2Fd"
-<a href=#2009 id=2009 data-nosnippet>2009</a>        </span>);
-<a href=#2010 id=2010 data-nosnippet>2010</a>    }
-<a href=#2011 id=2011 data-nosnippet>2011</a>
-<a href=#2012 id=2012 data-nosnippet>2012</a>    <span class="attr">#[test]
-<a href=#2013 id=2013 data-nosnippet>2013</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_reads_source_ids_only() {
-<a href=#2014 id=2014 data-nosnippet>2014</a>        <span class="kw">let 
</span>field: UnboundPartitionField = serde_json::from_str(
-<a href=#2015 id=2015 data-nosnippet>2015</a>            <span 
class="string">r#"{"source-ids": [1, 2], "name": "m", "transform": 
"bucket[4]"}"#</span>,
-<a href=#2016 id=2016 data-nosnippet>2016</a>        )
-<a href=#2017 id=2017 data-nosnippet>2017</a>        .unwrap();
+<a href=#1958 id=1958 data-nosnippet>1958</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"d"</span>, Type::Primitive(PrimitiveType::Double)).into(),
+<a href=#1959 id=1959 data-nosnippet>1959</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"f"</span>, Type::Primitive(PrimitiveType::Float)).into(),
+<a href=#1960 id=1960 data-nosnippet>1960</a>            ])
+<a href=#1961 id=1961 data-nosnippet>1961</a>            .build()
+<a href=#1962 id=1962 data-nosnippet>1962</a>            .unwrap();
+<a href=#1963 id=1963 data-nosnippet>1963</a>
+<a href=#1964 id=1964 data-nosnippet>1964</a>        <span class="kw">let 
</span>spec = PartitionSpec::builder(schema.clone())
+<a href=#1965 id=1965 data-nosnippet>1965</a>            
.add_partition_field(<span class="string">"d"</span>, <span 
class="string">"d"</span>, Transform::Identity)
+<a href=#1966 id=1966 data-nosnippet>1966</a>            .unwrap()
+<a href=#1967 id=1967 data-nosnippet>1967</a>            
.add_partition_field(<span class="string">"f"</span>, <span 
class="string">"f"</span>, Transform::Identity)
+<a href=#1968 id=1968 data-nosnippet>1968</a>            .unwrap()
+<a href=#1969 id=1969 data-nosnippet>1969</a>            .build()
+<a href=#1970 id=1970 data-nosnippet>1970</a>            .unwrap();
+<a href=#1971 id=1971 data-nosnippet>1971</a>
+<a href=#1972 id=1972 data-nosnippet>1972</a>        <span class="kw">let 
</span>data = Struct::from_iter([<span 
class="prelude-val">Some</span>(Literal::double(<span 
class="number">1.0</span>)), <span 
class="prelude-val">Some</span>(Literal::float(<span 
class="number">1.0e7_f32</span>))]);
+<a href=#1973 id=1973 data-nosnippet>1973</a>
+<a href=#1974 id=1974 data-nosnippet>1974</a>        <span 
class="macro">assert_eq!</span>(
+<a href=#1975 id=1975 data-nosnippet>1975</a>            
spec.partition_to_path(<span class="kw-2">&amp;</span>data, schema.into()),
+<a href=#1976 id=1976 data-nosnippet>1976</a>            <span 
class="string">"d=1.0/f=1.0E7"
+<a href=#1977 id=1977 data-nosnippet>1977</a>        </span>);
+<a href=#1978 id=1978 data-nosnippet>1978</a>    }
+<a href=#1979 id=1979 data-nosnippet>1979</a>
+<a href=#1980 id=1980 data-nosnippet>1980</a>    <span class="attr">#[test]
+<a href=#1981 id=1981 data-nosnippet>1981</a>    </span><span class="kw">fn 
</span>test_partition_to_path_escaped_strings() {
+<a href=#1982 id=1982 data-nosnippet>1982</a>        <span class="kw">let 
</span>schema = Schema::builder()
+<a href=#1983 id=1983 data-nosnippet>1983</a>            .with_fields(<span 
class="macro">vec!</span>[
+<a href=#1984 id=1984 data-nosnippet>1984</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"\"esc\"#1"</span>, Type::Primitive(PrimitiveType::String))
+<a href=#1985 id=1985 data-nosnippet>1985</a>                    .into(),
+<a href=#1986 id=1986 data-nosnippet>1986</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"data"</span>, Type::Primitive(PrimitiveType::String)).into(),
+<a href=#1987 id=1987 data-nosnippet>1987</a>            ])
+<a href=#1988 id=1988 data-nosnippet>1988</a>            .build()
+<a href=#1989 id=1989 data-nosnippet>1989</a>            .unwrap();
+<a href=#1990 id=1990 data-nosnippet>1990</a>
+<a href=#1991 id=1991 data-nosnippet>1991</a>        <span class="kw">let 
</span>spec = PartitionSpec::builder(schema.clone())
+<a href=#1992 id=1992 data-nosnippet>1992</a>            
.add_partition_field(<span class="string">"\"esc\"#1"</span>, <span 
class="string">"\"esc\"#1"</span>, Transform::Identity)
+<a href=#1993 id=1993 data-nosnippet>1993</a>            .unwrap()
+<a href=#1994 id=1994 data-nosnippet>1994</a>            .build()
+<a href=#1995 id=1995 data-nosnippet>1995</a>            .unwrap();
+<a href=#1996 id=1996 data-nosnippet>1996</a>
+<a href=#1997 id=1997 data-nosnippet>1997</a>        <span class="kw">let 
</span>data = Struct::from_iter([
+<a href=#1998 id=1998 data-nosnippet>1998</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"a/b/c/d"</span>)),
+<a href=#1999 id=1999 data-nosnippet>1999</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"val#1"</span>)),
+<a href=#2000 id=2000 data-nosnippet>2000</a>        ]);
+<a href=#2001 id=2001 data-nosnippet>2001</a>
+<a href=#2002 id=2002 data-nosnippet>2002</a>        <span 
class="macro">assert_eq!</span>(
+<a href=#2003 id=2003 data-nosnippet>2003</a>            
spec.partition_to_path(<span class="kw-2">&amp;</span>data, schema.into()),
+<a href=#2004 id=2004 data-nosnippet>2004</a>            <span 
class="string">"%22esc%22%231=a%2Fb%2Fc%2Fd"
+<a href=#2005 id=2005 data-nosnippet>2005</a>        </span>);
+<a href=#2006 id=2006 data-nosnippet>2006</a>    }
+<a href=#2007 id=2007 data-nosnippet>2007</a>
+<a href=#2008 id=2008 data-nosnippet>2008</a>    <span class="attr">#[test]
+<a href=#2009 id=2009 data-nosnippet>2009</a>    </span><span class="kw">fn 
</span>test_partition_to_path_escaped_field_name() {
+<a href=#2010 id=2010 data-nosnippet>2010</a>        <span class="kw">let 
</span>schema = Schema::builder()
+<a href=#2011 id=2011 data-nosnippet>2011</a>            .with_fields(<span 
class="macro">vec!</span>[
+<a href=#2012 id=2012 data-nosnippet>2012</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"\"esc\"#1"</span>, Type::Primitive(PrimitiveType::String))
+<a href=#2013 id=2013 data-nosnippet>2013</a>                    .into(),
+<a href=#2014 id=2014 data-nosnippet>2014</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"data"</span>, Type::Primitive(PrimitiveType::String)).into(),
+<a href=#2015 id=2015 data-nosnippet>2015</a>            ])
+<a href=#2016 id=2016 data-nosnippet>2016</a>            .build()
+<a href=#2017 id=2017 data-nosnippet>2017</a>            .unwrap();
 <a href=#2018 id=2018 data-nosnippet>2018</a>
-<a href=#2019 id=2019 data-nosnippet>2019</a>        <span 
class="macro">assert_eq!</span>([<span class="number">1</span>, <span 
class="number">2</span>], field.source_ids());
-<a href=#2020 id=2020 data-nosnippet>2020</a>        <span class="comment">// 
a multi-argument field has no single source id
-<a href=#2021 id=2021 data-nosnippet>2021</a>        </span><span 
class="macro">assert!</span>(
-<a href=#2022 id=2022 data-nosnippet>2022</a>            field
-<a href=#2023 id=2023 data-nosnippet>2023</a>                .source_id()
-<a href=#2024 id=2024 data-nosnippet>2024</a>                .unwrap_err()
-<a href=#2025 id=2025 data-nosnippet>2025</a>                .to_string()
-<a href=#2026 id=2026 data-nosnippet>2026</a>                .contains(<span 
class="string">"has no single source id"</span>)
-<a href=#2027 id=2027 data-nosnippet>2027</a>        );
-<a href=#2028 id=2028 data-nosnippet>2028</a>
-<a href=#2029 id=2029 data-nosnippet>2029</a>        <span class="kw">let 
</span>serialized = serde_json::to_value(<span 
class="kw-2">&amp;</span>field).unwrap();
-<a href=#2030 id=2030 data-nosnippet>2030</a>        <span 
class="macro">assert_eq!</span>(
-<a href=#2031 id=2031 data-nosnippet>2031</a>            <span 
class="prelude-val">Some</span>(<span class="kw-2">&amp;</span><span 
class="macro">serde_json::json!</span>([<span class="number">1</span>, <span 
class="number">2</span>])),
-<a href=#2032 id=2032 data-nosnippet>2032</a>            serialized.get(<span 
class="string">"source-ids"</span>)
-<a href=#2033 id=2033 data-nosnippet>2033</a>        );
-<a href=#2034 id=2034 data-nosnippet>2034</a>        <span 
class="macro">assert!</span>(serialized.get(<span 
class="string">"source-id"</span>).is_none());
-<a href=#2035 id=2035 data-nosnippet>2035</a>    }
-<a href=#2036 id=2036 data-nosnippet>2036</a>
-<a href=#2037 id=2037 data-nosnippet>2037</a>    <span class="attr">#[test]
-<a href=#2038 id=2038 data-nosnippet>2038</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_single_source_id_round_trip() {
-<a href=#2039 id=2039 data-nosnippet>2039</a>        <span class="kw">let 
</span>field: UnboundPartitionField =
-<a href=#2040 id=2040 data-nosnippet>2040</a>            
serde_json::from_str(<span class="string">r#"{"source-id": 1, "name": "m", 
"transform": "identity"}"#</span>)
-<a href=#2041 id=2041 data-nosnippet>2041</a>                .unwrap();
-<a href=#2042 id=2042 data-nosnippet>2042</a>
-<a href=#2043 id=2043 data-nosnippet>2043</a>        <span 
class="macro">assert_eq!</span>(<span class="number">1</span>, 
field.source_id().unwrap());
-<a href=#2044 id=2044 data-nosnippet>2044</a>        <span 
class="macro">assert_eq!</span>([<span class="number">1</span>], 
field.source_ids());
-<a href=#2045 id=2045 data-nosnippet>2045</a>
-<a href=#2046 id=2046 data-nosnippet>2046</a>        <span class="comment">// 
a single-argument field keeps writing source-id
-<a href=#2047 id=2047 data-nosnippet>2047</a>        </span><span 
class="kw">let </span>serialized = serde_json::to_value(<span 
class="kw-2">&amp;</span>field).unwrap();
-<a href=#2048 id=2048 data-nosnippet>2048</a>        <span 
class="macro">assert_eq!</span>(<span class="prelude-val">Some</span>(<span 
class="kw-2">&amp;</span><span class="macro">serde_json::json!</span>(<span 
class="number">1</span>)), serialized.get(<span 
class="string">"source-id"</span>));
-<a href=#2049 id=2049 data-nosnippet>2049</a>        <span 
class="macro">assert!</span>(serialized.get(<span 
class="string">"source-ids"</span>).is_none());
-<a href=#2050 id=2050 data-nosnippet>2050</a>    }
-<a href=#2051 id=2051 data-nosnippet>2051</a>
-<a href=#2052 id=2052 data-nosnippet>2052</a>    <span class="attr">#[test]
-<a href=#2053 id=2053 data-nosnippet>2053</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_rejects_malformed_source_ids() {
-<a href=#2054 id=2054 data-nosnippet>2054</a>        <span class="kw">for 
</span>(input, expected) <span class="kw">in </span>[
-<a href=#2055 id=2055 data-nosnippet>2055</a>            (
-<a href=#2056 id=2056 data-nosnippet>2056</a>                <span 
class="string">r#"{"source-ids": [], "name": "m", "transform": 
"identity"}"#</span>,
-<a href=#2057 id=2057 data-nosnippet>2057</a>                <span 
class="string">"Empty source-ids is not allowed"</span>,
-<a href=#2058 id=2058 data-nosnippet>2058</a>            ),
-<a href=#2059 id=2059 data-nosnippet>2059</a>            (
-<a href=#2060 id=2060 data-nosnippet>2060</a>                <span 
class="string">r#"{"name": "m", "transform": "identity"}"#</span>,
-<a href=#2061 id=2061 data-nosnippet>2061</a>                <span 
class="string">"Either `source-id` or `source-ids` must be present"</span>,
-<a href=#2062 id=2062 data-nosnippet>2062</a>            ),
-<a href=#2063 id=2063 data-nosnippet>2063</a>            (
-<a href=#2064 id=2064 data-nosnippet>2064</a>                <span 
class="string">r#"{"source-id": 1, "source-ids": [1], "name": "m", "transform": 
"identity"}"#</span>,
-<a href=#2065 id=2065 data-nosnippet>2065</a>                <span 
class="string">"mutually exclusive"</span>,
-<a href=#2066 id=2066 data-nosnippet>2066</a>            ),
-<a href=#2067 id=2067 data-nosnippet>2067</a>        ] {
-<a href=#2068 id=2068 data-nosnippet>2068</a>            <span class="kw">let 
</span>err = 
serde_json::from_str::&lt;UnboundPartitionField&gt;(input).unwrap_err();
-<a href=#2069 id=2069 data-nosnippet>2069</a>            <span 
class="macro">assert!</span>(
-<a href=#2070 id=2070 data-nosnippet>2070</a>                
err.to_string().contains(expected),
-<a href=#2071 id=2071 data-nosnippet>2071</a>                <span 
class="string">"unexpected error for {input}: {err}"
-<a href=#2072 id=2072 data-nosnippet>2072</a>            </span>);
-<a href=#2073 id=2073 data-nosnippet>2073</a>        }
-<a href=#2074 id=2074 data-nosnippet>2074</a>    }
-<a href=#2075 id=2075 data-nosnippet>2075</a>
-<a href=#2076 id=2076 data-nosnippet>2076</a>    <span class="attr">#[test]
-<a href=#2077 id=2077 data-nosnippet>2077</a>    </span><span class="kw">fn 
</span>test_binding_a_multi_argument_field_fails_loudly() {
-<a href=#2078 id=2078 data-nosnippet>2078</a>        <span class="kw">let 
</span>schema = Schema::builder()
-<a href=#2079 id=2079 data-nosnippet>2079</a>            .with_fields(<span 
class="macro">vec!</span>[
-<a href=#2080 id=2080 data-nosnippet>2080</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"a"</span>, Type::Primitive(PrimitiveType::Int)).into(),
-<a href=#2081 id=2081 data-nosnippet>2081</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"b"</span>, Type::Primitive(PrimitiveType::Int)).into(),
-<a href=#2082 id=2082 data-nosnippet>2082</a>            ])
-<a href=#2083 id=2083 data-nosnippet>2083</a>            .build()
-<a href=#2084 id=2084 data-nosnippet>2084</a>            .unwrap();
-<a href=#2085 id=2085 data-nosnippet>2085</a>
-<a href=#2086 id=2086 data-nosnippet>2086</a>        <span class="kw">let 
</span>spec: UnboundPartitionSpec = serde_json::from_str(
-<a href=#2087 id=2087 data-nosnippet>2087</a>            <span 
class="string">r#"{"spec-id": 1, "fields": [{"source-ids": [1, 2], "field-id": 
1000, "name": "m", "transform": "bucket[4]"}]}"#</span>,
-<a href=#2088 id=2088 data-nosnippet>2088</a>        )
-<a href=#2089 id=2089 data-nosnippet>2089</a>        .unwrap();
-<a href=#2090 id=2090 data-nosnippet>2090</a>
-<a href=#2091 id=2091 data-nosnippet>2091</a>        <span class="comment">// 
A bound PartitionField still carries a single source id, so binding has to 
refuse
-<a href=#2092 id=2092 data-nosnippet>2092</a>        // rather than quietly 
keep the first one.
-<a href=#2093 id=2093 data-nosnippet>2093</a>        </span><span 
class="kw">let </span>err = spec.bind(schema).unwrap_err();
-<a href=#2094 id=2094 data-nosnippet>2094</a>        <span 
class="macro">assert!</span>(
-<a href=#2095 id=2095 data-nosnippet>2095</a>            
err.to_string().contains(<span class="string">"has no single source id"</span>),
-<a href=#2096 id=2096 data-nosnippet>2096</a>            <span 
class="string">"unexpected error: {err}"
-<a href=#2097 id=2097 data-nosnippet>2097</a>        </span>);
-<a href=#2098 id=2098 data-nosnippet>2098</a>    }
-<a href=#2099 id=2099 data-nosnippet>2099</a>
-<a href=#2100 id=2100 data-nosnippet>2100</a>    <span class="attr">#[test]
-<a href=#2101 id=2101 data-nosnippet>2101</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_builder_rejects_empty_source_ids() {
-<a href=#2102 id=2102 data-nosnippet>2102</a>        <span class="kw">let 
</span>err = UnboundPartitionField::builder()
-<a href=#2103 id=2103 data-nosnippet>2103</a>            .source_ids(<span 
class="macro">vec!</span>[])
-<a href=#2104 id=2104 data-nosnippet>2104</a>            .name(<span 
class="string">"m"</span>)
-<a href=#2105 id=2105 data-nosnippet>2105</a>            
.transform(Transform::Identity)
-<a href=#2106 id=2106 data-nosnippet>2106</a>            .build()
-<a href=#2107 id=2107 data-nosnippet>2107</a>            .unwrap_err();
-<a href=#2108 id=2108 data-nosnippet>2108</a>        <span 
class="macro">assert!</span>(
-<a href=#2109 id=2109 data-nosnippet>2109</a>            
err.to_string().contains(<span class="string">"Empty source-ids is not 
allowed"</span>),
-<a href=#2110 id=2110 data-nosnippet>2110</a>            <span 
class="string">"unexpected error: {err}"
-<a href=#2111 id=2111 data-nosnippet>2111</a>        </span>);
-<a href=#2112 id=2112 data-nosnippet>2112</a>    }
-<a href=#2113 id=2113 data-nosnippet>2113</a>}
+<a href=#2019 id=2019 data-nosnippet>2019</a>        <span class="kw">let 
</span>spec = PartitionSpec::builder(schema.clone())
+<a href=#2020 id=2020 data-nosnippet>2020</a>            
.add_partition_field(<span class="string">"data"</span>, <span 
class="string">"data"</span>, Transform::Identity)
+<a href=#2021 id=2021 data-nosnippet>2021</a>            .unwrap()
+<a href=#2022 id=2022 data-nosnippet>2022</a>            
.add_partition_field(<span class="string">"data"</span>, <span 
class="string">"data_truc_10"</span>, Transform::Truncate(<span 
class="number">10</span>))
+<a href=#2023 id=2023 data-nosnippet>2023</a>            .unwrap()
+<a href=#2024 id=2024 data-nosnippet>2024</a>            .build()
+<a href=#2025 id=2025 data-nosnippet>2025</a>            .unwrap();
+<a href=#2026 id=2026 data-nosnippet>2026</a>
+<a href=#2027 id=2027 data-nosnippet>2027</a>        <span class="kw">let 
</span>data = Struct::from_iter([
+<a href=#2028 id=2028 data-nosnippet>2028</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"a/b/c/d"</span>)),
+<a href=#2029 id=2029 data-nosnippet>2029</a>            <span 
class="prelude-val">Some</span>(Literal::string(<span 
class="string">"a/b/c/d"</span>)),
+<a href=#2030 id=2030 data-nosnippet>2030</a>        ]);
+<a href=#2031 id=2031 data-nosnippet>2031</a>
+<a href=#2032 id=2032 data-nosnippet>2032</a>        <span 
class="macro">assert_eq!</span>(
+<a href=#2033 id=2033 data-nosnippet>2033</a>            
spec.partition_to_path(<span class="kw-2">&amp;</span>data, schema.into()),
+<a href=#2034 id=2034 data-nosnippet>2034</a>            <span 
class="string">"data=a%2Fb%2Fc%2Fd/data_truc_10=a%2Fb%2Fc%2Fd"
+<a href=#2035 id=2035 data-nosnippet>2035</a>        </span>);
+<a href=#2036 id=2036 data-nosnippet>2036</a>    }
+<a href=#2037 id=2037 data-nosnippet>2037</a>
+<a href=#2038 id=2038 data-nosnippet>2038</a>    <span class="attr">#[test]
+<a href=#2039 id=2039 data-nosnippet>2039</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_reads_source_ids_only() {
+<a href=#2040 id=2040 data-nosnippet>2040</a>        <span class="kw">let 
</span>field: UnboundPartitionField = serde_json::from_str(
+<a href=#2041 id=2041 data-nosnippet>2041</a>            <span 
class="string">r#"{"source-ids": [1, 2], "name": "m", "transform": 
"bucket[4]"}"#</span>,
+<a href=#2042 id=2042 data-nosnippet>2042</a>        )
+<a href=#2043 id=2043 data-nosnippet>2043</a>        .unwrap();
+<a href=#2044 id=2044 data-nosnippet>2044</a>
+<a href=#2045 id=2045 data-nosnippet>2045</a>        <span 
class="macro">assert_eq!</span>([<span class="number">1</span>, <span 
class="number">2</span>], field.source_ids());
+<a href=#2046 id=2046 data-nosnippet>2046</a>        <span class="comment">// 
a multi-argument field has no single source id
+<a href=#2047 id=2047 data-nosnippet>2047</a>        </span><span 
class="macro">assert!</span>(
+<a href=#2048 id=2048 data-nosnippet>2048</a>            field
+<a href=#2049 id=2049 data-nosnippet>2049</a>                .source_id()
+<a href=#2050 id=2050 data-nosnippet>2050</a>                .unwrap_err()
+<a href=#2051 id=2051 data-nosnippet>2051</a>                .to_string()
+<a href=#2052 id=2052 data-nosnippet>2052</a>                .contains(<span 
class="string">"has no single source id"</span>)
+<a href=#2053 id=2053 data-nosnippet>2053</a>        );
+<a href=#2054 id=2054 data-nosnippet>2054</a>
+<a href=#2055 id=2055 data-nosnippet>2055</a>        <span class="kw">let 
</span>serialized = serde_json::to_value(<span 
class="kw-2">&amp;</span>field).unwrap();
+<a href=#2056 id=2056 data-nosnippet>2056</a>        <span 
class="macro">assert_eq!</span>(
+<a href=#2057 id=2057 data-nosnippet>2057</a>            <span 
class="prelude-val">Some</span>(<span class="kw-2">&amp;</span><span 
class="macro">serde_json::json!</span>([<span class="number">1</span>, <span 
class="number">2</span>])),
+<a href=#2058 id=2058 data-nosnippet>2058</a>            serialized.get(<span 
class="string">"source-ids"</span>)
+<a href=#2059 id=2059 data-nosnippet>2059</a>        );
+<a href=#2060 id=2060 data-nosnippet>2060</a>        <span 
class="macro">assert!</span>(serialized.get(<span 
class="string">"source-id"</span>).is_none());
+<a href=#2061 id=2061 data-nosnippet>2061</a>    }
+<a href=#2062 id=2062 data-nosnippet>2062</a>
+<a href=#2063 id=2063 data-nosnippet>2063</a>    <span class="attr">#[test]
+<a href=#2064 id=2064 data-nosnippet>2064</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_single_source_id_round_trip() {
+<a href=#2065 id=2065 data-nosnippet>2065</a>        <span class="kw">let 
</span>field: UnboundPartitionField =
+<a href=#2066 id=2066 data-nosnippet>2066</a>            
serde_json::from_str(<span class="string">r#"{"source-id": 1, "name": "m", 
"transform": "identity"}"#</span>)
+<a href=#2067 id=2067 data-nosnippet>2067</a>                .unwrap();
+<a href=#2068 id=2068 data-nosnippet>2068</a>
+<a href=#2069 id=2069 data-nosnippet>2069</a>        <span 
class="macro">assert_eq!</span>(<span class="number">1</span>, 
field.source_id().unwrap());
+<a href=#2070 id=2070 data-nosnippet>2070</a>        <span 
class="macro">assert_eq!</span>([<span class="number">1</span>], 
field.source_ids());
+<a href=#2071 id=2071 data-nosnippet>2071</a>
+<a href=#2072 id=2072 data-nosnippet>2072</a>        <span class="comment">// 
a single-argument field keeps writing source-id
+<a href=#2073 id=2073 data-nosnippet>2073</a>        </span><span 
class="kw">let </span>serialized = serde_json::to_value(<span 
class="kw-2">&amp;</span>field).unwrap();
+<a href=#2074 id=2074 data-nosnippet>2074</a>        <span 
class="macro">assert_eq!</span>(<span class="prelude-val">Some</span>(<span 
class="kw-2">&amp;</span><span class="macro">serde_json::json!</span>(<span 
class="number">1</span>)), serialized.get(<span 
class="string">"source-id"</span>));
+<a href=#2075 id=2075 data-nosnippet>2075</a>        <span 
class="macro">assert!</span>(serialized.get(<span 
class="string">"source-ids"</span>).is_none());
+<a href=#2076 id=2076 data-nosnippet>2076</a>    }
+<a href=#2077 id=2077 data-nosnippet>2077</a>
+<a href=#2078 id=2078 data-nosnippet>2078</a>    <span class="attr">#[test]
+<a href=#2079 id=2079 data-nosnippet>2079</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_rejects_malformed_source_ids() {
+<a href=#2080 id=2080 data-nosnippet>2080</a>        <span class="kw">for 
</span>(input, expected) <span class="kw">in </span>[
+<a href=#2081 id=2081 data-nosnippet>2081</a>            (
+<a href=#2082 id=2082 data-nosnippet>2082</a>                <span 
class="string">r#"{"source-ids": [], "name": "m", "transform": 
"identity"}"#</span>,
+<a href=#2083 id=2083 data-nosnippet>2083</a>                <span 
class="string">"Empty source-ids is not allowed"</span>,
+<a href=#2084 id=2084 data-nosnippet>2084</a>            ),
+<a href=#2085 id=2085 data-nosnippet>2085</a>            (
+<a href=#2086 id=2086 data-nosnippet>2086</a>                <span 
class="string">r#"{"name": "m", "transform": "identity"}"#</span>,
+<a href=#2087 id=2087 data-nosnippet>2087</a>                <span 
class="string">"Either `source-id` or `source-ids` must be present"</span>,
+<a href=#2088 id=2088 data-nosnippet>2088</a>            ),
+<a href=#2089 id=2089 data-nosnippet>2089</a>            (
+<a href=#2090 id=2090 data-nosnippet>2090</a>                <span 
class="string">r#"{"source-id": 1, "source-ids": [1], "name": "m", "transform": 
"identity"}"#</span>,
+<a href=#2091 id=2091 data-nosnippet>2091</a>                <span 
class="string">"mutually exclusive"</span>,
+<a href=#2092 id=2092 data-nosnippet>2092</a>            ),
+<a href=#2093 id=2093 data-nosnippet>2093</a>        ] {
+<a href=#2094 id=2094 data-nosnippet>2094</a>            <span class="kw">let 
</span>err = 
serde_json::from_str::&lt;UnboundPartitionField&gt;(input).unwrap_err();
+<a href=#2095 id=2095 data-nosnippet>2095</a>            <span 
class="macro">assert!</span>(
+<a href=#2096 id=2096 data-nosnippet>2096</a>                
err.to_string().contains(expected),
+<a href=#2097 id=2097 data-nosnippet>2097</a>                <span 
class="string">"unexpected error for {input}: {err}"
+<a href=#2098 id=2098 data-nosnippet>2098</a>            </span>);
+<a href=#2099 id=2099 data-nosnippet>2099</a>        }
+<a href=#2100 id=2100 data-nosnippet>2100</a>    }
+<a href=#2101 id=2101 data-nosnippet>2101</a>
+<a href=#2102 id=2102 data-nosnippet>2102</a>    <span class="attr">#[test]
+<a href=#2103 id=2103 data-nosnippet>2103</a>    </span><span class="kw">fn 
</span>test_binding_a_multi_argument_field_fails_loudly() {
+<a href=#2104 id=2104 data-nosnippet>2104</a>        <span class="kw">let 
</span>schema = Schema::builder()
+<a href=#2105 id=2105 data-nosnippet>2105</a>            .with_fields(<span 
class="macro">vec!</span>[
+<a href=#2106 id=2106 data-nosnippet>2106</a>                
NestedField::required(<span class="number">1</span>, <span 
class="string">"a"</span>, Type::Primitive(PrimitiveType::Int)).into(),
+<a href=#2107 id=2107 data-nosnippet>2107</a>                
NestedField::required(<span class="number">2</span>, <span 
class="string">"b"</span>, Type::Primitive(PrimitiveType::Int)).into(),
+<a href=#2108 id=2108 data-nosnippet>2108</a>            ])
+<a href=#2109 id=2109 data-nosnippet>2109</a>            .build()
+<a href=#2110 id=2110 data-nosnippet>2110</a>            .unwrap();
+<a href=#2111 id=2111 data-nosnippet>2111</a>
+<a href=#2112 id=2112 data-nosnippet>2112</a>        <span class="kw">let 
</span>spec: UnboundPartitionSpec = serde_json::from_str(
+<a href=#2113 id=2113 data-nosnippet>2113</a>            <span 
class="string">r#"{"spec-id": 1, "fields": [{"source-ids": [1, 2], "field-id": 
1000, "name": "m", "transform": "bucket[4]"}]}"#</span>,
+<a href=#2114 id=2114 data-nosnippet>2114</a>        )
+<a href=#2115 id=2115 data-nosnippet>2115</a>        .unwrap();
+<a href=#2116 id=2116 data-nosnippet>2116</a>
+<a href=#2117 id=2117 data-nosnippet>2117</a>        <span class="comment">// 
A bound PartitionField still carries a single source id, so binding has to 
refuse
+<a href=#2118 id=2118 data-nosnippet>2118</a>        // rather than quietly 
keep the first one.
+<a href=#2119 id=2119 data-nosnippet>2119</a>        </span><span 
class="kw">let </span>err = spec.bind(schema).unwrap_err();
+<a href=#2120 id=2120 data-nosnippet>2120</a>        <span 
class="macro">assert!</span>(
+<a href=#2121 id=2121 data-nosnippet>2121</a>            
err.to_string().contains(<span class="string">"has no single source id"</span>),
+<a href=#2122 id=2122 data-nosnippet>2122</a>            <span 
class="string">"unexpected error: {err}"
+<a href=#2123 id=2123 data-nosnippet>2123</a>        </span>);
+<a href=#2124 id=2124 data-nosnippet>2124</a>    }
+<a href=#2125 id=2125 data-nosnippet>2125</a>
+<a href=#2126 id=2126 data-nosnippet>2126</a>    <span class="attr">#[test]
+<a href=#2127 id=2127 data-nosnippet>2127</a>    </span><span class="kw">fn 
</span>test_unbound_partition_field_builder_rejects_empty_source_ids() {
+<a href=#2128 id=2128 data-nosnippet>2128</a>        <span class="kw">let 
</span>err = UnboundPartitionField::builder()
+<a href=#2129 id=2129 data-nosnippet>2129</a>            .source_ids(<span 
class="macro">vec!</span>[])
+<a href=#2130 id=2130 data-nosnippet>2130</a>            .name(<span 
class="string">"m"</span>)
+<a href=#2131 id=2131 data-nosnippet>2131</a>            
.transform(Transform::Identity)
+<a href=#2132 id=2132 data-nosnippet>2132</a>            .build()
+<a href=#2133 id=2133 data-nosnippet>2133</a>            .unwrap_err();
+<a href=#2134 id=2134 data-nosnippet>2134</a>        <span 
class="macro">assert!</span>(
+<a href=#2135 id=2135 data-nosnippet>2135</a>            
err.to_string().contains(<span class="string">"Empty source-ids is not 
allowed"</span>),
+<a href=#2136 id=2136 data-nosnippet>2136</a>            <span 
class="string">"unexpected error: {err}"
+<a href=#2137 id=2137 data-nosnippet>2137</a>        </span>);
+<a href=#2138 id=2138 data-nosnippet>2138</a>    }
+<a href=#2139 id=2139 data-nosnippet>2139</a>}
 </code></pre></div></section></main></body></html>
\ No newline at end of file
diff --git a/api/src/iceberg/spec/values/datum.rs.html 
b/api/src/iceberg/spec/values/datum.rs.html
index 4195ba73d..576f77dbc 100644
--- a/api/src/iceberg/spec/values/datum.rs.html
+++ b/api/src/iceberg/spec/values/datum.rs.html
@@ -18,7 +18,7 @@
 <a href=#18 id=18 data-nosnippet>18</a></span><span class="doccomment">//! 
Typed literals with validation
 <a href=#19 id=19 data-nosnippet>19</a>
 <a href=#20 id=20 data-nosnippet>20</a></span><span class="kw">use 
</span>std::cmp::Ordering;
-<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use 
</span>std::fmt::{Display, Formatter};
+<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use 
</span>std::fmt::{Display, Formatter, LowerExp};
 <a href=#22 id=22 data-nosnippet>22</a><span class="kw">use 
</span>std::str::FromStr;
 <a href=#23 id=23 data-nosnippet>23</a>
 <a href=#24 id=24 data-nosnippet>24</a><span class="kw">use 
</span>chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
@@ -1226,12 +1226,67 @@
 <a href=#1226 id=1226 data-nosnippet>1226</a>    <span class="doccomment">/// 
Returns a human-readable string representation of this literal.
 <a href=#1227 id=1227 data-nosnippet>1227</a>    ///
 <a href=#1228 id=1228 data-nosnippet>1228</a>    /// For string literals, this 
returns the raw string value without quotes.
-<a href=#1229 id=1229 data-nosnippet>1229</a>    /// For all other literals, 
it falls back to [`to_string()`](ToString::to_string).
-<a href=#1230 id=1230 data-nosnippet>1230</a>    </span><span class="kw">pub 
fn </span>to_human_string(<span class="kw-2">&amp;</span><span 
class="self">self</span>) -&gt; String {
-<a href=#1231 id=1231 data-nosnippet>1231</a>        <span class="kw">match 
</span><span class="self">self</span>.literal() {
-<a href=#1232 id=1232 data-nosnippet>1232</a>            
PrimitiveLiteral::String(s) =&gt; s.to_string(),
-<a href=#1233 id=1233 data-nosnippet>1233</a>            <span class="kw">_ 
</span>=&gt; <span class="self">self</span>.to_string(),
-<a href=#1234 id=1234 data-nosnippet>1234</a>        }
-<a href=#1235 id=1235 data-nosnippet>1235</a>    }
-<a href=#1236 id=1236 data-nosnippet>1236</a>}
+<a href=#1229 id=1229 data-nosnippet>1229</a>    /// Float and double literals 
are formatted like Java's `Float.toString` /
+<a href=#1230 id=1230 data-nosnippet>1230</a>    /// `Double.toString` (JDK 
19+).
+<a href=#1231 id=1231 data-nosnippet>1231</a>    /// For all other literals, 
it falls back to [`to_string()`](ToString::to_string).
+<a href=#1232 id=1232 data-nosnippet>1232</a>    </span><span class="kw">pub 
fn </span>to_human_string(<span class="kw-2">&amp;</span><span 
class="self">self</span>) -&gt; String {
+<a href=#1233 id=1233 data-nosnippet>1233</a>        <span class="kw">match 
</span><span class="self">self</span>.literal() {
+<a href=#1234 id=1234 data-nosnippet>1234</a>            
PrimitiveLiteral::String(s) =&gt; s.to_string(),
+<a href=#1235 id=1235 data-nosnippet>1235</a>            
PrimitiveLiteral::Float(val) =&gt; human_float(val.<span 
class="number">0</span>),
+<a href=#1236 id=1236 data-nosnippet>1236</a>            
PrimitiveLiteral::Double(val) =&gt; human_float(val.<span 
class="number">0</span>),
+<a href=#1237 id=1237 data-nosnippet>1237</a>            <span class="kw">_ 
</span>=&gt; <span class="self">self</span>.to_string(),
+<a href=#1238 id=1238 data-nosnippet>1238</a>        }
+<a href=#1239 id=1239 data-nosnippet>1239</a>    }
+<a href=#1240 id=1240 data-nosnippet>1240</a>}
+<a href=#1241 id=1241 data-nosnippet>1241</a>
+<a href=#1242 id=1242 data-nosnippet>1242</a><span class="doccomment">/// 
Formats a float like Java's `Float.toString` / `Double.toString` (JDK 19+):
+<a href=#1243 id=1243 data-nosnippet>1243</a>/// plain decimal when `1e-3 
&lt;= |value| &lt; 1e7`, otherwise `&lt;d&gt;.&lt;ddd&gt;E&lt;exp&gt;`,
+<a href=#1244 id=1244 data-nosnippet>1244</a>/// always with at least one 
digit after the point.
+<a href=#1245 id=1245 data-nosnippet>1245</a></span><span class="kw">fn 
</span>human_float&lt;T: Float + LowerExp + FromStr&gt;(value: T) -&gt; String {
+<a href=#1246 id=1246 data-nosnippet>1246</a>    <span class="kw">if 
</span>value.is_nan() {
+<a href=#1247 id=1247 data-nosnippet>1247</a>        <span class="kw">return 
</span><span class="string">"NaN"</span>.to_string();
+<a href=#1248 id=1248 data-nosnippet>1248</a>    }
+<a href=#1249 id=1249 data-nosnippet>1249</a>    <span class="kw">let 
</span>sign = <span class="kw">if </span>value.is_sign_negative() { <span 
class="string">"-" </span>} <span class="kw">else </span>{ <span 
class="string">"" </span>};
+<a href=#1250 id=1250 data-nosnippet>1250</a>    <span class="kw">if 
</span>value.is_infinite() {
+<a href=#1251 id=1251 data-nosnippet>1251</a>        <span class="kw">return 
</span><span class="macro">format!</span>(<span 
class="string">"{sign}Infinity"</span>);
+<a href=#1252 id=1252 data-nosnippet>1252</a>    }
+<a href=#1253 id=1253 data-nosnippet>1253</a>    <span class="kw">if 
</span>value.is_zero() {
+<a href=#1254 id=1254 data-nosnippet>1254</a>        <span class="kw">return 
</span><span class="macro">format!</span>(<span 
class="string">"{sign}0.0"</span>);
+<a href=#1255 id=1255 data-nosnippet>1255</a>    }
+<a href=#1256 id=1256 data-nosnippet>1256</a>
+<a href=#1257 id=1257 data-nosnippet>1257</a>    <span class="kw">let 
</span>abs = value.abs();
+<a href=#1258 id=1258 data-nosnippet>1258</a>    <span class="comment">// 
`{:e}` gives the fewest digits that round-trip. Java uses at least two
+<a href=#1259 id=1259 data-nosnippet>1259</a>    // digits and, among decimals 
of that length that round-trip, the closest
+<a href=#1260 id=1260 data-nosnippet>1260</a>    // one, preferring an even 
last digit on ties (2097152.2 for 2097152.25f32,
+<a href=#1261 id=1261 data-nosnippet>1261</a>    // 4.9E-324 for 
f64::from_bits(1)). Exact formatting picks exactly that.
+<a href=#1262 id=1262 data-nosnippet>1262</a>    </span><span class="kw">let 
</span>shortest = <span class="macro">format!</span>(<span 
class="string">"{abs:e}"</span>);
+<a href=#1263 id=1263 data-nosnippet>1263</a>    <span class="kw">let 
</span>precision = shortest.find(<span 
class="string">'e'</span>).unwrap().saturating_sub(<span 
class="number">2</span>).max(<span class="number">1</span>);
+<a href=#1264 id=1264 data-nosnippet>1264</a>    <span class="kw">let 
</span>closest = <span class="macro">format!</span>(<span 
class="string">"{abs:.precision$e}"</span>);
+<a href=#1265 id=1265 data-nosnippet>1265</a>    <span class="kw">let 
</span>scientific = <span class="kw">if 
</span>closest.parse::&lt;T&gt;().is_ok_and(|v| v == abs) {
+<a href=#1266 id=1266 data-nosnippet>1266</a>        closest
+<a href=#1267 id=1267 data-nosnippet>1267</a>    } <span class="kw">else 
</span>{
+<a href=#1268 id=1268 data-nosnippet>1268</a>        shortest
+<a href=#1269 id=1269 data-nosnippet>1269</a>    };
+<a href=#1270 id=1270 data-nosnippet>1270</a>    <span class="kw">let 
</span>(mantissa, exponent) = scientific.split_once(<span 
class="string">'e'</span>).unwrap();
+<a href=#1271 id=1271 data-nosnippet>1271</a>    <span class="kw">let 
</span>exponent: i32 = exponent.parse().unwrap();
+<a href=#1272 id=1272 data-nosnippet>1272</a>    <span class="kw">let 
</span>digits = mantissa.replace(<span class="string">'.'</span>, <span 
class="string">""</span>);
+<a href=#1273 id=1273 data-nosnippet>1273</a>    <span class="kw">let 
</span>digits = digits.trim_end_matches(<span class="string">'0'</span>);
+<a href=#1274 id=1274 data-nosnippet>1274</a>
+<a href=#1275 id=1275 data-nosnippet>1275</a>    <span class="kw">if 
</span>(-<span class="number">3</span>..<span 
class="number">7</span>).contains(<span class="kw-2">&amp;</span>exponent) {
+<a href=#1276 id=1276 data-nosnippet>1276</a>        <span class="kw">if 
</span>exponent &lt; <span class="number">0 </span>{
+<a href=#1277 id=1277 data-nosnippet>1277</a>            <span class="kw">let 
</span>zeros = <span class="string">"0"</span>.repeat((-exponent - <span 
class="number">1</span>) <span class="kw">as </span>usize);
+<a href=#1278 id=1278 data-nosnippet>1278</a>            <span 
class="macro">format!</span>(<span 
class="string">"{sign}0.{zeros}{digits}"</span>)
+<a href=#1279 id=1279 data-nosnippet>1279</a>        } <span class="kw">else 
</span>{
+<a href=#1280 id=1280 data-nosnippet>1280</a>            <span class="kw">let 
</span>int_len = exponent <span class="kw">as </span>usize + <span 
class="number">1</span>;
+<a href=#1281 id=1281 data-nosnippet>1281</a>            <span class="kw">if 
</span>digits.len() &gt; int_len {
+<a href=#1282 id=1282 data-nosnippet>1282</a>                <span 
class="macro">format!</span>(<span class="string">"{sign}{}.{}"</span>, <span 
class="kw-2">&amp;</span>digits[..int_len], <span 
class="kw-2">&amp;</span>digits[int_len..])
+<a href=#1283 id=1283 data-nosnippet>1283</a>            } <span 
class="kw">else </span>{
+<a href=#1284 id=1284 data-nosnippet>1284</a>                <span 
class="macro">format!</span>(<span 
class="string">"{sign}{digits:0&lt;int_len$}.0"</span>)
+<a href=#1285 id=1285 data-nosnippet>1285</a>            }
+<a href=#1286 id=1286 data-nosnippet>1286</a>        }
+<a href=#1287 id=1287 data-nosnippet>1287</a>    } <span class="kw">else 
</span>{
+<a href=#1288 id=1288 data-nosnippet>1288</a>        <span class="kw">let 
</span>fraction = <span class="kw">if </span>digits.len() &gt; <span 
class="number">1 </span>{ <span class="kw-2">&amp;</span>digits[<span 
class="number">1</span>..] } <span class="kw">else </span>{ <span 
class="string">"0" </span>};
+<a href=#1289 id=1289 data-nosnippet>1289</a>        <span 
class="macro">format!</span>(<span 
class="string">"{sign}{}.{fraction}E{exponent}"</span>, <span 
class="kw-2">&amp;</span>digits[..<span class="number">1</span>])
+<a href=#1290 id=1290 data-nosnippet>1290</a>    }
+<a href=#1291 id=1291 data-nosnippet>1291</a>}
 </code></pre></div></section></main></body></html>
\ No newline at end of file

Reply via email to