summaryrefslogtreecommitdiff
path: root/lua.go
diff options
context:
space:
mode:
authorunwox <me@unwox.com>2024-09-14 15:54:27 +0600
committerunwox <me@unwox.com>2024-09-14 23:59:38 +0600
commitcc8d3cf4a7cd296d8c409fef5db9df138c3b238d (patch)
tree4eae9d64ce9927e8b505fad359511bab22eccd80 /lua.go
parent986522e417406956e83362e08adbd6a18ec904a5 (diff)
add luna.db.* module
Diffstat (limited to 'lua.go')
-rw-r--r--lua.go138
1 files changed, 108 insertions, 30 deletions
diff --git a/lua.go b/lua.go
index 8401d37..51af7d1 100644
--- a/lua.go
+++ b/lua.go
@@ -25,6 +25,7 @@ import (
"reflect"
"runtime/cgo"
"slices"
+ "time"
"unsafe"
)
@@ -66,7 +67,7 @@ func (l *Lua) Require(file string) error {
return nil
}
-// PCall calls a function with the stack index (-nargs - 1) expecting nresults
+// PCall calls a function with the stack index (-nargs-1) expecting nresults
// number of results.
func (l *Lua) PCall(nargs int, nresults int) error {
res := C.lua_pcallk(l.l, C.int(nargs), C.int(nresults), 0, 0, nil)
@@ -122,6 +123,11 @@ func (l *Lua) PushNumber(num int) {
C.lua_pushnumber(l.l, C.double(num))
}
+// PushNumber pushes the number onto the Lua stack.
+func (l *Lua) PushFloatNumber(num float64) {
+ C.lua_pushnumber(l.l, C.double(num))
+}
+
// PushString pushes the string onto the Lua stack.
func (l *Lua) PushString(str string) {
cstr := C.CString(str)
@@ -153,36 +159,64 @@ func (l *Lua) SetTableItem(key string) {
C.lua_setfield(l.l, -2, C.CString(key))
}
-// PushTable pushes string->any table onto the stack.
+// PushAny pushes value v onto the stack.
+func (l *Lua) PushAny(v any) error {
+ switch v.(type) {
+ case string:
+ v, _ := v.(string)
+ l.PushString(v)
+ case func (l *Lua) int:
+ v, _ := v.(func (l *Lua) int)
+ l.PushGoFunction(v)
+ case int:
+ v, _ := v.(int)
+ l.PushNumber(v)
+ case int64:
+ v, _ := v.(int64)
+ l.PushNumber(int(v))
+ case float64:
+ v, _ := v.(float64)
+ l.PushFloatNumber(v)
+ case map[string]any:
+ v, _ := v.(map[string]any)
+ l.PushObject(v)
+ case []any:
+ v, _ := v.([]any)
+ l.PushArray(v)
+ case time.Time:
+ v, _ := v.(time.Time)
+ l.PushString(v.Format(time.DateTime))
+ default:
+ return fmt.Errorf("unsupported value type: %T", v)
+ }
+ return nil
+}
+
+// PushObject recursively pushes string->any Go table onto the stack.
func (l *Lua) PushObject(table map[string]any) error {
- var pushTable func(t map[string]any) error
- pushTable = func (t map[string]any) error {
- l.CreateTable(len(t))
- for k, v := range t {
- switch v.(type) {
- case string:
- v, _ := v.(string)
- l.PushString(v)
- case func (l *Lua) int:
- v, _ := v.(func (l *Lua) int)
- l.PushGoFunction(v)
- case int:
- v, _ := v.(int)
- l.PushNumber(v)
- case map[string]any:
- v, _ := v.(map[string]any)
- pushTable(v)
- default:
- return fmt.Errorf(
- "unsupported value type: %T",
- v,
- )
- }
- l.SetTableItem(k)
+ l.CreateTable(len(table))
+ for k, v := range table {
+ err := l.PushAny(v)
+ if err != nil {
+ return err
}
- return nil
+ l.SetTableItem(k)
}
- return pushTable(table)
+ return nil
+}
+
+// PushArray recursively pushes an array of Go values onto the stack.
+func (l *Lua) PushArray(array []any) error {
+ l.CreateTable(len(array))
+ for k, v := range array {
+ l.PushNumber(k + 1)
+ err := l.PushAny(v)
+ if err != nil {
+ return err
+ }
+ C.lua_settable(l.l, C.int(-3))
+ }
+ return nil
}
// PushFromRef pushes a value from registry ref onto the stack.
@@ -190,6 +224,16 @@ func (l *Lua) PushFromRef(ref LuaRef) {
C.lua_rawgeti(l.l, C.LUA_REGISTRYINDEX, C.longlong(ref));
}
+// Type returns type of the value sitting at n index on the stack.
+func (l *Lua) Type(n int) int {
+ return int(C.lua_type(l.l, C.int(n)))
+}
+
+// IsNil checks if the stack contains nil under the given index.
+func (l *Lua) IsNil(index int) bool {
+ return C.lua_type(l.l, C.int(index)) == C.LUA_TNIL
+}
+
// IsString checks if the stack contains a string under the given index.
func (l *Lua) IsString(index int) bool {
return C.lua_isstring(l.l, C.int(index)) == 1
@@ -251,6 +295,15 @@ func (l *Lua) Scan(vars ...any) error {
)
}
*v.(*LuaRef) = l.PopToRef()
+ } else if t.String() == "cgo.Handle" {
+ if l.IsNumber(-1) == false {
+ return fmt.Errorf(
+ "passed arg #%d must be Go handler",
+ len(vars)-i,
+ )
+ }
+ *v.(*cgo.Handle) = cgo.Handle(uintptr(l.ToInt(-1)))
+ l.Pop(1)
} else if tk == reflect.String {
if l.IsString(-1) == false {
return fmt.Errorf(
@@ -287,13 +340,38 @@ func (l *Lua) Scan(vars ...any) error {
len(vars)-i,
)
}
- iv := l.ToString(-1)
+ v := l.ToString(-1)
l.Pop(1)
// We must not pop the item key from the stack
// because otherwise C.lua_next won't work
// properly.
k := l.ToString(-1)
- (*vm)[k] = iv
+ (*vm)[k] = v
+ }
+ l.Pop(1)
+ } else if tk == reflect.Slice &&
+ t.Elem().Kind() == reflect.Interface {
+ if !l.IsTable(-1) {
+ return fmt.Errorf(
+ "passed arg #%d must be a table",
+ len(vars)-i,
+ )
+ }
+ va, _ := v.(*[]any)
+ l.PushNil()
+ for l.Next() {
+ var v any = nil
+ if l.IsString(-1) {
+ v = l.ToString(-1)
+ } else if l.IsNumber(-1) {
+ v = l.ToInt(-1)
+ } else if l.IsNil(-1) {
+ v = nil
+ } else {
+ return fmt.Errorf("unknown value in array")
+ }
+ l.Pop(1)
+ (*va) = append((*va), v)
}
l.Pop(1)
} else {