github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/kv/key.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 2 // 3 // Copyright 2021 PingCAP, Inc. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package kv 18 19 import ( 20 "bytes" 21 "encoding/hex" 22 ) 23 24 // Key represents high-level Key type. 25 type Key []byte 26 27 // Next returns the next key in byte-order. 28 func (k Key) Next() Key { 29 // add 0x0 to the end of key 30 buf := make([]byte, len(k)+1) 31 copy(buf, k) 32 return buf 33 } 34 35 // PrefixNext returns the next prefix key. 36 // 37 // Assume there are keys like: 38 // 39 // rowkey1 40 // rowkey1_column1 41 // rowkey1_column2 42 // rowKey2 43 // 44 // If we seek 'rowkey1' Next, we will get 'rowkey1_column1'. 45 // If we seek 'rowkey1' PrefixNext, we will get 'rowkey2'. 46 func (k Key) PrefixNext() Key { 47 buf := make([]byte, len(k)) 48 copy(buf, k) 49 var i int 50 for i = len(k) - 1; i >= 0; i-- { 51 buf[i]++ 52 if buf[i] != 0 { 53 break 54 } 55 } 56 if i == -1 { 57 copy(buf, k) 58 buf = append(buf, 0) // nozero 59 } 60 return buf 61 } 62 63 // Cmp returns the comparison result of two key. 64 // The result will be 0 if a==b, -1 if a < b, and +1 if a > b. 65 func (k Key) Cmp(another Key) int { 66 return bytes.Compare(k, another) 67 } 68 69 // HasPrefix tests whether the Key begins with prefix. 70 func (k Key) HasPrefix(prefix Key) bool { 71 return bytes.HasPrefix(k, prefix) 72 } 73 74 // Clone returns a deep copy of the Key. 75 func (k Key) Clone() Key { 76 ck := make([]byte, len(k)) 77 copy(ck, k) 78 return ck 79 } 80 81 // String implements fmt.Stringer interface. 82 func (k Key) String() string { 83 return hex.EncodeToString(k) 84 } 85 86 // KeyRange represents a range where StartKey <= key < EndKey. 87 // Hack: make the layout exactly the same with github.com/pingcap/kvproto/pkg/coprocessor.KeyRange 88 // So we can avoid allocation of converting kv.KeyRange to coprocessor.KeyRange 89 // Not defined as "type KeyRange = coprocessor.KeyRange" because their field name are different. 90 // kv.KeyRange use StartKey,EndKey while coprocessor.KeyRange use Start,End 91 type KeyRange struct { 92 StartKey Key 93 EndKey Key 94 95 XXXNoUnkeyedLiteral struct{} 96 XXXunrecognized []byte 97 XXXsizecache int32 98 } 99 100 // IsPoint checks if the key range represents a point. 101 func (r *KeyRange) IsPoint() bool { 102 if len(r.StartKey) != len(r.EndKey) { 103 // Works like 104 // return bytes.Equal(r.StartKey.Next(), r.EndKey) 105 106 startLen := len(r.StartKey) 107 return startLen+1 == len(r.EndKey) && 108 r.EndKey[startLen] == 0 && 109 bytes.Equal(r.StartKey, r.EndKey[:startLen]) 110 } 111 // Works like 112 // return bytes.Equal(r.StartKey.PrefixNext(), r.EndKey) 113 114 i := len(r.StartKey) - 1 115 for ; i >= 0; i-- { 116 if r.StartKey[i] != 255 { 117 break 118 } 119 if r.EndKey[i] != 0 { 120 return false 121 } 122 } 123 if i < 0 { 124 // In case all bytes in StartKey are 255. 125 return false 126 } 127 // The byte at diffIdx in StartKey should be one less than the byte at diffIdx in EndKey. 128 // And bytes in StartKey and EndKey before diffIdx should be equal. 129 diffOneIdx := i 130 return r.StartKey[diffOneIdx]+1 == r.EndKey[diffOneIdx] && 131 bytes.Equal(r.StartKey[:diffOneIdx], r.EndKey[:diffOneIdx]) 132 } 133 134 // Entry is the entry for key and value 135 type Entry struct { 136 Key Key 137 Value []byte 138 } 139 140 // NextKey returns the next key in byte-order. 141 func NextKey(k []byte) []byte { 142 // add 0x0 to the end of key 143 buf := make([]byte, len(k)+1) 144 copy(buf, k) 145 return buf 146 } 147 148 // PrefixNextKey returns the next prefix key. 149 // 150 // Assume there are keys like: 151 // 152 // rowkey1 153 // rowkey1_column1 154 // rowkey1_column2 155 // rowKey2 156 // 157 // If we seek 'rowkey1' NextKey, we will get 'rowkey1_column1'. 158 // If we seek 'rowkey1' PrefixNextKey, we will get 'rowkey2'. 159 func PrefixNextKey(k []byte) []byte { 160 buf := make([]byte, len(k)) 161 copy(buf, k) 162 var i int 163 for i = len(k) - 1; i >= 0; i-- { 164 buf[i]++ 165 if buf[i] != 0 { 166 break 167 } 168 } 169 if i == -1 { 170 // Unlike TiDB, for the specific key 0xFF 171 // we return empty slice instead of {0xFF, 0x0} 172 buf = make([]byte, 0) 173 } 174 return buf 175 } 176 177 // CmpKey returns the comparison result of two key. 178 // The result will be 0 if a==b, -1 if a < b, and +1 if a > b. 179 func CmpKey(k, another []byte) int { 180 return bytes.Compare(k, another) 181 } 182 183 // StrKey returns string for key. 184 func StrKey(k []byte) string { 185 return hex.EncodeToString(k) 186 }