github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/utils/dbutil/compactdb/keys.go (about)

     1  package compactdb
     2  
     3  import (
     4  	"bytes"
     5  	"math/big"
     6  
     7  	"github.com/unicornultrafoundation/go-u2u/common"
     8  
     9  	"github.com/unicornultrafoundation/go-helios/u2udb"
    10  	"github.com/unicornultrafoundation/go-helios/u2udb/table"
    11  )
    12  
    13  func isEmptyDB(db u2udb.Iteratee) bool {
    14  	it := db.NewIterator(nil, nil)
    15  	defer it.Release()
    16  	return !it.Next()
    17  }
    18  
    19  func firstKey(db u2udb.Store) []byte {
    20  	it := db.NewIterator(nil, nil)
    21  	defer it.Release()
    22  	if !it.Next() {
    23  		return nil
    24  	}
    25  	return common.CopyBytes(it.Key())
    26  }
    27  
    28  func lastKey(db u2udb.Store) []byte {
    29  	var start []byte
    30  	for {
    31  		for b := 0xff; b >= 0; b-- {
    32  			if !isEmptyDB(table.New(db, append(start, byte(b)))) {
    33  				start = append(start, byte(b))
    34  				break
    35  			}
    36  			if b == 0 {
    37  				return start
    38  			}
    39  		}
    40  	}
    41  }
    42  
    43  func keysRange(db u2udb.Store) ([]byte, []byte, *big.Int) {
    44  	first := firstKey(db)
    45  	if first == nil {
    46  		return nil, nil, big.NewInt(0)
    47  	}
    48  	last := lastKey(db)
    49  	if last == nil {
    50  		return nil, nil, big.NewInt(0)
    51  	}
    52  	keySize := len(last)
    53  	if keySize < len(first) {
    54  		keySize = len(first)
    55  	}
    56  	first = common.RightPadBytes(first, keySize)
    57  	last = common.RightPadBytes(last, keySize)
    58  	firstBn := new(big.Int).SetBytes(first)
    59  	lastBn := new(big.Int).SetBytes(last)
    60  	return first, last, new(big.Int).Sub(lastBn, firstBn)
    61  }
    62  
    63  func addToKey(prefix *big.Int, diff *big.Int, size int) []byte {
    64  	endBn := new(big.Int).Set(prefix)
    65  	endBn.Add(endBn, diff)
    66  	if len(endBn.Bytes()) > size {
    67  		// overflow
    68  		return bytes.Repeat([]byte{0xff}, size)
    69  	}
    70  	end := endBn.Bytes()
    71  	res := make([]byte, size-len(end), size)
    72  	return append(res, end...)
    73  }
    74  
    75  // trimAfterDiff erases all bytes after first *maxDiff* differences between *a* and *b*
    76  func trimAfterDiff(a, b []byte, maxDiff int) ([]byte, []byte) {
    77  	size := len(a)
    78  	if size > len(b) {
    79  		size = len(b)
    80  	}
    81  	for i := 0; i < size; i++ {
    82  		if a[i] != b[i] {
    83  			maxDiff--
    84  			if maxDiff <= 0 {
    85  				size = i + 1
    86  				break
    87  			}
    88  		}
    89  	}
    90  	if len(a) > size {
    91  		a = a[:size]
    92  	}
    93  	if len(b) > size {
    94  		b = b[:size]
    95  	}
    96  	return a, b
    97  }