add type utilities

This commit is contained in:
Sky Johnson 2025-03-29 09:08:02 -05:00
parent 44337fffe3
commit a2b4b1c927

101
types.go
View File

@ -4,6 +4,10 @@ package luajit
#include <lua.h> #include <lua.h>
*/ */
import "C" import "C"
import (
"fmt"
"strconv"
)
// LuaType represents Lua value types // LuaType represents Lua value types
type LuaType int type LuaType int
@ -49,3 +53,100 @@ func (t LuaType) String() string {
return "unknown" return "unknown"
} }
} }
// ConvertValue converts a value to the requested type with proper type conversion
func ConvertValue[T any](value any) (T, bool) {
var zero T
// Handle nil case
if value == nil {
return zero, false
}
// Try direct type assertion first
if result, ok := value.(T); ok {
return result, true
}
// Type-specific conversions
switch any(zero).(type) {
case string:
switch v := value.(type) {
case float64:
return any(fmt.Sprintf("%g", v)).(T), true
case int:
return any(strconv.Itoa(v)).(T), true
case bool:
if v {
return any("true").(T), true
}
return any("false").(T), true
}
case int:
switch v := value.(type) {
case float64:
return any(int(v)).(T), true
case string:
if i, err := strconv.Atoi(v); err == nil {
return any(i).(T), true
}
case bool:
if v {
return any(1).(T), true
}
return any(0).(T), true
}
case float64:
switch v := value.(type) {
case int:
return any(float64(v)).(T), true
case string:
if f, err := strconv.ParseFloat(v, 64); err == nil {
return any(f).(T), true
}
case bool:
if v {
return any(1.0).(T), true
}
return any(0.0).(T), true
}
case bool:
switch v := value.(type) {
case string:
switch v {
case "true", "yes", "1":
return any(true).(T), true
case "false", "no", "0":
return any(false).(T), true
}
case int:
return any(v != 0).(T), true
case float64:
return any(v != 0).(T), true
}
}
return zero, false
}
// GetTypedValue gets a value from the state with type conversion
func GetTypedValue[T any](s *State, index int) (T, bool) {
var zero T
// Get the value as any type
value, err := s.ToValue(index)
if err != nil {
return zero, false
}
// Convert it to the requested type
return ConvertValue[T](value)
}
// GetGlobalTyped gets a global variable with type conversion
func GetGlobalTyped[T any](s *State, name string) (T, bool) {
s.GetGlobal(name)
defer s.Pop(1)
return GetTypedValue[T](s, -1)
}