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:
Evgeniy Stratonikov 2021-08-04 16:41:13 +03:00
parent cff8b1c24e
commit a5516e8c96
3 changed files with 42 additions and 61 deletions

View file

@ -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:

View file

@ -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"]`),
},
{

View file

@ -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