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 (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
@ -90,33 +89,17 @@ func mkInvConversion(from Item, to Type) error {
|
|||
func Make(v interface{}) Item {
|
||||
switch val := v.(type) {
|
||||
case int:
|
||||
return &BigInteger{
|
||||
value: big.NewInt(int64(val)),
|
||||
}
|
||||
return (*BigInteger)(big.NewInt(int64(val)))
|
||||
case int64:
|
||||
return &BigInteger{
|
||||
value: big.NewInt(val),
|
||||
}
|
||||
return (*BigInteger)(big.NewInt(val))
|
||||
case uint8:
|
||||
return &BigInteger{
|
||||
value: big.NewInt(int64(val)),
|
||||
}
|
||||
return (*BigInteger)(big.NewInt(int64(val)))
|
||||
case uint16:
|
||||
return &BigInteger{
|
||||
value: big.NewInt(int64(val)),
|
||||
}
|
||||
return (*BigInteger)(big.NewInt(int64(val)))
|
||||
case uint32:
|
||||
return &BigInteger{
|
||||
value: big.NewInt(int64(val)),
|
||||
}
|
||||
return (*BigInteger)(big.NewInt(int64(val)))
|
||||
case uint64:
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, val)
|
||||
bigInt := big.NewInt(0)
|
||||
bigInt.SetBytes(b)
|
||||
return &BigInteger{
|
||||
value: bigInt,
|
||||
}
|
||||
return (*BigInteger)(new(big.Int).SetUint64(val))
|
||||
case []byte:
|
||||
return &ByteArray{
|
||||
value: val,
|
||||
|
@ -400,9 +383,7 @@ func (i Null) Convert(typ Type) (Item, error) {
|
|||
}
|
||||
|
||||
// BigInteger represents a big integer on the stack.
|
||||
type BigInteger struct {
|
||||
value *big.Int
|
||||
}
|
||||
type BigInteger big.Int
|
||||
|
||||
// NewBigInteger returns an new BigInteger object.
|
||||
func NewBigInteger(value *big.Int) *BigInteger {
|
||||
|
@ -418,19 +399,22 @@ func NewBigInteger(value *big.Int) *BigInteger {
|
|||
panic(errTooBigInteger)
|
||||
}
|
||||
}
|
||||
return &BigInteger{
|
||||
value: value,
|
||||
}
|
||||
return (*BigInteger)(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.
|
||||
func (i *BigInteger) Bytes() []byte {
|
||||
return bigint.ToBytes(i.value)
|
||||
return bigint.ToBytes(i.Big())
|
||||
}
|
||||
|
||||
// TryBool implements Item interface.
|
||||
func (i *BigInteger) TryBool() (bool, error) {
|
||||
return i.value.Sign() != 0, nil
|
||||
return i.Big().Sign() != 0, nil
|
||||
}
|
||||
|
||||
// TryBytes implements Item interface.
|
||||
|
@ -440,7 +424,7 @@ func (i *BigInteger) TryBytes() ([]byte, error) {
|
|||
|
||||
// TryInteger implements Item interface.
|
||||
func (i *BigInteger) TryInteger() (*big.Int, error) {
|
||||
return i.value, nil
|
||||
return i.Big(), nil
|
||||
}
|
||||
|
||||
// Equals implements Item interface.
|
||||
|
@ -451,12 +435,12 @@ func (i *BigInteger) Equals(s Item) bool {
|
|||
return false
|
||||
}
|
||||
val, ok := s.(*BigInteger)
|
||||
return ok && i.value.Cmp(val.value) == 0
|
||||
return ok && i.Big().Cmp(val.Big()) == 0
|
||||
}
|
||||
|
||||
// Value implements Item interface.
|
||||
func (i *BigInteger) Value() interface{} {
|
||||
return i.value
|
||||
return i.Big()
|
||||
}
|
||||
|
||||
func (i *BigInteger) String() string {
|
||||
|
@ -466,7 +450,7 @@ func (i *BigInteger) String() string {
|
|||
// Dup implements Item interface.
|
||||
func (i *BigInteger) Dup() Item {
|
||||
n := new(big.Int)
|
||||
return &BigInteger{n.Set(i.value)}
|
||||
return (*BigInteger)(n.Set(i.Big()))
|
||||
}
|
||||
|
||||
// Type implements Item interface.
|
||||
|
@ -479,7 +463,7 @@ func (i *BigInteger) Convert(typ Type) (Item, error) {
|
|||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (i *BigInteger) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(i.value)
|
||||
return json.Marshal(i.Big())
|
||||
}
|
||||
|
||||
// Bool represents a boolean Item.
|
||||
|
@ -1156,11 +1140,8 @@ func deepCopy(item Item, seen map[Item]Item) Item {
|
|||
}
|
||||
return m
|
||||
case *BigInteger:
|
||||
bi := new(big.Int).SetBytes(it.value.Bytes())
|
||||
if it.value.Sign() == -1 {
|
||||
bi.Neg(bi)
|
||||
}
|
||||
return NewBigInteger(bi)
|
||||
bi := new(big.Int).Set(it.Big())
|
||||
return (*BigInteger)(bi)
|
||||
case *ByteArray:
|
||||
return NewByteArray(slice.Copy(it.value))
|
||||
case *Buffer:
|
||||
|
|
|
@ -15,35 +15,35 @@ var makeStackItemTestCases = []struct {
|
|||
}{
|
||||
{
|
||||
input: int64(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: int16(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: 3,
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: uint8(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: uint16(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: uint32(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: uint64(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: big.NewInt(3),
|
||||
result: &BigInteger{value: big.NewInt(3)},
|
||||
result: (*BigInteger)(big.NewInt(3)),
|
||||
},
|
||||
{
|
||||
input: []byte{1, 2, 3, 4},
|
||||
|
@ -70,12 +70,12 @@ var makeStackItemTestCases = []struct {
|
|||
result: Bool(false),
|
||||
},
|
||||
{
|
||||
input: []Item{&BigInteger{value: big.NewInt(3)}, &ByteArray{value: []byte{1, 2, 3}}},
|
||||
result: &Array{value: []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)(big.NewInt(3)), &ByteArray{value: []byte{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,
|
||||
},
|
||||
{
|
||||
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)}}),
|
||||
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))}),
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
item1: NewArray([]Item{&BigInteger{big.NewInt(1)}}),
|
||||
item1: NewArray([]Item{(*BigInteger)(big.NewInt(1))}),
|
||||
item2: NewBigInteger(big.NewInt(1)),
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
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)}}),
|
||||
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))}),
|
||||
result: false,
|
||||
},
|
||||
},
|
||||
|
@ -441,7 +441,7 @@ var marshalJSONTestCases = []struct {
|
|||
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"]`),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -110,10 +110,10 @@ func toJSON(data []byte, seen map[Item]sliceNoPointer, item Item) ([]byte, error
|
|||
data = append(data, '}')
|
||||
seen[item] = sliceNoPointer{start, len(data)}
|
||||
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)
|
||||
}
|
||||
data = append(data, it.value.String()...)
|
||||
data = append(data, it.Big().String()...)
|
||||
case *ByteArray, *Buffer:
|
||||
raw, err := itemToJSONString(it)
|
||||
if err != nil {
|
||||
|
@ -293,7 +293,7 @@ func toJSONWithTypes(item Item, seen map[Item]bool) (interface{}, error) {
|
|||
case *Buffer, *ByteArray:
|
||||
value = base64.StdEncoding.EncodeToString(it.Value().([]byte))
|
||||
case *BigInteger:
|
||||
value = it.value.String()
|
||||
value = it.Big().String()
|
||||
case *Map:
|
||||
if seen[item] {
|
||||
return "", ErrRecursive
|
||||
|
|
Loading…
Reference in a new issue