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

     1  package luar
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/dfcfw/lua"
     7  )
     8  
     9  func structIndex(L *lua.LState) int {
    10  	ref, mt := check(L, 1)
    11  	key := L.CheckString(2)
    12  
    13  	if fn := mt.method(key); fn != nil {
    14  		L.Push(fn)
    15  		return 1
    16  	}
    17  
    18  	ref = reflect.Indirect(ref)
    19  	index := mt.fieldIndex(key)
    20  	if index == nil {
    21  		return 0
    22  	}
    23  	field := ref.FieldByIndex(index)
    24  	if !field.CanInterface() {
    25  		L.RaiseError("cannot interface field " + key)
    26  	}
    27  
    28  	if (field.Kind() == reflect.Struct || field.Kind() == reflect.Array) && field.CanAddr() {
    29  		field = field.Addr()
    30  	}
    31  	L.Push(New(L, field.Interface()))
    32  	return 1
    33  }
    34  
    35  func structPtrIndex(L *lua.LState) int {
    36  	ref, mt := check(L, 1)
    37  	key := L.CheckString(2)
    38  
    39  	if fn := mt.method(key); fn != nil {
    40  		L.Push(fn)
    41  		return 1
    42  	}
    43  
    44  	ref = ref.Elem()
    45  	mt = MT(L, ref.Interface())
    46  	if fn := mt.method(key); fn != nil {
    47  		L.Push(fn)
    48  		return 1
    49  	}
    50  
    51  	index := mt.fieldIndex(key)
    52  	if index == nil {
    53  		return 0
    54  	}
    55  	field := ref.FieldByIndex(index)
    56  	if !field.CanInterface() {
    57  		L.RaiseError("cannot interface field " + key)
    58  	}
    59  
    60  	if (field.Kind() == reflect.Struct || field.Kind() == reflect.Array) && field.CanAddr() {
    61  		field = field.Addr()
    62  	}
    63  	L.Push(New(L, field.Interface()))
    64  	return 1
    65  }
    66  
    67  func structPtrNewIndex(L *lua.LState) int {
    68  	ref, mt := check(L, 1)
    69  	key := L.CheckString(2)
    70  	value := L.CheckAny(3)
    71  
    72  	ref = ref.Elem()
    73  	mt = MT(L, ref.Interface())
    74  
    75  	index := mt.fieldIndex(key)
    76  	if index == nil {
    77  		L.RaiseError("unknown field " + key)
    78  	}
    79  	field := ref.FieldByIndex(index)
    80  	if !field.CanSet() {
    81  		L.RaiseError("cannot set field " + key)
    82  	}
    83  	val, err := lValueToReflect(L, value, field.Type(), nil)
    84  	if err != nil {
    85  		L.ArgError(2, err.Error())
    86  	}
    87  	field.Set(val)
    88  	return 0
    89  }
    90  
    91  func structEq(L *lua.LState) int {
    92  	ref1, _ := check(L, 1)
    93  	ref2, _ := check(L, 2)
    94  
    95  	L.Push(lua.LBool(ref1.Interface() == ref2.Interface()))
    96  	return 1
    97  }