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 }