github.com/KinWaiYuen/client-go/v2@v2.5.4/util/codec/number.go (about) 1 // Copyright 2021 TiKV Authors 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 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/util/codec/number.go 19 // 20 21 // Copyright 2015 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package codec 36 37 import ( 38 "encoding/binary" 39 "math" 40 41 "github.com/pingcap/errors" 42 ) 43 44 const signMask uint64 = 0x8000000000000000 45 46 // EncodeIntToCmpUint make int v to comparable uint type 47 func EncodeIntToCmpUint(v int64) uint64 { 48 return uint64(v) ^ signMask 49 } 50 51 // DecodeCmpUintToInt decodes the u that encoded by EncodeIntToCmpUint 52 func DecodeCmpUintToInt(u uint64) int64 { 53 return int64(u ^ signMask) 54 } 55 56 // EncodeInt appends the encoded value to slice b and returns the appended slice. 57 // EncodeInt guarantees that the encoded value is in ascending order for comparison. 58 func EncodeInt(b []byte, v int64) []byte { 59 var data [8]byte 60 u := EncodeIntToCmpUint(v) 61 binary.BigEndian.PutUint64(data[:], u) 62 return append(b, data[:]...) 63 } 64 65 // EncodeIntDesc appends the encoded value to slice b and returns the appended slice. 66 // EncodeIntDesc guarantees that the encoded value is in descending order for comparison. 67 func EncodeIntDesc(b []byte, v int64) []byte { 68 var data [8]byte 69 u := EncodeIntToCmpUint(v) 70 binary.BigEndian.PutUint64(data[:], ^u) 71 return append(b, data[:]...) 72 } 73 74 // DecodeInt decodes value encoded by EncodeInt before. 75 // It returns the leftover un-decoded slice, decoded value if no error. 76 func DecodeInt(b []byte) ([]byte, int64, error) { 77 if len(b) < 8 { 78 return nil, 0, errors.New("insufficient bytes to decode value") 79 } 80 81 u := binary.BigEndian.Uint64(b[:8]) 82 v := DecodeCmpUintToInt(u) 83 b = b[8:] 84 return b, v, nil 85 } 86 87 // DecodeIntDesc decodes value encoded by EncodeInt before. 88 // It returns the leftover un-decoded slice, decoded value if no error. 89 func DecodeIntDesc(b []byte) ([]byte, int64, error) { 90 if len(b) < 8 { 91 return nil, 0, errors.New("insufficient bytes to decode value") 92 } 93 94 u := binary.BigEndian.Uint64(b[:8]) 95 v := DecodeCmpUintToInt(^u) 96 b = b[8:] 97 return b, v, nil 98 } 99 100 // EncodeUint appends the encoded value to slice b and returns the appended slice. 101 // EncodeUint guarantees that the encoded value is in ascending order for comparison. 102 func EncodeUint(b []byte, v uint64) []byte { 103 var data [8]byte 104 binary.BigEndian.PutUint64(data[:], v) 105 return append(b, data[:]...) 106 } 107 108 // EncodeUintDesc appends the encoded value to slice b and returns the appended slice. 109 // EncodeUintDesc guarantees that the encoded value is in descending order for comparison. 110 func EncodeUintDesc(b []byte, v uint64) []byte { 111 var data [8]byte 112 binary.BigEndian.PutUint64(data[:], ^v) 113 return append(b, data[:]...) 114 } 115 116 // DecodeUint decodes value encoded by EncodeUint before. 117 // It returns the leftover un-decoded slice, decoded value if no error. 118 func DecodeUint(b []byte) ([]byte, uint64, error) { 119 if len(b) < 8 { 120 return nil, 0, errors.New("insufficient bytes to decode value") 121 } 122 123 v := binary.BigEndian.Uint64(b[:8]) 124 b = b[8:] 125 return b, v, nil 126 } 127 128 // DecodeUintDesc decodes value encoded by EncodeInt before. 129 // It returns the leftover un-decoded slice, decoded value if no error. 130 func DecodeUintDesc(b []byte) ([]byte, uint64, error) { 131 if len(b) < 8 { 132 return nil, 0, errors.New("insufficient bytes to decode value") 133 } 134 135 data := b[:8] 136 v := binary.BigEndian.Uint64(data) 137 b = b[8:] 138 return b, ^v, nil 139 } 140 141 // EncodeVarint appends the encoded value to slice b and returns the appended slice. 142 // Note that the encoded result is not memcomparable. 143 func EncodeVarint(b []byte, v int64) []byte { 144 var data [binary.MaxVarintLen64]byte 145 n := binary.PutVarint(data[:], v) 146 return append(b, data[:n]...) 147 } 148 149 // DecodeVarint decodes value encoded by EncodeVarint before. 150 // It returns the leftover un-decoded slice, decoded value if no error. 151 func DecodeVarint(b []byte) ([]byte, int64, error) { 152 v, n := binary.Varint(b) 153 if n > 0 { 154 return b[n:], v, nil 155 } 156 if n < 0 { 157 return nil, 0, errors.New("value larger than 64 bits") 158 } 159 return nil, 0, errors.New("insufficient bytes to decode value") 160 } 161 162 // EncodeUvarint appends the encoded value to slice b and returns the appended slice. 163 // Note that the encoded result is not memcomparable. 164 func EncodeUvarint(b []byte, v uint64) []byte { 165 var data [binary.MaxVarintLen64]byte 166 n := binary.PutUvarint(data[:], v) 167 return append(b, data[:n]...) 168 } 169 170 // DecodeUvarint decodes value encoded by EncodeUvarint before. 171 // It returns the leftover un-decoded slice, decoded value if no error. 172 func DecodeUvarint(b []byte) ([]byte, uint64, error) { 173 v, n := binary.Uvarint(b) 174 if n > 0 { 175 return b[n:], v, nil 176 } 177 if n < 0 { 178 return nil, 0, errors.New("value larger than 64 bits") 179 } 180 return nil, 0, errors.New("insufficient bytes to decode value") 181 } 182 183 const ( 184 negativeTagEnd = 8 // negative tag is (negativeTagEnd - length). 185 positiveTagStart = 0xff - 8 // Positive tag is (positiveTagStart + length). 186 ) 187 188 // EncodeComparableVarint encodes an int64 to a mem-comparable bytes. 189 func EncodeComparableVarint(b []byte, v int64) []byte { 190 if v < 0 { 191 // All negative value has a tag byte prefix (negativeTagEnd - length). 192 // Smaller negative value encodes to more bytes, has smaller tag. 193 if v >= -0xff { 194 return append(b, negativeTagEnd-1, byte(v)) 195 } else if v >= -0xffff { 196 return append(b, negativeTagEnd-2, byte(v>>8), byte(v)) 197 } else if v >= -0xffffff { 198 return append(b, negativeTagEnd-3, byte(v>>16), byte(v>>8), byte(v)) 199 } else if v >= -0xffffffff { 200 return append(b, negativeTagEnd-4, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) 201 } else if v >= -0xffffffffff { 202 return append(b, negativeTagEnd-5, byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) 203 } else if v >= -0xffffffffffff { 204 return append(b, negativeTagEnd-6, byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), 205 byte(v)) 206 } else if v >= -0xffffffffffffff { 207 return append(b, negativeTagEnd-7, byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), 208 byte(v>>8), byte(v)) 209 } 210 return append(b, negativeTagEnd-8, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), 211 byte(v>>16), byte(v>>8), byte(v)) 212 } 213 return EncodeComparableUvarint(b, uint64(v)) 214 } 215 216 // EncodeComparableUvarint encodes uint64 into mem-comparable bytes. 217 func EncodeComparableUvarint(b []byte, v uint64) []byte { 218 // The first byte has 256 values, [0, 7] is reserved for negative tags, 219 // [248, 255] is reserved for larger positive tags, 220 // So we can store value [0, 239] in a single byte. 221 // Values cannot be stored in single byte has a tag byte prefix (positiveTagStart+length). 222 // Larger value encodes to more bytes, has larger tag. 223 if v <= positiveTagStart-negativeTagEnd { 224 return append(b, byte(v)+negativeTagEnd) 225 } else if v <= 0xff { 226 return append(b, positiveTagStart+1, byte(v)) 227 } else if v <= 0xffff { 228 return append(b, positiveTagStart+2, byte(v>>8), byte(v)) 229 } else if v <= 0xffffff { 230 return append(b, positiveTagStart+3, byte(v>>16), byte(v>>8), byte(v)) 231 } else if v <= 0xffffffff { 232 return append(b, positiveTagStart+4, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) 233 } else if v <= 0xffffffffff { 234 return append(b, positiveTagStart+5, byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) 235 } else if v <= 0xffffffffffff { 236 return append(b, positiveTagStart+6, byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), 237 byte(v)) 238 } else if v <= 0xffffffffffffff { 239 return append(b, positiveTagStart+7, byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), 240 byte(v>>8), byte(v)) 241 } 242 return append(b, positiveTagStart+8, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), 243 byte(v>>16), byte(v>>8), byte(v)) 244 } 245 246 var ( 247 errDecodeInsufficient = errors.New("insufficient bytes to decode value") 248 errDecodeInvalid = errors.New("invalid bytes to decode value") 249 ) 250 251 // DecodeComparableUvarint decodes mem-comparable uvarint. 252 func DecodeComparableUvarint(b []byte) ([]byte, uint64, error) { 253 if len(b) == 0 { 254 return nil, 0, errDecodeInsufficient 255 } 256 first := b[0] 257 b = b[1:] 258 if first < negativeTagEnd { 259 return nil, 0, errors.Trace(errDecodeInvalid) 260 } 261 if first <= positiveTagStart { 262 return b, uint64(first) - negativeTagEnd, nil 263 } 264 length := int(first) - positiveTagStart 265 if len(b) < length { 266 return nil, 0, errors.Trace(errDecodeInsufficient) 267 } 268 var v uint64 269 for _, c := range b[:length] { 270 v = (v << 8) | uint64(c) 271 } 272 return b[length:], v, nil 273 } 274 275 // DecodeComparableVarint decodes mem-comparable varint. 276 func DecodeComparableVarint(b []byte) ([]byte, int64, error) { 277 if len(b) == 0 { 278 return nil, 0, errors.Trace(errDecodeInsufficient) 279 } 280 first := b[0] 281 if first >= negativeTagEnd && first <= positiveTagStart { 282 return b, int64(first) - negativeTagEnd, nil 283 } 284 b = b[1:] 285 var length int 286 var v uint64 287 if first < negativeTagEnd { 288 length = negativeTagEnd - int(first) 289 v = math.MaxUint64 // negative value has all bits on by default. 290 } else { 291 length = int(first) - positiveTagStart 292 } 293 if len(b) < length { 294 return nil, 0, errors.Trace(errDecodeInsufficient) 295 } 296 for _, c := range b[:length] { 297 v = (v << 8) | uint64(c) 298 } 299 if first > positiveTagStart && v > math.MaxInt64 { 300 return nil, 0, errors.Trace(errDecodeInvalid) 301 } else if first < negativeTagEnd && v <= math.MaxInt64 { 302 return nil, 0, errors.Trace(errDecodeInvalid) 303 } 304 return b[length:], int64(v), nil 305 }