github.com/MetalBlockchain/metalgo@v1.11.9/utils/sorting.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package utils
     5  
     6  import (
     7  	"bytes"
     8  	"cmp"
     9  	"slices"
    10  
    11  	"github.com/MetalBlockchain/metalgo/utils/hashing"
    12  )
    13  
    14  // TODO can we handle sorting where the Compare function relies on a codec?
    15  
    16  type Sortable[T any] interface {
    17  	Compare(T) int
    18  }
    19  
    20  // Sorts the elements of [s].
    21  func Sort[T Sortable[T]](s []T) {
    22  	slices.SortFunc(s, T.Compare)
    23  }
    24  
    25  // Sorts the elements of [s] based on their hashes.
    26  func SortByHash[T ~[]byte](s []T) {
    27  	slices.SortFunc(s, func(i, j T) int {
    28  		iHash := hashing.ComputeHash256(i)
    29  		jHash := hashing.ComputeHash256(j)
    30  		return bytes.Compare(iHash, jHash)
    31  	})
    32  }
    33  
    34  // Returns true iff the elements in [s] are sorted.
    35  func IsSortedBytes[T ~[]byte](s []T) bool {
    36  	for i := 0; i < len(s)-1; i++ {
    37  		if bytes.Compare(s[i], s[i+1]) == 1 {
    38  			return false
    39  		}
    40  	}
    41  	return true
    42  }
    43  
    44  // Returns true iff the elements in [s] are unique and sorted.
    45  func IsSortedAndUnique[T Sortable[T]](s []T) bool {
    46  	for i := 0; i < len(s)-1; i++ {
    47  		if s[i].Compare(s[i+1]) >= 0 {
    48  			return false
    49  		}
    50  	}
    51  	return true
    52  }
    53  
    54  // Returns true iff the elements in [s] are unique and sorted.
    55  func IsSortedAndUniqueOrdered[T cmp.Ordered](s []T) bool {
    56  	for i := 0; i < len(s)-1; i++ {
    57  		if s[i] >= s[i+1] {
    58  			return false
    59  		}
    60  	}
    61  	return true
    62  }
    63  
    64  // Returns true iff the elements in [s] are unique and sorted
    65  // based by their hashes.
    66  func IsSortedAndUniqueByHash[T ~[]byte](s []T) bool {
    67  	if len(s) <= 1 {
    68  		return true
    69  	}
    70  	rightHash := hashing.ComputeHash256(s[0])
    71  	for i := 1; i < len(s); i++ {
    72  		leftHash := rightHash
    73  		rightHash = hashing.ComputeHash256(s[i])
    74  		if bytes.Compare(leftHash, rightHash) != -1 {
    75  			return false
    76  		}
    77  	}
    78  	return true
    79  }