package immutable
import (
"fmt"
"math/bits"
"reflect"
"sort"
"strings"
"golang.org/x/exp/constraints"
)
type List [T comparable ] struct {
root listNode [T ]
origin int
size int
}
func NewList [T comparable ]() *List [T ] {
return &List [T ]{
root : &listLeafNode [T ]{},
}
}
func (l *List [T ]) clone () *List [T ] {
other := *l
return &other
}
func (l *List [T ]) Len () int {
return l .size
}
func (l *List [T ]) cap () int {
return 1 << (l .root .depth () * listNodeBits )
}
func (l *List [T ]) Get (index int ) T {
if index < 0 || index >= l .size {
panic (fmt .Sprintf ("immutable.List.Get: index %d out of bounds" , index ))
}
return l .root .get (l .origin + index )
}
func (l *List [T ]) Set (index int , value T ) *List [T ] {
return l .set (index , value , false )
}
func (l *List [T ]) set (index int , value T , mutable bool ) *List [T ] {
if index < 0 || index >= l .size {
panic (fmt .Sprintf ("immutable.List.Set: index %d out of bounds" , index ))
}
other := l
if !mutable {
other = l .clone ()
}
other .root = other .root .set (l .origin +index , value , mutable )
return other
}
func (l *List [T ]) Append (value T ) *List [T ] {
return l .append (value , false )
}
func (l *List [T ]) append (value T , mutable bool ) *List [T ] {
other := l
if !mutable {
other = l .clone ()
}
if other .size +other .origin >= l .cap () {
newRoot := &listBranchNode [T ]{d : other .root .depth () + 1 }
newRoot .children [0 ] = other .root
other .root = newRoot
}
other .size ++
other .root = other .root .set (other .origin +other .size -1 , value , mutable )
return other
}
func (l *List [T ]) Prepend (value T ) *List [T ] {
return l .prepend (value , false )
}
func (l *List [T ]) prepend (value T , mutable bool ) *List [T ] {
other := l
if !mutable {
other = l .clone ()
}
if other .origin == 0 {
newRoot := &listBranchNode [T ]{d : other .root .depth () + 1 }
newRoot .children [listNodeSize -1 ] = other .root
other .root = newRoot
other .origin += (listNodeSize - 1 ) << (other .root .depth () * listNodeBits )
}
other .size ++
other .origin --
other .root = other .root .set (other .origin , value , mutable )
return other
}
func (l *List [T ]) Slice (start , end int ) *List [T ] {
return l .slice (start , end , false )
}
func (l *List [T ]) slice (start , end int , mutable bool ) *List [T ] {
if start < 0 || start > l .size {
panic (fmt .Sprintf ("immutable.List.Slice: start index %d out of bounds" , start ))
} else if end < 0 || end > l .size {
panic (fmt .Sprintf ("immutable.List.Slice: end index %d out of bounds" , end ))
} else if start > end {
panic (fmt .Sprintf ("immutable.List.Slice: invalid slice index: [%d:%d]" , start , end ))
}
if start == 0 && end == l .size {
return l
}
other := l
if !mutable {
other = l .clone ()
}
other .origin = l .origin + start
other .size = end - start
for other .root .depth () > 1 {
i := (other .origin >> (other .root .depth () * listNodeBits )) & listNodeMask
j := ((other .origin + other .size - 1 ) >> (other .root .depth () * listNodeBits )) & listNodeMask
if i != j {
break
}
other .origin -= i << (other .root .depth () * listNodeBits )
other .root = other .root .(*listBranchNode [T ]).children [i ]
}
other .root = other .root .deleteBefore (other .origin , mutable )
other .root = other .root .deleteAfter (other .origin +other .size -1 , mutable )
return other
}
func (l *List [T ]) Iterator () *ListIterator [T ] {
itr := &ListIterator [T ]{list : l }
itr .First ()
return itr
}
type ListBuilder [T comparable ] struct {
list *List [T ]
}
func NewListBuilder [T comparable ]() *ListBuilder [T ] {
return &ListBuilder [T ]{list : NewList [T ]()}
}
func (b *ListBuilder [T ]) List () *List [T ] {
assert (b .list != nil , "immutable.ListBuilder.List(): duplicate call to fetch list" )
list := b .list
b .list = nil
return list
}
func (b *ListBuilder [T ]) Len () int {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
return b .list .Len ()
}
func (b *ListBuilder [T ]) Get (index int ) T {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
return b .list .Get (index )
}
func (b *ListBuilder [T ]) Set (index int , value T ) {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
b .list = b .list .set (index , value , true )
}
func (b *ListBuilder [T ]) Append (value T ) {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
b .list = b .list .append (value , true )
}
func (b *ListBuilder [T ]) Prepend (value T ) {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
b .list = b .list .prepend (value , true )
}
func (b *ListBuilder [T ]) Slice (start , end int ) {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
b .list = b .list .slice (start , end , true )
}
func (b *ListBuilder [T ]) Iterator () *ListIterator [T ] {
assert (b .list != nil , "immutable.ListBuilder: builder invalid after List() invocation" )
return b .list .Iterator ()
}
const (
listNodeBits = 5
listNodeSize = 1 << listNodeBits
listNodeMask = listNodeSize - 1
)
type listNode[T comparable ] interface {
depth() uint
get(index int ) T
set(index int , v T , mutable bool ) listNode [T ]
containsBefore(index int ) bool
containsAfter(index int ) bool
deleteBefore(index int , mutable bool ) listNode [T ]
deleteAfter(index int , mutable bool ) listNode [T ]
}
func newListNode[T comparable ](depth uint ) listNode [T ] {
if depth == 0 {
return &listLeafNode [T ]{}
}
return &listBranchNode [T ]{d : depth }
}
type listBranchNode[T comparable ] struct {
d uint
children [listNodeSize ]listNode [T ]
}
func (n *listBranchNode [T ]) depth () uint { return n .d }
func (n *listBranchNode [T ]) get (index int ) T {
idx := (index >> (n .d * listNodeBits )) & listNodeMask
return n .children [idx ].get (index )
}
func (n *listBranchNode [T ]) set (index int , v T , mutable bool ) listNode [T ] {
idx := (index >> (n .d * listNodeBits )) & listNodeMask
child := n .children [idx ]
if child == nil {
child = newListNode [T ](n .depth () - 1 )
}
var other *listBranchNode [T ]
if mutable {
other = n
} else {
tmp := *n
other = &tmp
}
other .children [idx ] = child .set (index , v , mutable )
return other
}
func (n *listBranchNode [T ]) containsBefore (index int ) bool {
idx := (index >> (n .d * listNodeBits )) & listNodeMask
for i := 0 ; i < idx ; i ++ {
if n .children [i ] != nil {
return true
}
}
if n .children [idx ] != nil && n .children [idx ].containsBefore (index ) {
return true
}
return false
}
func (n *listBranchNode [T ]) containsAfter (index int ) bool {
idx := (index >> (n .d * listNodeBits )) & listNodeMask
for i := idx + 1 ; i < len (n .children ); i ++ {
if n .children [i ] != nil {
return true
}
}
if n .children [idx ] != nil && n .children [idx ].containsAfter (index ) {
return true
}
return false
}
func (n *listBranchNode [T ]) deleteBefore (index int , mutable bool ) listNode [T ] {
if !n .containsBefore (index ) {
return n
}
idx := (index >> (n .d * listNodeBits )) & listNodeMask
var other *listBranchNode [T ]
if mutable {
other = n
for i := 0 ; i < idx ; i ++ {
n .children [i ] = nil
}
} else {
other = &listBranchNode [T ]{d : n .d }
copy (other .children [idx :][:], n .children [idx :][:])
}
if other .children [idx ] != nil {
other .children [idx ] = other .children [idx ].deleteBefore (index , mutable )
}
return other
}
func (n *listBranchNode [T ]) deleteAfter (index int , mutable bool ) listNode [T ] {
if !n .containsAfter (index ) {
return n
}
idx := (index >> (n .d * listNodeBits )) & listNodeMask
var other *listBranchNode [T ]
if mutable {
other = n
for i := idx + 1 ; i < len (n .children ); i ++ {
n .children [i ] = nil
}
} else {
other = &listBranchNode [T ]{d : n .d }
copy (other .children [:idx +1 ], n .children [:idx +1 ])
}
if other .children [idx ] != nil {
other .children [idx ] = other .children [idx ].deleteAfter (index , mutable )
}
return other
}
type listLeafNode[T comparable ] struct {
children [listNodeSize ]T
}
func (n *listLeafNode [T ]) depth () uint { return 0 }
func (n *listLeafNode [T ]) get (index int ) T {
return n .children [index &listNodeMask ]
}
func (n *listLeafNode [T ]) set (index int , v T , mutable bool ) listNode [T ] {
idx := index & listNodeMask
var other *listLeafNode [T ]
if mutable {
other = n
} else {
tmp := *n
other = &tmp
}
other .children [idx ] = v
var otherLN listNode [T ]
otherLN = other
return otherLN
}
func (n *listLeafNode [T ]) containsBefore (index int ) bool {
idx := index & listNodeMask
var empty T
for i := 0 ; i < idx ; i ++ {
if n .children [i ] != empty {
return true
}
}
return false
}
func (n *listLeafNode [T ]) containsAfter (index int ) bool {
idx := index & listNodeMask
var empty T
for i := idx + 1 ; i < len (n .children ); i ++ {
if n .children [i ] != empty {
return true
}
}
return false
}
func (n *listLeafNode [T ]) deleteBefore (index int , mutable bool ) listNode [T ] {
if !n .containsBefore (index ) {
return n
}
idx := index & listNodeMask
var other *listLeafNode [T ]
if mutable {
other = n
var empty T
for i := 0 ; i < idx ; i ++ {
other .children [i ] = empty
}
} else {
other = &listLeafNode [T ]{}
copy (other .children [idx :][:], n .children [idx :][:])
}
return other
}
func (n *listLeafNode [T ]) deleteAfter (index int , mutable bool ) listNode [T ] {
if !n .containsAfter (index ) {
return n
}
idx := index & listNodeMask
var other *listLeafNode [T ]
if mutable {
other = n
var empty T
for i := idx + 1 ; i < len (n .children ); i ++ {
other .children [i ] = empty
}
} else {
other = &listLeafNode [T ]{}
copy (other .children [:idx +1 ][:], n .children [:idx +1 ][:])
}
return other
}
type ListIterator [T comparable ] struct {
list *List [T ]
index int
stack [32 ]listIteratorElem [T ]
depth int
}
func (itr *ListIterator [T ]) Done () bool {
return itr .index < 0 || itr .index >= itr .list .Len ()
}
func (itr *ListIterator [T ]) First () {
if itr .list .Len () != 0 {
itr .Seek (0 )
}
}
func (itr *ListIterator [T ]) Last () {
if n := itr .list .Len (); n != 0 {
itr .Seek (n - 1 )
}
}
func (itr *ListIterator [T ]) Seek (index int ) {
if index < 0 || index >= itr .list .Len () {
panic (fmt .Sprintf ("immutable.ListIterator.Seek: index %d out of bounds" , index ))
}
itr .index = index
itr .stack [0 ] = listIteratorElem [T ]{node : itr .list .root }
itr .depth = 0
itr .seek (index )
}
func (itr *ListIterator [T ]) Next () (index int , value T ) {
var empty T
if itr .Done () {
return -1 , empty
}
elem := &itr .stack [itr .depth ]
index , value = itr .index , elem .node .(*listLeafNode [T ]).children [elem .index ]
itr .index ++
if itr .Done () {
return index , value
}
for ; itr .depth > 0 && itr .stack [itr .depth ].index >= listNodeSize -1 ; itr .depth -- {
}
itr .seek (itr .index )
return index , value
}
func (itr *ListIterator [T ]) Prev () (index int , value T ) {
var empty T
if itr .Done () {
return -1 , empty
}
elem := &itr .stack [itr .depth ]
index , value = itr .index , elem .node .(*listLeafNode [T ]).children [elem .index ]
itr .index --
if itr .Done () {
return index , value
}
for ; itr .depth > 0 && itr .stack [itr .depth ].index == 0 ; itr .depth -- {
}
itr .seek (itr .index )
return index , value
}
func (itr *ListIterator [T ]) seek (index int ) {
for {
elem := &itr .stack [itr .depth ]
elem .index = ((itr .list .origin + index ) >> (elem .node .depth () * listNodeBits )) & listNodeMask
switch node := elem .node .(type ) {
case *listBranchNode [T ]:
child := node .children [elem .index ]
itr .stack [itr .depth +1 ] = listIteratorElem [T ]{node : child }
itr .depth ++
case *listLeafNode [T ]:
return
}
}
}
type listIteratorElem[T comparable ] struct {
node listNode [T ]
index int
}
const (
maxArrayMapSize = 8
maxBitmapIndexedSize = 16
)
const (
mapNodeBits = 5
mapNodeSize = 1 << mapNodeBits
mapNodeMask = mapNodeSize - 1
)
type Map [K constraints .Ordered , V any ] struct {
size int
root mapNode [K , V ]
hasher Hasher [K ]
}
func NewMap [K constraints .Ordered , V any ](hasher Hasher [K ]) *Map [K , V ] {
return &Map [K , V ]{
hasher : hasher ,
}
}
func (m *Map [K , V ]) Len () int {
return m .size
}
func (m *Map [K , V ]) clone () *Map [K , V ] {
other := *m
return &other
}
func (m *Map [K , V ]) Get (key K ) (value V , ok bool ) {
var empty V
if m .root == nil {
return empty , false
}
keyHash := m .hasher .Hash (key )
return m .root .get (key , 0 , keyHash , m .hasher )
}
func (m *Map [K , V ]) Set (key K , value V ) *Map [K , V ] {
return m .set (key , value , false )
}
func (m *Map [K , V ]) set (key K , value V , mutable bool ) *Map [K , V ] {
hasher := m .hasher
if hasher == nil {
hasher = NewHasher (key )
}
other := m
if !mutable {
other = m .clone ()
}
other .hasher = hasher
if m .root == nil {
other .size = 1
other .root = &mapArrayNode [K , V ]{entries : []mapEntry [K , V ]{{key : key , value : value }}}
return other
}
var resized bool
other .root = m .root .set (key , value , 0 , hasher .Hash (key ), hasher , mutable , &resized )
if resized {
other .size ++
}
return other
}
func (m *Map [K , V ]) Delete (key K ) *Map [K , V ] {
return m .delete (key , false )
}
func (m *Map [K , V ]) delete (key K , mutable bool ) *Map [K , V ] {
if m .root == nil {
return m
}
var resized bool
newRoot := m .root .delete (key , 0 , m .hasher .Hash (key ), m .hasher , mutable , &resized )
if !resized {
return m
}
other := m
if !mutable {
other = m .clone ()
}
other .size = m .size - 1
other .root = newRoot
return other
}
func (m *Map [K , V ]) Iterator () *MapIterator [K , V ] {
itr := &MapIterator [K , V ]{m : m }
itr .First ()
return itr
}
type MapBuilder [K constraints .Ordered , V any ] struct {
m *Map [K , V ]
}
func NewMapBuilder [K constraints .Ordered , V any ](hasher Hasher [K ]) *MapBuilder [K , V ] {
return &MapBuilder [K , V ]{m : NewMap [K , V ](hasher )}
}
func (b *MapBuilder [K , V ]) Map () *Map [K , V ] {
assert (b .m != nil , "immutable.SortedMapBuilder.Map(): duplicate call to fetch map" )
m := b .m
b .m = nil
return m
}
func (b *MapBuilder [K , V ]) Len () int {
assert (b .m != nil , "immutable.MapBuilder: builder invalid after Map() invocation" )
return b .m .Len ()
}
func (b *MapBuilder [K , V ]) Get (key K ) (value V , ok bool ) {
assert (b .m != nil , "immutable.MapBuilder: builder invalid after Map() invocation" )
return b .m .Get (key )
}
func (b *MapBuilder [K , V ]) Set (key K , value V ) {
assert (b .m != nil , "immutable.MapBuilder: builder invalid after Map() invocation" )
b .m = b .m .set (key , value , true )
}
func (b *MapBuilder [K , V ]) Delete (key K ) {
assert (b .m != nil , "immutable.MapBuilder: builder invalid after Map() invocation" )
b .m = b .m .delete (key , true )
}
func (b *MapBuilder [K , V ]) Iterator () *MapIterator [K , V ] {
assert (b .m != nil , "immutable.MapBuilder: builder invalid after Map() invocation" )
return b .m .Iterator ()
}
type mapNode[K constraints .Ordered , V any ] interface {
get(key K , shift uint , keyHash uint32 , h Hasher [K ]) (value V , ok bool )
set(key K , value V , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ]
delete(key K , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ]
}
var _ mapNode [string , any ] = (*mapArrayNode [string , any ])(nil )
var _ mapNode [string , any ] = (*mapBitmapIndexedNode [string , any ])(nil )
var _ mapNode [string , any ] = (*mapHashArrayNode [string , any ])(nil )
var _ mapNode [string , any ] = (*mapValueNode [string , any ])(nil )
var _ mapNode [string , any ] = (*mapHashCollisionNode [string , any ])(nil )
type mapLeafNode[K constraints .Ordered , V any ] interface {
mapNode [K , V ]
keyHashValue() uint32
}
var _ mapLeafNode [string , any ] = (*mapValueNode [string , any ])(nil )
var _ mapLeafNode [string , any ] = (*mapHashCollisionNode [string , any ])(nil )
type mapArrayNode[K constraints .Ordered , V any ] struct {
entries []mapEntry [K , V ]
}
func (n *mapArrayNode [K , V ]) indexOf (key K , h Hasher [K ]) int {
for i := range n .entries {
if h .Equal (n .entries [i ].key , key ) {
return i
}
}
return -1
}
func (n *mapArrayNode [K , V ]) get (key K , shift uint , keyHash uint32 , h Hasher [K ]) (value V , ok bool ) {
i := n .indexOf (key , h )
if i == -1 {
return value , false
}
return n .entries [i ].value , true
}
func (n *mapArrayNode [K , V ]) set (key K , value V , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
idx := n .indexOf (key , h )
if idx == -1 {
*resized = true
}
if idx == -1 && len (n .entries ) >= maxArrayMapSize {
var node mapNode [K , V ] = newMapValueNode (h .Hash (key ), key , value )
for _ , entry := range n .entries {
node = node .set (entry .key , entry .value , 0 , h .Hash (entry .key ), h , false , resized )
}
return node
}
if mutable {
if idx != -1 {
n .entries [idx ] = mapEntry [K , V ]{key , value }
} else {
n .entries = append (n .entries , mapEntry [K , V ]{key , value })
}
return n
}
var other mapArrayNode [K , V ]
if idx != -1 {
other .entries = make ([]mapEntry [K , V ], len (n .entries ))
copy (other .entries , n .entries )
other .entries [idx ] = mapEntry [K , V ]{key , value }
} else {
other .entries = make ([]mapEntry [K , V ], len (n .entries )+1 )
copy (other .entries , n .entries )
other .entries [len (other .entries )-1 ] = mapEntry [K , V ]{key , value }
}
return &other
}
func (n *mapArrayNode [K , V ]) delete (key K , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
idx := n .indexOf (key , h )
if idx == -1 {
return n
}
*resized = true
if len (n .entries ) == 1 {
return nil
}
if mutable {
copy (n .entries [idx :], n .entries [idx +1 :])
n .entries [len (n .entries )-1 ] = mapEntry [K , V ]{}
n .entries = n .entries [:len (n .entries )-1 ]
return n
}
other := &mapArrayNode [K , V ]{entries : make ([]mapEntry [K , V ], len (n .entries )-1 )}
copy (other .entries [:idx ], n .entries [:idx ])
copy (other .entries [idx :], n .entries [idx +1 :])
return other
}
type mapBitmapIndexedNode[K constraints .Ordered , V any ] struct {
bitmap uint32
nodes []mapNode [K , V ]
}
func (n *mapBitmapIndexedNode [K , V ]) get (key K , shift uint , keyHash uint32 , h Hasher [K ]) (value V , ok bool ) {
bit := uint32 (1 ) << ((keyHash >> shift ) & mapNodeMask )
if (n .bitmap & bit ) == 0 {
return value , false
}
child := n .nodes [bits .OnesCount32 (n .bitmap &(bit -1 ))]
return child .get (key , shift +mapNodeBits , keyHash , h )
}
func (n *mapBitmapIndexedNode [K , V ]) set (key K , value V , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
keyHashFrag := (keyHash >> shift ) & mapNodeMask
bit := uint32 (1 ) << keyHashFrag
exists := (n .bitmap & bit ) != 0
if !exists {
*resized = true
}
idx := bits .OnesCount32 (n .bitmap & (bit - 1 ))
var newNode mapNode [K , V ]
if exists {
newNode = n .nodes [idx ].set (key , value , shift +mapNodeBits , keyHash , h , mutable , resized )
} else {
newNode = newMapValueNode [K , V ](keyHash , key , value )
}
if !exists && len (n .nodes ) > maxBitmapIndexedSize {
var other mapHashArrayNode [K , V ]
for i := uint (0 ); i < uint (len (other .nodes )); i ++ {
if n .bitmap &(uint32 (1 )<<i ) != 0 {
other .nodes [i ] = n .nodes [other .count ]
other .count ++
}
}
other .nodes [keyHashFrag ] = newNode
other .count ++
return &other
}
if mutable {
if exists {
n .nodes [idx ] = newNode
} else {
n .bitmap |= bit
n .nodes = append (n .nodes , nil )
copy (n .nodes [idx +1 :], n .nodes [idx :])
n .nodes [idx ] = newNode
}
return n
}
other := &mapBitmapIndexedNode [K , V ]{bitmap : n .bitmap | bit }
if exists {
other .nodes = make ([]mapNode [K , V ], len (n .nodes ))
copy (other .nodes , n .nodes )
other .nodes [idx ] = newNode
} else {
other .nodes = make ([]mapNode [K , V ], len (n .nodes )+1 )
copy (other .nodes , n .nodes [:idx ])
other .nodes [idx ] = newNode
copy (other .nodes [idx +1 :], n .nodes [idx :])
}
return other
}
func (n *mapBitmapIndexedNode [K , V ]) delete (key K , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
bit := uint32 (1 ) << ((keyHash >> shift ) & mapNodeMask )
if (n .bitmap & bit ) == 0 {
return n
}
idx := bits .OnesCount32 (n .bitmap & (bit - 1 ))
child := n .nodes [idx ]
newChild := child .delete (key , shift +mapNodeBits , keyHash , h , mutable , resized )
if !*resized {
return n
}
if newChild == nil {
if len (n .nodes ) == 1 {
return nil
}
if mutable {
n .bitmap ^= bit
copy (n .nodes [idx :], n .nodes [idx +1 :])
n .nodes [len (n .nodes )-1 ] = nil
n .nodes = n .nodes [:len (n .nodes )-1 ]
return n
}
other := &mapBitmapIndexedNode [K , V ]{bitmap : n .bitmap ^ bit , nodes : make ([]mapNode [K , V ], len (n .nodes )-1 )}
copy (other .nodes [:idx ], n .nodes [:idx ])
copy (other .nodes [idx :], n .nodes [idx +1 :])
return other
}
other := n
if !mutable {
other = &mapBitmapIndexedNode [K , V ]{bitmap : n .bitmap , nodes : make ([]mapNode [K , V ], len (n .nodes ))}
copy (other .nodes , n .nodes )
}
other .nodes [idx ] = newChild
return other
}
type mapHashArrayNode[K constraints .Ordered , V any ] struct {
count uint
nodes [mapNodeSize ]mapNode [K , V ]
}
func (n *mapHashArrayNode [K , V ]) clone () *mapHashArrayNode [K , V ] {
other := *n
return &other
}
func (n *mapHashArrayNode [K , V ]) get (key K , shift uint , keyHash uint32 , h Hasher [K ]) (value V , ok bool ) {
node := n .nodes [(keyHash >>shift )&mapNodeMask ]
if node == nil {
return value , false
}
return node .get (key , shift +mapNodeBits , keyHash , h )
}
func (n *mapHashArrayNode [K , V ]) set (key K , value V , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
idx := (keyHash >> shift ) & mapNodeMask
node := n .nodes [idx ]
var newNode mapNode [K , V ]
if node == nil {
*resized = true
newNode = newMapValueNode (keyHash , key , value )
} else {
newNode = node .set (key , value , shift +mapNodeBits , keyHash , h , mutable , resized )
}
other := n
if !mutable {
other = n .clone ()
}
if node == nil {
other .count ++
}
other .nodes [idx ] = newNode
return other
}
func (n *mapHashArrayNode [K , V ]) delete (key K , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
idx := (keyHash >> shift ) & mapNodeMask
node := n .nodes [idx ]
if node == nil {
return n
}
newNode := node .delete (key , shift +mapNodeBits , keyHash , h , mutable , resized )
if !*resized {
return n
}
if newNode == nil && n .count <= maxBitmapIndexedSize {
other := &mapBitmapIndexedNode [K , V ]{nodes : make ([]mapNode [K , V ], 0 , n .count -1 )}
for i , child := range n .nodes {
if child != nil && uint32 (i ) != idx {
other .bitmap |= 1 << uint (i )
other .nodes = append (other .nodes , child )
}
}
return other
}
other := n
if !mutable {
other = n .clone ()
}
other .nodes [idx ] = newNode
if newNode == nil {
other .count --
}
return other
}
type mapValueNode[K constraints .Ordered , V any ] struct {
keyHash uint32
key K
value V
}
func newMapValueNode[K constraints .Ordered , V any ](keyHash uint32 , key K , value V ) *mapValueNode [K , V ] {
return &mapValueNode [K , V ]{
keyHash : keyHash ,
key : key ,
value : value ,
}
}
func (n *mapValueNode [K , V ]) keyHashValue () uint32 {
return n .keyHash
}
func (n *mapValueNode [K , V ]) get (key K , shift uint , keyHash uint32 , h Hasher [K ]) (value V , ok bool ) {
if !h .Equal (n .key , key ) {
return value , false
}
return n .value , true
}
func (n *mapValueNode [K , V ]) set (key K , value V , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
if h .Equal (n .key , key ) {
if mutable {
n .value = value
return n
}
return newMapValueNode (n .keyHash , key , value )
}
*resized = true
if n .keyHash != keyHash {
return mergeIntoNode [K , V ](n , shift , keyHash , key , value )
}
return &mapHashCollisionNode [K , V ]{keyHash : keyHash , entries : []mapEntry [K , V ]{
{key : n .key , value : n .value },
{key : key , value : value },
}}
}
func (n *mapValueNode [K , V ]) delete (key K , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
if !h .Equal (n .key , key ) {
return n
}
*resized = true
return nil
}
type mapHashCollisionNode[K constraints .Ordered , V any ] struct {
keyHash uint32
entries []mapEntry [K , V ]
}
func (n *mapHashCollisionNode [K , V ]) keyHashValue () uint32 {
return n .keyHash
}
func (n *mapHashCollisionNode [K , V ]) indexOf (key K , h Hasher [K ]) int {
for i := range n .entries {
if h .Equal (n .entries [i ].key , key ) {
return i
}
}
return -1
}
func (n *mapHashCollisionNode [K , V ]) get (key K , shift uint , keyHash uint32 , h Hasher [K ]) (value V , ok bool ) {
for i := range n .entries {
if h .Equal (n .entries [i ].key , key ) {
return n .entries [i ].value , true
}
}
return value , false
}
func (n *mapHashCollisionNode [K , V ]) set (key K , value V , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
if n .keyHash != keyHash {
*resized = true
return mergeIntoNode [K , V ](n , shift , keyHash , key , value )
}
if mutable {
if idx := n .indexOf (key , h ); idx == -1 {
*resized = true
n .entries = append (n .entries , mapEntry [K , V ]{key , value })
} else {
n .entries [idx ] = mapEntry [K , V ]{key , value }
}
return n
}
other := &mapHashCollisionNode [K , V ]{keyHash : n .keyHash }
if idx := n .indexOf (key , h ); idx == -1 {
*resized = true
other .entries = make ([]mapEntry [K , V ], len (n .entries )+1 )
copy (other .entries , n .entries )
other .entries [len (other .entries )-1 ] = mapEntry [K , V ]{key , value }
} else {
other .entries = make ([]mapEntry [K , V ], len (n .entries ))
copy (other .entries , n .entries )
other .entries [idx ] = mapEntry [K , V ]{key , value }
}
return other
}
func (n *mapHashCollisionNode [K , V ]) delete (key K , shift uint , keyHash uint32 , h Hasher [K ], mutable bool , resized *bool ) mapNode [K , V ] {
idx := n .indexOf (key , h )
if idx == -1 {
return n
}
*resized = true
if len (n .entries ) == 2 {
return &mapValueNode [K , V ]{
keyHash : n .keyHash ,
key : n .entries [idx ^1 ].key ,
value : n .entries [idx ^1 ].value ,
}
}
if mutable {
copy (n .entries [idx :], n .entries [idx +1 :])
n .entries [len (n .entries )-1 ] = mapEntry [K , V ]{}
n .entries = n .entries [:len (n .entries )-1 ]
return n
}
other := &mapHashCollisionNode [K , V ]{keyHash : n .keyHash , entries : make ([]mapEntry [K , V ], len (n .entries )-1 )}
copy (other .entries [:idx ], n .entries [:idx ])
copy (other .entries [idx :], n .entries [idx +1 :])
return other
}
func mergeIntoNode[K constraints .Ordered , V any ](node mapLeafNode [K , V ], shift uint , keyHash uint32 , key K , value V ) mapNode [K , V ] {
idx1 := (node .keyHashValue () >> shift ) & mapNodeMask
idx2 := (keyHash >> shift ) & mapNodeMask
other := &mapBitmapIndexedNode [K , V ]{bitmap : (1 << idx1 ) | (1 << idx2 )}
if idx1 == idx2 {
other .nodes = []mapNode [K , V ]{mergeIntoNode (node , shift +mapNodeBits , keyHash , key , value )}
} else {
if newNode := newMapValueNode (keyHash , key , value ); idx1 < idx2 {
other .nodes = []mapNode [K , V ]{node , newNode }
} else {
other .nodes = []mapNode [K , V ]{newNode , node }
}
}
return other
}
type mapEntry[K constraints .Ordered , V any ] struct {
key K
value V
}
type MapIterator [K constraints .Ordered , V any ] struct {
m *Map [K , V ]
stack [32 ]mapIteratorElem [K , V ]
depth int
}
func (itr *MapIterator [K , V ]) Done () bool {
return itr .depth == -1
}
func (itr *MapIterator [K , V ]) First () {
if itr .m .root == nil {
itr .depth = -1
return
}
itr .stack [0 ] = mapIteratorElem [K , V ]{node : itr .m .root }
itr .depth = 0
itr .first ()
}
func (itr *MapIterator [K , V ]) Next () (key K , value V , ok bool ) {
if itr .Done () {
return key , value , false
}
elem := &itr .stack [itr .depth ]
switch node := elem .node .(type ) {
case *mapArrayNode [K , V ]:
entry := &node .entries [elem .index ]
key , value = entry .key , entry .value
case *mapValueNode [K , V ]:
key , value = node .key , node .value
case *mapHashCollisionNode [K , V ]:
entry := &node .entries [elem .index ]
key , value = entry .key , entry .value
}
itr .next ()
return key , value , true
}
func (itr *MapIterator [K , V ]) next () {
for ; itr .depth >= 0 ; itr .depth -- {
elem := &itr .stack [itr .depth ]
switch node := elem .node .(type ) {
case *mapArrayNode [K , V ]:
if elem .index < len (node .entries )-1 {
elem .index ++
return
}
case *mapBitmapIndexedNode [K , V ]:
if elem .index < len (node .nodes )-1 {
elem .index ++
itr .stack [itr .depth +1 ].node = node .nodes [elem .index ]
itr .depth ++
itr .first ()
return
}
case *mapHashArrayNode [K , V ]:
for i := elem .index + 1 ; i < len (node .nodes ); i ++ {
if node .nodes [i ] != nil {
elem .index = i
itr .stack [itr .depth +1 ].node = node .nodes [elem .index ]
itr .depth ++
itr .first ()
return
}
}
case *mapValueNode [K , V ]:
continue
case *mapHashCollisionNode [K , V ]:
if elem .index < len (node .entries )-1 {
elem .index ++
return
}
}
}
}
func (itr *MapIterator [K , V ]) first () {
for ; ; itr .depth ++ {
elem := &itr .stack [itr .depth ]
switch node := elem .node .(type ) {
case *mapBitmapIndexedNode [K , V ]:
elem .index = 0
itr .stack [itr .depth +1 ].node = node .nodes [0 ]
case *mapHashArrayNode [K , V ]:
for i := 0 ; i < len (node .nodes ); i ++ {
if node .nodes [i ] != nil {
elem .index = i
itr .stack [itr .depth +1 ].node = node .nodes [i ]
break
}
}
default :
elem .index = 0
return
}
}
}
type mapIteratorElem[K constraints .Ordered , V any ] struct {
node mapNode [K , V ]
index int
}
const (
sortedMapNodeSize = 32
)
type SortedMap [K constraints .Ordered , V any ] struct {
size int
root sortedMapNode [K , V ]
comparer Comparer [K ]
}
func NewSortedMap [K constraints .Ordered , V any ](comparer Comparer [K ]) *SortedMap [K , V ] {
return &SortedMap [K , V ]{
comparer : comparer ,
}
}
func (m *SortedMap [K , V ]) Len () int {
return m .size
}
func (m *SortedMap [K , V ]) Get (key K ) (V , bool ) {
if m .root == nil {
var v V
return v , false
}
return m .root .get (key , m .comparer )
}
func (m *SortedMap [K , V ]) Set (key K , value V ) *SortedMap [K , V ] {
return m .set (key , value , false )
}
func (m *SortedMap [K , V ]) set (key K , value V , mutable bool ) *SortedMap [K , V ] {
comparer := m .comparer
if comparer == nil {
comparer = NewComparer [K ](key )
}
other := m
if !mutable {
other = m .clone ()
}
other .comparer = comparer
if m .root == nil {
other .size = 1
other .root = &sortedMapLeafNode [K , V ]{entries : []mapEntry [K , V ]{{key : key , value : value }}}
return other
}
var resized bool
newRoot , splitNode := m .root .set (key , value , comparer , mutable , &resized )
if splitNode != nil {
newRoot = newSortedMapBranchNode (newRoot , splitNode )
}
other .size = m .size
other .root = newRoot
if resized {
other .size ++
}
return other
}
func (m *SortedMap [K , V ]) Delete (key K ) *SortedMap [K , V ] {
return m .delete (key , false )
}
func (m *SortedMap [K , V ]) delete (key K , mutable bool ) *SortedMap [K , V ] {
if m .root == nil {
return m
}
var resized bool
newRoot := m .root .delete (key , m .comparer , mutable , &resized )
if !resized {
return m
}
other := m
if !mutable {
other = m .clone ()
}
other .size = m .size - 1
other .root = newRoot
return other
}
func (m *SortedMap [K , V ]) clone () *SortedMap [K , V ] {
other := *m
return &other
}
func (m *SortedMap [K , V ]) Iterator () *SortedMapIterator [K , V ] {
itr := &SortedMapIterator [K , V ]{m : m }
itr .First ()
return itr
}
type SortedMapBuilder [K constraints .Ordered , V any ] struct {
m *SortedMap [K , V ]
}
func NewSortedMapBuilder [K constraints .Ordered , V any ](comparer Comparer [K ]) *SortedMapBuilder [K , V ] {
return &SortedMapBuilder [K , V ]{m : NewSortedMap [K , V ](comparer )}
}
func (b *SortedMapBuilder [K , V ]) Map () *SortedMap [K , V ] {
assert (b .m != nil , "immutable.SortedMapBuilder.Map(): duplicate call to fetch map" )
m := b .m
b .m = nil
return m
}
func (b *SortedMapBuilder [K , V ]) Len () int {
assert (b .m != nil , "immutable.SortedMapBuilder: builder invalid after Map() invocation" )
return b .m .Len ()
}
func (b *SortedMapBuilder [K , V ]) Get (key K ) (value V , ok bool ) {
assert (b .m != nil , "immutable.SortedMapBuilder: builder invalid after Map() invocation" )
return b .m .Get (key )
}
func (b *SortedMapBuilder [K , V ]) Set (key K , value V ) {
assert (b .m != nil , "immutable.SortedMapBuilder: builder invalid after Map() invocation" )
b .m = b .m .set (key , value , true )
}
func (b *SortedMapBuilder [K , V ]) Delete (key K ) {
assert (b .m != nil , "immutable.SortedMapBuilder: builder invalid after Map() invocation" )
b .m = b .m .delete (key , true )
}
func (b *SortedMapBuilder [K , V ]) Iterator () *SortedMapIterator [K , V ] {
assert (b .m != nil , "immutable.SortedMapBuilder: builder invalid after Map() invocation" )
return b .m .Iterator ()
}
type sortedMapNode[K constraints .Ordered , V any ] interface {
minKey() K
indexOf(key K , c Comparer [K ]) int
get(key K , c Comparer [K ]) (value V , ok bool )
set(key K , value V , c Comparer [K ], mutable bool , resized *bool ) (sortedMapNode [K , V ], sortedMapNode [K , V ])
delete(key K , c Comparer [K ], mutable bool , resized *bool ) sortedMapNode [K , V ]
}
var _ sortedMapNode [string , any ] = (*sortedMapBranchNode [string , any ])(nil )
var _ sortedMapNode [string , any ] = (*sortedMapLeafNode [string , any ])(nil )
type sortedMapBranchNode[K constraints .Ordered , V any ] struct {
elems []sortedMapBranchElem [K , V ]
}
func newSortedMapBranchNode[K constraints .Ordered , V any ](children ...sortedMapNode [K , V ]) *sortedMapBranchNode [K , V ] {
elems := make ([]sortedMapBranchElem [K , V ], len (children ))
for i , child := range children {
elems [i ] = sortedMapBranchElem [K , V ]{
key : child .minKey (),
node : child ,
}
}
return &sortedMapBranchNode [K , V ]{elems : elems }
}
func (n *sortedMapBranchNode [K , V ]) minKey () K {
return n .elems [0 ].node .minKey ()
}
func (n *sortedMapBranchNode [K , V ]) indexOf (key K , c Comparer [K ]) int {
if idx := sort .Search (len (n .elems ), func (i int ) bool { return c .Compare (n .elems [i ].key , key ) == 1 }); idx > 0 {
return idx - 1
}
return 0
}
func (n *sortedMapBranchNode [K , V ]) get (key K , c Comparer [K ]) (value V , ok bool ) {
idx := n .indexOf (key , c )
return n .elems [idx ].node .get (key , c )
}
func (n *sortedMapBranchNode [K , V ]) set (key K , value V , c Comparer [K ], mutable bool , resized *bool ) (sortedMapNode [K , V ], sortedMapNode [K , V ]) {
idx := n .indexOf (key , c )
newNode , splitNode := n .elems [idx ].node .set (key , value , c , mutable , resized )
if mutable {
n .elems [idx ] = sortedMapBranchElem [K , V ]{key : newNode .minKey (), node : newNode }
if splitNode != nil {
n .elems = append (n .elems , sortedMapBranchElem [K , V ]{})
copy (n .elems [idx +1 :], n .elems [idx :])
n .elems [idx +1 ] = sortedMapBranchElem [K , V ]{key : splitNode .minKey (), node : splitNode }
}
if len (n .elems ) > sortedMapNodeSize {
splitIdx := len (n .elems ) / 2
newNode := &sortedMapBranchNode [K , V ]{elems : n .elems [:splitIdx :splitIdx ]}
splitNode := &sortedMapBranchNode [K , V ]{elems : n .elems [splitIdx :]}
return newNode , splitNode
}
return n , nil
}
var other sortedMapBranchNode [K , V ]
if splitNode == nil {
other .elems = make ([]sortedMapBranchElem [K , V ], len (n .elems ))
copy (other .elems , n .elems )
other .elems [idx ] = sortedMapBranchElem [K , V ]{
key : newNode .minKey (),
node : newNode ,
}
} else {
other .elems = make ([]sortedMapBranchElem [K , V ], len (n .elems )+1 )
copy (other .elems [:idx ], n .elems [:idx ])
copy (other .elems [idx +1 :], n .elems [idx :])
other .elems [idx ] = sortedMapBranchElem [K , V ]{
key : newNode .minKey (),
node : newNode ,
}
other .elems [idx +1 ] = sortedMapBranchElem [K , V ]{
key : splitNode .minKey (),
node : splitNode ,
}
}
if len (other .elems ) > sortedMapNodeSize {
splitIdx := len (other .elems ) / 2
newNode := &sortedMapBranchNode [K , V ]{elems : other .elems [:splitIdx :splitIdx ]}
splitNode := &sortedMapBranchNode [K , V ]{elems : other .elems [splitIdx :]}
return newNode , splitNode
}
return &other , nil
}
func (n *sortedMapBranchNode [K , V ]) delete (key K , c Comparer [K ], mutable bool , resized *bool ) sortedMapNode [K , V ] {
idx := n .indexOf (key , c )
newNode := n .elems [idx ].node .delete (key , c , mutable , resized )
if !*resized {
return n
}
if newNode == nil {
if len (n .elems ) == 1 {
return nil
}
if mutable {
copy (n .elems [idx :], n .elems [idx +1 :])
n .elems [len (n .elems )-1 ] = sortedMapBranchElem [K , V ]{}
n .elems = n .elems [:len (n .elems )-1 ]
return n
}
other := &sortedMapBranchNode [K , V ]{elems : make ([]sortedMapBranchElem [K , V ], len (n .elems )-1 )}
copy (other .elems [:idx ], n .elems [:idx ])
copy (other .elems [idx :], n .elems [idx +1 :])
return other
}
if mutable {
n .elems [idx ] = sortedMapBranchElem [K , V ]{key : newNode .minKey (), node : newNode }
return n
}
other := &sortedMapBranchNode [K , V ]{elems : make ([]sortedMapBranchElem [K , V ], len (n .elems ))}
copy (other .elems , n .elems )
other .elems [idx ] = sortedMapBranchElem [K , V ]{
key : newNode .minKey (),
node : newNode ,
}
return other
}
type sortedMapBranchElem[K constraints .Ordered , V any ] struct {
key K
node sortedMapNode [K , V ]
}
type sortedMapLeafNode[K constraints .Ordered , V any ] struct {
entries []mapEntry [K , V ]
}
func (n *sortedMapLeafNode [K , V ]) minKey () K {
return n .entries [0 ].key
}
func (n *sortedMapLeafNode [K , V ]) indexOf (key K , c Comparer [K ]) int {
return sort .Search (len (n .entries ), func (i int ) bool {
return c .Compare (n .entries [i ].key , key ) != -1
})
}
func (n *sortedMapLeafNode [K , V ]) get (key K , c Comparer [K ]) (value V , ok bool ) {
idx := n .indexOf (key , c )
if idx == len (n .entries ) || c .Compare (n .entries [idx ].key , key ) != 0 {
return value , false
}
return n .entries [idx ].value , true
}
func (n *sortedMapLeafNode [K , V ]) set (key K , value V , c Comparer [K ], mutable bool , resized *bool ) (sortedMapNode [K , V ], sortedMapNode [K , V ]) {
idx := n .indexOf (key , c )
exists := idx < len (n .entries ) && c .Compare (n .entries [idx ].key , key ) == 0
if mutable {
if !exists {
*resized = true
n .entries = append (n .entries , mapEntry [K , V ]{})
copy (n .entries [idx +1 :], n .entries [idx :])
}
n .entries [idx ] = mapEntry [K , V ]{key : key , value : value }
if len (n .entries ) > sortedMapNodeSize {
splitIdx := len (n .entries ) / 2
newNode := &sortedMapLeafNode [K , V ]{entries : n .entries [:splitIdx :splitIdx ]}
splitNode := &sortedMapLeafNode [K , V ]{entries : n .entries [splitIdx :]}
return newNode , splitNode
}
return n , nil
}
var newEntries []mapEntry [K , V ]
if exists {
newEntries = make ([]mapEntry [K , V ], len (n .entries ))
copy (newEntries , n .entries )
newEntries [idx ] = mapEntry [K , V ]{key : key , value : value }
} else {
*resized = true
newEntries = make ([]mapEntry [K , V ], len (n .entries )+1 )
copy (newEntries [:idx ], n .entries [:idx ])
newEntries [idx ] = mapEntry [K , V ]{key : key , value : value }
copy (newEntries [idx +1 :], n .entries [idx :])
}
if len (newEntries ) > sortedMapNodeSize {
splitIdx := len (newEntries ) / 2
newNode := &sortedMapLeafNode [K , V ]{entries : newEntries [:splitIdx :splitIdx ]}
splitNode := &sortedMapLeafNode [K , V ]{entries : newEntries [splitIdx :]}
return newNode , splitNode
}
return &sortedMapLeafNode [K , V ]{entries : newEntries }, nil
}
func (n *sortedMapLeafNode [K , V ]) delete (key K , c Comparer [K ], mutable bool , resized *bool ) sortedMapNode [K , V ] {
idx := n .indexOf (key , c )
if idx >= len (n .entries ) || c .Compare (n .entries [idx ].key , key ) != 0 {
return n
}
*resized = true
if len (n .entries ) == 1 {
return nil
}
if mutable {
copy (n .entries [idx :], n .entries [idx +1 :])
n .entries [len (n .entries )-1 ] = mapEntry [K , V ]{}
n .entries = n .entries [:len (n .entries )-1 ]
return n
}
other := &sortedMapLeafNode [K , V ]{entries : make ([]mapEntry [K , V ], len (n .entries )-1 )}
copy (other .entries [:idx ], n .entries [:idx ])
copy (other .entries [idx :], n .entries [idx +1 :])
return other
}
type SortedMapIterator [K constraints .Ordered , V any ] struct {
m *SortedMap [K , V ]
stack [32 ]sortedMapIteratorElem [K , V ]
depth int
}
func (itr *SortedMapIterator [K , V ]) Done () bool {
return itr .depth == -1
}
func (itr *SortedMapIterator [K , V ]) First () {
if itr .m .root == nil {
itr .depth = -1
return
}
itr .stack [0 ] = sortedMapIteratorElem [K , V ]{node : itr .m .root }
itr .depth = 0
itr .first ()
}
func (itr *SortedMapIterator [K , V ]) Last () {
if itr .m .root == nil {
itr .depth = -1
return
}
itr .stack [0 ] = sortedMapIteratorElem [K , V ]{node : itr .m .root }
itr .depth = 0
itr .last ()
}
func (itr *SortedMapIterator [K , V ]) Seek (key K ) {
if itr .m .root == nil {
itr .depth = -1
return
}
itr .stack [0 ] = sortedMapIteratorElem [K , V ]{node : itr .m .root }
itr .depth = 0
itr .seek (key )
}
func (itr *SortedMapIterator [K , V ]) Next () (key K , value V , ok bool ) {
if itr .Done () {
return key , value , false
}
leafElem := &itr .stack [itr .depth ]
leafNode := leafElem .node .(*sortedMapLeafNode [K , V ])
leafEntry := &leafNode .entries [leafElem .index ]
key , value = leafEntry .key , leafEntry .value
itr .next ()
return key , value , true
}
func (itr *SortedMapIterator [K , V ]) next () {
for ; itr .depth >= 0 ; itr .depth -- {
elem := &itr .stack [itr .depth ]
switch node := elem .node .(type ) {
case *sortedMapLeafNode [K , V ]:
if elem .index < len (node .entries )-1 {
elem .index ++
return
}
case *sortedMapBranchNode [K , V ]:
if elem .index < len (node .elems )-1 {
elem .index ++
itr .stack [itr .depth +1 ].node = node .elems [elem .index ].node
itr .depth ++
itr .first ()
return
}
}
}
}
func (itr *SortedMapIterator [K , V ]) Prev () (key K , value V , ok bool ) {
if itr .Done () {
return key , value , false
}
leafElem := &itr .stack [itr .depth ]
leafNode := leafElem .node .(*sortedMapLeafNode [K , V ])
leafEntry := &leafNode .entries [leafElem .index ]
key , value = leafEntry .key , leafEntry .value
itr .prev ()
return key , value , true
}
func (itr *SortedMapIterator [K , V ]) prev () {
for ; itr .depth >= 0 ; itr .depth -- {
elem := &itr .stack [itr .depth ]
switch node := elem .node .(type ) {
case *sortedMapLeafNode [K , V ]:
if elem .index > 0 {
elem .index --
return
}
case *sortedMapBranchNode [K , V ]:
if elem .index > 0 {
elem .index --
itr .stack [itr .depth +1 ].node = node .elems [elem .index ].node
itr .depth ++
itr .last ()
return
}
}
}
}
func (itr *SortedMapIterator [K , V ]) first () {
for {
elem := &itr .stack [itr .depth ]
elem .index = 0
switch node := elem .node .(type ) {
case *sortedMapBranchNode [K , V ]:
itr .stack [itr .depth +1 ] = sortedMapIteratorElem [K , V ]{node : node .elems [elem .index ].node }
itr .depth ++
case *sortedMapLeafNode [K , V ]:
return
}
}
}
func (itr *SortedMapIterator [K , V ]) last () {
for {
elem := &itr .stack [itr .depth ]
switch node := elem .node .(type ) {
case *sortedMapBranchNode [K , V ]:
elem .index = len (node .elems ) - 1
itr .stack [itr .depth +1 ] = sortedMapIteratorElem [K , V ]{node : node .elems [elem .index ].node }
itr .depth ++
case *sortedMapLeafNode [K , V ]:
elem .index = len (node .entries ) - 1
return
}
}
}
func (itr *SortedMapIterator [K , V ]) seek (key K ) {
for {
elem := &itr .stack [itr .depth ]
elem .index = elem .node .indexOf (key , itr .m .comparer )
switch node := elem .node .(type ) {
case *sortedMapBranchNode [K , V ]:
itr .stack [itr .depth +1 ] = sortedMapIteratorElem [K , V ]{node : node .elems [elem .index ].node }
itr .depth ++
case *sortedMapLeafNode [K , V ]:
if elem .index == len (node .entries ) {
itr .next ()
}
return
}
}
}
type sortedMapIteratorElem[K constraints .Ordered , V any ] struct {
node sortedMapNode [K , V ]
index int
}
type Hasher [K constraints .Ordered ] interface {
Hash (key K ) uint32
Equal (a, b K ) bool
}
func NewHasher [K constraints .Ordered ](key K ) Hasher [K ] {
switch (any (key )).(type ) {
case int , int8 , int16 , int32 , int64 , uint , uint8 , uint16 , uint32 , uint64 , uintptr , string :
return &defaultHasher [K ]{}
}
switch reflect .TypeOf (key ).Kind () {
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 , reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr , reflect .String :
return &reflectHasher [K ]{}
}
panic (fmt .Sprintf ("immutable.NewHasher: must set hasher for %T type" , key ))
}
func hashString(value string ) uint32 {
var hash uint32
for i , value := 0 , value ; i < len (value ); i ++ {
hash = 31 *hash + uint32 (value [i ])
}
return hash
}
type reflectHasher[K constraints .Ordered ] struct {}
func (h *reflectHasher [K ]) Hash (key K ) uint32 {
switch reflect .TypeOf (key ).Kind () {
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
return hashUint64 (uint64 (reflect .ValueOf (key ).Int ()))
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
return hashUint64 (reflect .ValueOf (key ).Uint ())
case reflect .String :
var hash uint32
s := reflect .ValueOf (key ).String ()
for i := 0 ; i < len (s ); i ++ {
hash = 31 *hash + uint32 (s [i ])
}
return hash
}
panic (fmt .Sprintf ("immutable.reflectHasher.Hash: reflectHasher does not support %T type" , key ))
}
func (h *reflectHasher [K ]) Equal (a , b K ) bool {
switch reflect .TypeOf (a ).Kind () {
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
return reflect .ValueOf (a ).Int () == reflect .ValueOf (b ).Int ()
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
return reflect .ValueOf (a ).Uint () == reflect .ValueOf (b ).Uint ()
case reflect .String :
return reflect .ValueOf (a ).String () == reflect .ValueOf (b ).String ()
}
panic (fmt .Sprintf ("immutable.reflectHasher.Equal: reflectHasher does not support %T type" , a ))
}
func hashUint64(value uint64 ) uint32 {
hash := value
for value > 0xffffffff {
value /= 0xffffffff
hash ^= value
}
return uint32 (hash )
}
type defaultHasher[K constraints .Ordered ] struct {}
func (h *defaultHasher [K ]) Hash (key K ) uint32 {
switch x := (any (key )).(type ) {
case int :
return hashUint64 (uint64 (x ))
case int8 :
return hashUint64 (uint64 (x ))
case int16 :
return hashUint64 (uint64 (x ))
case int32 :
return hashUint64 (uint64 (x ))
case int64 :
return hashUint64 (uint64 (x ))
case uint :
return hashUint64 (uint64 (x ))
case uint8 :
return hashUint64 (uint64 (x ))
case uint16 :
return hashUint64 (uint64 (x ))
case uint32 :
return hashUint64 (uint64 (x ))
case uint64 :
return hashUint64 (uint64 (x ))
case uintptr :
return hashUint64 (uint64 (x ))
case string :
return hashString (x )
}
panic (fmt .Sprintf ("immutable.defaultHasher.Hash: must set comparer for %T type" , key ))
}
func (h *defaultHasher [K ]) Equal (a , b K ) bool {
return a == b
}
type Comparer [K constraints .Ordered ] interface {
Compare (a, b K ) int
}
func NewComparer [K constraints .Ordered ](key K ) Comparer [K ] {
switch (any (key )).(type ) {
case int , int8 , int16 , int32 , int64 , uint , uint8 , uint16 , uint32 , uint64 , uintptr , string :
return &defaultComparer [K ]{}
}
switch reflect .TypeOf (key ).Kind () {
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 , reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr , reflect .String :
return &reflectComparer [K ]{}
}
panic (fmt .Sprintf ("immutable.NewComparer: must set comparer for %T type" , key ))
}
type defaultComparer[K constraints .Ordered ] struct {}
func (c *defaultComparer [K ]) Compare (i K , j K ) int {
if i < j {
return -1
} else if i > j {
return 1
}
return 0
}
type reflectComparer[K constraints .Ordered ] struct {}
func (c *reflectComparer [K ]) Compare (a , b K ) int {
switch reflect .TypeOf (a ).Kind () {
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
if i , j := reflect .ValueOf (a ).Int (), reflect .ValueOf (b ).Int (); i < j {
return -1
} else if i > j {
return 1
}
return 0
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uintptr :
if i , j := reflect .ValueOf (a ).Uint (), reflect .ValueOf (b ).Uint (); i < j {
return -1
} else if i > j {
return 1
}
return 0
case reflect .String :
return strings .Compare (reflect .ValueOf (a ).String (), reflect .ValueOf (b ).String ())
}
panic (fmt .Sprintf ("immutable.reflectComparer.Compare: must set comparer for %T type" , a ))
}
func assert(condition bool , message string ) {
if !condition {
panic (message )
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .