github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/ledger/util/uint64_encoding.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package util 8 9 import ( 10 "encoding/binary" 11 "math" 12 13 "github.com/golang/protobuf/proto" 14 ) 15 16 // EncodeReverseOrderVarUint64 returns a byte-representation for a uint64 number such that 17 // the number is first subtracted from MaxUint64 and then all the leading 0xff bytes 18 // are trimmed and replaced by the number of such trimmed bytes. This helps in reducing the size. 19 // In the byte order comparison this encoding ensures that EncodeReverseOrderVarUint64(A) > EncodeReverseOrderVarUint64(B), 20 // If B > A 21 func EncodeReverseOrderVarUint64(number uint64) []byte { 22 bytes := make([]byte, 8) 23 binary.BigEndian.PutUint64(bytes, math.MaxUint64-number) 24 numFFBytes := 0 25 for _, b := range bytes { 26 if b != 0xff { 27 break 28 } 29 numFFBytes++ 30 } 31 size := 8 - numFFBytes 32 encodedBytes := make([]byte, size+1) 33 encodedBytes[0] = proto.EncodeVarint(uint64(numFFBytes))[0] 34 copy(encodedBytes[1:], bytes[numFFBytes:]) 35 return encodedBytes 36 } 37 38 // DecodeReverseOrderVarUint64 decodes the number from the bytes obtained from function 'EncodeReverseOrderVarUint64'. 39 // Also, returns the number of bytes that are consumed in the process 40 func DecodeReverseOrderVarUint64(bytes []byte) (uint64, int) { 41 s, _ := proto.DecodeVarint(bytes) 42 numFFBytes := int(s) 43 decodedBytes := make([]byte, 8) 44 realBytesNum := 8 - numFFBytes 45 copy(decodedBytes[numFFBytes:], bytes[1:realBytesNum+1]) 46 numBytesConsumed := realBytesNum + 1 47 for i := 0; i < numFFBytes; i++ { 48 decodedBytes[i] = 0xff 49 } 50 return (math.MaxUint64 - binary.BigEndian.Uint64(decodedBytes)), numBytesConsumed 51 }