scream/vendor/src/github.com/layeh/gopher-luar/slice.go

94 lines
1.8 KiB
Go

package luar
import (
"reflect"
"github.com/yuin/gopher-lua"
)
func checkSlice(L *lua.LState, idx int) reflect.Value {
ud := L.CheckUserData(idx)
ref := reflect.ValueOf(ud.Value)
if ref.Kind() != reflect.Slice {
L.ArgError(idx, "expecting slice")
}
return ref
}
func sliceIndex(L *lua.LState) int {
ref := checkSlice(L, 1)
key := L.CheckAny(2)
switch converted := key.(type) {
case lua.LNumber:
index := int(converted)
if index < 1 || index > ref.Len() {
L.ArgError(2, "index out of range")
}
L.Push(New(L, ref.Index(index-1).Interface()))
case lua.LString:
switch string(converted) {
case "capacity":
L.Push(L.NewFunction(sliceCapacity))
case "append":
L.Push(L.NewFunction(sliceAppend))
default:
return 0
}
default:
L.ArgError(2, "must be a number or string")
}
return 1
}
func sliceNewIndex(L *lua.LState) int {
ref := checkSlice(L, 1)
index := L.CheckInt(2)
value := L.CheckAny(3)
if index < 1 || index > ref.Len() {
L.ArgError(2, "index out of range")
}
ref.Index(index - 1).Set(lValueToReflect(value, ref.Type().Elem()))
return 0
}
func sliceLen(L *lua.LState) int {
ref := checkSlice(L, 1)
L.Push(lua.LNumber(ref.Len()))
return 1
}
func sliceEq(L *lua.LState) int {
slice1 := checkSlice(L, 1)
slice2 := checkSlice(L, 2)
L.Push(lua.LBool(slice1 == slice2))
return 1
}
// slice methods
func sliceCapacity(L *lua.LState) int {
ref := checkSlice(L, 1)
L.Push(lua.LNumber(ref.Cap()))
return 1
}
func sliceAppend(L *lua.LState) int {
ref := checkSlice(L, 1)
hint := ref.Type().Elem()
values := make([]reflect.Value, L.GetTop()-1)
for i := 2; i <= L.GetTop(); i++ {
value := lValueToReflect(L.Get(i), hint)
if value.Type() != hint {
L.ArgError(i, "invalid type")
}
values[i-2] = value
}
newSlice := reflect.Append(ref, values...)
L.Push(New(L, newSlice.Interface()))
return 1
}