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 }