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 }