package encoder import ( "context" "sync" "unsafe" "github.com/goccy/go-json/internal/runtime" ) type compileContext struct { opcodeIndex uint32 ptrIndex int indent uint32 escapeKey bool structTypeToCodes map[uintptr]Opcodes recursiveCodes *Opcodes } func (c *compileContext) incIndent() { c.indent++ } func (c *compileContext) decIndent() { c.indent-- } func (c *compileContext) incIndex() { c.incOpcodeIndex() c.incPtrIndex() } func (c *compileContext) decIndex() { c.decOpcodeIndex() c.decPtrIndex() } func (c *compileContext) incOpcodeIndex() { c.opcodeIndex++ } func (c *compileContext) decOpcodeIndex() { c.opcodeIndex-- } func (c *compileContext) incPtrIndex() { c.ptrIndex++ } func (c *compileContext) decPtrIndex() { c.ptrIndex-- } const ( bufSize = 1024 ) var ( runtimeContextPool = sync.Pool{ New: func() interface{} { return &RuntimeContext{ Buf: make([]byte, 0, bufSize), Ptrs: make([]uintptr, 128), KeepRefs: make([]unsafe.Pointer, 0, 8), Option: &Option{}, } }, } ) type RuntimeContext struct { Context context.Context Buf []byte MarshalBuf []byte Ptrs []uintptr KeepRefs []unsafe.Pointer SeenPtr []uintptr BaseIndent uint32 Prefix []byte IndentStr []byte Option *Option } func (c *RuntimeContext) Init(p uintptr, codelen int) { if len(c.Ptrs) < codelen { c.Ptrs = make([]uintptr, codelen) } c.Ptrs[0] = p c.KeepRefs = c.KeepRefs[:0] c.SeenPtr = c.SeenPtr[:0] c.BaseIndent = 0 } func (c *RuntimeContext) Ptr() uintptr { header := (*runtime.SliceHeader)(unsafe.Pointer(&c.Ptrs)) return uintptr(header.Data) } func TakeRuntimeContext() *RuntimeContext { return runtimeContextPool.Get().(*RuntimeContext) } func ReleaseRuntimeContext(ctx *RuntimeContext) { runtimeContextPool.Put(ctx) }