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 }