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 }