github.com/nikandfor/tlog@v0.21.5-0.20231108111739-3ef89426a96d/tlwire/encoder.go (about)

     1  package tlwire
     2  
     3  import (
     4  	"math"
     5  	"time"
     6  
     7  	"github.com/nikandfor/hacked/hfmt"
     8  	"github.com/nikandfor/hacked/htime"
     9  )
    10  
    11  type (
    12  	Encoder struct {
    13  		LowEncoder
    14  
    15  		custom encoders
    16  	}
    17  
    18  	LowEncoder struct{}
    19  )
    20  
    21  func (e Encoder) AppendKey(b []byte, key string) []byte {
    22  	b = e.AppendTag(b, String, len(key))
    23  	return append(b, key...)
    24  }
    25  
    26  func (e Encoder) AppendKeyString(b []byte, k, v string) []byte {
    27  	b = e.AppendTag(b, String, len(k))
    28  	b = append(b, k...)
    29  
    30  	b = e.AppendTag(b, String, len(v))
    31  	b = append(b, v...)
    32  
    33  	return b
    34  }
    35  
    36  func (e Encoder) AppendKeyInt(b []byte, k string, v int) []byte {
    37  	b = e.AppendTag(b, String, len(k))
    38  	b = append(b, k...)
    39  	return e.AppendInt(b, v)
    40  }
    41  
    42  func (e Encoder) AppendKeyUint(b []byte, k string, v uint) []byte {
    43  	b = e.AppendTag(b, String, len(k))
    44  	b = append(b, k...)
    45  	return e.AppendTag64(b, Int, uint64(v))
    46  }
    47  
    48  func (e Encoder) AppendKeyInt64(b []byte, k string, v int64) []byte {
    49  	b = e.AppendTag(b, String, len(k))
    50  	b = append(b, k...)
    51  
    52  	if v < 0 {
    53  		return e.AppendTag64(b, Neg, uint64(-v))
    54  	}
    55  
    56  	return e.AppendTag64(b, Int, uint64(v))
    57  }
    58  
    59  func (e Encoder) AppendKeyUint64(b []byte, k string, v uint64) []byte {
    60  	b = e.AppendTag(b, String, len(k))
    61  	b = append(b, k...)
    62  	return e.AppendTag64(b, Int, v)
    63  }
    64  
    65  func (e Encoder) AppendError(b []byte, err error) []byte {
    66  	b = append(b, Semantic|Error)
    67  
    68  	if err == nil {
    69  		return append(b, Special|Nil)
    70  	}
    71  
    72  	return e.AppendString(b, err.Error())
    73  }
    74  
    75  func (e Encoder) AppendTime(b []byte, t time.Time) []byte {
    76  	b = append(b, Semantic|Time)
    77  	return e.AppendInt64(b, t.UnixNano())
    78  }
    79  
    80  func (e Encoder) AppendTimeTZ(b []byte, t time.Time) []byte {
    81  	b = append(b, Semantic|Time)
    82  	b = append(b, Map|2)
    83  
    84  	b = e.AppendKeyInt64(b, "t", t.UnixNano())
    85  
    86  	b = e.AppendKey(b, "z")
    87  	b = append(b, Array|2)
    88  
    89  	n, off := t.Zone()
    90  	b = e.AppendString(b, n)
    91  	b = e.AppendInt(b, off)
    92  
    93  	return b
    94  }
    95  
    96  func (e Encoder) AppendTimeMonoTZ(b []byte, t time.Time) []byte {
    97  	b = append(b, Semantic|Time)
    98  
    99  	mono := htime.MonotonicOf(t)
   100  	fields := 2
   101  
   102  	if mono != 0 {
   103  		fields++
   104  	}
   105  
   106  	b = append(b, Map|byte(fields))
   107  
   108  	b = e.AppendKeyInt64(b, "t", t.UnixNano())
   109  
   110  	if mono != 0 {
   111  		b = e.AppendKeyInt64(b, "m", mono)
   112  	}
   113  
   114  	b = e.AppendKey(b, "z")
   115  	b = append(b, Array|2)
   116  
   117  	n, off := t.Zone()
   118  	b = e.AppendString(b, n)
   119  	b = e.AppendInt(b, off)
   120  
   121  	return b
   122  }
   123  
   124  func (e Encoder) AppendTimestamp(b []byte, t int64) []byte {
   125  	b = append(b, Semantic|Time)
   126  	return e.AppendInt64(b, t)
   127  }
   128  
   129  func (e Encoder) AppendDuration(b []byte, d time.Duration) []byte {
   130  	b = append(b, Semantic|Duration)
   131  	return e.AppendInt64(b, d.Nanoseconds())
   132  }
   133  
   134  func (e Encoder) AppendFormat(b []byte, fmt string, args ...interface{}) []byte {
   135  	b = append(b, String)
   136  	st := len(b)
   137  
   138  	if fmt == "" {
   139  		b = hfmt.Append(b, args...)
   140  	} else {
   141  		b = hfmt.Appendf(b, fmt, args...)
   142  	}
   143  
   144  	l := len(b) - st
   145  
   146  	return e.InsertLen(b, st, l)
   147  }
   148  
   149  // InsertLen inserts length l before value starting at st copying l bytes forward if needed.
   150  // It is created for AppendFormat because we don't know the final message length.
   151  // But it can be also used in other similar situations.
   152  func (e Encoder) InsertLen(b []byte, st, l int) []byte {
   153  	if l < 0 {
   154  		panic(l)
   155  	}
   156  
   157  	b[st-1] &= TagMask
   158  
   159  	if l < Len1 {
   160  		b[st-1] |= byte(l)
   161  
   162  		return b
   163  	}
   164  
   165  	sz := e.TagSize(l) - 1
   166  
   167  	b = append(b, "        "[:sz]...)
   168  	copy(b[st+sz:], b[st:])
   169  
   170  	_ = e.AppendTag(b[:st-1], b[st-1], l)
   171  
   172  	return b
   173  }
   174  
   175  func (e LowEncoder) AppendMap(b []byte, l int) []byte {
   176  	return e.AppendTag(b, Map, l)
   177  }
   178  
   179  func (e LowEncoder) AppendArray(b []byte, l int) []byte {
   180  	return e.AppendTag(b, Array, l)
   181  }
   182  
   183  func (e LowEncoder) AppendString(b []byte, s string) []byte {
   184  	b = e.AppendTag(b, String, len(s))
   185  	return append(b, s...)
   186  }
   187  
   188  func (e LowEncoder) AppendBytes(b, s []byte) []byte {
   189  	b = e.AppendTag(b, Bytes, len(s))
   190  	return append(b, s...)
   191  }
   192  
   193  func (e LowEncoder) AppendTagString(b []byte, tag byte, s string) []byte {
   194  	b = e.AppendTag(b, tag, len(s))
   195  	return append(b, s...)
   196  }
   197  
   198  func (e LowEncoder) AppendTagBytes(b []byte, tag byte, s []byte) []byte {
   199  	b = e.AppendTag(b, tag, len(s))
   200  	return append(b, s...)
   201  }
   202  
   203  func (e LowEncoder) AppendInt(b []byte, v int) []byte {
   204  	if v < 0 {
   205  		return e.AppendTag64(b, Neg, uint64(-v))
   206  	}
   207  
   208  	return e.AppendTag64(b, Int, uint64(v))
   209  }
   210  
   211  func (e LowEncoder) AppendUint(b []byte, v uint) []byte {
   212  	return e.AppendTag64(b, Int, uint64(v))
   213  }
   214  
   215  func (e LowEncoder) AppendInt64(b []byte, v int64) []byte {
   216  	if v < 0 {
   217  		return e.AppendTag64(b, Neg, uint64(-v))
   218  	}
   219  
   220  	return e.AppendTag64(b, Int, uint64(v))
   221  }
   222  
   223  func (e LowEncoder) AppendUint64(b []byte, v uint64) []byte {
   224  	return e.AppendTag64(b, Int, v)
   225  }
   226  
   227  func (e LowEncoder) AppendFloat(b []byte, v float64) []byte {
   228  	if q := int8(v); float64(q) == v {
   229  		return append(b, Special|Float8, byte(q))
   230  	}
   231  
   232  	if q := float32(v); float64(q) == v {
   233  		r := math.Float32bits(q)
   234  
   235  		return append(b, Special|Float32, byte(r>>24), byte(r>>16), byte(r>>8), byte(r))
   236  	}
   237  
   238  	r := math.Float64bits(v)
   239  
   240  	return append(b, Special|Float64, byte(r>>56), byte(r>>48), byte(r>>40), byte(r>>32), byte(r>>24), byte(r>>16), byte(r>>8), byte(r))
   241  }
   242  
   243  func (e LowEncoder) AppendTag(b []byte, tag byte, v int) []byte {
   244  	switch {
   245  	case v == -1:
   246  		return append(b, tag|LenBreak)
   247  	case v < Len1:
   248  		return append(b, tag|byte(v))
   249  	case v <= 0xff:
   250  		return append(b, tag|Len1, byte(v))
   251  	case v <= 0xffff:
   252  		return append(b, tag|Len2, byte(v>>8), byte(v))
   253  	case v <= 0xffff_ffff:
   254  		return append(b, tag|Len4, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   255  	default:
   256  		return append(b, tag|Len8, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   257  	}
   258  }
   259  
   260  func (e LowEncoder) AppendTag64(b []byte, tag byte, v uint64) []byte {
   261  	switch {
   262  	case v < Len1:
   263  		return append(b, tag|byte(v))
   264  	case v <= 0xff:
   265  		return append(b, tag|Len1, byte(v))
   266  	case v <= 0xffff:
   267  		return append(b, tag|Len2, byte(v>>8), byte(v))
   268  	case v <= 0xffff_ffff:
   269  		return append(b, tag|Len4, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   270  	default:
   271  		return append(b, tag|Len8, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   272  	}
   273  }
   274  
   275  func (e LowEncoder) AppendTagBreak(b []byte, tag byte) []byte {
   276  	return append(b, tag|LenBreak)
   277  }
   278  
   279  func (e LowEncoder) AppendSemantic(b []byte, x int) []byte {
   280  	return e.AppendTag(b, Semantic, x)
   281  }
   282  
   283  func (e LowEncoder) AppendSpecial(b []byte, x byte) []byte {
   284  	return append(b, Special|x)
   285  }
   286  
   287  func (e LowEncoder) AppendBool(b []byte, v bool) []byte {
   288  	if v {
   289  		return append(b, Special|True)
   290  	}
   291  
   292  	return append(b, Special|False)
   293  }
   294  
   295  func (e LowEncoder) AppendNil(b []byte) []byte {
   296  	return append(b, Special|Nil)
   297  }
   298  
   299  func (e LowEncoder) AppendUndefined(b []byte) []byte {
   300  	return append(b, Special|Undefined)
   301  }
   302  
   303  func (e LowEncoder) AppendBreak(b []byte) []byte {
   304  	return append(b, Special|Break)
   305  }
   306  
   307  func (e LowEncoder) TagSize(v int) int {
   308  	switch {
   309  	case v == -1:
   310  		return 1
   311  	case v < Len1:
   312  		return 1
   313  	case v <= 0xff:
   314  		return 1 + 1
   315  	case v <= 0xffff:
   316  		return 1 + 2
   317  	case v <= 0xffff_ffff:
   318  		return 1 + 4
   319  	default:
   320  		return 1 + 8
   321  	}
   322  }
   323  
   324  func (e LowEncoder) Tag64Size(v uint64) int {
   325  	switch {
   326  	case v < Len1:
   327  		return 1
   328  	case v <= 0xff:
   329  		return 1 + 1
   330  	case v <= 0xffff:
   331  		return 1 + 2
   332  	case v <= 0xffff_ffff:
   333  		return 1 + 4
   334  	default:
   335  		return 1 + 8
   336  	}
   337  }