github.com/nikandfor/tlog@v0.21.3/wire.go (about) 1 package tlog 2 3 import ( 4 "unicode/utf8" 5 _ "unsafe" 6 7 "github.com/nikandfor/loc" 8 9 "github.com/nikandfor/tlog/low" 10 "github.com/nikandfor/tlog/tlwire" 11 ) 12 13 type ( 14 RawMessage []byte 15 16 Modify []byte 17 18 Timestamp int64 19 20 FormatNext string 21 22 format struct { 23 Fmt string 24 Args []interface{} 25 } 26 ) 27 28 const KeyAuto = "" 29 30 var ( 31 None = RawMessage{tlwire.Special | tlwire.None} 32 Nil = RawMessage{tlwire.Special | tlwire.Nil} 33 Break = RawMessage{tlwire.Special | tlwire.Break} 34 NextAsHex = Modify{tlwire.Semantic | tlwire.Hex} 35 NextAsMessage = Modify{tlwire.Semantic | WireMessage} 36 NextAsType = FormatNext("%T") 37 ) 38 39 const ( 40 WireLabel = tlwire.SemanticTlogBase + iota 41 WireID 42 WireMessage 43 WireEventKind 44 WireLogLevel 45 46 _ 47 _ 48 _ 49 _ 50 _ 51 52 SemanticUserBase 53 ) 54 55 var ( 56 e tlwire.Encoder 57 d tlwire.Decoder 58 ) 59 60 func AppendLabels(b []byte, kvs []interface{}) []byte { 61 const tag = tlwire.Semantic | WireLabel 62 63 w := len(b) 64 b = append(b, low.Spaces[:len(kvs)/2+1]...) 65 r := len(b) 66 67 b = AppendKVs(b, kvs) 68 69 for r < len(b) { 70 end := d.Skip(b, r) 71 72 w += copy(b[w:], b[r:end]) 73 r = end 74 75 end = d.Skip(b, r) 76 77 if b[r] != tag { 78 b[w] = tag 79 w++ 80 } 81 82 w += copy(b[w:], b[r:end]) 83 r = end 84 } 85 86 return b[:w] 87 } 88 89 func AppendKVs(b []byte, kvs []interface{}) []byte { 90 return appendKVs0(b, kvs) 91 } 92 93 func NextIs(semantic int) Modify { 94 return Modify(tlwire.LowEncoder{}.AppendTag(nil, tlwire.Semantic, semantic)) 95 } 96 97 func RawTag(tag byte, sub int) RawMessage { 98 return RawMessage(tlwire.LowEncoder{}.AppendTag(nil, tag, sub)) 99 } 100 101 func Special(value int) RawMessage { 102 return RawMessage(tlwire.LowEncoder{}.AppendTag(nil, tlwire.Special, value)) 103 } 104 105 //go:linkname appendKVs0 github.com/nikandfor/tlog.appendKVs 106 //go:noescape 107 func appendKVs0(b []byte, kvs []interface{}) []byte 108 109 func init() { // prevent deadcode warnings 110 appendKVs(nil, nil) 111 } 112 113 func appendKVs(b []byte, kvs []interface{}) []byte { 114 for i := 0; i < len(kvs); { 115 var k string 116 117 switch el := kvs[i].(type) { 118 case string: 119 k = el 120 121 if k == KeyAuto { 122 k = autoKey(kvs[i:]) 123 } 124 125 i++ 126 case RawMessage: 127 b = append(b, el...) 128 i++ 129 continue 130 default: 131 k = "MISSING_KEY" 132 } 133 134 b = e.AppendString(b, k) 135 136 value: 137 if i == len(kvs) { 138 b = append(b, tlwire.Special|tlwire.Undefined) 139 break 140 } 141 142 switch v := kvs[i].(type) { 143 case string: 144 b = e.AppendString(b, v) 145 case int: 146 b = e.AppendInt(b, v) 147 case RawMessage: 148 b = append(b, v...) 149 case Modify: 150 b = append(b, v...) 151 i++ 152 153 goto value 154 case FormatNext: 155 i++ 156 if i == len(kvs) { 157 b = append(b, tlwire.Special|tlwire.Undefined) 158 break 159 } 160 161 b = e.AppendFormat(b, string(v), kvs[i]) 162 default: 163 b = e.AppendValue(b, v) 164 } 165 166 i++ 167 } 168 169 return b 170 } 171 172 func autoKey(kvs []interface{}) (k string) { 173 if len(kvs) == 1 { 174 return "MISSING_VALUE" 175 } 176 177 switch kvs[1].(type) { 178 // case Message: 179 // k = KeyMessage 180 case ID: 181 k = KeySpan 182 case LogLevel: 183 k = KeyLogLevel 184 case EventKind: 185 k = KeyEventKind 186 case loc.PC: 187 k = KeyCaller 188 case loc.PCs: 189 k = KeyCaller 190 default: 191 k = "UNSUPPORTED_AUTO_KEY" 192 } 193 194 return 195 } 196 197 func (id ID) TlogAppend(b []byte) []byte { 198 b = append(b, tlwire.Semantic|WireID) 199 return e.AppendBytes(b, id[:]) 200 } 201 202 func (id *ID) TlogParse(p []byte, i int) int { 203 if p[i] != tlwire.Semantic|WireID { 204 panic("not an id") 205 } 206 207 i++ 208 209 if p[i] != tlwire.Bytes|16 { 210 panic("not an id") 211 } 212 213 i++ 214 215 i += copy((*id)[:], p[i:]) 216 217 return i 218 } 219 220 func (ek EventKind) TlogAppend(b []byte) []byte { 221 b = append(b, tlwire.Semantic|WireEventKind) 222 return e.AppendString(b, string(ek)) 223 } 224 225 func (ek *EventKind) TlogParse(p []byte, i int) int { 226 if p[i] != tlwire.Semantic|WireEventKind { 227 panic("not an event type") 228 } 229 230 i++ 231 232 v, i := d.Bytes(p, i) 233 234 r, w := utf8.DecodeRune(v) 235 if w == utf8.RuneError || w != len(v) { 236 panic("bad rune") 237 } 238 239 *ek = EventKind(r) 240 241 return i 242 } 243 244 func (l LogLevel) TlogAppend(b []byte) []byte { 245 b = append(b, tlwire.Semantic|WireLogLevel) 246 return e.AppendInt(b, int(l)) 247 } 248 249 func (l *LogLevel) TlogParse(p []byte, i int) int { 250 if p[i] != tlwire.Semantic|WireLogLevel { 251 panic("not a log level") 252 } 253 254 i++ 255 256 v, i := d.Signed(p, i) 257 258 *l = LogLevel(v) 259 260 return i 261 } 262 263 func (r RawMessage) TlogAppend(b []byte) []byte { 264 return append(b, r...) 265 } 266 267 func (r *RawMessage) TlogParse(p []byte, st int) (i int) { 268 i = d.Skip(p, st) 269 *r = append((*r)[:0], p[st:i]...) 270 return i 271 }