package luajit /* #include */ import "C" import ( "fmt" "strconv" ) // LuaType represents Lua value types type LuaType int const ( TypeNone LuaType = -1 TypeNil LuaType = 0 TypeBoolean LuaType = 1 TypeLightUserData LuaType = 2 TypeNumber LuaType = 3 TypeString LuaType = 4 TypeTable LuaType = 5 TypeFunction LuaType = 6 TypeUserData LuaType = 7 TypeThread LuaType = 8 ) func (t LuaType) String() string { switch t { case TypeNone: return "none" case TypeNil: return "nil" case TypeBoolean: return "boolean" case TypeLightUserData: return "lightuserdata" case TypeNumber: return "number" case TypeString: return "string" case TypeTable: return "table" case TypeFunction: return "function" case TypeUserData: return "userdata" case TypeThread: return "thread" default: return "unknown" } } // ConvertValue converts a value to the requested type with comprehensive type conversion func ConvertValue[T any](value any) (T, bool) { var zero T if value == nil { return zero, false } if result, ok := value.(T); ok { return result, true } switch any(zero).(type) { case string: return convertToString[T](value) case int: return convertToInt[T](value) case float64: return convertToFloat[T](value) case bool: return convertToBool[T](value) case []int: return convertToIntSlice[T](value) case []string: return convertToStringSlice[T](value) case []bool: return convertToBoolSlice[T](value) case []float64: return convertToFloatSlice[T](value) case []any: return convertToAnySlice[T](value) case map[string]string: return convertToStringMap[T](value) case map[string]int: return convertToIntMap[T](value) case map[int]any: return convertToIntKeyMap[T](value) case map[string]any: return convertToAnyMap[T](value) } return zero, false } func convertToString[T any](value any) (T, bool) { var zero T switch v := value.(type) { case float64: if v == float64(int(v)) { return any(strconv.Itoa(int(v))).(T), true } return any(fmt.Sprintf("%g", v)).(T), true case int: return any(strconv.Itoa(v)).(T), true case bool: return any(strconv.FormatBool(v)).(T), true } return zero, false } func convertToInt[T any](value any) (T, bool) { var zero T 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 } return zero, false } func convertToFloat[T any](value any) (T, bool) { var zero T 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 } return zero, false } func convertToBool[T any](value any) (T, bool) { var zero T 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 } func convertToIntSlice[T any](value any) (T, bool) { var zero T switch v := value.(type) { case []float64: result := make([]int, len(v)) for i, f := range v { result[i] = int(f) } return any(result).(T), true case []any: result := make([]int, 0, len(v)) for _, item := range v { if i, ok := ConvertValue[int](item); ok { result = append(result, i) } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToStringSlice[T any](value any) (T, bool) { var zero T if v, ok := value.([]any); ok { result := make([]string, 0, len(v)) for _, item := range v { if s, ok := ConvertValue[string](item); ok { result = append(result, s) } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToBoolSlice[T any](value any) (T, bool) { var zero T if v, ok := value.([]any); ok { result := make([]bool, 0, len(v)) for _, item := range v { if b, ok := ConvertValue[bool](item); ok { result = append(result, b) } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToFloatSlice[T any](value any) (T, bool) { var zero T switch v := value.(type) { case []int: result := make([]float64, len(v)) for i, n := range v { result[i] = float64(n) } return any(result).(T), true case []any: result := make([]float64, 0, len(v)) for _, item := range v { if f, ok := ConvertValue[float64](item); ok { result = append(result, f) } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToAnySlice[T any](value any) (T, bool) { var zero T switch v := value.(type) { case []int: result := make([]any, len(v)) for i, n := range v { result[i] = n } return any(result).(T), true case []string: result := make([]any, len(v)) for i, s := range v { result[i] = s } return any(result).(T), true case []bool: result := make([]any, len(v)) for i, b := range v { result[i] = b } return any(result).(T), true case []float64: result := make([]any, len(v)) for i, f := range v { result[i] = f } return any(result).(T), true } return zero, false } func convertToStringMap[T any](value any) (T, bool) { var zero T if v, ok := value.(map[string]any); ok { result := make(map[string]string, len(v)) for k, val := range v { if s, ok := ConvertValue[string](val); ok { result[k] = s } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToIntMap[T any](value any) (T, bool) { var zero T if v, ok := value.(map[string]any); ok { result := make(map[string]int, len(v)) for k, val := range v { if i, ok := ConvertValue[int](val); ok { result[k] = i } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToIntKeyMap[T any](value any) (T, bool) { var zero T if v, ok := value.(map[string]any); ok { result := make(map[int]any, len(v)) for k, val := range v { if i, err := strconv.Atoi(k); err == nil { result[i] = val } else { return zero, false } } return any(result).(T), true } return zero, false } func convertToAnyMap[T any](value any) (T, bool) { var zero T switch v := value.(type) { case map[string]string: result := make(map[string]any, len(v)) for k, s := range v { result[k] = s } return any(result).(T), true case map[string]int: result := make(map[string]any, len(v)) for k, i := range v { result[k] = i } return any(result).(T), true case map[int]any: result := make(map[string]any, len(v)) for k, val := range v { result[strconv.Itoa(k)] = val } return any(result).(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) { value, err := s.ToValue(index) if err != nil { var zero T return zero, false } 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) }