stackitem: make BigInteger
alias to big.Int
Remove one indirection step. `` name old time/op new time/op delta MakeInt-8 79.7ns ± 8% 56.2ns ± 8% -29.44% (p=0.000 n=10+10) name old alloc/op new alloc/op delta MakeInt-8 48.0B ± 0% 40.0B ± 0% -16.67% (p=0.000 n=10+10) name old allocs/op new allocs/op delta MakeInt-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=10+10) ``` Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
cff8b1c24e
commit
a5516e8c96
3 changed files with 42 additions and 61 deletions
|
@ -2,7 +2,6 @@ package stackitem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -90,33 +89,17 @@ func mkInvConversion(from Item, to Type) error {
|
||||||
func Make(v interface{}) Item {
|
func Make(v interface{}) Item {
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
case int:
|
case int:
|
||||||
return &BigInteger{
|
return (*BigInteger)(big.NewInt(int64(val)))
|
||||||
value: big.NewInt(int64(val)),
|
|
||||||
}
|
|
||||||
case int64:
|
case int64:
|
||||||
return &BigInteger{
|
return (*BigInteger)(big.NewInt(val))
|
||||||
value: big.NewInt(val),
|
|
||||||
}
|
|
||||||
case uint8:
|
case uint8:
|
||||||
return &BigInteger{
|
return (*BigInteger)(big.NewInt(int64(val)))
|
||||||
value: big.NewInt(int64(val)),
|
|
||||||
}
|
|
||||||
case uint16:
|
case uint16:
|
||||||
return &BigInteger{
|
return (*BigInteger)(big.NewInt(int64(val)))
|
||||||
value: big.NewInt(int64(val)),
|
|
||||||
}
|
|
||||||
case uint32:
|
case uint32:
|
||||||
return &BigInteger{
|
return (*BigInteger)(big.NewInt(int64(val)))
|
||||||
value: big.NewInt(int64(val)),
|
|
||||||
}
|
|
||||||
case uint64:
|
case uint64:
|
||||||
b := make([]byte, 8)
|
return (*BigInteger)(new(big.Int).SetUint64(val))
|
||||||
binary.BigEndian.PutUint64(b, val)
|
|
||||||
bigInt := big.NewInt(0)
|
|
||||||
bigInt.SetBytes(b)
|
|
||||||
return &BigInteger{
|
|
||||||
value: bigInt,
|
|
||||||
}
|
|
||||||
case []byte:
|
case []byte:
|
||||||
return &ByteArray{
|
return &ByteArray{
|
||||||
value: val,
|
value: val,
|
||||||
|
@ -400,9 +383,7 @@ func (i Null) Convert(typ Type) (Item, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BigInteger represents a big integer on the stack.
|
// BigInteger represents a big integer on the stack.
|
||||||
type BigInteger struct {
|
type BigInteger big.Int
|
||||||
value *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBigInteger returns an new BigInteger object.
|
// NewBigInteger returns an new BigInteger object.
|
||||||
func NewBigInteger(value *big.Int) *BigInteger {
|
func NewBigInteger(value *big.Int) *BigInteger {
|
||||||
|
@ -418,19 +399,22 @@ func NewBigInteger(value *big.Int) *BigInteger {
|
||||||
panic(errTooBigInteger)
|
panic(errTooBigInteger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &BigInteger{
|
return (*BigInteger)(value)
|
||||||
value: value,
|
}
|
||||||
}
|
|
||||||
|
// Big casts i to the big.Int type.
|
||||||
|
func (i *BigInteger) Big() *big.Int {
|
||||||
|
return (*big.Int)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes converts i to a slice of bytes.
|
// Bytes converts i to a slice of bytes.
|
||||||
func (i *BigInteger) Bytes() []byte {
|
func (i *BigInteger) Bytes() []byte {
|
||||||
return bigint.ToBytes(i.value)
|
return bigint.ToBytes(i.Big())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryBool implements Item interface.
|
// TryBool implements Item interface.
|
||||||
func (i *BigInteger) TryBool() (bool, error) {
|
func (i *BigInteger) TryBool() (bool, error) {
|
||||||
return i.value.Sign() != 0, nil
|
return i.Big().Sign() != 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryBytes implements Item interface.
|
// TryBytes implements Item interface.
|
||||||
|
@ -440,7 +424,7 @@ func (i *BigInteger) TryBytes() ([]byte, error) {
|
||||||
|
|
||||||
// TryInteger implements Item interface.
|
// TryInteger implements Item interface.
|
||||||
func (i *BigInteger) TryInteger() (*big.Int, error) {
|
func (i *BigInteger) TryInteger() (*big.Int, error) {
|
||||||
return i.value, nil
|
return i.Big(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equals implements Item interface.
|
// Equals implements Item interface.
|
||||||
|
@ -451,12 +435,12 @@ func (i *BigInteger) Equals(s Item) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val, ok := s.(*BigInteger)
|
val, ok := s.(*BigInteger)
|
||||||
return ok && i.value.Cmp(val.value) == 0
|
return ok && i.Big().Cmp(val.Big()) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value implements Item interface.
|
// Value implements Item interface.
|
||||||
func (i *BigInteger) Value() interface{} {
|
func (i *BigInteger) Value() interface{} {
|
||||||
return i.value
|
return i.Big()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *BigInteger) String() string {
|
func (i *BigInteger) String() string {
|
||||||
|
@ -466,7 +450,7 @@ func (i *BigInteger) String() string {
|
||||||
// Dup implements Item interface.
|
// Dup implements Item interface.
|
||||||
func (i *BigInteger) Dup() Item {
|
func (i *BigInteger) Dup() Item {
|
||||||
n := new(big.Int)
|
n := new(big.Int)
|
||||||
return &BigInteger{n.Set(i.value)}
|
return (*BigInteger)(n.Set(i.Big()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type implements Item interface.
|
// Type implements Item interface.
|
||||||
|
@ -479,7 +463,7 @@ func (i *BigInteger) Convert(typ Type) (Item, error) {
|
||||||
|
|
||||||
// MarshalJSON implements the json.Marshaler interface.
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
func (i *BigInteger) MarshalJSON() ([]byte, error) {
|
func (i *BigInteger) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(i.value)
|
return json.Marshal(i.Big())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool represents a boolean Item.
|
// Bool represents a boolean Item.
|
||||||
|
@ -1156,11 +1140,8 @@ func deepCopy(item Item, seen map[Item]Item) Item {
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
case *BigInteger:
|
case *BigInteger:
|
||||||
bi := new(big.Int).SetBytes(it.value.Bytes())
|
bi := new(big.Int).Set(it.Big())
|
||||||
if it.value.Sign() == -1 {
|
return (*BigInteger)(bi)
|
||||||
bi.Neg(bi)
|
|
||||||
}
|
|
||||||
return NewBigInteger(bi)
|
|
||||||
case *ByteArray:
|
case *ByteArray:
|
||||||
return NewByteArray(slice.Copy(it.value))
|
return NewByteArray(slice.Copy(it.value))
|
||||||
case *Buffer:
|
case *Buffer:
|
||||||
|
|
|
@ -15,35 +15,35 @@ var makeStackItemTestCases = []struct {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
input: int64(3),
|
input: int64(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: int16(3),
|
input: int16(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: 3,
|
input: 3,
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: uint8(3),
|
input: uint8(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: uint16(3),
|
input: uint16(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: uint32(3),
|
input: uint32(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: uint64(3),
|
input: uint64(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: big.NewInt(3),
|
input: big.NewInt(3),
|
||||||
result: &BigInteger{value: big.NewInt(3)},
|
result: (*BigInteger)(big.NewInt(3)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: []byte{1, 2, 3, 4},
|
input: []byte{1, 2, 3, 4},
|
||||||
|
@ -70,12 +70,12 @@ var makeStackItemTestCases = []struct {
|
||||||
result: Bool(false),
|
result: Bool(false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: []Item{&BigInteger{value: big.NewInt(3)}, &ByteArray{value: []byte{1, 2, 3}}},
|
input: []Item{(*BigInteger)(big.NewInt(3)), &ByteArray{value: []byte{1, 2, 3}}},
|
||||||
result: &Array{value: []Item{&BigInteger{value: big.NewInt(3)}, &ByteArray{value: []byte{1, 2, 3}}}},
|
result: &Array{value: []Item{(*BigInteger)(big.NewInt(3)), &ByteArray{value: []byte{1, 2, 3}}}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: []int{1, 2, 3},
|
input: []int{1, 2, 3},
|
||||||
result: &Array{value: []Item{&BigInteger{value: big.NewInt(1)}, &BigInteger{value: big.NewInt(2)}, &BigInteger{value: big.NewInt(3)}}},
|
result: &Array{value: []Item{(*BigInteger)(big.NewInt(1)), (*BigInteger)(big.NewInt(2)), (*BigInteger)(big.NewInt(3))}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,18 +281,18 @@ var equalsTestCases = map[string][]struct {
|
||||||
result: false,
|
result: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item1: NewArray([]Item{&BigInteger{big.NewInt(1)}, &BigInteger{big.NewInt(2)}, &BigInteger{big.NewInt(3)}}),
|
item1: NewArray([]Item{(*BigInteger)(big.NewInt(1)), (*BigInteger)(big.NewInt(2)), (*BigInteger)(big.NewInt(3))}),
|
||||||
item2: NewArray([]Item{&BigInteger{big.NewInt(1)}, &BigInteger{big.NewInt(2)}, &BigInteger{big.NewInt(3)}}),
|
item2: NewArray([]Item{(*BigInteger)(big.NewInt(1)), (*BigInteger)(big.NewInt(2)), (*BigInteger)(big.NewInt(3))}),
|
||||||
result: false,
|
result: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item1: NewArray([]Item{&BigInteger{big.NewInt(1)}}),
|
item1: NewArray([]Item{(*BigInteger)(big.NewInt(1))}),
|
||||||
item2: NewBigInteger(big.NewInt(1)),
|
item2: NewBigInteger(big.NewInt(1)),
|
||||||
result: false,
|
result: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item1: NewArray([]Item{&BigInteger{big.NewInt(1)}, &BigInteger{big.NewInt(2)}, &BigInteger{big.NewInt(3)}}),
|
item1: NewArray([]Item{(*BigInteger)(big.NewInt(1)), (*BigInteger)(big.NewInt(2)), (*BigInteger)(big.NewInt(3))}),
|
||||||
item2: NewArray([]Item{&BigInteger{big.NewInt(1)}, &BigInteger{big.NewInt(2)}, &BigInteger{big.NewInt(4)}}),
|
item2: NewArray([]Item{(*BigInteger)(big.NewInt(1)), (*BigInteger)(big.NewInt(2)), (*BigInteger)(big.NewInt(4))}),
|
||||||
result: false,
|
result: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -441,7 +441,7 @@ var marshalJSONTestCases = []struct {
|
||||||
result: []byte(`"010203"`),
|
result: []byte(`"010203"`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: &Array{value: []Item{&BigInteger{value: big.NewInt(3)}, &ByteArray{value: []byte{1, 2, 3}}}},
|
input: &Array{value: []Item{(*BigInteger)(big.NewInt(3)), &ByteArray{value: []byte{1, 2, 3}}}},
|
||||||
result: []byte(`[3,"010203"]`),
|
result: []byte(`[3,"010203"]`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -110,10 +110,10 @@ func toJSON(data []byte, seen map[Item]sliceNoPointer, item Item) ([]byte, error
|
||||||
data = append(data, '}')
|
data = append(data, '}')
|
||||||
seen[item] = sliceNoPointer{start, len(data)}
|
seen[item] = sliceNoPointer{start, len(data)}
|
||||||
case *BigInteger:
|
case *BigInteger:
|
||||||
if it.value.CmpAbs(big.NewInt(MaxAllowedInteger)) == 1 {
|
if it.Big().CmpAbs(big.NewInt(MaxAllowedInteger)) == 1 {
|
||||||
return nil, fmt.Errorf("%w (MaxAllowedInteger)", ErrInvalidValue)
|
return nil, fmt.Errorf("%w (MaxAllowedInteger)", ErrInvalidValue)
|
||||||
}
|
}
|
||||||
data = append(data, it.value.String()...)
|
data = append(data, it.Big().String()...)
|
||||||
case *ByteArray, *Buffer:
|
case *ByteArray, *Buffer:
|
||||||
raw, err := itemToJSONString(it)
|
raw, err := itemToJSONString(it)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -293,7 +293,7 @@ func toJSONWithTypes(item Item, seen map[Item]bool) (interface{}, error) {
|
||||||
case *Buffer, *ByteArray:
|
case *Buffer, *ByteArray:
|
||||||
value = base64.StdEncoding.EncodeToString(it.Value().([]byte))
|
value = base64.StdEncoding.EncodeToString(it.Value().([]byte))
|
||||||
case *BigInteger:
|
case *BigInteger:
|
||||||
value = it.value.String()
|
value = it.Big().String()
|
||||||
case *Map:
|
case *Map:
|
||||||
if seen[item] {
|
if seen[item] {
|
||||||
return "", ErrRecursive
|
return "", ErrRecursive
|
||||||
|
|
Loading…
Reference in a new issue