github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/flow/identifier_order.go (about)

     1  package flow
     2  
     3  import (
     4  	"bytes"
     5  )
     6  
     7  // IdentifierCanonical is a function that defines a weak strict ordering "<" for identifiers.
     8  // It returns:
     9  //   - a strict negative number if id1 < id2
    10  //   - a strict positive number if id2 < id1
    11  //   - zero if id1 and id2 are equal
    12  //
    13  // By definition, two Identifiers (id1, id2) are in canonical order if id1 is lexicographically
    14  // _strictly_ smaller than id2. The strictness is important, meaning that duplicates do not
    15  // satisfy canonical ordering (order is irreflexive). Hence, only a returned strictly negative
    16  // value means the pair is in canonical order.
    17  // Use `IsIdentifierCanonical` for canonical order checks.
    18  //
    19  // The current function is based on the identifiers bytes lexicographic comparison.
    20  // Example:
    21  //
    22  //	IdentifierCanonical(Identifier{1}, Identifier{2}) // -1
    23  //	IdentifierCanonical(Identifier{2}, Identifier{1}) // 1
    24  //	IdentifierCanonical(Identifier{1}, Identifier{1}) // 0
    25  //	IdentifierCanonical(Identifier{0, 1}, Identifier{0, 2}) // -1
    26  func IdentifierCanonical(id1 Identifier, id2 Identifier) int {
    27  	return bytes.Compare(id1[:], id2[:])
    28  }
    29  
    30  // IsIdentifierCanonical returns true if and only if the given identifiers are in canonical order.
    31  //
    32  // By convention, two identifiers (i1, i2) are in canonical order if i1's bytes
    33  // are lexicographically _strictly_ smaller than i2's bytes.
    34  //
    35  // The strictness is important, meaning that the canonical order
    36  // is irreflexive ((i,i) isn't in canonical order).
    37  func IsIdentifierCanonical(i1, i2 Identifier) bool {
    38  	return IdentifierCanonical(i1, i2) < 0
    39  }
    40  
    41  // IsIdentifierListCanonical returns true if and only if the given list is
    42  // _strictly_ sorted with regards to the canonical order.
    43  //
    44  // The strictness is important here, meaning that a list with 2 equal identifiers
    45  // isn't considered well sorted.
    46  func IsIdentifierListCanonical(il IdentifierList) bool {
    47  	for i := 0; i < len(il)-1; i++ {
    48  		if !IsIdentifierCanonical(il[i], il[i+1]) {
    49  			return false
    50  		}
    51  	}
    52  	return true
    53  }