@@ -24,7 +24,6 @@ import (
2424 "math"
2525 "reflect"
2626 "strconv"
27- "strings"
2827
2928 "github.com/shopspring/decimal"
3029 "github.com/vmihailenco/msgpack/v5"
@@ -180,8 +179,7 @@ func (d Decimal) String() string {
180179// StringFromInt64 is an internal method for converting int64
181180// and scale to a string (for numbers up to 19 digits).
182181func (d Decimal ) stringFromInt64 (value int64 , scale int ) string {
183-
184- var buf [48 ]byte
182+ var buf [64 ]byte
185183 pos := 0
186184
187185 negative := value < 0
@@ -197,7 +195,13 @@ func (d Decimal) stringFromInt64(value int64, scale int) string {
197195 str := strconv .FormatInt (value , 10 )
198196 length := len (str )
199197
198+ // Special case: zero value.
199+ if value == 0 {
200+ return "0" // Always return "0" regardless of scale.
201+ }
202+
200203 if scale == 0 {
204+ // No fractional part.
201205 if pos + length > len (buf ) {
202206 return d .Decimal .String ()
203207 }
@@ -207,8 +211,23 @@ func (d Decimal) stringFromInt64(value int64, scale int) string {
207211 }
208212
209213 if scale >= length {
214+ // Numbers like 0.00123.
215+ // Count trailing zeros in the fractional part.
216+ trailingZeros := 0
217+ // In this case, the fractional part consists of (scale-length) zeros followed by the number.
218+ // We need to count trailing zeros in the actual number part.
219+ for i := length - 1 ; i >= 0 && str [i ] == '0' ; i -- {
220+ trailingZeros ++
221+ }
210222
211- required := 2 + (scale - length ) + length
223+ effectiveDigits := length - trailingZeros
224+
225+ // If all digits are zeros after leading zeros, we need to adjust.
226+ if effectiveDigits == 0 {
227+ return "0"
228+ }
229+
230+ required := 2 + (scale - length ) + effectiveDigits
212231 if pos + required > len (buf ) {
213232 return d .Decimal .String ()
214233 }
@@ -217,39 +236,63 @@ func (d Decimal) stringFromInt64(value int64, scale int) string {
217236 buf [pos + 1 ] = '.'
218237 pos += 2
219238
239+ // Add leading zeros.
220240 zeros := scale - length
221241 for i := 0 ; i < zeros ; i ++ {
222242 buf [pos ] = '0'
223243 pos ++
224244 }
225245
226- copy (buf [pos :], str )
227- pos += length
246+ // Copy only significant digits (without trailing zeros).
247+ copy (buf [pos :], str [:effectiveDigits ])
248+ pos += effectiveDigits
228249 } else {
229-
250+ // Numbers like 123.45.
230251 integerLen := length - scale
231252
232- required := integerLen + 1 + scale
253+ // Count trailing zeros in fractional part.
254+ trailingZeros := 0
255+ for i := length - 1 ; i >= integerLen && str [i ] == '0' ; i -- {
256+ trailingZeros ++
257+ }
258+
259+ effectiveScale := scale - trailingZeros
260+
261+ // If all fractional digits are zeros, return just integer part.
262+ if effectiveScale == 0 {
263+ if pos + integerLen > len (buf ) {
264+ return d .Decimal .String ()
265+ }
266+ copy (buf [pos :], str [:integerLen ])
267+ pos += integerLen
268+ return string (buf [:pos ])
269+ }
270+
271+ required := integerLen + 1 + effectiveScale
233272 if pos + required > len (buf ) {
234273 return d .Decimal .String ()
235274 }
236275
276+ // Integer part.
237277 copy (buf [pos :], str [:integerLen ])
238278 pos += integerLen
239279
280+ // Decimal point.
240281 buf [pos ] = '.'
241282 pos ++
242283
243- copy (buf [pos :], str [integerLen :])
244- pos += scale
284+ // Fractional part without trailing zeros.
285+ fractionalEnd := integerLen + effectiveScale
286+ copy (buf [pos :], str [integerLen :fractionalEnd ])
287+ pos += effectiveScale
245288 }
246289
247290 return string (buf [:pos ])
248291}
249292func (d Decimal ) handleMinInt64 (scale int ) string {
250293 const minInt64Str = "9223372036854775808"
251294
252- var buf [48 ]byte
295+ var buf [64 ]byte
253296 pos := 0
254297
255298 buf [pos ] = '-'
@@ -259,19 +302,29 @@ func (d Decimal) handleMinInt64(scale int) string {
259302
260303 if scale == 0 {
261304 if pos + length > len (buf ) {
262- return "-" + minInt64Str // Fallback.
305+ return "-" + minInt64Str
263306 }
264307 copy (buf [pos :], minInt64Str )
265308 pos += length
266309 return string (buf [:pos ])
267310 }
268311
269312 if scale >= length {
270- required := 2 + (scale - length ) + length
313+ // Count trailing zeros in the actual number part.
314+ trailingZeros := 0
315+ for i := length - 1 ; i >= 0 && minInt64Str [i ] == '0' ; i -- {
316+ trailingZeros ++
317+ }
318+
319+ effectiveDigits := length - trailingZeros
320+
321+ if effectiveDigits == 0 {
322+ return "0"
323+ }
324+
325+ required := 2 + (scale - length ) + effectiveDigits
271326 if pos + required > len (buf ) {
272- // Fallback.
273- result := "0." + strings .Repeat ("0" , scale - length ) + minInt64Str
274- return "-" + result
327+ return d .Decimal .String ()
275328 }
276329
277330 buf [pos ] = '0'
@@ -284,13 +337,31 @@ func (d Decimal) handleMinInt64(scale int) string {
284337 pos ++
285338 }
286339
287- copy (buf [pos :], minInt64Str )
288- pos += length
340+ copy (buf [pos :], minInt64Str [: effectiveDigits ] )
341+ pos += effectiveDigits
289342 } else {
290343 integerLen := length - scale
291- required := integerLen + 1 + scale
344+
345+ // Count trailing zeros for minInt64Str fractional part.
346+ trailingZeros := 0
347+ for i := length - 1 ; i >= integerLen && minInt64Str [i ] == '0' ; i -- {
348+ trailingZeros ++
349+ }
350+
351+ effectiveScale := scale - trailingZeros
352+
353+ if effectiveScale == 0 {
354+ if pos + integerLen > len (buf ) {
355+ return d .Decimal .String ()
356+ }
357+ copy (buf [pos :], minInt64Str [:integerLen ])
358+ pos += integerLen
359+ return string (buf [:pos ])
360+ }
361+
362+ required := integerLen + 1 + effectiveScale
292363 if pos + required > len (buf ) {
293- return d .Decimal .String () // Fallback
364+ return d .Decimal .String ()
294365 }
295366
296367 copy (buf [pos :], minInt64Str [:integerLen ])
@@ -299,8 +370,9 @@ func (d Decimal) handleMinInt64(scale int) string {
299370 buf [pos ] = '.'
300371 pos ++
301372
302- copy (buf [pos :], minInt64Str [integerLen :])
303- pos += scale
373+ fractionalEnd := integerLen + effectiveScale
374+ copy (buf [pos :], minInt64Str [integerLen :fractionalEnd ])
375+ pos += effectiveScale
304376 }
305377
306378 return string (buf [:pos ])
0 commit comments