diff options
author | Matt Joiner <anacrolix@gmail.com> | 2019-11-01 12:23:59 +1100 |
---|---|---|
committer | Matt Joiner <anacrolix@gmail.com> | 2019-11-01 12:23:59 +1100 |
commit | 52e150e44234b631f8a9b2de11862434046b4992 (patch) | |
tree | b57bdf74630b62e2c2dfebe45569cc7da94838be /stmutil/containers.go | |
parent | Optimize a bunch of stuff (diff) | |
download | stm-52e150e44234b631f8a9b2de11862434046b4992.tar.gz stm-52e150e44234b631f8a9b2de11862434046b4992.tar.xz |
Add stmutil containers and ContextDoneVar
Diffstat (limited to 'stmutil/containers.go')
-rw-r--r-- | stmutil/containers.go | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/stmutil/containers.go b/stmutil/containers.go new file mode 100644 index 0000000..89f7b05 --- /dev/null +++ b/stmutil/containers.go @@ -0,0 +1,180 @@ +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 +} |