common/math: add HexOrDecimal64, HexOrDecimal256
This commit is contained in:
parent
61d2150a07
commit
04fa6a3744
@ -18,6 +18,7 @@
|
|||||||
package math
|
package math
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,6 +36,24 @@ const (
|
|||||||
wordBytes = wordBits / 8
|
wordBytes = wordBits / 8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HexOrDecimal256 marshals big.Int as hex or decimal.
|
||||||
|
type HexOrDecimal256 big.Int
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (i *HexOrDecimal256) UnmarshalText(input []byte) error {
|
||||||
|
bigint, ok := ParseBig256(string(input))
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid hex or decimal integer %q", input)
|
||||||
|
}
|
||||||
|
*i = HexOrDecimal256(*bigint)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (i *HexOrDecimal256) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(fmt.Sprintf("%#x", (*big.Int)(i))), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax.
|
// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax.
|
||||||
// Leading zeros are accepted. The empty string parses as zero.
|
// Leading zeros are accepted. The empty string parses as zero.
|
||||||
func ParseBig256(s string) (*big.Int, bool) {
|
func ParseBig256(s string) (*big.Int, bool) {
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseBig256(t *testing.T) {
|
func TestHexOrDecimal256(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input string
|
input string
|
||||||
num *big.Int
|
num *big.Int
|
||||||
@ -47,13 +47,14 @@ func TestParseBig256(t *testing.T) {
|
|||||||
{"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false},
|
{"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
num, ok := ParseBig256(test.input)
|
var num HexOrDecimal256
|
||||||
if ok != test.ok {
|
err := num.UnmarshalText([]byte(test.input))
|
||||||
t.Errorf("ParseBig(%q) -> ok = %t, want %t", test.input, ok, test.ok)
|
if (err == nil) != test.ok {
|
||||||
|
t.Errorf("ParseBig(%q) -> (err == nil) == %t, want %t", test.input, err == nil, test.ok)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if num != nil && test.num != nil && num.Cmp(test.num) != 0 {
|
if test.num != nil && (*big.Int)(&num).Cmp(test.num) != 0 {
|
||||||
t.Errorf("ParseBig(%q) -> %d, want %d", test.input, num, test.num)
|
t.Errorf("ParseBig(%q) -> %d, want %d", test.input, (*big.Int)(&num), test.num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Integer limit values.
|
// Integer limit values.
|
||||||
@ -34,6 +37,24 @@ const (
|
|||||||
MaxUint64 = 1<<64 - 1
|
MaxUint64 = 1<<64 - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
||||||
|
type HexOrDecimal64 uint64
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (i *HexOrDecimal64) UnmarshalText(input []byte) error {
|
||||||
|
int, ok := ParseUint64(string(input))
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid hex or decimal integer %q", input)
|
||||||
|
}
|
||||||
|
*i = HexOrDecimal64(int)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
|
func (i HexOrDecimal64) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(fmt.Sprintf("%#x", uint64(i))), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseUint64 parses s as an integer in decimal or hexadecimal syntax.
|
// ParseUint64 parses s as an integer in decimal or hexadecimal syntax.
|
||||||
// Leading zeros are accepted. The empty string parses as zero.
|
// Leading zeros are accepted. The empty string parses as zero.
|
||||||
func ParseUint64(s string) (uint64, bool) {
|
func ParseUint64(s string) (uint64, bool) {
|
||||||
|
@ -65,7 +65,7 @@ func TestOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseUint64(t *testing.T) {
|
func TestHexOrDecimal64(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input string
|
input string
|
||||||
num uint64
|
num uint64
|
||||||
@ -88,12 +88,13 @@ func TestParseUint64(t *testing.T) {
|
|||||||
{"18446744073709551617", 0, false},
|
{"18446744073709551617", 0, false},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
num, ok := ParseUint64(test.input)
|
var num HexOrDecimal64
|
||||||
if ok != test.ok {
|
err := num.UnmarshalText([]byte(test.input))
|
||||||
t.Errorf("ParseUint64(%q) -> ok = %t, want %t", test.input, ok, test.ok)
|
if (err == nil) != test.ok {
|
||||||
|
t.Errorf("ParseUint64(%q) -> (err == nil) = %t, want %t", test.input, err == nil, test.ok)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ok && num != test.num {
|
if err == nil && uint64(num) != test.num {
|
||||||
t.Errorf("ParseUint64(%q) -> %d, want %d", test.input, num, test.num)
|
t.Errorf("ParseUint64(%q) -> %d, want %d", test.input, num, test.num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user