go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/common/cl.go (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package common 16 17 import ( 18 "sort" 19 ) 20 21 // CLID is a unique ID of a CL used internally in CV. 22 // 23 // It's just 8 bytes long and is thus much shorter than ExternalID, 24 // which reduces CPU & RAM & storage costs of CL graphs for multi-CL Runs. 25 type CLID int64 26 27 // CLIDsAsInt64s returns proto representation of CLIDs. 28 func CLIDsAsInt64s(ids []CLID) []int64 { 29 r := make([]int64, len(ids)) 30 for i, id := range ids { 31 r[i] = int64(id) 32 } 33 return r 34 } 35 36 // CLIDs is a convenience type to facilitate handling of a slice of CLID. 37 type CLIDs []CLID 38 39 // Dedupe removes duplicates in place and sorts the slice. 40 // 41 // Note: Does not preserve original order. 42 func (p *CLIDs) Dedupe() { 43 clids := *p 44 if len(clids) <= 1 { 45 return 46 } 47 sort.Sort(clids) 48 n, prev, skipped := 0, clids[0], false 49 for _, id := range clids[1:] { 50 if id == prev { 51 skipped = true 52 continue 53 } 54 n++ 55 if skipped { 56 clids[n] = id 57 } 58 prev = id 59 } 60 *p = clids[:n+1] 61 } 62 63 // Len is the number of elements in the collection. 64 func (ids CLIDs) Len() int { 65 return len(ids) 66 } 67 68 // Less reports whether the element with 69 // index i should sort before the element with index j. 70 func (ids CLIDs) Less(i int, j int) bool { 71 return ids[i] < ids[j] 72 } 73 74 // Swap swaps the elements with indexes i and j. 75 func (ids CLIDs) Swap(i int, j int) { 76 ids[i], ids[j] = ids[j], ids[i] 77 } 78 79 // Set returns a new set of CLIDs. 80 func (ids CLIDs) Set() CLIDsSet { 81 if len(ids) == 0 { 82 return nil 83 } 84 ret := make(CLIDsSet, len(ids)) 85 for _, id := range ids { 86 ret.Add(id) 87 } 88 return ret 89 } 90 91 // Contains returns true if CLID is inside these CLIDs. 92 func (ids CLIDs) Contains(id CLID) bool { 93 for _, x := range ids { 94 if x == id { 95 return true 96 } 97 } 98 return false 99 } 100 101 // MakeCLIDs returns CLIDs from list of clids in int64. 102 func MakeCLIDs(ids ...int64) CLIDs { 103 if ids == nil { 104 return nil 105 } 106 ret := make(CLIDs, len(ids)) 107 for i, id := range ids { 108 ret[i] = CLID(id) 109 } 110 return ret 111 } 112 113 // CLIDsSet is convenience type to reduce the boilerplate. 114 type CLIDsSet map[CLID]struct{} 115 116 // MakeCLIDsSet returns new CLIDsSet from list of clids in int64. 117 func MakeCLIDsSet(ids ...int64) CLIDsSet { 118 if len(ids) == 0 { 119 return nil 120 } 121 ret := make(CLIDsSet, len(ids)) 122 for _, id := range ids { 123 ret.AddI64(id) 124 } 125 return ret 126 } 127 128 // Reset resets the set to contain just the given IDs. 129 func (s CLIDsSet) Reset(ids ...CLID) { 130 for id := range s { 131 delete(s, CLID(id)) 132 } 133 for _, id := range ids { 134 s.Add(id) 135 } 136 } 137 func (s CLIDsSet) Add(clid CLID) { 138 s[clid] = struct{}{} 139 } 140 func (s CLIDsSet) Has(clid CLID) bool { 141 _, exists := s[clid] 142 return exists 143 } 144 func (s CLIDsSet) Del(id CLID) { 145 delete(s, id) 146 } 147 func (s CLIDsSet) DelAll(ids CLIDs) { 148 for _, id := range ids { 149 s.Del(id) 150 } 151 } 152 153 func (s CLIDsSet) ToCLIDs() CLIDs { 154 ret := make(CLIDs, 0, len(s)) 155 for id := range s { 156 ret = append(ret, id) 157 } 158 return ret 159 } 160 161 func (s CLIDsSet) AddI64(id int64) { s.Add(CLID(id)) } 162 func (s CLIDsSet) HasI64(id int64) bool { return s.Has(CLID(id)) } 163 func (s CLIDsSet) DelI64(id int64) { s.Del(CLID(id)) } 164 func (s CLIDsSet) ResetI64(ids ...int64) { 165 for id := range s { 166 delete(s, CLID(id)) 167 } 168 for _, id := range ids { 169 s.AddI64(id) 170 } 171 }