@@ -121,12 +121,7 @@ impl From<Value> for ByteBuf {
121121 Value :: UUID ( val) => ByteBuf :: from ( val. as_u128 ( ) . to_be_bytes ( ) ) ,
122122 Value :: Fixed ( _, val) => ByteBuf :: from ( val) ,
123123 Value :: Binary ( val) => ByteBuf :: from ( val) ,
124- Value :: Decimal ( val) => {
125- // rust_decimal mantissa is 96 bits
126- // so we can remove the first 32 bits of the i128 representation
127- let bytes = val. mantissa ( ) . to_be_bytes ( ) [ 4 ..] . to_vec ( ) ;
128- ByteBuf :: from ( bytes)
129- }
124+ Value :: Decimal ( val) => ByteBuf :: from ( i128_to_minimal_signed_be_bytes ( val. mantissa ( ) ) ) ,
130125 _ => todo ! ( ) ,
131126 }
132127 }
@@ -755,6 +750,24 @@ pub fn sign_extend_be<const N: usize>(b: &[u8]) -> [u8; N] {
755750 result
756751}
757752
753+ /// Encodes a signed integer using the minimal big-endian two's-complement
754+ /// representation required for Iceberg decimal values.
755+ pub fn i128_to_minimal_signed_be_bytes ( value : i128 ) -> Vec < u8 > {
756+ let bytes = value. to_be_bytes ( ) ;
757+ let sign_extension = if value < 0 { 0xff } else { 0x00 } ;
758+ let sign_bit = sign_extension & 0x80 ;
759+ let mut start = 0 ;
760+
761+ while start < bytes. len ( ) - 1
762+ && bytes[ start] == sign_extension
763+ && ( bytes[ start + 1 ] & 0x80 ) == sign_bit
764+ {
765+ start += 1 ;
766+ }
767+
768+ bytes[ start..] . to_vec ( )
769+ }
770+
758771impl From < & Value > for JsonValue {
759772 fn from ( value : & Value ) -> Self {
760773 match value {
@@ -1364,10 +1377,7 @@ mod tests {
13641377 // Test serialization
13651378 let byte_buf: ByteBuf = value. clone ( ) . into ( ) ;
13661379 let bytes: Vec < u8 > = byte_buf. into_vec ( ) ;
1367- assert_eq ! (
1368- bytes,
1369- vec![ 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 0u8 , 160u8 , 16u8 , 94u8 ]
1370- ) ;
1380+ assert_eq ! ( bytes, vec![ 0u8 , 160u8 , 16u8 , 94u8 ] ) ;
13711381
13721382 // Test deserialization
13731383 check_avro_bytes_serde (
@@ -1380,6 +1390,16 @@ mod tests {
13801390 ) ;
13811391 }
13821392
1393+ #[ test]
1394+ fn decimal_bytes_are_minimal_signed_big_endian ( ) {
1395+ assert_eq ! ( i128_to_minimal_signed_be_bytes( 0 ) , vec![ 0 ] ) ;
1396+ assert_eq ! ( i128_to_minimal_signed_be_bytes( 2 ) , vec![ 2 ] ) ;
1397+ assert_eq ! ( i128_to_minimal_signed_be_bytes( 127 ) , vec![ 127 ] ) ;
1398+ assert_eq ! ( i128_to_minimal_signed_be_bytes( 128 ) , vec![ 0 , 128 ] ) ;
1399+ assert_eq ! ( i128_to_minimal_signed_be_bytes( -1 ) , vec![ 255 ] ) ;
1400+ assert_eq ! ( i128_to_minimal_signed_be_bytes( -129 ) , vec![ 255 , 127 ] ) ;
1401+ }
1402+
13831403 #[ test]
13841404 fn test_transform_identity ( ) {
13851405 let value = Value :: Int ( 42 ) ;
0 commit comments