// Package immutable provides immutable collection types. // // Introduction // // Immutable collections provide an efficient, safe way to share collections // of data while minimizing locks. The collections in this package provide // List, Map, and SortedMap implementations. These act similarly to slices // and maps, respectively, except that altering a collection returns a new // copy of the collection with that change. // // Because collections are unable to change, they are safe for multiple // goroutines to read from at the same time without a mutex. However, these // types of collections come with increased CPU & memory usage as compared // with Go's built-in collection types so please evaluate for your specific // use. // // Collection Types // // The List type provides an API similar to Go slices. They allow appending, // prepending, and updating of elements. Elements can also be fetched by index // or iterated over using a ListIterator. // // The Map & SortedMap types provide an API similar to Go maps. They allow // values to be assigned to unique keys and allow for the deletion of keys. // Values can be fetched by key and key/value pairs can be iterated over using // the appropriate iterator type. Both map types provide the same API. The // SortedMap, however, provides iteration over sorted keys while the Map // provides iteration over unsorted keys. Maps improved performance and memory // usage as compared to SortedMaps. // // Hashing and Sorting // // Map types require the use of a Hasher implementation to calculate hashes for // their keys and check for key equality. SortedMaps require the use of a // Comparer implementation to sort keys in the map. // // These collection types automatically provide built-in hasher and comparers // for int, string, and byte slice keys. If you are using one of these key types // then simply pass a nil into the constructor. Otherwise you will need to // implement a custom Hasher or Comparer type. Please see the provided // implementations for reference.
package immutable import ( ) // List is a dense, ordered, indexed collections. They are analogous to slices // in Go. They can be updated by appending to the end of the list, prepending // values to the beginning of the list, or updating existing indexes in the // list. type List[ comparable] struct { root listNode[] // root node origin int // offset to zero index element size int // total number of elements in use } // NewList returns a new empty instance of List. func [ comparable]() *List[] { return &List[]{ root: &listLeafNode[]{}, } } // clone returns a copy of the list. func ( *List[]) () *List[] { := * return & } // Len returns the number of elements in the list. func ( *List[]) () int { return .size } // cap returns the total number of possible elements for the current depth. func ( *List[]) () int { return 1 << (.root.depth() * listNodeBits) } // Get returns the value at the given index. Similar to slices, this method will // panic if index is below zero or is greater than or equal to the list size. func ( *List[]) ( int) { if < 0 || >= .size { panic(fmt.Sprintf("immutable.List.Get: index %d out of bounds", )) } return .root.get(.origin + ) } // Set returns a new list with value set at index. Similar to slices, this // method will panic if index is below zero or if the index is greater than // or equal to the list size. func ( *List[]) ( int, ) *List[] { return .set(, , false) } func ( *List[]) ( int, , bool) *List[] { if < 0 || >= .size { panic(fmt.Sprintf("immutable.List.Set: index %d out of bounds", )) } := if ! { = .clone() } .root = .root.set(.origin+, , ) return } // Append returns a new list with value added to the end of the list. func ( *List[]) ( ) *List[] { return .append(, false) } func ( *List[]) ( , bool) *List[] { := if ! { = .clone() } // Expand list to the right if no slots remain. if .size+.origin >= .cap() { := &listBranchNode[]{d: .root.depth() + 1} .children[0] = .root .root = } // Increase size and set the last element to the new value. .size++ .root = .root.set(.origin+.size-1, , ) return } // Prepend returns a new list with value added to the beginning of the list. func ( *List[]) ( ) *List[] { return .prepend(, false) } func ( *List[]) ( , bool) *List[] { := if ! { = .clone() } // Expand list to the left if no slots remain. if .origin == 0 { := &listBranchNode[]{d: .root.depth() + 1} .children[listNodeSize-1] = .root .root = .origin += (listNodeSize - 1) << (.root.depth() * listNodeBits) } // Increase size and move origin back. Update first element to value. .size++ .origin-- .root = .root.set(.origin, , ) return } // Slice returns a new list of elements between start index and end index. // Similar to slices, this method will panic if start or end are below zero or // greater than the list size. A panic will also occur if start is greater than // end. // // Unlike Go slices, references to inaccessible elements will be automatically // removed so they can be garbage collected. func ( *List[]) (, int) *List[] { return .slice(, , false) } func ( *List[]) (, int, bool) *List[] { // Panics similar to Go slices. if < 0 || > .size { panic(fmt.Sprintf("immutable.List.Slice: start index %d out of bounds", )) } else if < 0 || > .size { panic(fmt.Sprintf("immutable.List.Slice: end index %d out of bounds", )) } else if > { panic(fmt.Sprintf("immutable.List.Slice: invalid slice index: [%d:%d]", , )) } // Return the same list if the start and end are the entire range. if == 0 && == .size { return } // Create copy, if immutable. := if ! { = .clone() } // Update origin/size. .origin = .origin + .size = - // Contract tree while the start & end are in the same child node. for .root.depth() > 1 { := (.origin >> (.root.depth() * listNodeBits)) & listNodeMask := ((.origin + .size - 1) >> (.root.depth() * listNodeBits)) & listNodeMask if != { break // branch contains at least two nodes, exit } // Replace the current root with the single child & update origin offset. .origin -= << (.root.depth() * listNodeBits) .root = .root.(*listBranchNode[]).children[] } // Ensure all references are removed before start & after end. .root = .root.deleteBefore(.origin, ) .root = .root.deleteAfter(.origin+.size-1, ) return } // Iterator returns a new iterator for this list positioned at the first index. func ( *List[]) () *ListIterator[] { := &ListIterator[]{list: } .First() return } // ListBuilder represents an efficient builder for creating new Lists. type ListBuilder[ comparable] struct { list *List[] // current state } // NewListBuilder returns a new instance of ListBuilder. func [ comparable]() *ListBuilder[] { return &ListBuilder[]{list: NewList[]()} } // List returns the current copy of the list. // The builder should not be used again after the list after this call. func ( *ListBuilder[]) () *List[] { assert(.list != nil, "immutable.ListBuilder.List(): duplicate call to fetch list") := .list .list = nil return } // Len returns the number of elements in the underlying list. func ( *ListBuilder[]) () int { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") return .list.Len() } // Get returns the value at the given index. Similar to slices, this method will // panic if index is below zero or is greater than or equal to the list size. func ( *ListBuilder[]) ( int) { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") return .list.Get() } // Set updates the value at the given index. Similar to slices, this method will // panic if index is below zero or if the index is greater than or equal to the // list size. func ( *ListBuilder[]) ( int, ) { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") .list = .list.set(, , true) } // Append adds value to the end of the list. func ( *ListBuilder[]) ( ) { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") .list = .list.append(, true) } // Prepend adds value to the beginning of the list. func ( *ListBuilder[]) ( ) { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") .list = .list.prepend(, true) } // Slice updates the list with a sublist of elements between start and end index. // See List.Slice() for more details. func ( *ListBuilder[]) (, int) { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") .list = .list.slice(, , true) } // Iterator returns a new iterator for the underlying list. func ( *ListBuilder[]) () *ListIterator[] { assert(.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") return .list.Iterator() } // Constants for bit shifts used for levels in the List trie. const ( listNodeBits = 5 listNodeSize = 1 << listNodeBits listNodeMask = listNodeSize - 1 ) // listNode represents either a branch or leaf node in a List. type listNode[ comparable] interface { depth() uint get(index int) set(index int, v , mutable bool) listNode[] containsBefore(index int) bool containsAfter(index int) bool deleteBefore(index int, mutable bool) listNode[] deleteAfter(index int, mutable bool) listNode[] } // newListNode returns a leaf node for depth zero, otherwise returns a branch node. func newListNode[ comparable]( uint) listNode[] { if == 0 { return &listLeafNode[]{} } return &listBranchNode[]{d: } } // listBranchNode represents a branch of a List tree at a given depth. type listBranchNode[ comparable] struct { d uint // depth children [listNodeSize]listNode[] } // depth returns the depth of this branch node from the leaf. func ( *listBranchNode[]) () uint { return .d } // get returns the child node at the segment of the index for this depth. func ( *listBranchNode[]) ( int) { := ( >> (.d * listNodeBits)) & listNodeMask return .children[].get() } // set recursively updates the value at index for each lower depth from the node. func ( *listBranchNode[]) ( int, , bool) listNode[] { := ( >> (.d * listNodeBits)) & listNodeMask // Find child for the given value in the branch. Create new if it doesn't exist. := .children[] if == nil { = newListNode[](.depth() - 1) } // Return a copy of this branch with the new child. var *listBranchNode[] if { = } else { := * = & } .children[] = .set(, , ) return } // containsBefore returns true if non-nil values exists between [0,index). func ( *listBranchNode[]) ( int) bool { := ( >> (.d * listNodeBits)) & listNodeMask // Quickly check if any direct children exist before this segment of the index. for := 0; < ; ++ { if .children[] != nil { return true } } // Recursively check for children directly at the given index at this segment. if .children[] != nil && .children[].containsBefore() { return true } return false } // containsAfter returns true if non-nil values exists between (index,listNodeSize). func ( *listBranchNode[]) ( int) bool { := ( >> (.d * listNodeBits)) & listNodeMask // Quickly check if any direct children exist after this segment of the index. for := + 1; < len(.children); ++ { if .children[] != nil { return true } } // Recursively check for children directly at the given index at this segment. if .children[] != nil && .children[].containsAfter() { return true } return false } // deleteBefore returns a new node with all elements before index removed. func ( *listBranchNode[]) ( int, bool) listNode[] { // Ignore if no nodes exist before the given index. if !.containsBefore() { return } // Return a copy with any nodes prior to the index removed. := ( >> (.d * listNodeBits)) & listNodeMask var *listBranchNode[] if { = for := 0; < ; ++ { .children[] = nil } } else { = &listBranchNode[]{d: .d} copy(.children[:][:], .children[:][:]) } if .children[] != nil { .children[] = .children[].deleteBefore(, ) } return } // deleteBefore returns a new node with all elements before index removed. func ( *listBranchNode[]) ( int, bool) listNode[] { // Ignore if no nodes exist after the given index. if !.containsAfter() { return } // Return a copy with any nodes after the index removed. := ( >> (.d * listNodeBits)) & listNodeMask var *listBranchNode[] if { = for := + 1; < len(.children); ++ { .children[] = nil } } else { = &listBranchNode[]{d: .d} copy(.children[:+1], .children[:+1]) } if .children[] != nil { .children[] = .children[].deleteAfter(, ) } return } // listLeafNode represents a leaf node in a List. type listLeafNode[ comparable] struct { children [listNodeSize] } // depth always returns 0 for leaf nodes. func ( *listLeafNode[]) () uint { return 0 } // get returns the value at the given index. func ( *listLeafNode[]) ( int) { return .children[&listNodeMask] } // set returns a copy of the node with the value at the index updated to v. func ( *listLeafNode[]) ( int, , bool) listNode[] { := & listNodeMask var *listLeafNode[] if { = } else { := * = & } .children[] = var listNode[] = return } // containsBefore returns true if non-nil values exists between [0,index). func ( *listLeafNode[]) ( int) bool { := & listNodeMask var for := 0; < ; ++ { if .children[] != { return true } } return false } // containsAfter returns true if non-nil values exists between (index,listNodeSize). func ( *listLeafNode[]) ( int) bool { := & listNodeMask var for := + 1; < len(.children); ++ { if .children[] != { return true } } return false } // deleteBefore returns a new node with all elements before index removed. func ( *listLeafNode[]) ( int, bool) listNode[] { if !.containsBefore() { return } := & listNodeMask var *listLeafNode[] if { = var for := 0; < ; ++ { .children[] = } } else { = &listLeafNode[]{} copy(.children[:][:], .children[:][:]) } return } // deleteBefore returns a new node with all elements before index removed. func ( *listLeafNode[]) ( int, bool) listNode[] { if !.containsAfter() { return } := & listNodeMask var *listLeafNode[] if { = var for := + 1; < len(.children); ++ { .children[] = } } else { = &listLeafNode[]{} copy(.children[:+1][:], .children[:+1][:]) } return } // ListIterator represents an ordered iterator over a list. type ListIterator[ comparable] struct { list *List[] // source list index int // current index position stack [32]listIteratorElem[] // search stack depth int // stack depth } // Done returns true if no more elements remain in the iterator. func ( *ListIterator[]) () bool { return .index < 0 || .index >= .list.Len() } // First positions the iterator on the first index. // If source list is empty then no change is made. func ( *ListIterator[]) () { if .list.Len() != 0 { .Seek(0) } } // Last positions the iterator on the last index. // If source list is empty then no change is made. func ( *ListIterator[]) () { if := .list.Len(); != 0 { .Seek( - 1) } } // Seek moves the iterator position to the given index in the list. // Similar to Go slices, this method will panic if index is below zero or if // the index is greater than or equal to the list size. func ( *ListIterator[]) ( int) { // Panic similar to Go slices. if < 0 || >= .list.Len() { panic(fmt.Sprintf("immutable.ListIterator.Seek: index %d out of bounds", )) } .index = // Reset to the bottom of the stack at seek to the correct position. .stack[0] = listIteratorElem[]{node: .list.root} .depth = 0 .seek() } // Next returns the current index and its value & moves the iterator forward. // Returns an index of -1 if the there are no more elements to return. func ( *ListIterator[]) () ( int, ) { // Exit immediately if there are no elements remaining. var if .Done() { return -1, } // Retrieve current index & value. := &.stack[.depth] , = .index, .node.(*listLeafNode[]).children[.index] // Increase index. If index is at the end then return immediately. .index++ if .Done() { return , } // Move up stack until we find a node that has remaining position ahead. for ; .depth > 0 && .stack[.depth].index >= listNodeSize-1; .depth-- { } // Seek to correct position from current depth. .seek(.index) return , } // Prev returns the current index and value and moves the iterator backward. // Returns an index of -1 if the there are no more elements to return. func ( *ListIterator[]) () ( int, ) { // Exit immediately if there are no elements remaining. var if .Done() { return -1, } // Retrieve current index & value. := &.stack[.depth] , = .index, .node.(*listLeafNode[]).children[.index] // Decrease index. If index is past the beginning then return immediately. .index-- if .Done() { return , } // Move up stack until we find a node that has remaining position behind. for ; .depth > 0 && .stack[.depth].index == 0; .depth-- { } // Seek to correct position from current depth. .seek(.index) return , } // seek positions the stack to the given index from the current depth. // Elements and indexes below the current depth are assumed to be correct. func ( *ListIterator[]) ( int) { // Iterate over each level until we reach a leaf node. for { := &.stack[.depth] .index = ((.list.origin + ) >> (.node.depth() * listNodeBits)) & listNodeMask switch node := .node.(type) { case *listBranchNode[]: := .children[.index] .stack[.depth+1] = listIteratorElem[]{node: } .depth++ case *listLeafNode[]: return } } } // listIteratorElem represents the node and it's child index within the stack. type listIteratorElem[ comparable] struct { node listNode[] index int } // Size thresholds for each type of branch node. const ( maxArrayMapSize = 8 maxBitmapIndexedSize = 16 ) // Segment bit shifts within the map tree. const ( mapNodeBits = 5 mapNodeSize = 1 << mapNodeBits mapNodeMask = mapNodeSize - 1 ) // Map represents an immutable hash map implementation. The map uses a Hasher // to generate hashes and check for equality of key values. // // It is implemented as an Hash Array Mapped Trie. type Map[ constraints.Ordered, any] struct { size int // total number of key/value pairs root mapNode[, ] // root node of trie hasher Hasher[] // hasher implementation } // NewMap returns a new instance of Map. If hasher is nil, a default hasher // implementation will automatically be chosen based on the first key added. // Default hasher implementations only exist for int, string, and byte slice types. func [ constraints.Ordered, any]( Hasher[]) *Map[, ] { return &Map[, ]{ hasher: , } } // Len returns the number of elements in the map. func ( *Map[, ]) () int { return .size } // clone returns a shallow copy of m. func ( *Map[, ]) () *Map[, ] { := * return & } // Get returns the value for a given key and a flag indicating whether the // key exists. This flag distinguishes a nil value set on a key versus a // non-existent key in the map. func ( *Map[, ]) ( ) ( , bool) { var if .root == nil { return , false } := .hasher.Hash() return .root.get(, 0, , .hasher) } // Set returns a map with the key set to the new value. A nil value is allowed. // // This function will return a new map even if the updated value is the same as // the existing value because Map does not track value equality. func ( *Map[, ]) ( , ) *Map[, ] { return .set(, , false) } func ( *Map[, ]) ( , , bool) *Map[, ] { // Set a hasher on the first value if one does not already exist. := .hasher if == nil { = NewHasher() } // Generate copy if necessary. := if ! { = .clone() } .hasher = // If the map is empty, initialize with a simple array node. if .root == nil { .size = 1 .root = &mapArrayNode[, ]{entries: []mapEntry[, ]{{key: , value: }}} return } // Otherwise copy the map and delegate insertion to the root. // Resized will return true if the key does not currently exist. var bool .root = .root.set(, , 0, .Hash(), , , &) if { .size++ } return } // Delete returns a map with the given key removed. // Removing a non-existent key will cause this method to return the same map. func ( *Map[, ]) ( ) *Map[, ] { return .delete(, false) } func ( *Map[, ]) ( , bool) *Map[, ] { // Return original map if no keys exist. if .root == nil { return } // If the delete did not change the node then return the original map. var bool := .root.delete(, 0, .hasher.Hash(), .hasher, , &) if ! { return } // Generate copy if necessary. := if ! { = .clone() } // Return copy of map with new root and decreased size. .size = .size - 1 .root = return } // Iterator returns a new iterator for the map. func ( *Map[, ]) () *MapIterator[, ] { := &MapIterator[, ]{m: } .First() return } // MapBuilder represents an efficient builder for creating Maps. type MapBuilder[ constraints.Ordered, any] struct { m *Map[, ] // current state } // NewMapBuilder returns a new instance of MapBuilder. func [ constraints.Ordered, any]( Hasher[]) *MapBuilder[, ] { return &MapBuilder[, ]{m: NewMap[, ]()} } // Map returns the underlying map. Only call once. // Builder is invalid after call. Will panic on second invocation. func ( *MapBuilder[, ]) () *Map[, ] { assert(.m != nil, "immutable.SortedMapBuilder.Map(): duplicate call to fetch map") := .m .m = nil return } // Len returns the number of elements in the underlying map. func ( *MapBuilder[, ]) () int { assert(.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") return .m.Len() } // Get returns the value for the given key. func ( *MapBuilder[, ]) ( ) ( , bool) { assert(.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") return .m.Get() } // Set sets the value of the given key. See Map.Set() for additional details. func ( *MapBuilder[, ]) ( , ) { assert(.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") .m = .m.set(, , true) } // Delete removes the given key. See Map.Delete() for additional details. func ( *MapBuilder[, ]) ( ) { assert(.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") .m = .m.delete(, true) } // Iterator returns a new iterator for the underlying map. func ( *MapBuilder[, ]) () *MapIterator[, ] { assert(.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") return .m.Iterator() } // mapNode represents any node in the map tree. type mapNode[ constraints.Ordered, any] interface { get(key , shift uint, keyHash uint32, h Hasher[]) (value , ok bool) set(key , value , shift uint, keyHash uint32, h Hasher[], mutable bool, resized *bool) mapNode[, ] delete(key , shift uint, keyHash uint32, h Hasher[], mutable bool, resized *bool) mapNode[, ] } 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) // mapLeafNode represents a node that stores a single key hash at the leaf of the map tree. type mapLeafNode[ constraints.Ordered, any] interface { mapNode[, ] keyHashValue() uint32 } var _ mapLeafNode[string, any] = (*mapValueNode[string, any])(nil) var _ mapLeafNode[string, any] = (*mapHashCollisionNode[string, any])(nil) // mapArrayNode is a map node that stores key/value pairs in a slice. // Entries are stored in insertion order. An array node expands into a bitmap // indexed node once a given threshold size is crossed. type mapArrayNode[ constraints.Ordered, any] struct { entries []mapEntry[, ] } // indexOf returns the entry index of the given key. Returns -1 if key not found. func ( *mapArrayNode[, ]) ( , Hasher[]) int { for := range .entries { if .Equal(.entries[].key, ) { return } } return -1 } // get returns the value for the given key. func ( *mapArrayNode[, ]) ( , uint, uint32, Hasher[]) ( , bool) { := .indexOf(, ) if == -1 { return , false } return .entries[].value, true } // set inserts or updates the value for a given key. If the key is inserted and // the new size crosses the max size threshold, a bitmap indexed node is returned. func ( *mapArrayNode[, ]) ( , , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { := .indexOf(, ) // Mark as resized if the key doesn't exist. if == -1 { * = true } // If we are adding and it crosses the max size threshold, expand the node. // We do this by continually setting the entries to a value node and expanding. if == -1 && len(.entries) >= maxArrayMapSize { var mapNode[, ] = newMapValueNode(.Hash(), , ) for , := range .entries { = .set(.key, .value, 0, .Hash(.key), , false, ) } return } // Update in-place if mutable. if { if != -1 { .entries[] = mapEntry[, ]{, } } else { .entries = append(.entries, mapEntry[, ]{, }) } return } // Update existing entry if a match is found. // Otherwise append to the end of the element list if it doesn't exist. var mapArrayNode[, ] if != -1 { .entries = make([]mapEntry[, ], len(.entries)) copy(.entries, .entries) .entries[] = mapEntry[, ]{, } } else { .entries = make([]mapEntry[, ], len(.entries)+1) copy(.entries, .entries) .entries[len(.entries)-1] = mapEntry[, ]{, } } return & } // delete removes the given key from the node. Returns the same node if key does // not exist. Returns a nil node when removing the last entry. func ( *mapArrayNode[, ]) ( , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { := .indexOf(, ) // Return original node if key does not exist. if == -1 { return } * = true // Return nil if this node will contain no nodes. if len(.entries) == 1 { return nil } // Update in-place, if mutable. if { copy(.entries[:], .entries[+1:]) .entries[len(.entries)-1] = mapEntry[, ]{} .entries = .entries[:len(.entries)-1] return } // Otherwise create a copy with the given entry removed. := &mapArrayNode[, ]{entries: make([]mapEntry[, ], len(.entries)-1)} copy(.entries[:], .entries[:]) copy(.entries[:], .entries[+1:]) return } // mapBitmapIndexedNode represents a map branch node with a variable number of // node slots and indexed using a bitmap. Indexes for the node slots are // calculated by counting the number of set bits before the target bit using popcount. type mapBitmapIndexedNode[ constraints.Ordered, any] struct { bitmap uint32 nodes []mapNode[, ] } // get returns the value for the given key. func ( *mapBitmapIndexedNode[, ]) ( , uint, uint32, Hasher[]) ( , bool) { := uint32(1) << (( >> ) & mapNodeMask) if (.bitmap & ) == 0 { return , false } := .nodes[bits.OnesCount32(.bitmap&(-1))] return .get(, +mapNodeBits, , ) } // set inserts or updates the value for the given key. If a new key is inserted // and the size crosses the max size threshold then a hash array node is returned. func ( *mapBitmapIndexedNode[, ]) ( , , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { // Extract the index for the bit segment of the key hash. := ( >> ) & mapNodeMask // Determine the bit based on the hash index. := uint32(1) << := (.bitmap & ) != 0 // Mark as resized if the key doesn't exist. if ! { * = true } // Find index of node based on popcount of bits before it. := bits.OnesCount32(.bitmap & ( - 1)) // If the node already exists, delegate set operation to it. // If the node doesn't exist then create a simple value leaf node. var mapNode[, ] if { = .nodes[].set(, , +mapNodeBits, , , , ) } else { = newMapValueNode[, ](, , ) } // Convert to a hash-array node once we exceed the max bitmap size. // Copy each node based on their bit position within the bitmap. if ! && len(.nodes) > maxBitmapIndexedSize { var mapHashArrayNode[, ] for := uint(0); < uint(len(.nodes)); ++ { if .bitmap&(uint32(1)<<) != 0 { .nodes[] = .nodes[.count] .count++ } } .nodes[] = .count++ return & } // Update in-place if mutable. if { if { .nodes[] = } else { .bitmap |= .nodes = append(.nodes, nil) copy(.nodes[+1:], .nodes[:]) .nodes[] = } return } // If node exists at given slot then overwrite it with new node. // Otherwise expand the node list and insert new node into appropriate position. := &mapBitmapIndexedNode[, ]{bitmap: .bitmap | } if { .nodes = make([]mapNode[, ], len(.nodes)) copy(.nodes, .nodes) .nodes[] = } else { .nodes = make([]mapNode[, ], len(.nodes)+1) copy(.nodes, .nodes[:]) .nodes[] = copy(.nodes[+1:], .nodes[:]) } return } // delete removes the key from the tree. If the key does not exist then the // original node is returned. If removing the last child node then a nil is // returned. Note that shrinking the node will not convert it to an array node. func ( *mapBitmapIndexedNode[, ]) ( , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { := uint32(1) << (( >> ) & mapNodeMask) // Return original node if key does not exist. if (.bitmap & ) == 0 { return } // Find index of node based on popcount of bits before it. := bits.OnesCount32(.bitmap & ( - 1)) // Delegate delete to child node. := .nodes[] := .delete(, +mapNodeBits, , , , ) // Return original node if key doesn't exist in child. if !* { return } // Remove if returned child has been deleted. if == nil { // If we won't have any children then return nil. if len(.nodes) == 1 { return nil } // Update in-place if mutable. if { .bitmap ^= copy(.nodes[:], .nodes[+1:]) .nodes[len(.nodes)-1] = nil .nodes = .nodes[:len(.nodes)-1] return } // Return copy with bit removed from bitmap and node removed from node list. := &mapBitmapIndexedNode[, ]{bitmap: .bitmap ^ , nodes: make([]mapNode[, ], len(.nodes)-1)} copy(.nodes[:], .nodes[:]) copy(.nodes[:], .nodes[+1:]) return } // Generate copy, if necessary. := if ! { = &mapBitmapIndexedNode[, ]{bitmap: .bitmap, nodes: make([]mapNode[, ], len(.nodes))} copy(.nodes, .nodes) } // Update child. .nodes[] = return } // mapHashArrayNode is a map branch node that stores nodes in a fixed length // array. Child nodes are indexed by their index bit segment for the current depth. type mapHashArrayNode[ constraints.Ordered, any] struct { count uint // number of set nodes nodes [mapNodeSize]mapNode[, ] // child node slots, may contain empties } // clone returns a shallow copy of n. func ( *mapHashArrayNode[, ]) () *mapHashArrayNode[, ] { := * return & } // get returns the value for the given key. func ( *mapHashArrayNode[, ]) ( , uint, uint32, Hasher[]) ( , bool) { := .nodes[(>>)&mapNodeMask] if == nil { return , false } return .get(, +mapNodeBits, , ) } // set returns a node with the value set for the given key. func ( *mapHashArrayNode[, ]) ( , , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { := ( >> ) & mapNodeMask := .nodes[] // If node at index doesn't exist, create a simple value leaf node. // Otherwise delegate set to child node. var mapNode[, ] if == nil { * = true = newMapValueNode(, , ) } else { = .set(, , +mapNodeBits, , , , ) } // Generate copy, if necessary. := if ! { = .clone() } // Update child node (and update size, if new). if == nil { .count++ } .nodes[] = return } // delete returns a node with the given key removed. Returns the same node if // the key does not exist. If node shrinks to within bitmap-indexed size then // converts to a bitmap-indexed node. func ( *mapHashArrayNode[, ]) ( , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { := ( >> ) & mapNodeMask := .nodes[] // Return original node if child is not found. if == nil { return } // Return original node if child is unchanged. := .delete(, +mapNodeBits, , , , ) if !* { return } // If we remove a node and drop below a threshold, convert back to bitmap indexed node. if == nil && .count <= maxBitmapIndexedSize { := &mapBitmapIndexedNode[, ]{nodes: make([]mapNode[, ], 0, .count-1)} for , := range .nodes { if != nil && uint32() != { .bitmap |= 1 << uint() .nodes = append(.nodes, ) } } return } // Generate copy, if necessary. := if ! { = .clone() } // Return copy of node with child updated. .nodes[] = if == nil { .count-- } return } // mapValueNode represents a leaf node with a single key/value pair. // A value node can be converted to a hash collision leaf node if a different // key with the same keyHash is inserted. type mapValueNode[ constraints.Ordered, any] struct { keyHash uint32 key value } // newMapValueNode returns a new instance of mapValueNode. func newMapValueNode[ constraints.Ordered, any]( uint32, , ) *mapValueNode[, ] { return &mapValueNode[, ]{ keyHash: , key: , value: , } } // keyHashValue returns the key hash for this node. func ( *mapValueNode[, ]) () uint32 { return .keyHash } // get returns the value for the given key. func ( *mapValueNode[, ]) ( , uint, uint32, Hasher[]) ( , bool) { if !.Equal(.key, ) { return , false } return .value, true } // set returns a new node with the new value set for the key. If the key equals // the node's key then a new value node is returned. If key is not equal to the // node's key but has the same hash then a hash collision node is returned. // Otherwise the nodes are merged into a branch node. func ( *mapValueNode[, ]) ( , , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { // If the keys match then return a new value node overwriting the value. if .Equal(.key, ) { // Update in-place if mutable. if { .value = return } // Otherwise return a new copy. return newMapValueNode(.keyHash, , ) } * = true // Recursively merge nodes together if key hashes are different. if .keyHash != { return mergeIntoNode[, ](, , , , ) } // Merge into collision node if hash matches. return &mapHashCollisionNode[, ]{keyHash: , entries: []mapEntry[, ]{ {key: .key, value: .value}, {key: , value: }, }} } // delete returns nil if the key matches the node's key. Otherwise returns the original node. func ( *mapValueNode[, ]) ( , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { // Return original node if the keys do not match. if !.Equal(.key, ) { return } // Otherwise remove the node if keys do match. * = true return nil } // mapHashCollisionNode represents a leaf node that contains two or more key/value // pairs with the same key hash. Single pairs for a hash are stored as value nodes. type mapHashCollisionNode[ constraints.Ordered, any] struct { keyHash uint32 // key hash for all entries entries []mapEntry[, ] } // keyHashValue returns the key hash for all entries on the node. func ( *mapHashCollisionNode[, ]) () uint32 { return .keyHash } // indexOf returns the index of the entry for the given key. // Returns -1 if the key does not exist in the node. func ( *mapHashCollisionNode[, ]) ( , Hasher[]) int { for := range .entries { if .Equal(.entries[].key, ) { return } } return -1 } // get returns the value for the given key. func ( *mapHashCollisionNode[, ]) ( , uint, uint32, Hasher[]) ( , bool) { for := range .entries { if .Equal(.entries[].key, ) { return .entries[].value, true } } return , false } // set returns a copy of the node with key set to the given value. func ( *mapHashCollisionNode[, ]) ( , , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { // Merge node with key/value pair if this is not a hash collision. if .keyHash != { * = true return mergeIntoNode[, ](, , , , ) } // Update in-place if mutable. if { if := .indexOf(, ); == -1 { * = true .entries = append(.entries, mapEntry[, ]{, }) } else { .entries[] = mapEntry[, ]{, } } return } // Append to end of node if key doesn't exist & mark resized. // Otherwise copy nodes and overwrite at matching key index. := &mapHashCollisionNode[, ]{keyHash: .keyHash} if := .indexOf(, ); == -1 { * = true .entries = make([]mapEntry[, ], len(.entries)+1) copy(.entries, .entries) .entries[len(.entries)-1] = mapEntry[, ]{, } } else { .entries = make([]mapEntry[, ], len(.entries)) copy(.entries, .entries) .entries[] = mapEntry[, ]{, } } return } // delete returns a node with the given key deleted. Returns the same node if // the key does not exist. If removing the key would shrink the node to a single // entry then a value node is returned. func ( *mapHashCollisionNode[, ]) ( , uint, uint32, Hasher[], bool, *bool) mapNode[, ] { := .indexOf(, ) // Return original node if key is not found. if == -1 { return } // Mark as resized if key exists. * = true // Convert to value node if we move to one entry. if len(.entries) == 2 { return &mapValueNode[, ]{ keyHash: .keyHash, key: .entries[^1].key, value: .entries[^1].value, } } // Remove entry in-place if mutable. if { copy(.entries[:], .entries[+1:]) .entries[len(.entries)-1] = mapEntry[, ]{} .entries = .entries[:len(.entries)-1] return } // Return copy without entry if immutable. := &mapHashCollisionNode[, ]{keyHash: .keyHash, entries: make([]mapEntry[, ], len(.entries)-1)} copy(.entries[:], .entries[:]) copy(.entries[:], .entries[+1:]) return } // mergeIntoNode merges a key/value pair into an existing node. // Caller must verify that node's keyHash is not equal to keyHash. func mergeIntoNode[ constraints.Ordered, any]( mapLeafNode[, ], uint, uint32, , ) mapNode[, ] { := (.keyHashValue() >> ) & mapNodeMask := ( >> ) & mapNodeMask // Recursively build branch nodes to combine the node and its key. := &mapBitmapIndexedNode[, ]{bitmap: (1 << ) | (1 << )} if == { .nodes = []mapNode[, ]{(, +mapNodeBits, , , )} } else { if := newMapValueNode(, , ); < { .nodes = []mapNode[, ]{, } } else { .nodes = []mapNode[, ]{, } } } return } // mapEntry represents a single key/value pair. type mapEntry[ constraints.Ordered, any] struct { key value } // MapIterator represents an iterator over a map's key/value pairs. Although // map keys are not sorted, the iterator's order is deterministic. type MapIterator[ constraints.Ordered, any] struct { m *Map[, ] // source map stack [32]mapIteratorElem[, ] // search stack depth int // stack depth } // Done returns true if no more elements remain in the iterator. func ( *MapIterator[, ]) () bool { return .depth == -1 } // First resets the iterator to the first key/value pair. func ( *MapIterator[, ]) () { // Exit immediately if the map is empty. if .m.root == nil { .depth = -1 return } // Initialize the stack to the left most element. .stack[0] = mapIteratorElem[, ]{node: .m.root} .depth = 0 .first() } // Next returns the next key/value pair. Returns a nil key when no elements remain. func ( *MapIterator[, ]) () ( , , bool) { // Return nil key if iteration is done. if .Done() { return , , false } // Retrieve current index & value. Current node is always a leaf. := &.stack[.depth] switch node := .node.(type) { case *mapArrayNode[, ]: := &.entries[.index] , = .key, .value case *mapValueNode[, ]: , = .key, .value case *mapHashCollisionNode[, ]: := &.entries[.index] , = .key, .value } // Move up stack until we find a node that has remaining position ahead // and move that element forward by one. .next() return , , true } // next moves to the next available key. func ( *MapIterator[, ]) () { for ; .depth >= 0; .depth-- { := &.stack[.depth] switch node := .node.(type) { case *mapArrayNode[, ]: if .index < len(.entries)-1 { .index++ return } case *mapBitmapIndexedNode[, ]: if .index < len(.nodes)-1 { .index++ .stack[.depth+1].node = .nodes[.index] .depth++ .first() return } case *mapHashArrayNode[, ]: for := .index + 1; < len(.nodes); ++ { if .nodes[] != nil { .index = .stack[.depth+1].node = .nodes[.index] .depth++ .first() return } } case *mapValueNode[, ]: continue // always the last value, traverse up case *mapHashCollisionNode[, ]: if .index < len(.entries)-1 { .index++ return } } } } // first positions the stack left most index. // Elements and indexes at and below the current depth are assumed to be correct. func ( *MapIterator[, ]) () { for ; ; .depth++ { := &.stack[.depth] switch node := .node.(type) { case *mapBitmapIndexedNode[, ]: .index = 0 .stack[.depth+1].node = .nodes[0] case *mapHashArrayNode[, ]: for := 0; < len(.nodes); ++ { if .nodes[] != nil { // find first node .index = .stack[.depth+1].node = .nodes[] break } } default: // *mapArrayNode, mapLeafNode .index = 0 return } } } // mapIteratorElem represents a node/index pair in the MapIterator stack. type mapIteratorElem[ constraints.Ordered, any] struct { node mapNode[, ] index int } // Sorted map child node limit size. const ( sortedMapNodeSize = 32 ) // SortedMap represents a map of key/value pairs sorted by key. The sort order // is determined by the Comparer used by the map. // // This map is implemented as a B+tree. type SortedMap[ constraints.Ordered, any] struct { size int // total number of key/value pairs root sortedMapNode[, ] // root of b+tree comparer Comparer[] } // NewSortedMap returns a new instance of SortedMap. If comparer is nil then // a default comparer is set after the first key is inserted. Default comparers // exist for int, string, and byte slice keys. func [ constraints.Ordered, any]( Comparer[]) *SortedMap[, ] { return &SortedMap[, ]{ comparer: , } } // Len returns the number of elements in the sorted map. func ( *SortedMap[, ]) () int { return .size } // Get returns the value for a given key and a flag indicating if the key is set. // The flag can be used to distinguish between a nil-set key versus an unset key. func ( *SortedMap[, ]) ( ) (, bool) { if .root == nil { var return , false } return .root.get(, .comparer) } // Set returns a copy of the map with the key set to the given value. func ( *SortedMap[, ]) ( , ) *SortedMap[, ] { return .set(, , false) } func ( *SortedMap[, ]) ( , , bool) *SortedMap[, ] { // Set a comparer on the first value if one does not already exist. := .comparer if == nil { = NewComparer[]() } // Create copy, if necessary. := if ! { = .clone() } .comparer = // If no values are set then initialize with a leaf node. if .root == nil { .size = 1 .root = &sortedMapLeafNode[, ]{entries: []mapEntry[, ]{{key: , value: }}} return } // Otherwise delegate to root node. // If a split occurs then grow the tree from the root. var bool , := .root.set(, , , , &) if != nil { = newSortedMapBranchNode(, ) } // Update root and size (if resized). .size = .size .root = if { .size++ } return } // Delete returns a copy of the map with the key removed. // Returns the original map if key does not exist. func ( *SortedMap[, ]) ( ) *SortedMap[, ] { return .delete(, false) } func ( *SortedMap[, ]) ( , bool) *SortedMap[, ] { // Return original map if no keys exist. if .root == nil { return } // If the delete did not change the node then return the original map. var bool := .root.delete(, .comparer, , &) if ! { return } // Create copy, if necessary. := if ! { = .clone() } // Update root and size. .size = .size - 1 .root = return } // clone returns a shallow copy of m. func ( *SortedMap[, ]) () *SortedMap[, ] { := * return & } // Iterator returns a new iterator for this map positioned at the first key. func ( *SortedMap[, ]) () *SortedMapIterator[, ] { := &SortedMapIterator[, ]{m: } .First() return } // SortedMapBuilder represents an efficient builder for creating sorted maps. type SortedMapBuilder[ constraints.Ordered, any] struct { m *SortedMap[, ] // current state } // NewSortedMapBuilder returns a new instance of SortedMapBuilder. func [ constraints.Ordered, any]( Comparer[]) *SortedMapBuilder[, ] { return &SortedMapBuilder[, ]{m: NewSortedMap[, ]()} } // SortedMap returns the current copy of the map. // The returned map is safe to use even if after the builder continues to be used. func ( *SortedMapBuilder[, ]) () *SortedMap[, ] { assert(.m != nil, "immutable.SortedMapBuilder.Map(): duplicate call to fetch map") := .m .m = nil return } // Len returns the number of elements in the underlying map. func ( *SortedMapBuilder[, ]) () int { assert(.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") return .m.Len() } // Get returns the value for the given key. func ( *SortedMapBuilder[, ]) ( ) ( , bool) { assert(.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") return .m.Get() } // Set sets the value of the given key. See SortedMap.Set() for additional details. func ( *SortedMapBuilder[, ]) ( , ) { assert(.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") .m = .m.set(, , true) } // Delete removes the given key. See SortedMap.Delete() for additional details. func ( *SortedMapBuilder[, ]) ( ) { assert(.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") .m = .m.delete(, true) } // Iterator returns a new iterator for the underlying map positioned at the first key. func ( *SortedMapBuilder[, ]) () *SortedMapIterator[, ] { assert(.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") return .m.Iterator() } // sortedMapNode represents a branch or leaf node in the sorted map. type sortedMapNode[ constraints.Ordered, any] interface { minKey() indexOf(key , c Comparer[]) int get(key , c Comparer[]) (value , ok bool) set(key , value , c Comparer[], mutable bool, resized *bool) (sortedMapNode[, ], sortedMapNode[, ]) delete(key , c Comparer[], mutable bool, resized *bool) sortedMapNode[, ] } var _ sortedMapNode[string, any] = (*sortedMapBranchNode[string, any])(nil) var _ sortedMapNode[string, any] = (*sortedMapLeafNode[string, any])(nil) // sortedMapBranchNode represents a branch in the sorted map. type sortedMapBranchNode[ constraints.Ordered, any] struct { elems []sortedMapBranchElem[, ] } // newSortedMapBranchNode returns a new branch node with the given child nodes. func newSortedMapBranchNode[ constraints.Ordered, any]( ...sortedMapNode[, ]) *sortedMapBranchNode[, ] { // Fetch min keys for every child. := make([]sortedMapBranchElem[, ], len()) for , := range { [] = sortedMapBranchElem[, ]{ key: .minKey(), node: , } } return &sortedMapBranchNode[, ]{elems: } } // minKey returns the lowest key stored in this node's tree. func ( *sortedMapBranchNode[, ]) () { return .elems[0].node.minKey() } // indexOf returns the index of the key within the child nodes. func ( *sortedMapBranchNode[, ]) ( , Comparer[]) int { if := sort.Search(len(.elems), func( int) bool { return .Compare(.elems[].key, ) == 1 }); > 0 { return - 1 } return 0 } // get returns the value for the given key. func ( *sortedMapBranchNode[, ]) ( , Comparer[]) ( , bool) { := .indexOf(, ) return .elems[].node.get(, ) } // set returns a copy of the node with the key set to the given value. func ( *sortedMapBranchNode[, ]) ( , , Comparer[], bool, *bool) (sortedMapNode[, ], sortedMapNode[, ]) { := .indexOf(, ) // Delegate insert to child node. , := .elems[].node.set(, , , , ) // Update in-place, if mutable. if { .elems[] = sortedMapBranchElem[, ]{key: .minKey(), node: } if != nil { .elems = append(.elems, sortedMapBranchElem[, ]{}) copy(.elems[+1:], .elems[:]) .elems[+1] = sortedMapBranchElem[, ]{key: .minKey(), node: } } // If the child splits and we have no more room then we split too. if len(.elems) > sortedMapNodeSize { := len(.elems) / 2 := &sortedMapBranchNode[, ]{elems: .elems[::]} := &sortedMapBranchNode[, ]{elems: .elems[:]} return , } return , nil } // If no split occurs, copy branch and update keys. // If the child splits, insert new key/child into copy of branch. var sortedMapBranchNode[, ] if == nil { .elems = make([]sortedMapBranchElem[, ], len(.elems)) copy(.elems, .elems) .elems[] = sortedMapBranchElem[, ]{ key: .minKey(), node: , } } else { .elems = make([]sortedMapBranchElem[, ], len(.elems)+1) copy(.elems[:], .elems[:]) copy(.elems[+1:], .elems[:]) .elems[] = sortedMapBranchElem[, ]{ key: .minKey(), node: , } .elems[+1] = sortedMapBranchElem[, ]{ key: .minKey(), node: , } } // If the child splits and we have no more room then we split too. if len(.elems) > sortedMapNodeSize { := len(.elems) / 2 := &sortedMapBranchNode[, ]{elems: .elems[::]} := &sortedMapBranchNode[, ]{elems: .elems[:]} return , } // Otherwise return the new branch node with the updated entry. return &, nil } // delete returns a node with the key removed. Returns the same node if the key // does not exist. Returns nil if all child nodes are removed. func ( *sortedMapBranchNode[, ]) ( , Comparer[], bool, *bool) sortedMapNode[, ] { := .indexOf(, ) // Return original node if child has not changed. := .elems[].node.delete(, , , ) if !* { return } // Remove child if it is now nil. if == nil { // If this node will become empty then simply return nil. if len(.elems) == 1 { return nil } // If mutable, update in-place. if { copy(.elems[:], .elems[+1:]) .elems[len(.elems)-1] = sortedMapBranchElem[, ]{} .elems = .elems[:len(.elems)-1] return } // Return a copy without the given node. := &sortedMapBranchNode[, ]{elems: make([]sortedMapBranchElem[, ], len(.elems)-1)} copy(.elems[:], .elems[:]) copy(.elems[:], .elems[+1:]) return } // If mutable, update in-place. if { .elems[] = sortedMapBranchElem[, ]{key: .minKey(), node: } return } // Return a copy with the updated node. := &sortedMapBranchNode[, ]{elems: make([]sortedMapBranchElem[, ], len(.elems))} copy(.elems, .elems) .elems[] = sortedMapBranchElem[, ]{ key: .minKey(), node: , } return } type sortedMapBranchElem[ constraints.Ordered, any] struct { key node sortedMapNode[, ] } // sortedMapLeafNode represents a leaf node in the sorted map. type sortedMapLeafNode[ constraints.Ordered, any] struct { entries []mapEntry[, ] } // minKey returns the first key stored in this node. func ( *sortedMapLeafNode[, ]) () { return .entries[0].key } // indexOf returns the index of the given key. func ( *sortedMapLeafNode[, ]) ( , Comparer[]) int { return sort.Search(len(.entries), func( int) bool { return .Compare(.entries[].key, ) != -1 // GTE }) } // get returns the value of the given key. func ( *sortedMapLeafNode[, ]) ( , Comparer[]) ( , bool) { := .indexOf(, ) // If the index is beyond the entry count or the key is not equal then return 'not found'. if == len(.entries) || .Compare(.entries[].key, ) != 0 { return , false } // If the key matches then return its value. return .entries[].value, true } // set returns a copy of node with the key set to the given value. If the update // causes the node to grow beyond the maximum size then it is split in two. func ( *sortedMapLeafNode[, ]) ( , , Comparer[], bool, *bool) (sortedMapNode[, ], sortedMapNode[, ]) { // Find the insertion index for the key. := .indexOf(, ) := < len(.entries) && .Compare(.entries[].key, ) == 0 // Update in-place, if mutable. if { if ! { * = true .entries = append(.entries, mapEntry[, ]{}) copy(.entries[+1:], .entries[:]) } .entries[] = mapEntry[, ]{key: , value: } // If the key doesn't exist and we exceed our max allowed values then split. if len(.entries) > sortedMapNodeSize { := len(.entries) / 2 := &sortedMapLeafNode[, ]{entries: .entries[::]} := &sortedMapLeafNode[, ]{entries: .entries[:]} return , } return , nil } // If the key matches then simply return a copy with the entry overridden. // If there is no match then insert new entry and mark as resized. var []mapEntry[, ] if { = make([]mapEntry[, ], len(.entries)) copy(, .entries) [] = mapEntry[, ]{key: , value: } } else { * = true = make([]mapEntry[, ], len(.entries)+1) copy([:], .entries[:]) [] = mapEntry[, ]{key: , value: } copy([+1:], .entries[:]) } // If the key doesn't exist and we exceed our max allowed values then split. if len() > sortedMapNodeSize { := len() / 2 := &sortedMapLeafNode[, ]{entries: [::]} := &sortedMapLeafNode[, ]{entries: [:]} return , } // Otherwise return the new leaf node with the updated entry. return &sortedMapLeafNode[, ]{entries: }, nil } // delete returns a copy of node with key removed. Returns the original node if // the key does not exist. Returns nil if the removed key is the last remaining key. func ( *sortedMapLeafNode[, ]) ( , Comparer[], bool, *bool) sortedMapNode[, ] { := .indexOf(, ) // Return original node if key is not found. if >= len(.entries) || .Compare(.entries[].key, ) != 0 { return } * = true // If this is the last entry then return nil. if len(.entries) == 1 { return nil } // Update in-place, if mutable. if { copy(.entries[:], .entries[+1:]) .entries[len(.entries)-1] = mapEntry[, ]{} .entries = .entries[:len(.entries)-1] return } // Return copy of node with entry removed. := &sortedMapLeafNode[, ]{entries: make([]mapEntry[, ], len(.entries)-1)} copy(.entries[:], .entries[:]) copy(.entries[:], .entries[+1:]) return } // SortedMapIterator represents an iterator over a sorted map. // Iteration can occur in natural or reverse order based on use of Next() or Prev(). type SortedMapIterator[ constraints.Ordered, any] struct { m *SortedMap[, ] // source map stack [32]sortedMapIteratorElem[, ] // search stack depth int // stack depth } // Done returns true if no more key/value pairs remain in the iterator. func ( *SortedMapIterator[, ]) () bool { return .depth == -1 } // First moves the iterator to the first key/value pair. func ( *SortedMapIterator[, ]) () { if .m.root == nil { .depth = -1 return } .stack[0] = sortedMapIteratorElem[, ]{node: .m.root} .depth = 0 .first() } // Last moves the iterator to the last key/value pair. func ( *SortedMapIterator[, ]) () { if .m.root == nil { .depth = -1 return } .stack[0] = sortedMapIteratorElem[, ]{node: .m.root} .depth = 0 .last() } // Seek moves the iterator position to the given key in the map. // If the key does not exist then the next key is used. If no more keys exist // then the iteartor is marked as done. func ( *SortedMapIterator[, ]) ( ) { if .m.root == nil { .depth = -1 return } .stack[0] = sortedMapIteratorElem[, ]{node: .m.root} .depth = 0 .seek() } // Next returns the current key/value pair and moves the iterator forward. // Returns a nil key if the there are no more elements to return. func ( *SortedMapIterator[, ]) () ( , , bool) { // Return nil key if iteration is complete. if .Done() { return , , false } // Retrieve current key/value pair. := &.stack[.depth] := .node.(*sortedMapLeafNode[, ]) := &.entries[.index] , = .key, .value // Move to the next available key/value pair. .next() // Only occurs when iterator is done. return , , true } // next moves to the next key. If no keys are after then depth is set to -1. func ( *SortedMapIterator[, ]) () { for ; .depth >= 0; .depth-- { := &.stack[.depth] switch node := .node.(type) { case *sortedMapLeafNode[, ]: if .index < len(.entries)-1 { .index++ return } case *sortedMapBranchNode[, ]: if .index < len(.elems)-1 { .index++ .stack[.depth+1].node = .elems[.index].node .depth++ .first() return } } } } // Prev returns the current key/value pair and moves the iterator backward. // Returns a nil key if the there are no more elements to return. func ( *SortedMapIterator[, ]) () ( , , bool) { // Return nil key if iteration is complete. if .Done() { return , , false } // Retrieve current key/value pair. := &.stack[.depth] := .node.(*sortedMapLeafNode[, ]) := &.entries[.index] , = .key, .value .prev() return , , true } // prev moves to the previous key. If no keys are before then depth is set to -1. func ( *SortedMapIterator[, ]) () { for ; .depth >= 0; .depth-- { := &.stack[.depth] switch node := .node.(type) { case *sortedMapLeafNode[, ]: if .index > 0 { .index-- return } case *sortedMapBranchNode[, ]: if .index > 0 { .index-- .stack[.depth+1].node = .elems[.index].node .depth++ .last() return } } } } // first positions the stack to the leftmost key from the current depth. // Elements and indexes below the current depth are assumed to be correct. func ( *SortedMapIterator[, ]) () { for { := &.stack[.depth] .index = 0 switch node := .node.(type) { case *sortedMapBranchNode[, ]: .stack[.depth+1] = sortedMapIteratorElem[, ]{node: .elems[.index].node} .depth++ case *sortedMapLeafNode[, ]: return } } } // last positions the stack to the rightmost key from the current depth. // Elements and indexes below the current depth are assumed to be correct. func ( *SortedMapIterator[, ]) () { for { := &.stack[.depth] switch node := .node.(type) { case *sortedMapBranchNode[, ]: .index = len(.elems) - 1 .stack[.depth+1] = sortedMapIteratorElem[, ]{node: .elems[.index].node} .depth++ case *sortedMapLeafNode[, ]: .index = len(.entries) - 1 return } } } // seek positions the stack to the given key from the current depth. // Elements and indexes below the current depth are assumed to be correct. func ( *SortedMapIterator[, ]) ( ) { for { := &.stack[.depth] .index = .node.indexOf(, .m.comparer) switch node := .node.(type) { case *sortedMapBranchNode[, ]: .stack[.depth+1] = sortedMapIteratorElem[, ]{node: .elems[.index].node} .depth++ case *sortedMapLeafNode[, ]: if .index == len(.entries) { .next() } return } } } // sortedMapIteratorElem represents node/index pair in the SortedMapIterator stack. type sortedMapIteratorElem[ constraints.Ordered, any] struct { node sortedMapNode[, ] index int } // Hasher hashes keys and checks them for equality. type Hasher[ constraints.Ordered] interface { // Computes a hash for key. Hash(key ) uint32 // Returns true if a and b are equal. Equal(a, b ) bool } // NewHasher returns the built-in hasher for a given key type. func [ constraints.Ordered]( ) Hasher[] { // Attempt to use non-reflection based hasher first. switch (any()).(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, string: return &defaultHasher[]{} } // Fallback to reflection-based hasher otherwise. // This is used when caller wraps a type around a primitive type. switch reflect.TypeOf().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[]{} } // If no hashers match then panic. // This is a compile time issue so it should not return an error. panic(fmt.Sprintf("immutable.NewHasher: must set hasher for %T type", )) } // Hash returns a hash for value. func hashString( string) uint32 { var uint32 for , := 0, ; < len(); ++ { = 31* + uint32([]) } return } // reflectIntHasher implements a reflection-based Hasher for int keys. type reflectHasher[ constraints.Ordered] struct{} // Hash returns a hash for key. func ( *reflectHasher[]) ( ) uint32 { switch reflect.TypeOf().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return hashUint64(uint64(reflect.ValueOf().Int())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return hashUint64(reflect.ValueOf().Uint()) case reflect.String: var uint32 := reflect.ValueOf().String() for := 0; < len(); ++ { = 31* + uint32([]) } return } panic(fmt.Sprintf("immutable.reflectHasher.Hash: reflectHasher does not support %T type", )) } // Equal returns true if a is equal to b. Otherwise returns false. // Panics if a and b are not ints. func ( *reflectHasher[]) (, ) bool { switch reflect.TypeOf().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return reflect.ValueOf().Int() == reflect.ValueOf().Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return reflect.ValueOf().Uint() == reflect.ValueOf().Uint() case reflect.String: return reflect.ValueOf().String() == reflect.ValueOf().String() } panic(fmt.Sprintf("immutable.reflectHasher.Equal: reflectHasher does not support %T type", )) } // hashUint64 returns a 32-bit hash for a 64-bit value. func hashUint64( uint64) uint32 { := for > 0xffffffff { /= 0xffffffff ^= } return uint32() } // defaultHasher implements Hasher. type defaultHasher[ constraints.Ordered] struct{} // Hash returns a hash for key. func ( *defaultHasher[]) ( ) uint32 { // Attempt to use non-reflection based hasher first. switch x := (any()).(type) { case int: return hashUint64(uint64()) case int8: return hashUint64(uint64()) case int16: return hashUint64(uint64()) case int32: return hashUint64(uint64()) case int64: return hashUint64(uint64()) case uint: return hashUint64(uint64()) case uint8: return hashUint64(uint64()) case uint16: return hashUint64(uint64()) case uint32: return hashUint64(uint64()) case uint64: return hashUint64(uint64()) case uintptr: return hashUint64(uint64()) case string: return hashString() } panic(fmt.Sprintf("immutable.defaultHasher.Hash: must set comparer for %T type", )) } // Equal returns true if a is equal to b. Otherwise returns false. // Panics if a and b are not ints. func ( *defaultHasher[]) (, ) bool { return == } // Comparer allows the comparison of two keys for the purpose of sorting. type Comparer[ constraints.Ordered] interface { // Returns -1 if a is less than b, returns 1 if a is greater than b, // and returns 0 if a is equal to b. Compare(a, b ) int } // NewComparer returns the built-in comparer for a given key type. func [ constraints.Ordered]( ) Comparer[] { // Attempt to use non-reflection based comparer first. switch (any()).(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, string: return &defaultComparer[]{} } // Fallback to reflection-based comparer otherwise. // This is used when caller wraps a type around a primitive type. switch reflect.TypeOf().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[]{} } // If no comparers match then panic. // This is a compile time issue so it should not return an error. panic(fmt.Sprintf("immutable.NewComparer: must set comparer for %T type", )) } // defaultComparer compares two integers. Implements Comparer. type defaultComparer[ constraints.Ordered] struct{} // Compare returns -1 if a is less than b, returns 1 if a is greater than b, and // returns 0 if a is equal to b. Panic if a or b is not an int. func ( *defaultComparer[]) ( , ) int { if < { return -1 } else if > { return 1 } return 0 } // reflectIntComparer compares two int values using reflection. Implements Comparer. type reflectComparer[ constraints.Ordered] struct{} // Compare returns -1 if a is less than b, returns 1 if a is greater than b, and // returns 0 if a is equal to b. Panic if a or b is not an int. func ( *reflectComparer[]) (, ) int { switch reflect.TypeOf().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if , := reflect.ValueOf().Int(), reflect.ValueOf().Int(); < { return -1 } else if > { return 1 } return 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: if , := reflect.ValueOf().Uint(), reflect.ValueOf().Uint(); < { return -1 } else if > { return 1 } return 0 case reflect.String: return strings.Compare(reflect.ValueOf().String(), reflect.ValueOf().String()) } panic(fmt.Sprintf("immutable.reflectComparer.Compare: must set comparer for %T type", )) } func assert( bool, string) { if ! { panic() } }