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  }