tlog.app/go/tlog@v0.23.1/wire.go (about)

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