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

     1  package tlwire
     2  
     3  import (
     4  	"math"
     5  	"time"
     6  )
     7  
     8  type (
     9  	Decoder struct {
    10  		LowDecoder
    11  	}
    12  
    13  	LowDecoder struct{}
    14  )
    15  
    16  func (d Decoder) Time(p []byte, st int) (t time.Time, i int) {
    17  	if p[st] != Semantic|Time {
    18  		panic("not a time")
    19  	}
    20  
    21  	tag, sub, i := d.Tag(p, st+1)
    22  
    23  	if tag == Int {
    24  		return time.Unix(0, sub), i
    25  	}
    26  
    27  	if tag != Map || sub == -1 {
    28  		panic("unsupported time")
    29  	}
    30  
    31  	var (
    32  		k     []byte
    33  		ts    int64
    34  		tzN   []byte
    35  		tzOff int64
    36  	)
    37  
    38  	for el := 0; el < int(sub); el++ {
    39  		k, i = d.Bytes(p, i)
    40  
    41  		switch string(k) {
    42  		case "t":
    43  			ts, i = d.Signed(p, i)
    44  		case "z":
    45  			if p[i] != Array|2 {
    46  				panic("unsupported time zone")
    47  			}
    48  			i++
    49  
    50  			tzN, i = d.Bytes(p, i)
    51  			tzOff, i = d.Signed(p, i)
    52  		default:
    53  			i = d.Skip(p, i)
    54  		}
    55  	}
    56  
    57  	if ts != 0 {
    58  		t = time.Unix(0, ts)
    59  	}
    60  
    61  	if tzN != nil || tzOff != 0 {
    62  		l := time.FixedZone(string(tzN), int(tzOff))
    63  		t = t.In(l)
    64  	}
    65  
    66  	return
    67  }
    68  
    69  func (d Decoder) Timestamp(p []byte, st int) (ts int64, i int) {
    70  	if p[st] != Semantic|Time {
    71  		panic("not a time")
    72  	}
    73  
    74  	tag, sub, i := d.Tag(p, st+1)
    75  
    76  	if tag == Int {
    77  		return sub, i
    78  	}
    79  
    80  	if tag != Map || sub == -1 {
    81  		panic("unsupported time")
    82  	}
    83  
    84  	var k []byte
    85  
    86  	for el := 0; el < int(sub); el++ {
    87  		k, i = d.Bytes(p, i)
    88  
    89  		switch string(k) {
    90  		case "t":
    91  			ts, i = d.Signed(p, i)
    92  		default:
    93  			i = d.Skip(p, i)
    94  		}
    95  	}
    96  
    97  	return
    98  }
    99  
   100  func (d Decoder) Duration(p []byte, st int) (dr time.Duration, i int) {
   101  	if p[st] != Semantic|Duration {
   102  		panic("not a duration")
   103  	}
   104  
   105  	tag, sub, i := d.Tag(p, st+1)
   106  
   107  	if tag != Int && tag != Neg {
   108  		panic("unsupported duration")
   109  	}
   110  
   111  	if tag == Neg {
   112  		sub = -sub
   113  	}
   114  
   115  	return time.Duration(sub), i
   116  }
   117  
   118  func (d LowDecoder) Skip(b []byte, st int) (i int) {
   119  	_, _, i = d.SkipTag(b, st)
   120  	return
   121  }
   122  
   123  func (d LowDecoder) SkipTag(b []byte, st int) (tag byte, sub int64, i int) {
   124  	tag, sub, i = d.Tag(b, st)
   125  
   126  	//	println(fmt.Sprintf("Skip %x  tag %x %x %x  data % x", st, tag, sub, i, b[st:]))
   127  
   128  	switch tag {
   129  	case Int, Neg:
   130  		_, i = d.Unsigned(b, st)
   131  	case String, Bytes:
   132  		_, i = d.Bytes(b, st)
   133  	case Array, Map:
   134  		for el := 0; sub == -1 || el < int(sub); el++ {
   135  			if sub == -1 && d.Break(b, &i) {
   136  				break
   137  			}
   138  
   139  			if tag == Map {
   140  				_, i = d.Bytes(b, i)
   141  			}
   142  
   143  			i = d.Skip(b, i)
   144  		}
   145  	case Semantic:
   146  		i = d.Skip(b, i)
   147  	case Special:
   148  		switch sub {
   149  		case False,
   150  			True,
   151  			Nil,
   152  			Undefined,
   153  			None,
   154  			Hidden,
   155  			SelfRef,
   156  			Break:
   157  		case Float8, Float16, Float32, Float64:
   158  			i += 1 << (int(sub) - Float8)
   159  		default:
   160  			panic("unsupported special")
   161  		}
   162  	}
   163  
   164  	return
   165  }
   166  
   167  func (d LowDecoder) Break(b []byte, i *int) bool {
   168  	if b[*i] != Special|Break {
   169  		return false
   170  	}
   171  
   172  	*i++
   173  
   174  	return true
   175  }
   176  
   177  func (d LowDecoder) Bytes(b []byte, st int) (v []byte, i int) {
   178  	_, l, i := d.Tag(b, st)
   179  
   180  	return b[i : i+int(l)], i + int(l)
   181  }
   182  
   183  func (d LowDecoder) TagOnly(b []byte, st int) (tag byte) {
   184  	return b[st] & TagMask
   185  }
   186  
   187  func (d LowDecoder) Tag(b []byte, st int) (tag byte, sub int64, i int) {
   188  	i = st
   189  
   190  	tag = b[i] & TagMask
   191  	sub = int64(b[i] & TagDetMask)
   192  	i++
   193  
   194  	if tag == Special {
   195  		return
   196  	}
   197  
   198  	switch {
   199  	case sub < Len1:
   200  		// we are ok
   201  	case sub == LenBreak:
   202  		sub = -1
   203  	case sub == Len1:
   204  		sub = int64(b[i])
   205  		i++
   206  	case sub == Len2:
   207  		sub = int64(b[i])<<8 | int64(b[i+1])
   208  		i += 2
   209  	case sub == Len4:
   210  		sub = int64(b[i])<<24 | int64(b[i+1])<<16 | int64(b[i+2])<<8 | int64(b[i+3])
   211  		i += 4
   212  	case sub == Len8:
   213  		sub = int64(b[i])<<56 | int64(b[i+1])<<48 | int64(b[i+2])<<40 | int64(b[i+3])<<32 |
   214  			int64(b[i+4])<<24 | int64(b[i+5])<<16 | int64(b[i+6])<<8 | int64(b[i+7])
   215  		i += 8
   216  	default:
   217  		panic("malformed message")
   218  	}
   219  
   220  	return
   221  }
   222  
   223  func (d LowDecoder) Signed(b []byte, st int) (v int64, i int) {
   224  	u, i := d.Unsigned(b, st)
   225  
   226  	if b[st]&TagMask == Int {
   227  		return int64(u), i
   228  	}
   229  
   230  	return -int64(u), i
   231  }
   232  
   233  func (d LowDecoder) Unsigned(b []byte, st int) (v uint64, i int) {
   234  	i = st
   235  
   236  	v = uint64(b[i]) & TagDetMask
   237  	i++
   238  
   239  	switch {
   240  	case v < Len1:
   241  		// we are ok
   242  	case v == Len1:
   243  		v = uint64(b[i])
   244  		i++
   245  	case v == Len2:
   246  		v = uint64(b[i])<<8 | uint64(b[i+1])
   247  		i += 2
   248  	case v == Len4:
   249  		v = uint64(b[i])<<24 | uint64(b[i+1])<<16 | uint64(b[i+2])<<8 | uint64(b[i+3])
   250  		i += 4
   251  	case v == Len8:
   252  		v = uint64(b[i])<<56 | uint64(b[i+1])<<48 | uint64(b[i+2])<<40 | uint64(b[i+3])<<32 |
   253  			uint64(b[i+4])<<24 | uint64(b[i+5])<<16 | uint64(b[i+6])<<8 | uint64(b[i+7])
   254  		i += 8
   255  	default:
   256  		panic("malformed message")
   257  	}
   258  
   259  	return
   260  }
   261  
   262  func (d LowDecoder) Float(b []byte, st int) (v float64, i int) {
   263  	i = st
   264  
   265  	st = int(b[i]) & TagDetMask
   266  	i++
   267  
   268  	switch {
   269  	case st == Float8:
   270  		v = float64(int8(b[i]))
   271  		i++
   272  	case st == Float32:
   273  		v = float64(math.Float32frombits(
   274  			uint32(b[i])<<24 | uint32(b[i+1])<<16 | uint32(b[i+2])<<8 | uint32(b[i+3]),
   275  		))
   276  
   277  		i += 4
   278  	case st == Float64:
   279  		v = math.Float64frombits(
   280  			uint64(b[i])<<56 | uint64(b[i+1])<<48 | uint64(b[i+2])<<40 | uint64(b[i+3])<<32 |
   281  				uint64(b[i+4])<<24 | uint64(b[i+5])<<16 | uint64(b[i+6])<<8 | uint64(b[i+7]),
   282  		)
   283  
   284  		i += 8
   285  	default:
   286  		panic("malformed message")
   287  	}
   288  
   289  	return
   290  }