1
0
LuaJIT-to-Go/builder.go
2025-07-02 11:12:26 -05:00

142 lines
3.3 KiB
Go

package luajit
// TableBuilder provides a fluent interface for building Lua tables
type TableBuilder struct {
state *State
index int
}
// NewTableBuilder creates a new table and returns a builder
func (s *State) NewTableBuilder() *TableBuilder {
s.NewTable()
return &TableBuilder{
state: s,
index: s.GetTop(),
}
}
// SetString sets a string field
func (tb *TableBuilder) SetString(key, value string) *TableBuilder {
tb.state.PushString(value)
tb.state.SetField(tb.index, key)
return tb
}
// SetNumber sets a number field
func (tb *TableBuilder) SetNumber(key string, value float64) *TableBuilder {
tb.state.PushNumber(value)
tb.state.SetField(tb.index, key)
return tb
}
// SetBool sets a boolean field
func (tb *TableBuilder) SetBool(key string, value bool) *TableBuilder {
tb.state.PushBoolean(value)
tb.state.SetField(tb.index, key)
return tb
}
// SetNil sets a nil field
func (tb *TableBuilder) SetNil(key string) *TableBuilder {
tb.state.PushNil()
tb.state.SetField(tb.index, key)
return tb
}
// SetTable sets a table field
func (tb *TableBuilder) SetTable(key string, value any) *TableBuilder {
if err := tb.state.PushValue(value); err == nil {
tb.state.SetField(tb.index, key)
}
return tb
}
// SetArray sets an array field
func (tb *TableBuilder) SetArray(key string, values []any) *TableBuilder {
tb.state.CreateTable(len(values), 0)
for i, v := range values {
tb.state.PushNumber(float64(i + 1))
if err := tb.state.PushValue(v); err == nil {
tb.state.SetTable(-3)
} else {
tb.state.Pop(1)
}
}
tb.state.SetField(tb.index, key)
return tb
}
// BatchBuild builds a table from a map using batched operations
func (tb *TableBuilder) BatchBuild(data map[string]any) *TableBuilder {
stringFields := make(map[string]string)
numberFields := make(map[string]float64)
boolFields := make(map[string]bool)
// Separate fields by type for batching
for key, value := range data {
switch v := value.(type) {
case string:
stringFields[key] = v
case int:
numberFields[key] = float64(v)
case int64:
numberFields[key] = float64(v)
case float64:
numberFields[key] = v
case float32:
numberFields[key] = float64(v)
case bool:
boolFields[key] = v
case []int:
if len(v) > 5 {
tb.state.BatchPushIntArray(v)
} else {
tb.state.PushValue(value)
}
tb.state.SetField(tb.index, key)
case []string:
if len(v) > 3 {
tb.state.BatchPushStringArray(v)
} else {
tb.state.PushValue(value)
}
tb.state.SetField(tb.index, key)
case []float64:
if len(v) > 5 {
tb.state.BatchPushFloatArray(v)
} else {
tb.state.PushValue(value)
}
tb.state.SetField(tb.index, key)
case []bool:
if len(v) > 5 {
tb.state.BatchPushBoolArray(v)
} else {
tb.state.PushValue(value)
}
tb.state.SetField(tb.index, key)
default:
tb.state.PushValue(value)
tb.state.SetField(tb.index, key)
}
}
// Execute batched operations
if len(stringFields) > 0 {
tb.state.BatchSetStringFields(tb.index, stringFields)
}
if len(numberFields) > 0 {
tb.state.BatchSetNumberFields(tb.index, numberFields)
}
if len(boolFields) > 0 {
tb.state.BatchSetBoolFields(tb.index, boolFields)
}
return tb
}
// Build finalizes the table (no-op, table is already on stack)
func (tb *TableBuilder) Build() {
// Table is already on the stack at tb.index
}