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  }