1package dependency 2 3import ( 4 "strings" 5 "sync" 6) 7 8// Set is a dependency-specific set implementation. Relative ordering is 9// preserved. 10type Set struct { 11 once sync.Once 12 sync.RWMutex 13 list []string 14 set map[string]Dependency 15} 16 17// Add adds a new element to the set if it does not already exist. 18func (s *Set) Add(d Dependency) bool { 19 s.init() 20 s.Lock() 21 defer s.Unlock() 22 if _, ok := s.set[d.String()]; !ok { 23 s.list = append(s.list, d.String()) 24 s.set[d.String()] = d 25 return true 26 } 27 return false 28} 29 30// Get retrieves a single element from the set by name. 31func (s *Set) Get(v string) Dependency { 32 s.RLock() 33 defer s.RUnlock() 34 return s.set[v] 35} 36 37// List returns the insertion-ordered list of dependencies. 38func (s *Set) List() []Dependency { 39 s.RLock() 40 defer s.RUnlock() 41 r := make([]Dependency, len(s.list)) 42 for i, k := range s.list { 43 r[i] = s.set[k] 44 } 45 return r 46} 47 48// Len is the size of the set. 49func (s *Set) Len() int { 50 s.RLock() 51 defer s.RUnlock() 52 return len(s.list) 53} 54 55// String is a string representation of the set. 56func (s *Set) String() string { 57 s.RLock() 58 defer s.RUnlock() 59 return strings.Join(s.list, ", ") 60} 61 62func (s *Set) init() { 63 s.once.Do(func() { 64 if s.list == nil { 65 s.list = make([]string, 0, 8) 66 } 67 68 if s.set == nil { 69 s.set = make(map[string]Dependency) 70 } 71 }) 72} 73