github.com/dfcfw/lua@v0.0.0-20230325031207-0cc7ffb7b8b9/luar/slice.go (about)

     1  package luar
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/dfcfw/lua"
     7  )
     8  
     9  func sliceIndex(L *lua.LState) int {
    10  	ref, mt := check(L, 1)
    11  	key := L.CheckAny(2)
    12  
    13  	switch converted := key.(type) {
    14  	case lua.LNumber:
    15  		index := int(converted)
    16  		if index < 1 || index > ref.Len() {
    17  			L.ArgError(2, "index out of range")
    18  		}
    19  		val := ref.Index(index - 1)
    20  		if (val.Kind() == reflect.Struct || val.Kind() == reflect.Array) && val.CanAddr() {
    21  			val = val.Addr()
    22  		}
    23  		L.Push(New(L, val.Interface()))
    24  	case lua.LString:
    25  		if fn := mt.method(string(converted)); fn != nil {
    26  			L.Push(fn)
    27  			return 1
    28  		}
    29  		return 0
    30  	default:
    31  		L.ArgError(2, "must be a number or string")
    32  	}
    33  	return 1
    34  }
    35  
    36  func sliceNewIndex(L *lua.LState) int {
    37  	ref, _ := check(L, 1)
    38  	index := L.CheckInt(2)
    39  	value := L.CheckAny(3)
    40  
    41  	if index < 1 || index > ref.Len() {
    42  		L.ArgError(2, "index out of range")
    43  	}
    44  	val, err := lValueToReflect(L, value, ref.Type().Elem(), nil)
    45  	if err != nil {
    46  		L.ArgError(3, err.Error())
    47  	}
    48  	ref.Index(index - 1).Set(val)
    49  	return 0
    50  }
    51  
    52  func sliceLen(L *lua.LState) int {
    53  	ref, _ := check(L, 1)
    54  
    55  	L.Push(lua.LNumber(ref.Len()))
    56  	return 1
    57  }
    58  
    59  func sliceCall(L *lua.LState) int {
    60  	ref, _ := check(L, 1)
    61  
    62  	i := 0
    63  	fn := func(L *lua.LState) int {
    64  		if i >= ref.Len() {
    65  			return 0
    66  		}
    67  		item := ref.Index(i).Interface()
    68  		L.Push(lua.LNumber(i + 1))
    69  		L.Push(New(L, item))
    70  		i++
    71  		return 2
    72  	}
    73  
    74  	L.Push(L.NewFunction(fn))
    75  	return 1
    76  }
    77  
    78  func sliceAdd(L *lua.LState) int {
    79  	ref, _ := check(L, 1)
    80  	item := L.CheckAny(2)
    81  
    82  	hint := ref.Type().Elem()
    83  	value, err := lValueToReflect(L, item, hint, nil)
    84  	if err != nil {
    85  		L.ArgError(2, err.Error())
    86  	}
    87  
    88  	ref = reflect.Append(ref, value)
    89  	L.Push(New(L, ref.Interface()))
    90  	return 1
    91  }