github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/dump/dumpvar.go (about)

     1  package dump
     2  
     3  import (
     4  	"unsafe"
     5  	"github.com/v2pro/plz/msgfmt/jsonfmt"
     6  	"reflect"
     7  	"context"
     8  	"encoding/json"
     9  )
    10  
    11  var addrMapKey = 2020020002
    12  var dumper = jsonfmt.Config{
    13  	IncludesUnexported: true,
    14  	Extensions: []jsonfmt.Extension{&dumpExtension{}},
    15  }.Froze()
    16  
    17  var efaceType = reflect.TypeOf(eface{})
    18  var efaceEncoderInst = dumper.EncoderOf(reflect.TypeOf(eface{}))
    19  var addrMapEncoderInst = jsonfmt.EncoderOf(reflect.TypeOf(map[string]json.RawMessage{}))
    20  
    21  type Var struct {
    22  	Object interface{}
    23  }
    24  
    25  func (v Var) String() string {
    26  	addrMap := map[string]json.RawMessage{}
    27  	ctx := context.WithValue(context.Background(), addrMapKey, addrMap)
    28  	rootPtr := unsafe.Pointer(&v.Object)
    29  	output := efaceEncoderInst.Encode(ctx, nil, rootPtr)
    30  	addrMap["__root__"] = json.RawMessage(output)
    31  	output = addrMapEncoderInst.Encode(nil, nil, reflect2.PtrOf(addrMap))
    32  	return string(output)
    33  }
    34  
    35  type VarSnapshot string
    36  
    37  func Snapshot(obj interface{}) VarSnapshot {
    38  	return VarSnapshot(Var{Object: obj}.String())
    39  }
    40  
    41  func (snapshot VarSnapshot) String() string {
    42  	return string(snapshot)
    43  }
    44  
    45  func ptrToStr(ptr uintptr) string {
    46  	return string(jsonfmt.WriteUint64(nil, uint64(ptr)))
    47  }
    48  
    49  type dumpExtension struct {
    50  }
    51  
    52  func (extension *dumpExtension) EncoderOf(prefix string, valType reflect.Type) jsonfmt.Encoder {
    53  	if valType == efaceType {
    54  		return &efaceEncoder{}
    55  	}
    56  	switch valType.Kind() {
    57  	case reflect.String:
    58  		return &stringEncoder{}
    59  	case reflect.Ptr:
    60  		return &pointerEncoder{
    61  			elemEncoder: dumper.EncoderOf(valType.Elem()),
    62  		}
    63  	case reflect.Slice:
    64  		return &sliceEncoder{
    65  			elemEncoder: dumper.EncoderOf(valType.Elem()),
    66  			elemSize:    valType.Elem().Size(),
    67  		}
    68  	case reflect.Map:
    69  		return newMapEncoder(dumper, valType)
    70  	}
    71  	return nil
    72  }
    73  
    74  type iface struct {
    75  	itab unsafe.Pointer
    76  	data unsafe.Pointer
    77  }