mirror of
https://github.com/restic/restic.git
synced 2025-12-08 06:09:56 +00:00
index: add sub and intersect method to AssociatedSet
This commit is contained in:
parent
7e80536a9b
commit
0f05277b47
2 changed files with 112 additions and 0 deletions
|
|
@ -108,6 +108,40 @@ func (a *AssociatedSet[T]) Delete(bh restic.BlobHandle) {
|
|||
}
|
||||
}
|
||||
|
||||
type haser interface {
|
||||
Has(bh restic.BlobHandle) bool
|
||||
}
|
||||
|
||||
// Intersect returns a new set containing the handles that are present in both sets.
|
||||
func (a *AssociatedSet[T]) Intersect(other haser) *AssociatedSet[T] {
|
||||
result := NewAssociatedSet[T](a.idx)
|
||||
// Determining the smaller set already requires iterating over all keys
|
||||
// and thus provides no performance benefit.
|
||||
for bh := range a.Keys() {
|
||||
if other.Has(bh) {
|
||||
// preserve value receiver
|
||||
val, _ := a.Get(bh)
|
||||
result.Set(bh, val)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Sub returns a new set containing all handles that are present in a but not in
|
||||
// other.
|
||||
func (a *AssociatedSet[T]) Sub(other haser) *AssociatedSet[T] {
|
||||
result := NewAssociatedSet[T](a.idx)
|
||||
for bh := range a.Keys() {
|
||||
if !other.Has(bh) {
|
||||
val, _ := a.Get(bh)
|
||||
result.Set(bh, val)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (a *AssociatedSet[T]) Len() int {
|
||||
count := 0
|
||||
for range a.All() {
|
||||
|
|
|
|||
|
|
@ -157,3 +157,81 @@ func TestAssociatedSetWithExtendedIndex(t *testing.T) {
|
|||
test.Equals(t, list(bs), restic.BlobHandles(nil))
|
||||
test.Equals(t, 0, len(bs.overflow))
|
||||
}
|
||||
|
||||
func TestAssociatedSetIntersectAndSub(t *testing.T) {
|
||||
mi := NewMasterIndex()
|
||||
saver := &noopSaver{}
|
||||
|
||||
bh1, blob1 := makeFakePackedBlob()
|
||||
bh2, blob2 := makeFakePackedBlob()
|
||||
bh3, blob3 := makeFakePackedBlob()
|
||||
bh4, blob4 := makeFakePackedBlob()
|
||||
|
||||
test.OK(t, mi.StorePack(context.TODO(), blob1.PackID, []restic.Blob{blob1.Blob}, saver))
|
||||
test.OK(t, mi.StorePack(context.TODO(), blob2.PackID, []restic.Blob{blob2.Blob}, saver))
|
||||
test.OK(t, mi.StorePack(context.TODO(), blob3.PackID, []restic.Blob{blob3.Blob}, saver))
|
||||
test.OK(t, mi.StorePack(context.TODO(), blob4.PackID, []restic.Blob{blob4.Blob}, saver))
|
||||
test.OK(t, mi.Flush(context.TODO(), saver))
|
||||
|
||||
t.Run("Intersect", func(t *testing.T) {
|
||||
bs1, bs2 := NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
test.Equals(t, bs1.Intersect(bs2).Len(), 0)
|
||||
|
||||
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
bs1.Set(bh1, 10)
|
||||
bs2.Set(bh2, 20)
|
||||
test.Equals(t, bs1.Intersect(bs2).Len(), 0)
|
||||
|
||||
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
bs1.Set(bh3, 40)
|
||||
bs2.Set(bh3, 50)
|
||||
bs2.Set(bh4, 60)
|
||||
result := bs1.Intersect(bs2)
|
||||
test.Equals(t, result.Len(), 1)
|
||||
val, _ := result.Get(bh3)
|
||||
test.Equals(t, uint8(40), val)
|
||||
|
||||
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
bs1.Set(bh3, 40)
|
||||
bs1.Set(bh4, 70)
|
||||
bs2.Set(bh3, 50)
|
||||
bs2.Set(bh4, 60)
|
||||
result = bs1.Intersect(bs2)
|
||||
test.Equals(t, result.Len(), 2)
|
||||
val, _ = result.Get(bh3)
|
||||
test.Equals(t, uint8(40), val)
|
||||
val, _ = result.Get(bh4)
|
||||
test.Equals(t, uint8(70), val)
|
||||
})
|
||||
|
||||
t.Run("Sub", func(t *testing.T) {
|
||||
bs1, bs2 := NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
test.Equals(t, bs1.Sub(bs2).Len(), 0)
|
||||
|
||||
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
bs1.Set(bh1, 10)
|
||||
bs1.Set(bh2, 20)
|
||||
bs2.Set(bh3, 30)
|
||||
result := bs1.Sub(bs2)
|
||||
test.Equals(t, result.Len(), 2)
|
||||
val, _ := result.Get(bh1)
|
||||
test.Equals(t, uint8(10), val)
|
||||
val, _ = result.Get(bh2)
|
||||
test.Equals(t, uint8(20), val)
|
||||
|
||||
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
bs1.Set(bh1, 10)
|
||||
bs1.Set(bh2, 20)
|
||||
bs1.Set(bh3, 40)
|
||||
bs2.Set(bh2, 50)
|
||||
result = bs1.Sub(bs2)
|
||||
test.Equals(t, result.Len(), 2)
|
||||
test.Assert(t, result.Has(bh1) && result.Has(bh3) && !result.Has(bh2), "only bh1 and bh3 should be in result")
|
||||
|
||||
bs1, bs2 = NewAssociatedSet[uint8](mi), NewAssociatedSet[uint8](mi)
|
||||
bs1.Set(bh1, 60)
|
||||
bs2.Set(bh1, 70)
|
||||
bs2.Set(bh2, 80)
|
||||
test.Equals(t, bs1.Sub(bs2).Len(), 0)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue