github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/dump/slice.go (about) 1 package dump 2 3 import ( 4 "context" 5 "unsafe" 6 "github.com/v2pro/plz/msgfmt/jsonfmt" 7 "encoding/json" 8 ) 9 10 type sliceHeader struct { 11 data unsafe.Pointer 12 len int 13 cap int 14 } 15 16 type sliceEncoder struct { 17 elemEncoder jsonfmt.Encoder 18 elemSize uintptr 19 } 20 21 func (encoder *sliceEncoder) Encode(ctx context.Context, space []byte, ptr unsafe.Pointer) []byte { 22 header := (*sliceHeader)(ptr) 23 space = append(space, `{"data":{"__ptr__":"`...) 24 ptrStr := ptrToStr(uintptr(header.data)) 25 space = append(space, ptrStr...) 26 space = append(space, `"},"len":`...) 27 space = jsonfmt.WriteInt64(space, int64(header.len)) 28 space = append(space, `,"cap":`...) 29 space = jsonfmt.WriteInt64(space, int64(header.cap)) 30 space = append(space, `}`...) 31 data := encoder.encodeData(ctx, nil, ptr) 32 if uintptr(header.data) != 0 { 33 addrMap := ctx.Value(addrMapKey).(map[string]json.RawMessage) 34 addrMap[ptrStr] = json.RawMessage(data) 35 } 36 return space 37 } 38 39 func (encoder *sliceEncoder) encodeData(ctx context.Context, space []byte, ptr unsafe.Pointer) []byte { 40 slice := (*sliceHeader)(ptr) 41 space = append(space, '[') 42 offset := uintptr(slice.data) 43 for i := 0; i < slice.len; i++ { 44 if i != 0 { 45 space = append(space, ',') 46 } 47 space = encoder.elemEncoder.Encode(ctx, space, unsafe.Pointer(offset)) 48 offset += encoder.elemSize 49 } 50 space = append(space, ']') 51 return space 52 }