package stmutil import ( "unsafe" "github.com/benbjohnson/immutable" "golang.org/x/exp/constraints" "github.com/anacrolix/missinggo/v2/iter" ) type Settish[K constraints.Ordered] interface { Add(K) Settish[K] Delete(K) Settish[K] Contains(K) bool Range(func(K) bool) iter.Iterable Len() int } type mapToSet[K constraints.Ordered, V any] struct { m Mappish[K, V] } type interhash[K constraints.Ordered] struct{} func (interhash[K]) Hash(x K) uint32 { return uint32(nilinterhash(unsafe.Pointer(&x), 0)) } func (interhash[K]) Equal(i, j K) bool { return i == j } func NewSet[K constraints.Ordered]() Settish[K] { return mapToSet[K, struct{}]{NewMap[K, struct{}]()} } func NewSortedSet[K constraints.Ordered, V any](lesser lessFunc[K]) Settish[K] { return mapToSet[K, V]{NewSortedMap[K, V](lesser)} } func (s mapToSet[K, V]) Add(x K) Settish[K] { var v V s.m = s.m.Set(x, v) return s } func (s mapToSet[K, V]) Delete(x K) Settish[K] { s.m = s.m.Delete(x) return s } func (s mapToSet[K, V]) Len() int { return s.m.Len() } func (s mapToSet[K, V]) Contains(x K) bool { _, ok := s.m.Get(x) return ok } func (s mapToSet[K, V]) Range(f func(K) bool) { s.m.Range(func(k K, _ V) bool { return f(k) }) } func (s mapToSet[K, V]) Iter(cb iter.Callback) { s.Range(func(k K) bool { return cb(k) }) } type Map[K constraints.Ordered, V any] struct { *immutable.Map[K, V] } func NewMap[K constraints.Ordered, V any]() Mappish[K, V] { return Map[K, V]{immutable.NewMap[K, V](interhash[K]{})} } func (m Map[K, V]) Delete(x K) Mappish[K, V] { m.Map = m.Map.Delete(x) return m } func (m Map[K, V]) Set(key K, value V) Mappish[K, V] { m.Map = m.Map.Set(key, value) return m } func (sm Map[K, V]) Range(f func(K, V) bool) { iter := sm.Map.Iterator() for { k, v, ok := iter.Next() if !ok { break } if !f(k, v) { return } } } func (sm Map[K, V]) Iter(cb iter.Callback) { sm.Range(func(key K, _ V) bool { return cb(key) }) } type SortedMap[K constraints.Ordered, V any] struct { *immutable.SortedMap[K, V] } func (sm SortedMap[K, V]) Set(key K, value V) Mappish[K, V] { sm.SortedMap = sm.SortedMap.Set(key, value) return sm } func (sm SortedMap[K, V]) Delete(key K) Mappish[K, V] { sm.SortedMap = sm.SortedMap.Delete(key) return sm } func (sm SortedMap[K, V]) Range(f func(key K, value V) bool) { iter := sm.SortedMap.Iterator() for { k, v, ok := iter.Next() if !ok { break } if !f(k, v) { return } } } func (sm SortedMap[K, V]) Iter(cb iter.Callback) { sm.Range(func(key K, _ V) bool { return cb(key) }) } type lessFunc[T constraints.Ordered] func(l, r T) bool type comparer[K constraints.Ordered] struct { less lessFunc[K] } func (me comparer[K]) Compare(i, j K) int { if me.less(i, j) { return -1 } else if me.less(j, i) { return 1 } else { return 0 } } func NewSortedMap[K constraints.Ordered, V any](less lessFunc[K]) Mappish[K, V] { return SortedMap[K, V]{ SortedMap: immutable.NewSortedMap[K, V](comparer[K]{less}), } } type Mappish[K, V any] interface { Set(K, V) Mappish[K, V] Delete(key K) Mappish[K, V] Get(key K) (V, bool) Range(func(K, V) bool) Len() int iter.Iterable } func GetLeft(l, _ any) any { return l } //go:noescape //go:linkname nilinterhash runtime.nilinterhash func nilinterhash(p unsafe.Pointer, h uintptr) uintptr func interfaceHash(x any) uint32 { return uint32(nilinterhash(unsafe.Pointer(&x), 0)) } type Lenner interface { Len() int }