Skip to content

Commit e8d4fa1

Browse files
committed
fix: use allocation-free conversion of negative big.Int to two's complement representation
1 parent 7ebdb94 commit e8d4fa1

File tree

1 file changed

+11
-11
lines changed

1 file changed

+11
-11
lines changed

decimal.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,23 @@ func bigIntToTwosComplement(value *big.Int) ([32]byte, uint8, error) {
163163
}
164164

165165
bitLen := value.BitLen()
166-
byteLen := (bitLen + 8) / 8
167-
if byteLen == 0 {
168-
byteLen = 1
166+
if bitLen > 255 {
167+
return [32]byte{}, 0, fmt.Errorf("decimal unscaled value exceeds 32 bytes")
169168
}
169+
byteLen := (bitLen + 8) / 8
170170

171171
tmp := new(big.Int).Lsh(big.NewInt(1), uint(byteLen*8))
172172
tmp.Add(tmp, value) // value is negative, so this subtracts magnitude
173-
bytes := tmp.Bytes()
174-
if len(bytes) < int(byteLen) {
175-
padding := make([]byte, int(byteLen)-len(bytes))
176-
bytes = append(padding, bytes...)
173+
buf := [32]byte{}
174+
tmp.FillBytes(buf[:])
175+
offset := 32 - uint8(byteLen)
176+
if buf[offset]&0x80 == 0 {
177+
// Ensure sign bit is set for negative numbers
178+
buf[offset-1] = 0xFF
179+
offset--
177180
}
178181

179-
if bytes[0]&0x80 == 0 {
180-
bytes = append([]byte{0xFF}, bytes...)
181-
}
182-
return normalizeTwosComplement(bytes)
182+
return buf, offset, nil
183183
}
184184

185185
// normalizeTwosComplement normalizes a two's complement big-endian byte slice to fit within 32 bytes and returns the normalized value along with the offset to the first significant byte.

0 commit comments

Comments
 (0)