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 }