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  }