tlog.app/go/tlog@v0.23.1/tlwire/dumper.go (about) 1 package tlwire 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "io" 7 8 "github.com/nikandfor/hacked/hfmt" 9 "github.com/nikandfor/hacked/low" 10 ) 11 12 type ( 13 Dumper struct { 14 LowDecoder 15 16 io.Writer 17 pos int64 18 19 NoGlobalOffset bool 20 21 b []byte 22 } 23 ) 24 25 func Dump(p []byte) (r string) { 26 if len(p) == 0 { 27 return "" 28 } 29 30 d := Dumper{ 31 NoGlobalOffset: true, 32 b: make([]byte, len(p)*3), 33 } 34 35 defer func() { 36 e := recover() 37 if e == nil { 38 return 39 } 40 41 r = fmt.Sprintf("%s\npanic: %v\nhex.Dump\n%s", d.b, e, hex.Dump(p)) 42 }() 43 44 _, _ = d.Write(p) 45 46 d.b = hfmt.Appendf(d.b, "%4x\n", len(p)) 47 48 return string(d.b) 49 } 50 51 func NewDumper(w io.Writer) *Dumper { 52 return &Dumper{Writer: w} 53 } 54 55 func (d *Dumper) Write(p []byte) (n int, err error) { 56 d.b = d.b[:0] 57 58 defer func() { 59 rp := recover() 60 if rp == nil { 61 return 62 } 63 64 hfmt.Appendf(d.b, "panic: %v\n%s", rp, hex.Dump(p)) 65 }() 66 67 var i int 68 69 for i < len(p) { 70 i = d.dump(p, i, 0) 71 } 72 73 d.pos += int64(i) 74 75 if d.Writer != nil { 76 _, err = d.Writer.Write(d.b) 77 } 78 79 return len(p), err 80 } 81 82 func (d *Dumper) dump(p []byte, st, depth int) (i int) { 83 tag, sub, i := d.Tag(p, st) 84 85 if !d.NoGlobalOffset { 86 d.b = hfmt.Appendf(d.b, "%8x ", d.pos+int64(st)) 87 } 88 89 d.b = hfmt.Appendf(d.b, "%4x %s% x - ", st, low.Spaces[:depth*2], p[st:i]) 90 91 switch tag { 92 case Int, Neg: 93 var v int64 94 v, i = d.Signed(p, st) 95 96 d.b = hfmt.Appendf(d.b, "int %10v\n", v) 97 case Bytes, String: 98 var s []byte 99 s, i = d.Bytes(p, st) 100 101 if tag == Bytes { 102 d.b = hfmt.Appendf(d.b, "% x\n", s) 103 } else { 104 d.b = hfmt.Appendf(d.b, "%q\n", s) 105 } 106 case Array, Map: 107 tg := "array" 108 if tag == Map { 109 tg = "map" 110 } 111 112 d.b = hfmt.Appendf(d.b, "%v: len %v\n", tg, sub) 113 114 for el := 0; sub == -1 || el < int(sub); el++ { 115 if sub == -1 && d.Break(p, &i) { 116 i = d.dump(p, i-1, depth+1) 117 break 118 } 119 120 i = d.dump(p, i, depth+1) 121 122 if tag == Map { 123 i = d.dump(p, i, depth+1) 124 } 125 } 126 case Semantic: 127 d.b = hfmt.Appendf(d.b, "semantic %2x\n", sub) 128 129 i = d.dump(p, i, depth+1) 130 case Special: 131 switch sub { 132 case False: 133 d.b = hfmt.Appendf(d.b, "false\n") 134 case True: 135 d.b = hfmt.Appendf(d.b, "true\n") 136 case Nil: 137 d.b = hfmt.Appendf(d.b, "null\n") 138 case Undefined: 139 d.b = hfmt.Appendf(d.b, "undefined\n") 140 case Float8, Float16, Float32, Float64: 141 var f float64 142 143 f, i = d.Float(p, st) 144 145 d.b = hfmt.Appendf(d.b, "%v\n", f) 146 case Break: 147 d.b = hfmt.Appendf(d.b, "break\n") 148 default: 149 d.b = hfmt.Appendf(d.b, "special: %x\n", sub) 150 151 panic("unsupported special") 152 } 153 } 154 155 return 156 }