2025-10-15 10:12:44 +03:00

67 lines
1.5 KiB
Go

package jsnum
import (
"fmt"
"math/big"
"strings"
)
// PseudoBigInt represents a JS-like bigint. The zero state of the struct represents the value 0.
type PseudoBigInt struct {
Negative bool // true if the value is a non-zero negative number.
Base10Value string // The absolute value in base 10 with no leading zeros. The value zero is represented as an empty string.
}
func NewPseudoBigInt(value string, negative bool) PseudoBigInt {
value = strings.TrimLeft(value, "0")
return PseudoBigInt{Negative: negative && len(value) != 0, Base10Value: value}
}
func (value PseudoBigInt) String() string {
if len(value.Base10Value) == 0 {
return "0"
}
if value.Negative {
return "-" + value.Base10Value
}
return value.Base10Value
}
func (value PseudoBigInt) Sign() int {
if len(value.Base10Value) == 0 {
return 0
}
if value.Negative {
return -1
}
return 1
}
func ParseValidBigInt(text string) PseudoBigInt {
text, negative := strings.CutPrefix(text, "-")
return NewPseudoBigInt(ParsePseudoBigInt(text), negative)
}
func ParsePseudoBigInt(stringValue string) string {
stringValue = strings.TrimSuffix(stringValue, "n")
var b1 byte
if len(stringValue) > 1 {
b1 = stringValue[1]
}
switch b1 {
case 'b', 'B', 'o', 'O', 'x', 'X':
// Not decimal.
default:
stringValue = strings.TrimLeft(stringValue, "0")
if stringValue == "" {
return "0"
}
return stringValue
}
bi, ok := new(big.Int).SetString(stringValue, 0)
if !ok {
panic(fmt.Sprintf("Failed to parse big int: %q", stringValue))
}
return bi.String() // !!!
}