diff --git a/fn/go.mod b/fn/go.mod index b199b1e2c..4d1528efe 100644 --- a/fn/go.mod +++ b/fn/go.mod @@ -2,4 +2,7 @@ module github.com/lightningnetwork/lnd/fn go 1.19 -require github.com/lightninglabs/neutrino/cache v1.1.2 +require ( + github.com/lightninglabs/neutrino/cache v1.1.2 + golang.org/x/exp v0.0.0-20231226003508-02704c960a9b +) diff --git a/fn/go.sum b/fn/go.sum index 3c118d23a..d066b9820 100644 --- a/fn/go.sum +++ b/fn/go.sum @@ -3,4 +3,6 @@ github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3 github.com/lightninglabs/neutrino/cache v1.1.2/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4= +golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/fn/set.go b/fn/set.go new file mode 100644 index 000000000..51368b210 --- /dev/null +++ b/fn/set.go @@ -0,0 +1,95 @@ +package fn + +import "golang.org/x/exp/maps" + +// Set is a generic set using type params that supports the following +// operations: diff, union, intersection, and subset. +type Set[T comparable] map[T]struct{} + +// NewSet returns a new set with the given elements. +func NewSet[T comparable](elems ...T) Set[T] { + s := make(Set[T]) + for _, e := range elems { + s.Add(e) + } + return s +} + +// Add adds an element to the set. +func (s Set[T]) Add(e T) { + s[e] = struct{}{} +} + +// Remove removes an element from the set. +func (s Set[T]) Remove(e T) { + delete(s, e) +} + +// Contains returns true if the set contains the element. +func (s Set[T]) Contains(e T) bool { + _, ok := s[e] + return ok +} + +// Diff returns the difference between two sets. +func (s Set[T]) Diff(other Set[T]) Set[T] { + diff := make(Set[T]) + for e := range s { + if !other.Contains(e) { + diff.Add(e) + } + } + return diff +} + +// Union returns the union of two sets. +func (s Set[T]) Union(other Set[T]) Set[T] { + union := make(Set[T]) + for e := range s { + union.Add(e) + } + for e := range other { + union.Add(e) + } + return union +} + +// Intersect returns the intersection of two sets. +func (s Set[T]) Intersect(other Set[T]) Set[T] { + intersect := make(Set[T]) + for e := range s { + if other.Contains(e) { + intersect.Add(e) + } + } + return intersect +} + +// Subset returns true if the set is a subset of the other set. +func (s Set[T]) Subset(other Set[T]) bool { + for e := range s { + if !other.Contains(e) { + return false + } + } + return true +} + +// Equal returns true if the set is equal to the other set. +func (s Set[T]) Equal(other Set[T]) bool { + return s.Subset(other) && other.Subset(s) +} + +// ToSlice returns the set as a slice. +func (s Set[T]) ToSlice() []T { + return maps.Keys(s) +} + +// SetDiff returns all the items that are in the first set but not in the +// second. +func SetDiff[T comparable](a, b []T) []T { + setA := NewSet(a...) + setB := NewSet(b...) + + return setA.Diff(setB).ToSlice() +}