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 }