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

     1  package luar
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/dfcfw/lua"
     7  )
     8  
     9  func checkPtr(L *lua.LState, idx int) (ref reflect.Value, mt *Metatable) {
    10  	ud := L.CheckUserData(idx)
    11  	ref = reflect.ValueOf(ud.Value)
    12  	if expecting := reflect.Ptr; ref.Kind() != expecting {
    13  		L.ArgError(idx, "expecting "+expecting.String())
    14  	}
    15  	mt = &Metatable{LTable: ud.Metatable.(*lua.LTable)}
    16  	return
    17  }
    18  
    19  func ptrIndex(L *lua.LState) int {
    20  	ref, mt := checkPtr(L, 1)
    21  	key := L.CheckString(2)
    22  
    23  	if fn := mt.method(key); fn != nil {
    24  		L.Push(fn)
    25  		return 1
    26  	}
    27  
    28  	// fallback to non-pointer method
    29  	ref = ref.Elem()
    30  	mt = MT(L, ref.Interface())
    31  	if fn := mt.method(key); fn != nil {
    32  		L.Push(fn)
    33  		return 1
    34  	}
    35  
    36  	return 0
    37  }
    38  
    39  func ptrPow(L *lua.LState) int {
    40  	ref, _ := checkPtr(L, 1)
    41  	val := L.CheckAny(2)
    42  
    43  	elem := ref.Elem()
    44  	if !elem.CanSet() {
    45  		L.RaiseError("unable to set pointer value")
    46  	}
    47  	value, err := lValueToReflect(L, val, elem.Type(), nil)
    48  	if err != nil {
    49  		L.ArgError(2, err.Error())
    50  	}
    51  	elem.Set(value)
    52  	L.SetTop(1)
    53  	return 1
    54  }
    55  
    56  func ptrUnm(L *lua.LState) int {
    57  	ref, _ := checkPtr(L, 1)
    58  	elem := ref.Elem()
    59  	if !elem.CanInterface() {
    60  		L.RaiseError("cannot interface pointer type " + elem.String())
    61  	}
    62  	L.Push(New(L, elem.Interface()))
    63  	return 1
    64  }
    65  
    66  func ptrEq(L *lua.LState) int {
    67  	ref1, _ := checkPtr(L, 1)
    68  	ref2, _ := checkPtr(L, 2)
    69  
    70  	L.Push(lua.LBool(ref1.Pointer() == ref2.Pointer()))
    71  	return 1
    72  }