github.com/mailru/activerecord@v1.12.2/pkg/octopus/pack.go (about) 1 package octopus 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "github.com/mailru/activerecord/pkg/iproto/iproto" 8 ) 9 10 func ByteLen(length uint32) uint32 { 11 switch { 12 case length < (1 << 7): 13 return 1 + length 14 case length < (1 << 14): 15 return 2 + length 16 case length < (1 << 21): 17 return 3 + length 18 case length < (1 << 28): 19 return 4 + length 20 default: 21 return 5 + length 22 } 23 } 24 25 func PackedTupleLen(keys [][]byte) (length uint32) { 26 length = 4 27 28 for _, k := range keys { 29 length += PackedFieldLen(k) 30 } 31 32 return length 33 } 34 35 func PackedKeysLen(keys [][]byte) (length uint32) { 36 length = 4 37 38 for _, k := range keys { 39 length += PackedFieldLen(k) 40 } 41 42 return length 43 } 44 45 func PackedKeyLen(keys [][]byte) (length uint32) { 46 return PackedKeysLen(keys) 47 } 48 49 func PackedUpdateOpsLen(updateOps []Ops) (length uint32) { 50 length = OpsLen 51 52 for _, op := range updateOps { 53 length += OpFieldNumLen + OpOpLen + ByteLen(uint32(len(op.Value))) 54 } 55 56 return length 57 } 58 59 func PackedFieldLen(field []byte) uint32 { 60 return ByteLen(uint32(len(field))) 61 } 62 63 func PackFieldNums(w []byte, cnt uint32) []byte { 64 return iproto.PackUint32(w, cnt, iproto.ModeDefault) 65 } 66 67 func UnpackFieldNums(r *bytes.Reader) (uint32, error) { 68 var fieldsNum uint32 69 70 if err := iproto.UnpackUint32(r, &fieldsNum, iproto.ModeDefault); err != nil { 71 return 0, fmt.Errorf("can't unpack fieldsNum: %w", err) 72 } 73 74 return fieldsNum, nil 75 } 76 77 func PackedTuplesLen(keys [][][]byte) (length uint32) { 78 length = 4 79 80 for _, kt := range keys { 81 length += PackedTupleLen(kt) 82 } 83 84 return length 85 } 86 87 func PackBool(w []byte, v bool, mode iproto.PackMode) ([]byte, error) { 88 if v { 89 return iproto.PackUint8(w, 1, mode), nil 90 } 91 92 return iproto.PackUint8(w, 0, mode), nil 93 } 94 95 func PackField(w []byte, field []byte) []byte { 96 return iproto.PackBytes(w, field, iproto.ModeBER) 97 } 98 99 func UnpackField(r *bytes.Reader) ([]byte, error) { 100 field := []byte{} 101 102 if err := iproto.UnpackBytes(r, &field, iproto.ModeBER); err != nil { 103 return nil, fmt.Errorf("can't unpack field: %w", err) 104 } 105 106 return field, nil 107 } 108 109 func PackKey(w []byte, key [][]byte) []byte { 110 w = iproto.PackUint32(w, uint32(len(key)), iproto.ModeDefault) 111 for _, k := range key { 112 w = PackField(w, k) 113 } 114 115 return w 116 } 117 118 func UnpackKey(r *bytes.Reader) ([][]byte, error) { 119 ret := [][]byte{} 120 fieldNum := uint32(0) 121 122 err := iproto.UnpackUint32(r, &fieldNum, iproto.ModeDefault) 123 if err != nil { 124 return nil, fmt.Errorf("can't unpack fieldnum: %s", err) 125 } 126 127 for f := uint32(0); f < fieldNum; f++ { 128 field, err := UnpackField(r) 129 if err != nil { 130 return nil, fmt.Errorf("can't unpack field %d: %s", f, err) 131 } 132 133 ret = append(ret, field) 134 } 135 136 return ret, nil 137 } 138 139 func PackTuples(w []byte, keys [][][]byte) []byte { 140 w = iproto.PackUint32(w, uint32(len(keys)), iproto.ModeDefault) 141 142 for _, kt := range keys { 143 w = PackTuple(w, kt) 144 } 145 146 return w 147 } 148 149 func UnpackTuples(r *bytes.Reader) ([][][]byte, error) { 150 ret := [][][]byte{} 151 152 var tuples uint32 153 154 if err := iproto.UnpackUint32(r, &tuples, iproto.ModeDefault); err != nil { 155 return nil, fmt.Errorf("can't unpack tuple cnt: %w", err) 156 } 157 158 for t := uint32(0); t < tuples; t++ { 159 tuple, err := UnpackTuple(r) 160 if err != nil { 161 return nil, fmt.Errorf("can't unpack tuple: %w", err) 162 } 163 164 ret = append(ret, tuple) 165 } 166 167 return ret, nil 168 } 169 170 func PackTuple(w []byte, keys [][]byte) []byte { 171 w = PackFieldNums(w, uint32(len(keys))) 172 173 for _, k := range keys { 174 w = PackField(w, k) 175 } 176 177 return w 178 } 179 180 func UnpackTuple(r *bytes.Reader) ([][]byte, error) { 181 ret := [][]byte{} 182 183 fieldsNum, err := UnpackFieldNums(r) 184 if err != nil { 185 return nil, fmt.Errorf("can't unpack fieldnum: %w", err) 186 } 187 188 for f := uint32(0); f < fieldsNum; f++ { 189 field, err := UnpackField(r) 190 if err != nil { 191 return nil, fmt.Errorf("can't unpack field: %w", err) 192 } 193 194 ret = append(ret, field) 195 } 196 197 return ret, nil 198 } 199 200 func PackSpace(w []byte, space uint32) []byte { 201 return iproto.PackUint32(w, space, iproto.ModeDefault) 202 } 203 204 func UnpackSpace(r *bytes.Reader) (uint32, error) { 205 var space uint32 206 207 if err := iproto.UnpackUint32(r, &space, iproto.ModeDefault); err != nil { 208 return 0, fmt.Errorf("can't unpack space: %w", err) 209 } 210 211 return space, nil 212 } 213 214 func PackIndexNum(w []byte, indexnum uint32) []byte { 215 return iproto.PackUint32(w, indexnum, iproto.ModeDefault) 216 } 217 218 func UnpackIndexNum(r *bytes.Reader) (uint32, error) { 219 var indexnum uint32 220 221 if err := iproto.UnpackUint32(r, &indexnum, iproto.ModeDefault); err != nil { 222 return 0, fmt.Errorf("can't unpack indexnum: %w", err) 223 } 224 225 return indexnum, nil 226 } 227 228 func PackRequestFlagsVal(w []byte, ret bool, mode InsertMode) []byte { 229 var flags uint32 230 231 if ret { 232 flags = 1 233 } 234 235 if mode != 0 { 236 flags |= 1 << uint32(mode) 237 } 238 239 return iproto.PackUint32(w, flags, iproto.ModeDefault) 240 } 241 242 func UnpackRequestFlagsVal(r *bytes.Reader) (bool, InsertMode, error) { 243 var flags uint32 244 245 err := iproto.UnpackUint32(r, &flags, iproto.ModeDefault) 246 if err != nil { 247 return false, 0, fmt.Errorf("can't unpack flags: %w", err) 248 } 249 250 if flags&1 == 1 { 251 return true, InsertMode(flags ^ 1), nil 252 } 253 254 return false, InsertMode(flags), nil 255 } 256 257 func PackDeleteFlagsVal(w []byte, ret bool) []byte { 258 var flags uint32 259 260 if ret { 261 flags = 1 262 } 263 264 return iproto.PackUint32(w, flags, iproto.ModeDefault) 265 } 266 267 func PackLimit(w []byte, limit uint32) []byte { 268 if limit == 0 { 269 limit = 0xffffffff 270 } 271 272 return iproto.PackUint32(w, limit, iproto.ModeDefault) 273 } 274 275 func UnpackLimit(r *bytes.Reader) (uint32, error) { 276 var limit uint32 277 278 if err := iproto.UnpackUint32(r, &limit, iproto.ModeDefault); err != nil { 279 return 0, fmt.Errorf("can't unpack limit: %w", err) 280 } 281 282 if limit == 0xffffffff { 283 limit = 0 284 } 285 286 return limit, nil 287 } 288 289 func PackOffset(w []byte, offset uint32) []byte { 290 return iproto.PackUint32(w, offset, iproto.ModeDefault) 291 } 292 293 func UnpackOffset(r *bytes.Reader) (uint32, error) { 294 var limit uint32 295 296 if err := iproto.UnpackUint32(r, &limit, iproto.ModeDefault); err != nil { 297 return 0, fmt.Errorf("can't unpack offset: %w", err) 298 } 299 300 return limit, nil 301 } 302 303 func UnpackResopnseStatus(data []byte) (uint32, []byte, error) { 304 rdr := bytes.NewReader(data) 305 306 var retCode uint32 307 308 if err := iproto.UnpackUint32(rdr, &retCode, iproto.ModeDefault); err != nil { 309 return 0, []byte{}, fmt.Errorf("error unpack retCode: %w", err) 310 } 311 312 if RetCode(retCode) == RcOK { 313 if rdr.Len() == 0 { 314 return 0, []byte{}, nil 315 } 316 317 if rdr.Len() < 4 { 318 return 0, nil, fmt.Errorf("error unpack tuple cnt data to small: '%d'", rdr.Len()) 319 } 320 321 var cnt uint32 322 323 err := iproto.UnpackUint32(rdr, &cnt, iproto.ModeDefault) 324 if err != nil { 325 return 0, nil, fmt.Errorf("error unpack tuple cnt in boxResp: '%w'", err) 326 } 327 328 return cnt, data[len(data)-rdr.Len():], nil 329 } 330 331 errStr := data[4:] 332 if len(errStr) > 0 && errStr[len(errStr)-1] == 0x0 { 333 errStr = errStr[:len(errStr)-1] 334 } 335 336 return 0, nil, fmt.Errorf("error request to octopus `%s`", errStr) 337 } 338 339 func PackResopnseStatus(statusCode RetCode, data [][][]byte) ([]byte, error) { 340 resp := []byte{} 341 resp = iproto.PackUint32(resp, uint32(statusCode), iproto.ModeDefault) 342 343 if statusCode == RcOK { 344 if len(data) == 0 { 345 return resp, nil 346 } 347 348 resp = iproto.PackUint32(resp, uint32(len(data)), iproto.ModeDefault) 349 350 for _, tuple := range data { 351 payload := iproto.PackUint32([]byte{}, uint32(len(tuple)), iproto.ModeDefault) 352 353 for _, field := range tuple { 354 payload = PackField(payload, field) 355 } 356 357 resp = iproto.PackUint32(resp, uint32(len(payload)), iproto.ModeDefault) 358 resp = append(resp, payload...) 359 } 360 361 return resp, nil 362 } 363 364 resp = iproto.PackUint32(resp, uint32(len(data[0])), iproto.ModeDefault) 365 resp = append(resp, data[0][0]...) 366 367 return resp, nil 368 } 369 370 func PackString(w []byte, field string, mode iproto.PackMode) []byte { 371 return append(w, field...) 372 } 373 374 func UnpackString(r *bytes.Reader, res *string, mode iproto.PackMode) error { 375 len := r.Len() 376 if len == 0 { 377 *res = "" 378 return nil 379 } 380 381 bres := make([]byte, len) 382 383 rlen, err := r.Read(bres) 384 if err != nil { 385 return fmt.Errorf("error unpack string: '%s'", err) 386 } 387 388 if rlen != len { 389 return fmt.Errorf("error len while unpack string: %d, want %d", rlen, len) 390 } 391 392 *res = string(bres) 393 394 return nil 395 } 396 397 func BoolToUint(v bool) uint8 { 398 if v { 399 return 1 400 } 401 402 return 0 403 } 404 405 func UintToBool(v uint8) bool { 406 return v != 0 407 }