Files
obitools4/pkg/obilua/lua_push_interface.go
2024-12-04 10:58:17 +01:00

228 lines
6.7 KiB
Go

package obilua
import (
"sync"
log "github.com/sirupsen/logrus"
lua "github.com/yuin/gopher-lua"
)
// pushInterfaceToLua converts a Go interface{} value to an equivalent Lua value and pushes it onto the stack.
//
// L *lua.LState: the Lua state onto which the value will be pushed.
// val interface{}: the Go interface value to be converted and pushed. This can be a basic type such as string, bool, int, float64,
// or slices and maps of these basic types. Custom complex types will be converted to userdata with a predefined metatable.
//
// No return values. This function operates directly on the Lua state stack.
func pushInterfaceToLua(L *lua.LState, val interface{}) {
switch v := val.(type) {
case string:
L.Push(lua.LString(v))
case bool:
L.Push(lua.LBool(v))
case int:
L.Push(lua.LNumber(v))
case float64:
L.Push(lua.LNumber(v))
// Add other cases as needed for different types
case map[string]int:
pushMapStringIntToLua(L, v)
case map[string]string:
pushMapStringStringToLua(L, v)
case map[string]bool:
pushMapStringBoolToLua(L, v)
case map[string]float64:
pushMapStringFloat64ToLua(L, v)
case map[string]interface{}:
pushMapStringInterfaceToLua(L, v)
case []string:
pushSliceStringToLua(L, v)
case []int:
pushSliceNumericToLua(L, v)
case []byte:
pushSliceNumericToLua(L, v)
case []float64:
pushSliceNumericToLua(L, v)
case []bool:
pushSliceBoolToLua(L, v)
case []interface{}:
pushSliceInterfaceToLua(L, v)
case nil:
L.Push(lua.LNil)
case *sync.Mutex:
pushMutexToLua(L, v)
default:
log.Fatalf("Cannot deal with value (%T) : %v", val, val)
}
}
func pushMapStringInterfaceToLua(L *lua.LState, m map[string]interface{}) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go map and set the key-value pairs in the Lua table
for key, value := range m {
switch v := value.(type) {
case int:
luaTable.RawSetString(key, lua.LNumber(v))
case float64:
luaTable.RawSetString(key, lua.LNumber(v))
case bool:
luaTable.RawSetString(key, lua.LBool(v))
case string:
luaTable.RawSetString(key, lua.LString(v))
default:
log.Fatalf("Doesn't deal with map containing value %v of type %T", v, v)
}
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
func pushSliceInterfaceToLua(L *lua.LState, s []interface{}) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go map and set the key-value pairs in the Lua table
for _, value := range s {
switch v := value.(type) {
case int:
luaTable.Append(lua.LNumber(v))
case float64:
luaTable.Append(lua.LNumber(v))
case bool:
luaTable.Append(lua.LBool(v))
case string:
luaTable.Append(lua.LString(v))
default:
log.Fatalf("Doesn't deal with slice containing value %v of type %T", v, v)
}
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
// pushMapStringIntToLua creates a new Lua table and iterates over the Go map to set key-value pairs in the Lua table. It then pushes the Lua table onto the stack.
//
// L *lua.LState - the Lua state
// m map[string]int - the Go map containing string to int key-value pairs
func pushMapStringIntToLua(L *lua.LState, m map[string]int) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go map and set the key-value pairs in the Lua table
for key, value := range m {
L.SetTable(luaTable, lua.LString(key), lua.LNumber(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
// pushMapStringStringToLua creates a new Lua table and sets key-value pairs from the Go map, then pushes the Lua table onto the stack.
//
// L *lua.LState, m map[string]string. No return value.
func pushMapStringStringToLua(L *lua.LState, m map[string]string) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go map and set the key-value pairs in the Lua table
for key, value := range m {
L.SetTable(luaTable, lua.LString(key), lua.LString(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
// pushMapStringBoolToLua creates a new Lua table, iterates over the Go map, sets the key-value pairs in the Lua table, and then pushes the Lua table onto the stack.
//
// Parameters:
//
// L *lua.LState - the Lua state
// m map[string]bool - the Go map
//
// Return type(s): None
func pushMapStringBoolToLua(L *lua.LState, m map[string]bool) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go map and set the key-value pairs in the Lua table
for key, value := range m {
L.SetTable(luaTable, lua.LString(key), lua.LBool(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
// pushMapStringFloat64ToLua pushes a map of string-float64 pairs to a Lua table on the stack.
//
// L *lua.LState - the Lua state
// m map[string]float64 - the map to be pushed to Lua
func pushMapStringFloat64ToLua(L *lua.LState, m map[string]float64) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go map and set the key-value pairs in the Lua table
for key, value := range m {
// Use lua.LNumber since Lua does not differentiate between float and int
L.SetTable(luaTable, lua.LString(key), lua.LNumber(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
func pushSliceNumericToLua[T float64 | int | byte](L *lua.LState, slice []T) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go slice and set the elements in the Lua table
for _, value := range slice {
// Append the value to the Lua table
// Lua is 1-indexed, so we use the length of the table + 1 as the next index
luaTable.Append(lua.LNumber(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
// pushSliceStringToLua creates a new Lua table and sets the elements in the table from the given Go slice. It then pushes the Lua table onto the stack.
//
// L *lua.LState - The Lua state
// slice []string - The Go slice of strings
func pushSliceStringToLua(L *lua.LState, slice []string) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go slice and set the elements in the Lua table
for _, value := range slice {
// Append the value to the Lua table
luaTable.Append(lua.LString(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}
// pushSliceBoolToLua creates a new Lua table and pushes the boolean values from the given slice onto the Lua stack.
//
// L *lua.LState - the Lua state
// slice []bool - the Go slice containing boolean values
func pushSliceBoolToLua(L *lua.LState, slice []bool) {
// Create a new Lua table
luaTable := L.NewTable()
// Iterate over the Go slice and insert each boolean into the Lua table
for _, value := range slice {
// Lua is 1-indexed, so we use the length of the table + 1 as the next index
luaTable.Append(lua.LBool(value))
}
// Push the Lua table onto the stack
L.Push(luaTable)
}