github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/codec/row.go (about)

     1  // Copyright 2022 zGraph Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package codec
    16  
    17  import (
    18  	"reflect"
    19  	"sort"
    20  	"unsafe"
    21  
    22  	"github.com/pingcap/errors"
    23  )
    24  
    25  var errInvalidCodecVer = errors.New("invalid codec version")
    26  
    27  // rowFlag represents the flag of first byte of value encoded bytes.
    28  type rowFlag byte
    29  
    30  // Flag:
    31  // 0 0 0 0 0 0 0 0
    32  // |         |   |
    33  // |         +---+----- Encode Version (max to 8 versions)
    34  // |+--------+--------- Reserved flag bits
    35  
    36  const (
    37  	version             = 0
    38  	versionMask rowFlag = 0x07
    39  )
    40  
    41  func (f rowFlag) version() byte {
    42  	return byte(f & versionMask)
    43  }
    44  
    45  // rowBytes is used to encode/decode the value bytes.
    46  // Value Encode:
    47  // Flag[1byte]+LabelCount(varint)+LabelIDs+PropertyCount(varint)+PropertyIDs+PropertyOffsets+Data
    48  type rowBytes struct {
    49  	labelIDs    []uint16
    50  	propertyIDs []uint16
    51  	offsets     []uint16
    52  	data        []byte
    53  }
    54  
    55  // getData gets the row data at index `i`.
    56  func (r *rowBytes) getData(i int) []byte {
    57  	var start, end uint16
    58  	if i > 0 {
    59  		start = r.offsets[i-1]
    60  	}
    61  	end = r.offsets[i]
    62  	return r.data[start:end]
    63  }
    64  
    65  func (r *rowBytes) hasLabel(labelID uint16) bool {
    66  	i := sort.Search(len(r.labelIDs), func(i int) bool {
    67  		return r.labelIDs[i] >= labelID
    68  	})
    69  	return i < len(r.labelIDs) && r.labelIDs[i] == labelID
    70  }
    71  
    72  // findProperty finds the property index of the row. -1 returned if not found.
    73  func (r *rowBytes) findProperty(propertyID uint16) int {
    74  	i := sort.Search(len(r.propertyIDs), func(i int) bool {
    75  		return r.propertyIDs[i] >= propertyID
    76  	})
    77  	if i < len(r.propertyIDs) && r.propertyIDs[i] == propertyID {
    78  		return i
    79  	} else {
    80  		return -1
    81  	}
    82  }
    83  
    84  func (r *rowBytes) toBytes(buf []byte) []byte {
    85  	buf = append(buf, version)
    86  	buf = EncodeUvarint(buf, uint64(len(r.labelIDs)))
    87  	buf = append(buf, u16SliceToBytes(r.labelIDs)...)
    88  	buf = EncodeUvarint(buf, uint64(len(r.propertyIDs)))
    89  	buf = append(buf, u16SliceToBytes(r.propertyIDs)...)
    90  	buf = append(buf, u16SliceToBytes(r.offsets)...)
    91  	buf = append(buf, r.data...)
    92  	return buf
    93  }
    94  
    95  func (r *rowBytes) fromBytes(rowData []byte) error {
    96  	if rowFlag(rowData[0]).version() != version {
    97  		return errInvalidCodecVer
    98  	}
    99  
   100  	rowData, labelCount, err := DecodeUvarint(rowData[1:])
   101  	if err != nil {
   102  		return err
   103  	}
   104  	r.labelIDs = bytes2U16Slice(rowData[:labelCount*2])
   105  	rowData = rowData[labelCount*2:]
   106  
   107  	rowData, propertyCount, err := DecodeUvarint(rowData)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	r.propertyIDs = bytes2U16Slice(rowData[:propertyCount*2])
   112  	rowData = rowData[propertyCount*2:]
   113  
   114  	r.offsets = bytes2U16Slice(rowData[:propertyCount*2])
   115  	r.data = rowData[propertyCount*2:]
   116  	return nil
   117  }
   118  
   119  func bytes2U16Slice(b []byte) []uint16 {
   120  	if len(b) == 0 {
   121  		return nil
   122  	}
   123  	var u16s []uint16
   124  	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&u16s))
   125  	hdr.Len = len(b) / 2
   126  	hdr.Cap = hdr.Len
   127  	hdr.Data = uintptr(unsafe.Pointer(&b[0]))
   128  	return u16s
   129  }
   130  
   131  func u16SliceToBytes(u16s []uint16) []byte {
   132  	if len(u16s) == 0 {
   133  		return nil
   134  	}
   135  	var b []byte
   136  	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
   137  	hdr.Len = len(u16s) * 2
   138  	hdr.Cap = hdr.Len
   139  	hdr.Data = uintptr(unsafe.Pointer(&u16s[0]))
   140  	return b
   141  }