forked from TrueCloudLab/neoneo-go
core, interop: add strLen
method for native StdLib contract
Close #3195. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
b5cf3f592f
commit
406c9f8b92
4 changed files with 64 additions and 0 deletions
|
@ -277,6 +277,29 @@ func TestCurrentSigners(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStdLib_StrLen(t *testing.T) {
|
||||||
|
bc, acc := chain.NewSingle(t)
|
||||||
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
|
src := `package foo
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
||||||
|
)
|
||||||
|
func Main(s string) int {
|
||||||
|
return std.StrLen(s)
|
||||||
|
}`
|
||||||
|
ctr := neotest.CompileSource(t, e.CommitteeHash, strings.NewReader(src), &compiler.Options{Name: "Helper"})
|
||||||
|
e.DeployContract(t, ctr, nil)
|
||||||
|
c := e.CommitteeInvoker(ctr.Hash)
|
||||||
|
|
||||||
|
expected := stackitem.Make(1)
|
||||||
|
c.Invoke(t, expected, "main", "🦆")
|
||||||
|
c.Invoke(t, expected, "main", "ã")
|
||||||
|
c.Invoke(t, expected, "main", "a")
|
||||||
|
|
||||||
|
expected = stackitem.Make(7)
|
||||||
|
c.Invoke(t, expected, "main", "abc 123")
|
||||||
|
}
|
||||||
|
|
||||||
func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM {
|
func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM {
|
||||||
b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
|
b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
|
@ -159,6 +160,11 @@ func newStd() *Std {
|
||||||
md = newMethodAndPrice(s.stringSplit3, 1<<8, callflag.NoneFlag)
|
md = newMethodAndPrice(s.stringSplit3, 1<<8, callflag.NoneFlag)
|
||||||
s.AddMethod(md, desc)
|
s.AddMethod(md, desc)
|
||||||
|
|
||||||
|
desc = newDescriptor("strLen", smartcontract.IntegerType,
|
||||||
|
manifest.NewParameter("str", smartcontract.StringType))
|
||||||
|
md = newMethodAndPrice(s.strLen, 1<<8, callflag.NoneFlag)
|
||||||
|
s.AddMethod(md, desc)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +427,12 @@ func (s *Std) stringSplitAux(str, sep string, removeEmpty bool) []stackitem.Item
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Std) strLen(_ *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
|
str := s.toLimitedString(args[0])
|
||||||
|
|
||||||
|
return stackitem.NewBigInteger(big.NewInt(int64(utf8.RuneCountInString(str))))
|
||||||
|
}
|
||||||
|
|
||||||
// Metadata implements the Contract interface.
|
// Metadata implements the Contract interface.
|
||||||
func (s *Std) Metadata() *interop.ContractMD {
|
func (s *Std) Metadata() *interop.ContractMD {
|
||||||
return &s.ContractMD
|
return &s.ContractMD
|
||||||
|
|
|
@ -558,3 +558,25 @@ func TestStringSplit(t *testing.T) {
|
||||||
func() { s.stringSplit2(ic, []stackitem.Item{s1, s2}) })
|
func() { s.stringSplit2(ic, []stackitem.Item{s1, s2}) })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStd_StrLen(t *testing.T) {
|
||||||
|
s := newStd()
|
||||||
|
ic := &interop.Context{VM: vm.New()}
|
||||||
|
|
||||||
|
check := func(t *testing.T, expected int64, str string) {
|
||||||
|
args := []stackitem.Item{stackitem.Make(str)}
|
||||||
|
actual := s.strLen(ic, args)
|
||||||
|
l, ok := actual.Value().(*big.Int)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, expected, l.Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
// These tests are taken from https://github.com/neo-project/neo/pull/2854/files.
|
||||||
|
check(t, 1, "🦆")
|
||||||
|
check(t, 1, "ã")
|
||||||
|
check(t, 1, "a")
|
||||||
|
|
||||||
|
bad := string(rune(0xff))
|
||||||
|
check(t, 1, bad)
|
||||||
|
check(t, 3, bad+"ab")
|
||||||
|
}
|
||||||
|
|
|
@ -173,3 +173,10 @@ func StringSplitNonEmpty(s, sep string) []string {
|
||||||
return neogointernal.CallWithToken(Hash, "stringSplit", int(contract.NoneFlag),
|
return neogointernal.CallWithToken(Hash, "stringSplit", int(contract.NoneFlag),
|
||||||
s, sep, true).([]string)
|
s, sep, true).([]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StrLen returns length of the string in Utf- characters.
|
||||||
|
// It uses `strLen` method of StdLib native contract.
|
||||||
|
func StrLen(s string) int {
|
||||||
|
return neogointernal.CallWithToken(Hash, "strLen", int(contract.NoneFlag),
|
||||||
|
s).(int)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue