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  }