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