Add Memory.WriteString (#820)

Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
This commit is contained in:
Anuraag Agrawal
2022-10-03 17:26:36 +09:00
committed by GitHub
parent 2fc5f6d0c5
commit 0b4dbfd8d6
3 changed files with 60 additions and 0 deletions

View File

@@ -459,6 +459,9 @@ type Memory interface {
// Write writes the slice to the underlying buffer at the offset or returns false if out of range.
Write(ctx context.Context, offset uint32, v []byte) bool
// WriteString writes the string to the underlying buffer at the offset or returns false if out of range.
WriteString(ctx context.Context, offset uint32, v string) bool
}
// EncodeExternref encodes the input as a ValueTypeExternref.

View File

@@ -162,6 +162,15 @@ func (m *MemoryInstance) Write(_ context.Context, offset uint32, val []byte) boo
return true
}
// WriteString implements the same method as documented on api.Memory.
func (m *MemoryInstance) WriteString(_ context.Context, offset uint32, val string) bool {
if !m.hasSize(offset, uint32(len(val))) {
return false
}
copy(m.Buffer[offset:], val)
return true
}
// MemoryPagesToBytesNum converts the given pages into the number of bytes contained in these pages.
func MemoryPagesToBytesNum(pages uint32) (bytesNum uint64) {
return uint64(pages) << MemoryPageSizeInBits

View File

@@ -3,8 +3,10 @@ package wasm
import (
"context"
"math"
"strings"
"testing"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/testing/require"
)
@@ -763,3 +765,49 @@ func TestMemoryInstance_Write(t *testing.T) {
require.False(t, ok)
}
}
func TestMemoryInstance_WriteString(t *testing.T) {
for _, ctx := range []context.Context{nil, testCtx} { // Ensure it doesn't crash on nil!
var mem = &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1}
s := "bear"
require.True(t, mem.WriteString(ctx, 4, s))
require.Equal(t, []byte{0, 0, 0, 0, 'b', 'e', 'a', 'r'}, mem.Buffer)
ok := mem.WriteString(ctx, 5, s)
require.False(t, ok)
ok = mem.WriteString(ctx, 9, s)
require.False(t, ok)
}
}
func BenchmarkWriteString(b *testing.B) {
tests := []string{
"",
"bear",
"hello world",
strings.Repeat("hello ", 10),
}
// nolint intentionally testing interface access
var mem api.Memory
mem = &MemoryInstance{Buffer: make([]byte, 1000), Min: 1}
for _, tt := range tests {
b.Run("", func(b *testing.B) {
b.Run("Write", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if !mem.Write(testCtx, 0, []byte(tt)) {
b.Fail()
}
}
})
b.Run("WriteString", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if !mem.WriteString(testCtx, 0, tt) {
b.Fail()
}
}
})
})
}
}