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