package restic import ( "fmt" "sort" "strings" ) // BlobSet is a set of blobs. type BlobSet map[BlobHandle]struct{} // NewBlobSet returns a new BlobSet, populated with ids. func NewBlobSet(handles ...BlobHandle) BlobSet { m := make(BlobSet) for _, h := range handles { m[h] = struct{}{} } return m } // Has returns true iff id is contained in the set. func (s BlobSet) Has(h BlobHandle) bool { _, ok := s[h] return ok } // Insert adds id to the set. func (s BlobSet) Insert(h BlobHandle) { s[h] = struct{}{} } // Delete removes id from the set. func (s BlobSet) Delete(h BlobHandle) { delete(s, h) } func (s BlobSet) Len() int { return len(s) } // Equals returns true iff s equals other. func (s BlobSet) Equals(other BlobSet) bool { if len(s) != len(other) { return false } for h := range s { if _, ok := other[h]; !ok { return false } } return true } // Merge adds the blobs in other to the current set. func (s BlobSet) Merge(other BlobSet) { for h := range other { s.Insert(h) } } // Intersect returns a new set containing the handles that are present in both sets. func (s BlobSet) Intersect(other BlobSet) (result BlobSet) { result = NewBlobSet() set1 := s set2 := other // iterate over the smaller set if len(set2) < len(set1) { set1, set2 = set2, set1 } for h := range set1 { if set2.Has(h) { result.Insert(h) } } return result } // Sub returns a new set containing all handles that are present in s but not in // other. func (s BlobSet) Sub(other BlobSet) (result BlobSet) { result = NewBlobSet() for h := range s { if !other.Has(h) { result.Insert(h) } } return result } // List returns a sorted slice of all BlobHandle in the set. func (s BlobSet) List() BlobHandles { list := make(BlobHandles, 0, len(s)) for h := range s { list = append(list, h) } sort.Sort(list) return list } // String produces a human-readable representation of ids. // It is meant for producing error messages, // so it only returns a summary if ids is long. func (s BlobSet) String() string { const maxelems = 10 sb := new(strings.Builder) sb.WriteByte('{') n := 0 for k := range s { if n != 0 { sb.WriteByte(' ') } sb.WriteString(k.String()) if n++; n == maxelems { fmt.Fprintf(sb, " (%d more)", len(s)-n-1) break } } sb.WriteByte('}') return sb.String() }