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 {
|
||||
b, di, err := compiler.CompileWithOptions("foo.go", strings.NewReader(src), nil)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
|
@ -159,6 +160,11 @@ func newStd() *Std {
|
|||
md = newMethodAndPrice(s.stringSplit3, 1<<8, callflag.NoneFlag)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -421,6 +427,12 @@ func (s *Std) stringSplitAux(str, sep string, removeEmpty bool) []stackitem.Item
|
|||
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.
|
||||
func (s *Std) Metadata() *interop.ContractMD {
|
||||
return &s.ContractMD
|
||||
|
|
|
@ -558,3 +558,25 @@ func TestStringSplit(t *testing.T) {
|
|||
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),
|
||||
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