// Also for arrays. func copySliceToTable(L *lua.State, vslice reflect.Value, visited visitor) int { ref := vslice for vslice.Kind() == reflect.Ptr { // For arrays. vslice = vslice.Elem() } if vslice.IsValid() && (vslice.Kind() == reflect.Slice || vslice.Kind() == reflect.Array) { n := vslice.Len() L.CreateTable(n, 0) if vslice.Kind() == reflect.Slice { visited.mark(vslice) } else if ref.Kind() == reflect.Ptr { visited.mark(ref) } for i := 0; i < n; i++ { L.PushInteger(int64(i + 1)) v := vslice.Index(i) if isNil(v) { v = nullv } goToLua(L, nil, v, true, visited) L.SetTable(-3) } return 1 } L.PushNil() L.PushString("not a slice/array") return 2 }
func copyStructToTable(L *lua.State, vstruct reflect.Value, visited visitor) int { // If 'vstruct' is a pointer to struct, use the pointer to mark as visited. ref := vstruct for vstruct.Kind() == reflect.Ptr { vstruct = vstruct.Elem() } if vstruct.IsValid() && vstruct.Type().Kind() == reflect.Struct { n := vstruct.NumField() L.CreateTable(n, 0) if ref.Kind() == reflect.Ptr { visited.mark(ref) } for i := 0; i < n; i++ { st := vstruct.Type() field := st.Field(i) key := field.Name tag := field.Tag.Get("lua") if tag != "" { key = tag } goToLua(L, nil, reflect.ValueOf(key), true, visited) v := vstruct.Field(i) goToLua(L, nil, v, true, visited) L.SetTable(-3) } return 1 } L.PushNil() L.PushString("not a struct") return 2 }
func pushMap(L *lua.State, m map[string]interface{}, lower bool) { L.CreateTable(0, len(m)) for k, v := range m { if lower { L.PushString(strings.ToLower(k)) } else { L.PushString(k) } switch t := v.(type) { case string: L.PushString(t) case int64: L.PushInteger(t) case int: L.PushInteger(int64(t)) case float64: L.PushNumber(t) case bool: L.PushBoolean(t) case map[string]interface{}: pushMap(L, t, false) default: L.PushNil() } L.SetTable(-3) } }
func PushStringVec(L *lua.State, v []string) { L.CheckStack(3) L.CreateTable(len(v), 0) for idx, val := range v { SetTableIntString(L, int64(idx+1), val) } }
func MessThingContents(state *lua.State, thing *Thing) int { // make a new table state.CreateTable(len(thing.Contents), 0) // ( -- tbl ) // for each content add a new lua-space Thing for i, contentId := range thing.Contents { state.PushInteger(int64(i)) pushValue(state, contentId) state.SetTable(-3) // ( tbl key val -- tbl ) } // ( tbl -- tbl ) return 1 }
func PushTime(L *lua.State, t time.Time) { L.CheckStack(3) L.CreateTable(0, 7) SetTableInt(L, "year", int64(t.Year())) SetTableInt(L, "month", int64(t.Month())) SetTableInt(L, "day", int64(t.Day())) SetTableInt(L, "weekday", int64(t.Weekday())) SetTableInt(L, "hour", int64(t.Hour())) SetTableInt(L, "minute", int64(t.Minute())) SetTableInt(L, "second", int64(t.Second())) }
// copy a Go slice to a Lua table func CopySliceToTable(L *lua.State, vslice reflect.Value) int { if vslice.IsValid() && vslice.Type().Kind() == reflect.Slice { n := vslice.Len() L.CreateTable(n, 0) for i := 0; i < n; i++ { L.PushInteger(int64(i + 1)) GoToLua(L, nil, vslice.Index(i)) L.SetTable(-3) } return 1 } else { L.PushNil() L.PushString("not a slice!") } return 2 }
// copy a Go map to a Lua table func CopyMapToTable(L *lua.State, vmap reflect.Value) int { if vmap.IsValid() && vmap.Type().Kind() == reflect.Map { n := vmap.Len() L.CreateTable(0, n) for _, key := range vmap.MapKeys() { val := vmap.MapIndex(key) GoToLua(L, nil, key) GoToLua(L, nil, val) L.SetTable(-3) } return 1 } else { L.PushNil() L.PushString("not a map!") } return 2 }
func copyMapToTable(L *lua.State, vmap reflect.Value, visited visitor) int { if vmap.IsValid() && vmap.Type().Kind() == reflect.Map { n := vmap.Len() L.CreateTable(0, n) visited.mark(vmap) for _, key := range vmap.MapKeys() { v := vmap.MapIndex(key) goToLua(L, nil, key, false, visited) if isNil(v) { v = nullv } goToLua(L, nil, v, true, visited) L.SetTable(-3) } return 1 } L.PushNil() L.PushString("not a map!") return 2 }
// Copy a Go struct to a Lua table. nils in both slices and structs // are represented as luar.null. Defines luar.struct2table // Use tags to set field names. func CopyStructToTable(L *lua.State, vstruct reflect.Value) int { if vstruct.IsValid() && vstruct.Type().Kind() == reflect.Struct { n := vstruct.NumField() L.CreateTable(n, 0) for i := 0; i < n; i++ { st := vstruct.Type() field := st.Field(i) key := field.Name tag := field.Tag.Get("lua") if tag != "" { key = tag } GoToLua(L, nil, reflect.ValueOf(key), true) v := vstruct.Field(i) GoToLua(L, nil, v, true) L.SetTable(-3) } return 1 } else { L.PushNil() L.PushString("not a struct!") } return 2 }
func pushValue(state *lua.State, value interface{}) error { switch v := value.(type) { default: return fmt.Errorf("An item of unknown type was included in the environment or arguments of a Lua call (skipping it): %v", value) case nil: log.Println("Pushing nil onto lua stack") state.PushNil() case string: log.Println("Pushing string onto lua stack") state.PushString(v) case int: log.Println("Pushing int onto lua stack") state.PushInteger(int64(v)) case int64: log.Println("Pushing int64 onto lua stack") state.PushInteger(v) case float64: log.Println("Pushing float64 onto lua stack") state.PushNumber(v) case bool: log.Println("Pushing bool onto lua stack") state.PushBoolean(v) case map[string]interface{}: log.Println("Pushing map[string]interface{} onto lua stack") state.CreateTable(0, len(v)) for name, value := range v { err := pushValue(state, value) if err != nil { // error means nothing was added to stack. So pop our new table so *we* leave nothing added to the stack. state.Pop(1) return err } state.SetField(-2, name) } // then leave the table on the stack case ThingType: // These are singleton sentinel values, so load them from Lua-land. state.GetGlobal("world") state.GetField(-1, strings.Title(v.String())) state.Remove(-2) case *Thing: log.Println("Pushing *Thing onto lua stack") return pushValue(state, v.Id) case ThingId: log.Println("Pushing ThingId onto lua stack") // We're pushing a ThingId, so make a new userdata for it, with the Thing metatable. userdata := state.NewUserdata(uintptr(unsafe.Sizeof(int64(0)))) thingPtr := (*int64)(userdata) *thingPtr = int64(v) if !state.IsUserdata(-1) { log.Println("!!! HOGAD JUST PUSHED NEW USERDATA BUT IT ISN'T OMG !!!") } log.Println("Pushed ThingId", *thingPtr, "onto lua stack") // Now make it act like a Thing. state.LGetMetaTable(ThingMetaTableName) // ( udata -- udata mtbl ) state.SetMetaTable(-2) // ( udata mtbl -- udata ) // Let's just check that it's that, for sures. if !state.IsUserdata(-1) { log.Println("!!! WOOP WOOP DID NOT SET METATABLE RIGHT :( !!!") } } return nil }