142 lines
3.3 KiB
Go
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
|
|
}
|