Skip to content

Commit b6c2f3c

Browse files
added copy from slice to array copy
1 parent 956409c commit b6c2f3c

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

compiler/prelude/types.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,16 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
150150
}), "$");
151151
};
152152
typ.copy = (dst, src) => {
153-
$copyArray(dst, src, 0, 0, src.length, elem);
153+
if (src.length === undefined) {
154+
// copy from a slice, the slice may be bigger but not smaller than the array
155+
if (src.$length < dst.length) {
156+
$throwRuntimeError("cannot convert slice with length "+src.$length+" to array or pointer to array with length "+dst.length);
157+
}
158+
$copyArray(dst, src.$array, 0, 0, dst.length, elem);
159+
} else {
160+
// copy from another array
161+
$copyArray(dst, src, 0, 0, src.length, elem);
162+
}
154163
};
155164
typ.ptr.init(typ);
156165
Object.defineProperty(typ.ptr.nil, "nilCheck", { get: $throwNilPointerError });

tests/arrays_test.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tests
22

33
import (
4+
"fmt"
45
"reflect"
56
"testing"
67
"unsafe"
@@ -121,3 +122,113 @@ func TestNilPrototypeNotModifiedByReflectGrow(t *testing.T) {
121122
println("s2:", s2)
122123
}
123124
}
125+
126+
func TestConversionFromSliceToArray(t *testing.T) {
127+
t.Run(`nil byte slice to zero byte array`, func(t *testing.T) {
128+
s := []byte(nil)
129+
_ = [0]byte(s) // should not have runtime panic
130+
})
131+
132+
t.Run(`empty byte slice to zero byte array`, func(t *testing.T) {
133+
s := []byte{}
134+
_ = [0]byte(s) // should not have runtime panic
135+
})
136+
137+
t.Run(`3 byte slice to 3 byte array`, func(t *testing.T) {
138+
s := []byte{12, 34, 56}
139+
a := [3]byte(s)
140+
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] {
141+
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
142+
}
143+
})
144+
145+
t.Run(`4 byte slice to 4 byte array`, func(t *testing.T) {
146+
s := []byte{12, 34, 56, 78}
147+
a := [4]byte(s)
148+
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
149+
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
150+
}
151+
})
152+
153+
t.Run(`5 byte slice to 5 byte array`, func(t *testing.T) {
154+
s := []byte{12, 34, 56, 78, 90}
155+
a := [5]byte(s)
156+
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] || s[4] != a[4] {
157+
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
158+
}
159+
})
160+
161+
t.Run(`larger 5 byte slice to smaller 4 byte array`, func(t *testing.T) {
162+
s := []byte{12, 34, 56, 78, 90}
163+
a := [4]byte(s)
164+
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
165+
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
166+
}
167+
})
168+
169+
t.Run(`larger 4 byte slice to smaller zero byte array`, func(t *testing.T) {
170+
s := []byte{12, 34, 56, 78}
171+
_ = [0]byte(s) // should not have runtime panic
172+
})
173+
174+
t.Run(`smaller 3 byte slice to larger 4 byte array`, func(t *testing.T) {
175+
defer func() {
176+
if r := recover(); r != nil {
177+
err := fmt.Sprintf(`%v`, r)
178+
exp := `runtime error: cannot convert slice with length 3 to array or pointer to array with length 4`
179+
if err != exp {
180+
t.Error(`unexpected panic message:`, r)
181+
t.Log("\texpected:", exp)
182+
}
183+
}
184+
}()
185+
186+
s := []byte{12, 34, 56}
187+
a := [4]byte(s)
188+
t.Errorf("expected a runtime panic:\n\tslice: %#v\n\tarray: %#v", s, a)
189+
})
190+
191+
t.Run(`nil byte slice to 5 byte array`, func(t *testing.T) {
192+
defer func() {
193+
if r := recover(); r != nil {
194+
err := fmt.Sprintf(`%v`, r)
195+
exp := `runtime error: cannot convert slice with length 0 to array or pointer to array with length 5`
196+
if err != exp {
197+
t.Error(`unexpected panic message:`, r)
198+
t.Log("\texpected:", exp)
199+
}
200+
}
201+
}()
202+
203+
s := []byte(nil)
204+
a := [5]byte(s)
205+
t.Errorf("expected a runtime panic:\n\tslice: %#v\n\tarray: %#v", s, a)
206+
})
207+
208+
type Cat struct {
209+
name string
210+
age int
211+
}
212+
cats := []Cat{
213+
{name: "Tom", age: 3},
214+
{name: "Jonesy", age: 5},
215+
{name: "Sylvester", age: 7},
216+
{name: "Rita", age: 2},
217+
}
218+
219+
t.Run(`4 Cat slice to 4 Cat array`, func(t *testing.T) {
220+
s := cats
221+
a := [4]Cat(s)
222+
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
223+
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
224+
}
225+
})
226+
227+
t.Run(`4 *Cat slice to 4 *Cat array`, func(t *testing.T) {
228+
s := []*Cat{&cats[0], &cats[1], &cats[2], &cats[3]}
229+
a := [4]*Cat(s)
230+
if s[0] != a[0] || s[1] != a[1] || s[2] != a[2] || s[3] != a[3] {
231+
t.Errorf("slice and array are not equal after conversion:\n\tslice: %#v\n\tarray: %#v", s, a)
232+
}
233+
})
234+
}

0 commit comments

Comments
 (0)