@@ -81,22 +81,55 @@ pub fn variant_to_json(json_buffer: &mut impl Write, variant: &Variant) -> Resul
8181 write ! ( json_buffer, "{}" , f) ?;
8282 }
8383 Variant :: Decimal4 { integer, scale } => {
84- // Convert decimal to string representation
85- let divisor = 10_i32 . pow ( * scale as u32 ) ;
86- let decimal_value = * integer as f64 / divisor as f64 ;
87- write ! ( json_buffer, "{}" , decimal_value) ?;
84+ // Convert decimal to string representation using integer arithmetic
85+ if * scale == 0 {
86+ write ! ( json_buffer, "{}" , integer) ?;
87+ } else {
88+ let divisor = 10_i32 . pow ( * scale as u32 ) ;
89+ let quotient = integer / divisor;
90+ let remainder = ( integer % divisor) . abs ( ) ;
91+ let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
92+ let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
93+ if trimmed_remainder. is_empty ( ) {
94+ write ! ( json_buffer, "{}" , quotient) ?;
95+ } else {
96+ write ! ( json_buffer, "{}.{}" , quotient, trimmed_remainder) ?;
97+ }
98+ }
8899 }
89100 Variant :: Decimal8 { integer, scale } => {
90- // Convert decimal to string representation
91- let divisor = 10_i64 . pow ( * scale as u32 ) ;
92- let decimal_value = * integer as f64 / divisor as f64 ;
93- write ! ( json_buffer, "{}" , decimal_value) ?;
101+ // Convert decimal to string representation using integer arithmetic
102+ if * scale == 0 {
103+ write ! ( json_buffer, "{}" , integer) ?;
104+ } else {
105+ let divisor = 10_i64 . pow ( * scale as u32 ) ;
106+ let quotient = integer / divisor;
107+ let remainder = ( integer % divisor) . abs ( ) ;
108+ let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
109+ let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
110+ if trimmed_remainder. is_empty ( ) {
111+ write ! ( json_buffer, "{}" , quotient) ?;
112+ } else {
113+ write ! ( json_buffer, "{}.{}" , quotient, trimmed_remainder) ?;
114+ }
115+ }
94116 }
95117 Variant :: Decimal16 { integer, scale } => {
96- // Convert decimal to string representation
97- let divisor = 10_i128 . pow ( * scale as u32 ) ;
98- let decimal_value = * integer as f64 / divisor as f64 ;
99- write ! ( json_buffer, "{}" , decimal_value) ?;
118+ // Convert decimal to string representation using integer arithmetic
119+ if * scale == 0 {
120+ write ! ( json_buffer, "{}" , integer) ?;
121+ } else {
122+ let divisor = 10_i128 . pow ( * scale as u32 ) ;
123+ let quotient = integer / divisor;
124+ let remainder = ( integer % divisor) . abs ( ) ;
125+ let formatted_remainder = format ! ( "{:0width$}" , remainder, width = * scale as usize ) ;
126+ let trimmed_remainder = formatted_remainder. trim_end_matches ( '0' ) ;
127+ if trimmed_remainder. is_empty ( ) {
128+ write ! ( json_buffer, "{}" , quotient) ?;
129+ } else {
130+ write ! ( json_buffer, "{}.{}" , quotient, trimmed_remainder) ?;
131+ }
132+ }
100133 }
101134 Variant :: Date ( date) => {
102135 write ! ( json_buffer, "\" {}\" " , date. format( "%Y-%m-%d" ) ) ?;
@@ -252,30 +285,30 @@ pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
252285 . map ( Value :: Number )
253286 . ok_or_else ( || ArrowError :: InvalidArgumentError ( "Invalid double value" . to_string ( ) ) ) ,
254287 Variant :: Decimal4 { integer, scale } => {
255- let divisor = 10_i32 . pow ( * scale as u32 ) ;
256- let decimal_value = * integer as f64 / divisor as f64 ;
288+ let divisor = 10_i32 . pow ( * scale as u32 ) ;
289+ let decimal_value = * integer as f64 / divisor as f64 ;
257290 serde_json:: Number :: from_f64 ( decimal_value)
258291 . map ( Value :: Number )
259292 . ok_or_else ( || {
260- ArrowError :: InvalidArgumentError ( "Invalid decimal value" . to_string ( ) )
293+ ArrowError :: InvalidArgumentError ( "Invalid decimal value" . to_string ( ) )
261294 } )
262295 }
263296 Variant :: Decimal8 { integer, scale } => {
264- let divisor = 10_i64 . pow ( * scale as u32 ) ;
265- let decimal_value = * integer as f64 / divisor as f64 ;
297+ let divisor = 10_i64 . pow ( * scale as u32 ) ;
298+ let decimal_value = * integer as f64 / divisor as f64 ;
266299 serde_json:: Number :: from_f64 ( decimal_value)
267300 . map ( Value :: Number )
268301 . ok_or_else ( || {
269- ArrowError :: InvalidArgumentError ( "Invalid decimal value" . to_string ( ) )
302+ ArrowError :: InvalidArgumentError ( "Invalid decimal value" . to_string ( ) )
270303 } )
271304 }
272305 Variant :: Decimal16 { integer, scale } => {
273- let divisor = 10_i128 . pow ( * scale as u32 ) ;
274- let decimal_value = * integer as f64 / divisor as f64 ;
306+ let divisor = 10_i128 . pow ( * scale as u32 ) ;
307+ let decimal_value = * integer as f64 / divisor as f64 ;
275308 serde_json:: Number :: from_f64 ( decimal_value)
276309 . map ( Value :: Number )
277310 . ok_or_else ( || {
278- ArrowError :: InvalidArgumentError ( "Invalid decimal value" . to_string ( ) )
311+ ArrowError :: InvalidArgumentError ( "Invalid decimal value" . to_string ( ) )
279312 } )
280313 }
281314 Variant :: Date ( date) => Ok ( Value :: String ( date. format ( "%Y-%m-%d" ) . to_string ( ) ) ) ,
0 commit comments