Skip to content

Commit

Permalink
added copy from slice to array copy
Browse files Browse the repository at this point in the history
  • Loading branch information
grantnelson-wf committed Jul 24, 2024
1 parent 956409c commit b6c2f3c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 1 deletion.
11 changes: 10 additions & 1 deletion compiler/prelude/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,16 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
}), "$");
};
typ.copy = (dst, src) => {
$copyArray(dst, src, 0, 0, src.length, elem);
if (src.length === undefined) {
// copy from a slice, the slice may be bigger but not smaller than the array
if (src.$length < dst.length) {
$throwRuntimeError("cannot convert slice with length "+src.$length+" to array or pointer to array with length "+dst.length);
}
$copyArray(dst, src.$array, 0, 0, dst.length, elem);
} else {
// copy from another array
$copyArray(dst, src, 0, 0, src.length, elem);
}
};
typ.ptr.init(typ);
Object.defineProperty(typ.ptr.nil, "nilCheck", { get: $throwNilPointerError });
Expand Down
111 changes: 111 additions & 0 deletions tests/arrays_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tests

import (
"fmt"
"reflect"
"testing"
"unsafe"
Expand Down Expand Up @@ -121,3 +122,113 @@ func TestNilPrototypeNotModifiedByReflectGrow(t *testing.T) {
println("s2:", s2)
}
}

func TestConversionFromSliceToArray(t *testing.T) {
t.Run(`nil byte slice to zero byte array`, func(t *testing.T) {
s := []byte(nil)
_ = [0]byte(s) // should not have runtime panic
})

t.Run(`empty byte slice to zero byte array`, func(t *testing.T) {
s := []byte{}
_ = [0]byte(s) // should not have runtime panic
})

t.Run(`3 byte slice to 3 byte array`, func(t *testing.T) {
s := []byte{12, 34, 56}
a := [3]byte(s)
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] {
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
}
})

t.Run(`4 byte slice to 4 byte array`, func(t *testing.T) {
s := []byte{12, 34, 56, 78}
a := [4]byte(s)
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
}
})

t.Run(`5 byte slice to 5 byte array`, func(t *testing.T) {
s := []byte{12, 34, 56, 78, 90}
a := [5]byte(s)
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] || s[4] != a[4] {
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
}
})

t.Run(`larger 5 byte slice to smaller 4 byte array`, func(t *testing.T) {
s := []byte{12, 34, 56, 78, 90}
a := [4]byte(s)
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
}
})

t.Run(`larger 4 byte slice to smaller zero byte array`, func(t *testing.T) {
s := []byte{12, 34, 56, 78}
_ = [0]byte(s) // should not have runtime panic
})

t.Run(`smaller 3 byte slice to larger 4 byte array`, func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
err := fmt.Sprintf(`%v`, r)
exp := `runtime error: cannot convert slice with length 3 to array or pointer to array with length 4`
if err != exp {
t.Error(`unexpected panic message:`, r)
t.Log("\texpected:", exp)
}
}
}()

s := []byte{12, 34, 56}
a := [4]byte(s)
t.Errorf("expected a runtime panic:\n\tslice: %#v\n\tarray: %#v", s, a)
})

t.Run(`nil byte slice to 5 byte array`, func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
err := fmt.Sprintf(`%v`, r)
exp := `runtime error: cannot convert slice with length 0 to array or pointer to array with length 5`
if err != exp {
t.Error(`unexpected panic message:`, r)
t.Log("\texpected:", exp)
}
}
}()

s := []byte(nil)
a := [5]byte(s)
t.Errorf("expected a runtime panic:\n\tslice: %#v\n\tarray: %#v", s, a)
})

type Cat struct {
name string
age int
}
cats := []Cat{
{name: "Tom", age: 3},
{name: "Jonesy", age: 5},
{name: "Sylvester", age: 7},
{name: "Rita", age: 2},
}

t.Run(`4 Cat slice to 4 Cat array`, func(t *testing.T) {
s := cats
a := [4]Cat(s)
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
}
})

t.Run(`4 *Cat slice to 4 *Cat array`, func(t *testing.T) {
s := []*Cat{&cats[0], &cats[1], &cats[2], &cats[3]}
a := [4]*Cat(s)
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
}
})
}

0 comments on commit b6c2f3c

Please sign in to comment.