├── .github └── workflows │ └── test.yml ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── immutable.go ├── immutable_test.go ├── sets.go └── sets_test.go /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: [pull_request] 2 | name: test 3 | jobs: 4 | short: 5 | strategy: 6 | matrix: 7 | os: [ubuntu-latest, windows-latest] 8 | runs-on: ${{ matrix.os }} 9 | steps: 10 | - name: Install Go 11 | uses: actions/setup-go@v2 12 | with: 13 | go-version: 1.18.x 14 | - name: Checkout code 15 | uses: actions/checkout@v2 16 | - name: Short test 17 | run: go test -short . 18 | 19 | full: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Install Go 23 | uses: actions/setup-go@v2 24 | with: 25 | go-version: 1.18.x 26 | - name: Checkout code 27 | uses: actions/checkout@v2 28 | - name: Test 29 | run: go test -parallel 10 . 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Ben Johnson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Immutable [![release](https://img.shields.io/github/release/benbjohnson/immutable.svg)](https://pkg.go.dev/github.com/benbjohnson/immutable) ![test](https://github.com/benbjohnson/immutable/workflows/test/badge.svg) ![coverage](https://img.shields.io/codecov/c/github/benbjohnson/immutable/master.svg) ![license](https://img.shields.io/github/license/benbjohnson/immutable.svg) 2 | ========= 3 | 4 | This repository contains *generic* immutable collection types for Go. It includes 5 | `List`, `Map`, `SortedMap`, `Set` and `SortedSet` implementations. Immutable collections can 6 | provide efficient, lock free sharing of data by requiring that edits to the 7 | collections return new collections. 8 | 9 | The collection types in this library are meant to mimic Go built-in collections 10 | such as`slice` and `map`. The primary usage difference between Go collections 11 | and `immutable` collections is that `immutable` collections always return a new 12 | collection on mutation so you will need to save the new reference. 13 | 14 | Immutable collections are not for every situation, however, as they can incur 15 | additional CPU and memory overhead. Please evaluate the cost/benefit for your 16 | particular project. 17 | 18 | Special thanks to the [Immutable.js](https://immutable-js.github.io/immutable-js/) 19 | team as the `List` & `Map` implementations are loose ports from that project. 20 | 21 | 22 | ## List 23 | 24 | The `List` type represents a sorted, indexed collection of values and operates 25 | similarly to a Go slice. It supports efficient append, prepend, update, and 26 | slice operations. 27 | 28 | 29 | ### Adding list elements 30 | 31 | Elements can be added to the end of the list with the `Append()` method or added 32 | to the beginning of the list with the `Prepend()` method. Unlike Go slices, 33 | prepending is as efficient as appending. 34 | 35 | ```go 36 | // Create a list with 3 elements. 37 | l := immutable.NewList[string]() 38 | l = l.Append("foo") 39 | l = l.Append("bar") 40 | l = l.Prepend("baz") 41 | 42 | fmt.Println(l.Len()) // 3 43 | fmt.Println(l.Get(0)) // "baz" 44 | fmt.Println(l.Get(1)) // "foo" 45 | fmt.Println(l.Get(2)) // "bar" 46 | ``` 47 | 48 | Note that each change to the list results in a new list being created. These 49 | lists are all snapshots at that point in time and cannot be changed so they 50 | are safe to share between multiple goroutines. 51 | 52 | ### Updating list elements 53 | 54 | You can also overwrite existing elements by using the `Set()` method. In the 55 | following example, we'll update the third element in our list and return the 56 | new list to a new variable. You can see that our old `l` variable retains a 57 | snapshot of the original value. 58 | 59 | ```go 60 | l := immutable.NewList[string]() 61 | l = l.Append("foo") 62 | l = l.Append("bar") 63 | newList := l.Set(2, "baz") 64 | 65 | fmt.Println(l.Get(1)) // "bar" 66 | fmt.Println(newList.Get(1)) // "baz" 67 | ``` 68 | 69 | ### Deriving sublists 70 | 71 | You can create a sublist by using the `Slice()` method. This method works with 72 | the same rules as subslicing a Go slice: 73 | 74 | ```go 75 | l = l.Slice(0, 2) 76 | 77 | fmt.Println(l.Len()) // 2 78 | fmt.Println(l.Get(0)) // "baz" 79 | fmt.Println(l.Get(1)) // "foo" 80 | ``` 81 | 82 | Please note that since `List` follows the same rules as slices, it will panic if 83 | you try to `Get()`, `Set()`, or `Slice()` with indexes that are outside of 84 | the range of the `List`. 85 | 86 | 87 | 88 | ### Iterating lists 89 | 90 | Iterators provide a clean, simple way to iterate over the elements of the list 91 | in order. This is more efficient than simply calling `Get()` for each index. 92 | 93 | Below is an example of iterating over all elements of our list from above: 94 | 95 | ```go 96 | itr := l.Iterator() 97 | for !itr.Done() { 98 | index, value, _ := itr.Next() 99 | fmt.Printf("Index %d equals %v\n", index, value) 100 | } 101 | 102 | // Index 0 equals baz 103 | // Index 1 equals foo 104 | ``` 105 | 106 | By default iterators start from index zero, however, the `Seek()` method can be 107 | used to jump to a given index. 108 | 109 | 110 | ### Efficiently building lists 111 | 112 | If you are building large lists, it is significantly more efficient to use the 113 | `ListBuilder`. It uses nearly the same API as `List` except that it updates 114 | a list in-place until you are ready to use it. This can improve bulk list 115 | building by 10x or more. 116 | 117 | ```go 118 | b := immutable.NewListBuilder[string]() 119 | b.Append("foo") 120 | b.Append("bar") 121 | b.Set(2, "baz") 122 | 123 | l := b.List() 124 | fmt.Println(l.Get(0)) // "foo" 125 | fmt.Println(l.Get(1)) // "baz" 126 | ``` 127 | 128 | Builders are invalid after the call to `List()`. 129 | 130 | 131 | ## Map 132 | 133 | The `Map` represents an associative array that maps unique keys to values. It 134 | is implemented to act similarly to the built-in Go `map` type. It is implemented 135 | as a [Hash-Array Mapped Trie](https://lampwww.epfl.ch/papers/idealhashtrees.pdf). 136 | 137 | Maps require a `Hasher` to hash keys and check for equality. There are built-in 138 | hasher implementations for most primitive types such as `int`, `uint`, and 139 | `string` keys. You may pass in a `nil` hasher to `NewMap()` if you are using 140 | one of these key types. 141 | 142 | ### Setting map key/value pairs 143 | 144 | You can add a key/value pair to the map by using the `Set()` method. It will 145 | add the key if it does not exist or it will overwrite the value for the key if 146 | it does exist. 147 | 148 | Values may be fetched for a key using the `Get()` method. This method returns 149 | the value as well as a flag indicating if the key existed. The flag is useful 150 | to check if a `nil` value was set for a key versus a key did not exist. 151 | 152 | ```go 153 | m := immutable.NewMap[string,int](nil) 154 | m = m.Set("jane", 100) 155 | m = m.Set("susy", 200) 156 | m = m.Set("jane", 300) // overwrite 157 | 158 | fmt.Println(m.Len()) // 2 159 | 160 | v, ok := m.Get("jane") 161 | fmt.Println(v, ok) // 300 true 162 | 163 | v, ok = m.Get("susy") 164 | fmt.Println(v, ok) // 200, true 165 | 166 | v, ok = m.Get("john") 167 | fmt.Println(v, ok) // nil, false 168 | ``` 169 | 170 | 171 | ### Removing map keys 172 | 173 | Keys may be removed from the map by using the `Delete()` method. If the key does 174 | not exist then the original map is returned instead of a new one. 175 | 176 | ```go 177 | m := immutable.NewMap[string,int](nil) 178 | m = m.Set("jane", 100) 179 | m = m.Delete("jane") 180 | 181 | fmt.Println(m.Len()) // 0 182 | 183 | v, ok := m.Get("jane") 184 | fmt.Println(v, ok) // nil false 185 | ``` 186 | 187 | 188 | ### Iterating maps 189 | 190 | Maps are unsorted, however, iterators can be used to loop over all key/value 191 | pairs in the collection. Unlike Go maps, iterators are deterministic when 192 | iterating over key/value pairs. 193 | 194 | ```go 195 | m := immutable.NewMap[string,int](nil) 196 | m = m.Set("jane", 100) 197 | m = m.Set("susy", 200) 198 | 199 | itr := m.Iterator() 200 | for !itr.Done() { 201 | k, v := itr.Next() 202 | fmt.Println(k, v) 203 | } 204 | 205 | // susy 200 206 | // jane 100 207 | ``` 208 | 209 | Note that you should not rely on two maps with the same key/value pairs to 210 | iterate in the same order. Ordering can be insertion order dependent when two 211 | keys generate the same hash. 212 | 213 | 214 | ### Efficiently building maps 215 | 216 | If you are executing multiple mutations on a map, it can be much more efficient 217 | to use the `MapBuilder`. It uses nearly the same API as `Map` except that it 218 | updates a map in-place until you are ready to use it. 219 | 220 | ```go 221 | b := immutable.NewMapBuilder[string,int](nil) 222 | b.Set("foo", 100) 223 | b.Set("bar", 200) 224 | b.Set("foo", 300) 225 | 226 | m := b.Map() 227 | fmt.Println(m.Get("foo")) // "300" 228 | fmt.Println(m.Get("bar")) // "200" 229 | ``` 230 | 231 | Builders are invalid after the call to `Map()`. 232 | 233 | 234 | ### Implementing a custom Hasher 235 | 236 | If you need to use a key type besides `int`, `uint`, or `string` then you'll 237 | need to create a custom `Hasher` implementation and pass it to `NewMap()` on 238 | creation. 239 | 240 | Hashers are fairly simple. They only need to generate hashes for a given key 241 | and check equality given two keys. 242 | 243 | ```go 244 | type Hasher[K any] interface { 245 | Hash(key K) uint32 246 | Equal(a, b K) bool 247 | } 248 | ``` 249 | 250 | Please see the internal `intHasher`, `uintHasher`, `stringHasher`, and 251 | `byteSliceHasher` for examples. 252 | 253 | 254 | ## Sorted Map 255 | 256 | The `SortedMap` represents an associative array that maps unique keys to values. 257 | Unlike the `Map`, however, keys can be iterated over in-order. It is implemented 258 | as a B+tree. 259 | 260 | Sorted maps require a `Comparer` to sort keys and check for equality. There are 261 | built-in comparer implementations for `int`, `uint`, and `string` keys. You may 262 | pass a `nil` comparer to `NewSortedMap()` if you are using one of these key 263 | types. 264 | 265 | The API is identical to the `Map` implementation. The sorted map also has a 266 | companion `SortedMapBuilder` for more efficiently building maps. 267 | 268 | 269 | ### Implementing a custom Comparer 270 | 271 | If you need to use a key type besides `int`, `uint`, or `string` or derived types, then you'll 272 | need to create a custom `Comparer` implementation and pass it to 273 | `NewSortedMap()` on creation. 274 | 275 | Comparers on have one method—`Compare()`. It works the same as the 276 | `strings.Compare()` function. It returns `-1` if `a` is less than `b`, returns 277 | `1` if a is greater than `b`, and returns `0` if `a` is equal to `b`. 278 | 279 | ```go 280 | type Comparer[K any] interface { 281 | Compare(a, b K) int 282 | } 283 | ``` 284 | 285 | Please see the internal `defaultComparer` for an example, bearing in mind that it works for several types. 286 | 287 | ## Set 288 | 289 | The `Set` represents a collection of unique values, and it is implemented as a 290 | wrapper around a `Map[T, struct{}]`. 291 | 292 | Like Maps, Sets require a `Hasher` to hash keys and check for equality. There are built-in 293 | hasher implementations for most primitive types such as `int`, `uint`, and 294 | `string` keys. You may pass in a `nil` hasher to `NewSet()` if you are using 295 | one of these key types. 296 | 297 | 298 | ## Sorted Set 299 | 300 | The `SortedSet` represents a sorted collection of unique values. 301 | Unlike the `Set`, however, keys can be iterated over in-order. It is implemented 302 | as a B+tree. 303 | 304 | Sorted sets require a `Comparer` to sort values and check for equality. There are 305 | built-in comparer implementations for `int`, `uint`, and `string` keys. You may 306 | pass a `nil` comparer to `NewSortedSet()` if you are using one of these key 307 | types. 308 | 309 | The API is identical to the `Set` implementation. 310 | 311 | 312 | ## Contributing 313 | 314 | The goal of `immutable` is to provide stable, reasonably performant, immutable 315 | collections library for Go that has a simple, idiomatic API. As such, additional 316 | features and minor performance improvements will generally not be accepted. If 317 | you have a suggestion for a clearer API or substantial performance improvement, 318 | _please_ open an issue first to discuss. All pull requests without a related 319 | issue will be closed immediately. 320 | 321 | Please submit issues relating to bugs & documentation improvements. 322 | 323 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/benbjohnson/immutable 2 | 3 | go 1.18 4 | 5 | require golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf // indirect 6 | 7 | retract v0.4.2 8 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf h1:oXVg4h2qJDd9htKxb5SCpFBHLipW6hXmL3qpUixS2jw= 2 | golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf/go.mod h1:yh0Ynu2b5ZUe3MQfp2nM0ecK7wsgouWTDN0FNeJuIys= 3 | -------------------------------------------------------------------------------- /immutable.go: -------------------------------------------------------------------------------- 1 | // Package immutable provides immutable collection types. 2 | // 3 | // # Introduction 4 | // 5 | // Immutable collections provide an efficient, safe way to share collections 6 | // of data while minimizing locks. The collections in this package provide 7 | // List, Map, and SortedMap implementations. These act similarly to slices 8 | // and maps, respectively, except that altering a collection returns a new 9 | // copy of the collection with that change. 10 | // 11 | // Because collections are unable to change, they are safe for multiple 12 | // goroutines to read from at the same time without a mutex. However, these 13 | // types of collections come with increased CPU & memory usage as compared 14 | // with Go's built-in collection types so please evaluate for your specific 15 | // use. 16 | // 17 | // # Collection Types 18 | // 19 | // The List type provides an API similar to Go slices. They allow appending, 20 | // prepending, and updating of elements. Elements can also be fetched by index 21 | // or iterated over using a ListIterator. 22 | // 23 | // The Map & SortedMap types provide an API similar to Go maps. They allow 24 | // values to be assigned to unique keys and allow for the deletion of keys. 25 | // Values can be fetched by key and key/value pairs can be iterated over using 26 | // the appropriate iterator type. Both map types provide the same API. The 27 | // SortedMap, however, provides iteration over sorted keys while the Map 28 | // provides iteration over unsorted keys. Maps improved performance and memory 29 | // usage as compared to SortedMaps. 30 | // 31 | // # Hashing and Sorting 32 | // 33 | // Map types require the use of a Hasher implementation to calculate hashes for 34 | // their keys and check for key equality. SortedMaps require the use of a 35 | // Comparer implementation to sort keys in the map. 36 | // 37 | // These collection types automatically provide built-in hasher and comparers 38 | // for int, string, and byte slice keys. If you are using one of these key types 39 | // then simply pass a nil into the constructor. Otherwise you will need to 40 | // implement a custom Hasher or Comparer type. Please see the provided 41 | // implementations for reference. 42 | package immutable 43 | 44 | import ( 45 | "fmt" 46 | "math/bits" 47 | "reflect" 48 | "sort" 49 | "strings" 50 | 51 | "golang.org/x/exp/constraints" 52 | ) 53 | 54 | // List is a dense, ordered, indexed collections. They are analogous to slices 55 | // in Go. They can be updated by appending to the end of the list, prepending 56 | // values to the beginning of the list, or updating existing indexes in the 57 | // list. 58 | type List[T any] struct { 59 | root listNode[T] // root node 60 | origin int // offset to zero index element 61 | size int // total number of elements in use 62 | } 63 | 64 | // NewList returns a new empty instance of List. 65 | func NewList[T any](values ...T) *List[T] { 66 | l := &List[T]{ 67 | root: &listLeafNode[T]{}, 68 | } 69 | for _, value := range values { 70 | l.append(value, true) 71 | } 72 | return l 73 | } 74 | 75 | // clone returns a copy of the list. 76 | func (l *List[T]) clone() *List[T] { 77 | other := *l 78 | return &other 79 | } 80 | 81 | // Len returns the number of elements in the list. 82 | func (l *List[T]) Len() int { 83 | return l.size 84 | } 85 | 86 | // cap returns the total number of possible elements for the current depth. 87 | func (l *List[T]) cap() int { 88 | return 1 << (l.root.depth() * listNodeBits) 89 | } 90 | 91 | // Get returns the value at the given index. Similar to slices, this method will 92 | // panic if index is below zero or is greater than or equal to the list size. 93 | func (l *List[T]) Get(index int) T { 94 | if index < 0 || index >= l.size { 95 | panic(fmt.Sprintf("immutable.List.Get: index %d out of bounds", index)) 96 | } 97 | return l.root.get(l.origin + index) 98 | } 99 | 100 | // Set returns a new list with value set at index. Similar to slices, this 101 | // method will panic if index is below zero or if the index is greater than 102 | // or equal to the list size. 103 | func (l *List[T]) Set(index int, value T) *List[T] { 104 | return l.set(index, value, false) 105 | } 106 | 107 | func (l *List[T]) set(index int, value T, mutable bool) *List[T] { 108 | if index < 0 || index >= l.size { 109 | panic(fmt.Sprintf("immutable.List.Set: index %d out of bounds", index)) 110 | } 111 | other := l 112 | if !mutable { 113 | other = l.clone() 114 | } 115 | other.root = other.root.set(l.origin+index, value, mutable) 116 | return other 117 | } 118 | 119 | // Append returns a new list with value added to the end of the list. 120 | func (l *List[T]) Append(value T) *List[T] { 121 | return l.append(value, false) 122 | } 123 | 124 | func (l *List[T]) append(value T, mutable bool) *List[T] { 125 | other := l 126 | if !mutable { 127 | other = l.clone() 128 | } 129 | 130 | // Expand list to the right if no slots remain. 131 | if other.size+other.origin >= l.cap() { 132 | newRoot := &listBranchNode[T]{d: other.root.depth() + 1} 133 | newRoot.children[0] = other.root 134 | other.root = newRoot 135 | } 136 | 137 | // Increase size and set the last element to the new value. 138 | other.size++ 139 | other.root = other.root.set(other.origin+other.size-1, value, mutable) 140 | return other 141 | } 142 | 143 | // Prepend returns a new list with value(s) added to the beginning of the list. 144 | func (l *List[T]) Prepend(value T) *List[T] { 145 | return l.prepend(value, false) 146 | } 147 | 148 | func (l *List[T]) prepend(value T, mutable bool) *List[T] { 149 | other := l 150 | if !mutable { 151 | other = l.clone() 152 | } 153 | 154 | // Expand list to the left if no slots remain. 155 | if other.origin == 0 { 156 | newRoot := &listBranchNode[T]{d: other.root.depth() + 1} 157 | newRoot.children[listNodeSize-1] = other.root 158 | other.root = newRoot 159 | other.origin += (listNodeSize - 1) << (other.root.depth() * listNodeBits) 160 | } 161 | 162 | // Increase size and move origin back. Update first element to value. 163 | other.size++ 164 | other.origin-- 165 | other.root = other.root.set(other.origin, value, mutable) 166 | return other 167 | } 168 | 169 | // Slice returns a new list of elements between start index and end index. 170 | // Similar to slices, this method will panic if start or end are below zero or 171 | // greater than the list size. A panic will also occur if start is greater than 172 | // end. 173 | // 174 | // Unlike Go slices, references to inaccessible elements will be automatically 175 | // removed so they can be garbage collected. 176 | func (l *List[T]) Slice(start, end int) *List[T] { 177 | return l.slice(start, end, false) 178 | } 179 | 180 | func (l *List[T]) slice(start, end int, mutable bool) *List[T] { 181 | // Panics similar to Go slices. 182 | if start < 0 || start > l.size { 183 | panic(fmt.Sprintf("immutable.List.Slice: start index %d out of bounds", start)) 184 | } else if end < 0 || end > l.size { 185 | panic(fmt.Sprintf("immutable.List.Slice: end index %d out of bounds", end)) 186 | } else if start > end { 187 | panic(fmt.Sprintf("immutable.List.Slice: invalid slice index: [%d:%d]", start, end)) 188 | } 189 | 190 | // Return the same list if the start and end are the entire range. 191 | if start == 0 && end == l.size { 192 | return l 193 | } 194 | 195 | // Create copy, if immutable. 196 | other := l 197 | if !mutable { 198 | other = l.clone() 199 | } 200 | 201 | // Update origin/size. 202 | other.origin = l.origin + start 203 | other.size = end - start 204 | 205 | // Contract tree while the start & end are in the same child node. 206 | for other.root.depth() > 1 { 207 | i := (other.origin >> (other.root.depth() * listNodeBits)) & listNodeMask 208 | j := ((other.origin + other.size - 1) >> (other.root.depth() * listNodeBits)) & listNodeMask 209 | if i != j { 210 | break // branch contains at least two nodes, exit 211 | } 212 | 213 | // Replace the current root with the single child & update origin offset. 214 | other.origin -= i << (other.root.depth() * listNodeBits) 215 | other.root = other.root.(*listBranchNode[T]).children[i] 216 | } 217 | 218 | // Ensure all references are removed before start & after end. 219 | other.root = other.root.deleteBefore(other.origin, mutable) 220 | other.root = other.root.deleteAfter(other.origin+other.size-1, mutable) 221 | 222 | return other 223 | } 224 | 225 | // Iterator returns a new iterator for this list positioned at the first index. 226 | func (l *List[T]) Iterator() *ListIterator[T] { 227 | itr := &ListIterator[T]{list: l} 228 | itr.First() 229 | return itr 230 | } 231 | 232 | // ListBuilder represents an efficient builder for creating new Lists. 233 | type ListBuilder[T any] struct { 234 | list *List[T] // current state 235 | } 236 | 237 | // NewListBuilder returns a new instance of ListBuilder. 238 | func NewListBuilder[T any]() *ListBuilder[T] { 239 | return &ListBuilder[T]{list: NewList[T]()} 240 | } 241 | 242 | // List returns the current copy of the list. 243 | // The builder should not be used again after the list after this call. 244 | func (b *ListBuilder[T]) List() *List[T] { 245 | assert(b.list != nil, "immutable.ListBuilder.List(): duplicate call to fetch list") 246 | list := b.list 247 | b.list = nil 248 | return list 249 | } 250 | 251 | // Len returns the number of elements in the underlying list. 252 | func (b *ListBuilder[T]) Len() int { 253 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 254 | return b.list.Len() 255 | } 256 | 257 | // Get returns the value at the given index. Similar to slices, this method will 258 | // panic if index is below zero or is greater than or equal to the list size. 259 | func (b *ListBuilder[T]) Get(index int) T { 260 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 261 | return b.list.Get(index) 262 | } 263 | 264 | // Set updates the value at the given index. Similar to slices, this method will 265 | // panic if index is below zero or if the index is greater than or equal to the 266 | // list size. 267 | func (b *ListBuilder[T]) Set(index int, value T) { 268 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 269 | b.list = b.list.set(index, value, true) 270 | } 271 | 272 | // Append adds value to the end of the list. 273 | func (b *ListBuilder[T]) Append(value T) { 274 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 275 | b.list = b.list.append(value, true) 276 | } 277 | 278 | // Prepend adds value to the beginning of the list. 279 | func (b *ListBuilder[T]) Prepend(value T) { 280 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 281 | b.list = b.list.prepend(value, true) 282 | } 283 | 284 | // Slice updates the list with a sublist of elements between start and end index. 285 | // See List.Slice() for more details. 286 | func (b *ListBuilder[T]) Slice(start, end int) { 287 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 288 | b.list = b.list.slice(start, end, true) 289 | } 290 | 291 | // Iterator returns a new iterator for the underlying list. 292 | func (b *ListBuilder[T]) Iterator() *ListIterator[T] { 293 | assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation") 294 | return b.list.Iterator() 295 | } 296 | 297 | // Constants for bit shifts used for levels in the List trie. 298 | const ( 299 | listNodeBits = 5 300 | listNodeSize = 1 << listNodeBits 301 | listNodeMask = listNodeSize - 1 302 | ) 303 | 304 | // listNode represents either a branch or leaf node in a List. 305 | type listNode[T any] interface { 306 | depth() uint 307 | get(index int) T 308 | set(index int, v T, mutable bool) listNode[T] 309 | 310 | containsBefore(index int) bool 311 | containsAfter(index int) bool 312 | 313 | deleteBefore(index int, mutable bool) listNode[T] 314 | deleteAfter(index int, mutable bool) listNode[T] 315 | } 316 | 317 | // newListNode returns a leaf node for depth zero, otherwise returns a branch node. 318 | func newListNode[T any](depth uint) listNode[T] { 319 | if depth == 0 { 320 | return &listLeafNode[T]{} 321 | } 322 | return &listBranchNode[T]{d: depth} 323 | } 324 | 325 | // listBranchNode represents a branch of a List tree at a given depth. 326 | type listBranchNode[T any] struct { 327 | d uint // depth 328 | children [listNodeSize]listNode[T] 329 | } 330 | 331 | // depth returns the depth of this branch node from the leaf. 332 | func (n *listBranchNode[T]) depth() uint { return n.d } 333 | 334 | // get returns the child node at the segment of the index for this depth. 335 | func (n *listBranchNode[T]) get(index int) T { 336 | idx := (index >> (n.d * listNodeBits)) & listNodeMask 337 | return n.children[idx].get(index) 338 | } 339 | 340 | // set recursively updates the value at index for each lower depth from the node. 341 | func (n *listBranchNode[T]) set(index int, v T, mutable bool) listNode[T] { 342 | idx := (index >> (n.d * listNodeBits)) & listNodeMask 343 | 344 | // Find child for the given value in the branch. Create new if it doesn't exist. 345 | child := n.children[idx] 346 | if child == nil { 347 | child = newListNode[T](n.depth() - 1) 348 | } 349 | 350 | // Return a copy of this branch with the new child. 351 | var other *listBranchNode[T] 352 | if mutable { 353 | other = n 354 | } else { 355 | tmp := *n 356 | other = &tmp 357 | } 358 | other.children[idx] = child.set(index, v, mutable) 359 | return other 360 | } 361 | 362 | // containsBefore returns true if non-nil values exists between [0,index). 363 | func (n *listBranchNode[T]) containsBefore(index int) bool { 364 | idx := (index >> (n.d * listNodeBits)) & listNodeMask 365 | 366 | // Quickly check if any direct children exist before this segment of the index. 367 | for i := 0; i < idx; i++ { 368 | if n.children[i] != nil { 369 | return true 370 | } 371 | } 372 | 373 | // Recursively check for children directly at the given index at this segment. 374 | if n.children[idx] != nil && n.children[idx].containsBefore(index) { 375 | return true 376 | } 377 | return false 378 | } 379 | 380 | // containsAfter returns true if non-nil values exists between (index,listNodeSize). 381 | func (n *listBranchNode[T]) containsAfter(index int) bool { 382 | idx := (index >> (n.d * listNodeBits)) & listNodeMask 383 | 384 | // Quickly check if any direct children exist after this segment of the index. 385 | for i := idx + 1; i < len(n.children); i++ { 386 | if n.children[i] != nil { 387 | return true 388 | } 389 | } 390 | 391 | // Recursively check for children directly at the given index at this segment. 392 | if n.children[idx] != nil && n.children[idx].containsAfter(index) { 393 | return true 394 | } 395 | return false 396 | } 397 | 398 | // deleteBefore returns a new node with all elements before index removed. 399 | func (n *listBranchNode[T]) deleteBefore(index int, mutable bool) listNode[T] { 400 | // Ignore if no nodes exist before the given index. 401 | if !n.containsBefore(index) { 402 | return n 403 | } 404 | 405 | // Return a copy with any nodes prior to the index removed. 406 | idx := (index >> (n.d * listNodeBits)) & listNodeMask 407 | 408 | var other *listBranchNode[T] 409 | if mutable { 410 | other = n 411 | for i := 0; i < idx; i++ { 412 | n.children[i] = nil 413 | } 414 | } else { 415 | other = &listBranchNode[T]{d: n.d} 416 | copy(other.children[idx:][:], n.children[idx:][:]) 417 | } 418 | 419 | if other.children[idx] != nil { 420 | other.children[idx] = other.children[idx].deleteBefore(index, mutable) 421 | } 422 | return other 423 | } 424 | 425 | // deleteBefore returns a new node with all elements before index removed. 426 | func (n *listBranchNode[T]) deleteAfter(index int, mutable bool) listNode[T] { 427 | // Ignore if no nodes exist after the given index. 428 | if !n.containsAfter(index) { 429 | return n 430 | } 431 | 432 | // Return a copy with any nodes after the index removed. 433 | idx := (index >> (n.d * listNodeBits)) & listNodeMask 434 | 435 | var other *listBranchNode[T] 436 | if mutable { 437 | other = n 438 | for i := idx + 1; i < len(n.children); i++ { 439 | n.children[i] = nil 440 | } 441 | } else { 442 | other = &listBranchNode[T]{d: n.d} 443 | copy(other.children[:idx+1], n.children[:idx+1]) 444 | } 445 | 446 | if other.children[idx] != nil { 447 | other.children[idx] = other.children[idx].deleteAfter(index, mutable) 448 | } 449 | return other 450 | } 451 | 452 | // listLeafNode represents a leaf node in a List. 453 | type listLeafNode[T any] struct { 454 | children [listNodeSize]T 455 | // bitset with ones at occupied positions, position 0 is the LSB 456 | occupied uint32 457 | } 458 | 459 | // depth always returns 0 for leaf nodes. 460 | func (n *listLeafNode[T]) depth() uint { return 0 } 461 | 462 | // get returns the value at the given index. 463 | func (n *listLeafNode[T]) get(index int) T { 464 | return n.children[index&listNodeMask] 465 | } 466 | 467 | // set returns a copy of the node with the value at the index updated to v. 468 | func (n *listLeafNode[T]) set(index int, v T, mutable bool) listNode[T] { 469 | idx := index & listNodeMask 470 | var other *listLeafNode[T] 471 | if mutable { 472 | other = n 473 | } else { 474 | tmp := *n 475 | other = &tmp 476 | } 477 | other.children[idx] = v 478 | other.occupied |= 1 << idx 479 | return other 480 | } 481 | 482 | // containsBefore returns true if non-nil values exists between [0,index). 483 | func (n *listLeafNode[T]) containsBefore(index int) bool { 484 | idx := index & listNodeMask 485 | return bits.TrailingZeros32(n.occupied) < idx 486 | } 487 | 488 | // containsAfter returns true if non-nil values exists between (index,listNodeSize). 489 | func (n *listLeafNode[T]) containsAfter(index int) bool { 490 | idx := index & listNodeMask 491 | lastSetPos := 31 - bits.LeadingZeros32(n.occupied) 492 | return lastSetPos > idx 493 | } 494 | 495 | // deleteBefore returns a new node with all elements before index removed. 496 | func (n *listLeafNode[T]) deleteBefore(index int, mutable bool) listNode[T] { 497 | if !n.containsBefore(index) { 498 | return n 499 | } 500 | 501 | idx := index & listNodeMask 502 | var other *listLeafNode[T] 503 | if mutable { 504 | other = n 505 | var empty T 506 | for i := 0; i < idx; i++ { 507 | other.children[i] = empty 508 | } 509 | } else { 510 | other = &listLeafNode[T]{occupied: n.occupied} 511 | copy(other.children[idx:][:], n.children[idx:][:]) 512 | } 513 | // Set the first idx bits to 0. 514 | other.occupied &= ^((1 << idx) - 1) 515 | return other 516 | } 517 | 518 | // deleteAfter returns a new node with all elements after index removed. 519 | func (n *listLeafNode[T]) deleteAfter(index int, mutable bool) listNode[T] { 520 | if !n.containsAfter(index) { 521 | return n 522 | } 523 | 524 | idx := index & listNodeMask 525 | var other *listLeafNode[T] 526 | if mutable { 527 | other = n 528 | var empty T 529 | for i := idx + 1; i < len(n.children); i++ { 530 | other.children[i] = empty 531 | } 532 | } else { 533 | other = &listLeafNode[T]{occupied: n.occupied} 534 | copy(other.children[:idx+1][:], n.children[:idx+1][:]) 535 | } 536 | // Set bits after idx to 0. idx < 31 because n.containsAfter(index) == true. 537 | other.occupied &= (1 << (idx + 1)) - 1 538 | return other 539 | } 540 | 541 | // ListIterator represents an ordered iterator over a list. 542 | type ListIterator[T any] struct { 543 | list *List[T] // source list 544 | index int // current index position 545 | 546 | stack [32]listIteratorElem[T] // search stack 547 | depth int // stack depth 548 | } 549 | 550 | // Done returns true if no more elements remain in the iterator. 551 | func (itr *ListIterator[T]) Done() bool { 552 | return itr.index < 0 || itr.index >= itr.list.Len() 553 | } 554 | 555 | // First positions the iterator on the first index. 556 | // If source list is empty then no change is made. 557 | func (itr *ListIterator[T]) First() { 558 | if itr.list.Len() != 0 { 559 | itr.Seek(0) 560 | } 561 | } 562 | 563 | // Last positions the iterator on the last index. 564 | // If source list is empty then no change is made. 565 | func (itr *ListIterator[T]) Last() { 566 | if n := itr.list.Len(); n != 0 { 567 | itr.Seek(n - 1) 568 | } 569 | } 570 | 571 | // Seek moves the iterator position to the given index in the list. 572 | // Similar to Go slices, this method will panic if index is below zero or if 573 | // the index is greater than or equal to the list size. 574 | func (itr *ListIterator[T]) Seek(index int) { 575 | // Panic similar to Go slices. 576 | if index < 0 || index >= itr.list.Len() { 577 | panic(fmt.Sprintf("immutable.ListIterator.Seek: index %d out of bounds", index)) 578 | } 579 | itr.index = index 580 | 581 | // Reset to the bottom of the stack at seek to the correct position. 582 | itr.stack[0] = listIteratorElem[T]{node: itr.list.root} 583 | itr.depth = 0 584 | itr.seek(index) 585 | } 586 | 587 | // Next returns the current index and its value & moves the iterator forward. 588 | // Returns an index of -1 if the there are no more elements to return. 589 | func (itr *ListIterator[T]) Next() (index int, value T) { 590 | // Exit immediately if there are no elements remaining. 591 | var empty T 592 | if itr.Done() { 593 | return -1, empty 594 | } 595 | 596 | // Retrieve current index & value. 597 | elem := &itr.stack[itr.depth] 598 | index, value = itr.index, elem.node.(*listLeafNode[T]).children[elem.index] 599 | 600 | // Increase index. If index is at the end then return immediately. 601 | itr.index++ 602 | if itr.Done() { 603 | return index, value 604 | } 605 | 606 | // Move up stack until we find a node that has remaining position ahead. 607 | for ; itr.depth > 0 && itr.stack[itr.depth].index >= listNodeSize-1; itr.depth-- { 608 | } 609 | 610 | // Seek to correct position from current depth. 611 | itr.seek(itr.index) 612 | 613 | return index, value 614 | } 615 | 616 | // Prev returns the current index and value and moves the iterator backward. 617 | // Returns an index of -1 if the there are no more elements to return. 618 | func (itr *ListIterator[T]) Prev() (index int, value T) { 619 | // Exit immediately if there are no elements remaining. 620 | var empty T 621 | if itr.Done() { 622 | return -1, empty 623 | } 624 | 625 | // Retrieve current index & value. 626 | elem := &itr.stack[itr.depth] 627 | index, value = itr.index, elem.node.(*listLeafNode[T]).children[elem.index] 628 | 629 | // Decrease index. If index is past the beginning then return immediately. 630 | itr.index-- 631 | if itr.Done() { 632 | return index, value 633 | } 634 | 635 | // Move up stack until we find a node that has remaining position behind. 636 | for ; itr.depth > 0 && itr.stack[itr.depth].index == 0; itr.depth-- { 637 | } 638 | 639 | // Seek to correct position from current depth. 640 | itr.seek(itr.index) 641 | 642 | return index, value 643 | } 644 | 645 | // seek positions the stack to the given index from the current depth. 646 | // Elements and indexes below the current depth are assumed to be correct. 647 | func (itr *ListIterator[T]) seek(index int) { 648 | // Iterate over each level until we reach a leaf node. 649 | for { 650 | elem := &itr.stack[itr.depth] 651 | elem.index = ((itr.list.origin + index) >> (elem.node.depth() * listNodeBits)) & listNodeMask 652 | 653 | switch node := elem.node.(type) { 654 | case *listBranchNode[T]: 655 | child := node.children[elem.index] 656 | itr.stack[itr.depth+1] = listIteratorElem[T]{node: child} 657 | itr.depth++ 658 | case *listLeafNode[T]: 659 | return 660 | } 661 | } 662 | } 663 | 664 | // listIteratorElem represents the node and it's child index within the stack. 665 | type listIteratorElem[T any] struct { 666 | node listNode[T] 667 | index int 668 | } 669 | 670 | // Size thresholds for each type of branch node. 671 | const ( 672 | maxArrayMapSize = 8 673 | maxBitmapIndexedSize = 16 674 | ) 675 | 676 | // Segment bit shifts within the map tree. 677 | const ( 678 | mapNodeBits = 5 679 | mapNodeSize = 1 << mapNodeBits 680 | mapNodeMask = mapNodeSize - 1 681 | ) 682 | 683 | // Map represents an immutable hash map implementation. The map uses a Hasher 684 | // to generate hashes and check for equality of key values. 685 | // 686 | // It is implemented as an Hash Array Mapped Trie. 687 | type Map[K, V any] struct { 688 | size int // total number of key/value pairs 689 | root mapNode[K, V] // root node of trie 690 | hasher Hasher[K] // hasher implementation 691 | } 692 | 693 | // NewMap returns a new instance of Map. If hasher is nil, a default hasher 694 | // implementation will automatically be chosen based on the first key added. 695 | // Default hasher implementations only exist for int, string, and byte slice types. 696 | func NewMap[K, V any](hasher Hasher[K]) *Map[K, V] { 697 | return &Map[K, V]{ 698 | hasher: hasher, 699 | } 700 | } 701 | 702 | // NewMapOf returns a new instance of Map, containing a map of provided entries. 703 | // 704 | // If hasher is nil, a default hasher implementation will automatically be chosen based on the first key added. 705 | // Default hasher implementations only exist for int, string, and byte slice types. 706 | func NewMapOf[K comparable, V any](hasher Hasher[K], entries map[K]V) *Map[K, V] { 707 | m := &Map[K, V]{ 708 | hasher: hasher, 709 | } 710 | for k, v := range entries { 711 | m.set(k, v, true) 712 | } 713 | return m 714 | } 715 | 716 | // Len returns the number of elements in the map. 717 | func (m *Map[K, V]) Len() int { 718 | return m.size 719 | } 720 | 721 | // clone returns a shallow copy of m. 722 | func (m *Map[K, V]) clone() *Map[K, V] { 723 | other := *m 724 | return &other 725 | } 726 | 727 | // Get returns the value for a given key and a flag indicating whether the 728 | // key exists. This flag distinguishes a nil value set on a key versus a 729 | // non-existent key in the map. 730 | func (m *Map[K, V]) Get(key K) (value V, ok bool) { 731 | var empty V 732 | if m.root == nil { 733 | return empty, false 734 | } 735 | keyHash := m.hasher.Hash(key) 736 | return m.root.get(key, 0, keyHash, m.hasher) 737 | } 738 | 739 | // Set returns a map with the key set to the new value. A nil value is allowed. 740 | // 741 | // This function will return a new map even if the updated value is the same as 742 | // the existing value because Map does not track value equality. 743 | func (m *Map[K, V]) Set(key K, value V) *Map[K, V] { 744 | return m.set(key, value, false) 745 | } 746 | 747 | func (m *Map[K, V]) set(key K, value V, mutable bool) *Map[K, V] { 748 | // Set a hasher on the first value if one does not already exist. 749 | hasher := m.hasher 750 | if hasher == nil { 751 | hasher = NewHasher(key) 752 | } 753 | 754 | // Generate copy if necessary. 755 | other := m 756 | if !mutable { 757 | other = m.clone() 758 | } 759 | other.hasher = hasher 760 | 761 | // If the map is empty, initialize with a simple array node. 762 | if m.root == nil { 763 | other.size = 1 764 | other.root = &mapArrayNode[K, V]{entries: []mapEntry[K, V]{{key: key, value: value}}} 765 | return other 766 | } 767 | 768 | // Otherwise copy the map and delegate insertion to the root. 769 | // Resized will return true if the key does not currently exist. 770 | var resized bool 771 | other.root = m.root.set(key, value, 0, hasher.Hash(key), hasher, mutable, &resized) 772 | if resized { 773 | other.size++ 774 | } 775 | return other 776 | } 777 | 778 | // Delete returns a map with the given key removed. 779 | // Removing a non-existent key will cause this method to return the same map. 780 | func (m *Map[K, V]) Delete(key K) *Map[K, V] { 781 | return m.delete(key, false) 782 | } 783 | 784 | func (m *Map[K, V]) delete(key K, mutable bool) *Map[K, V] { 785 | // Return original map if no keys exist. 786 | if m.root == nil { 787 | return m 788 | } 789 | 790 | // If the delete did not change the node then return the original map. 791 | var resized bool 792 | newRoot := m.root.delete(key, 0, m.hasher.Hash(key), m.hasher, mutable, &resized) 793 | if !resized { 794 | return m 795 | } 796 | 797 | // Generate copy if necessary. 798 | other := m 799 | if !mutable { 800 | other = m.clone() 801 | } 802 | 803 | // Return copy of map with new root and decreased size. 804 | other.size = m.size - 1 805 | other.root = newRoot 806 | return other 807 | } 808 | 809 | // Iterator returns a new iterator for the map. 810 | func (m *Map[K, V]) Iterator() *MapIterator[K, V] { 811 | itr := &MapIterator[K, V]{m: m} 812 | itr.First() 813 | return itr 814 | } 815 | 816 | // MapBuilder represents an efficient builder for creating Maps. 817 | type MapBuilder[K, V any] struct { 818 | m *Map[K, V] // current state 819 | } 820 | 821 | // NewMapBuilder returns a new instance of MapBuilder. 822 | func NewMapBuilder[K, V any](hasher Hasher[K]) *MapBuilder[K, V] { 823 | return &MapBuilder[K, V]{m: NewMap[K, V](hasher)} 824 | } 825 | 826 | // Map returns the underlying map. Only call once. 827 | // Builder is invalid after call. Will panic on second invocation. 828 | func (b *MapBuilder[K, V]) Map() *Map[K, V] { 829 | assert(b.m != nil, "immutable.SortedMapBuilder.Map(): duplicate call to fetch map") 830 | m := b.m 831 | b.m = nil 832 | return m 833 | } 834 | 835 | // Len returns the number of elements in the underlying map. 836 | func (b *MapBuilder[K, V]) Len() int { 837 | assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") 838 | return b.m.Len() 839 | } 840 | 841 | // Get returns the value for the given key. 842 | func (b *MapBuilder[K, V]) Get(key K) (value V, ok bool) { 843 | assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") 844 | return b.m.Get(key) 845 | } 846 | 847 | // Set sets the value of the given key. See Map.Set() for additional details. 848 | func (b *MapBuilder[K, V]) Set(key K, value V) { 849 | assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") 850 | b.m = b.m.set(key, value, true) 851 | } 852 | 853 | // Delete removes the given key. See Map.Delete() for additional details. 854 | func (b *MapBuilder[K, V]) Delete(key K) { 855 | assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") 856 | b.m = b.m.delete(key, true) 857 | } 858 | 859 | // Iterator returns a new iterator for the underlying map. 860 | func (b *MapBuilder[K, V]) Iterator() *MapIterator[K, V] { 861 | assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation") 862 | return b.m.Iterator() 863 | } 864 | 865 | // mapNode represents any node in the map tree. 866 | type mapNode[K, V any] interface { 867 | get(key K, shift uint, keyHash uint32, h Hasher[K]) (value V, ok bool) 868 | set(key K, value V, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] 869 | delete(key K, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] 870 | } 871 | 872 | var _ mapNode[string, any] = (*mapArrayNode[string, any])(nil) 873 | var _ mapNode[string, any] = (*mapBitmapIndexedNode[string, any])(nil) 874 | var _ mapNode[string, any] = (*mapHashArrayNode[string, any])(nil) 875 | var _ mapNode[string, any] = (*mapValueNode[string, any])(nil) 876 | var _ mapNode[string, any] = (*mapHashCollisionNode[string, any])(nil) 877 | 878 | // mapLeafNode represents a node that stores a single key hash at the leaf of the map tree. 879 | type mapLeafNode[K, V any] interface { 880 | mapNode[K, V] 881 | keyHashValue() uint32 882 | } 883 | 884 | var _ mapLeafNode[string, any] = (*mapValueNode[string, any])(nil) 885 | var _ mapLeafNode[string, any] = (*mapHashCollisionNode[string, any])(nil) 886 | 887 | // mapArrayNode is a map node that stores key/value pairs in a slice. 888 | // Entries are stored in insertion order. An array node expands into a bitmap 889 | // indexed node once a given threshold size is crossed. 890 | type mapArrayNode[K, V any] struct { 891 | entries []mapEntry[K, V] 892 | } 893 | 894 | // indexOf returns the entry index of the given key. Returns -1 if key not found. 895 | func (n *mapArrayNode[K, V]) indexOf(key K, h Hasher[K]) int { 896 | for i := range n.entries { 897 | if h.Equal(n.entries[i].key, key) { 898 | return i 899 | } 900 | } 901 | return -1 902 | } 903 | 904 | // get returns the value for the given key. 905 | func (n *mapArrayNode[K, V]) get(key K, shift uint, keyHash uint32, h Hasher[K]) (value V, ok bool) { 906 | i := n.indexOf(key, h) 907 | if i == -1 { 908 | return value, false 909 | } 910 | return n.entries[i].value, true 911 | } 912 | 913 | // set inserts or updates the value for a given key. If the key is inserted and 914 | // the new size crosses the max size threshold, a bitmap indexed node is returned. 915 | func (n *mapArrayNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 916 | idx := n.indexOf(key, h) 917 | 918 | // Mark as resized if the key doesn't exist. 919 | if idx == -1 { 920 | *resized = true 921 | } 922 | 923 | // If we are adding and it crosses the max size threshold, expand the node. 924 | // We do this by continually setting the entries to a value node and expanding. 925 | if idx == -1 && len(n.entries) >= maxArrayMapSize { 926 | var node mapNode[K, V] = newMapValueNode(h.Hash(key), key, value) 927 | for _, entry := range n.entries { 928 | node = node.set(entry.key, entry.value, 0, h.Hash(entry.key), h, false, resized) 929 | } 930 | return node 931 | } 932 | 933 | // Update in-place if mutable. 934 | if mutable { 935 | if idx != -1 { 936 | n.entries[idx] = mapEntry[K, V]{key, value} 937 | } else { 938 | n.entries = append(n.entries, mapEntry[K, V]{key, value}) 939 | } 940 | return n 941 | } 942 | 943 | // Update existing entry if a match is found. 944 | // Otherwise append to the end of the element list if it doesn't exist. 945 | var other mapArrayNode[K, V] 946 | if idx != -1 { 947 | other.entries = make([]mapEntry[K, V], len(n.entries)) 948 | copy(other.entries, n.entries) 949 | other.entries[idx] = mapEntry[K, V]{key, value} 950 | } else { 951 | other.entries = make([]mapEntry[K, V], len(n.entries)+1) 952 | copy(other.entries, n.entries) 953 | other.entries[len(other.entries)-1] = mapEntry[K, V]{key, value} 954 | } 955 | return &other 956 | } 957 | 958 | // delete removes the given key from the node. Returns the same node if key does 959 | // not exist. Returns a nil node when removing the last entry. 960 | func (n *mapArrayNode[K, V]) delete(key K, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 961 | idx := n.indexOf(key, h) 962 | 963 | // Return original node if key does not exist. 964 | if idx == -1 { 965 | return n 966 | } 967 | *resized = true 968 | 969 | // Return nil if this node will contain no nodes. 970 | if len(n.entries) == 1 { 971 | return nil 972 | } 973 | 974 | // Update in-place, if mutable. 975 | if mutable { 976 | copy(n.entries[idx:], n.entries[idx+1:]) 977 | n.entries[len(n.entries)-1] = mapEntry[K, V]{} 978 | n.entries = n.entries[:len(n.entries)-1] 979 | return n 980 | } 981 | 982 | // Otherwise create a copy with the given entry removed. 983 | other := &mapArrayNode[K, V]{entries: make([]mapEntry[K, V], len(n.entries)-1)} 984 | copy(other.entries[:idx], n.entries[:idx]) 985 | copy(other.entries[idx:], n.entries[idx+1:]) 986 | return other 987 | } 988 | 989 | // mapBitmapIndexedNode represents a map branch node with a variable number of 990 | // node slots and indexed using a bitmap. Indexes for the node slots are 991 | // calculated by counting the number of set bits before the target bit using popcount. 992 | type mapBitmapIndexedNode[K, V any] struct { 993 | bitmap uint32 994 | nodes []mapNode[K, V] 995 | } 996 | 997 | // get returns the value for the given key. 998 | func (n *mapBitmapIndexedNode[K, V]) get(key K, shift uint, keyHash uint32, h Hasher[K]) (value V, ok bool) { 999 | bit := uint32(1) << ((keyHash >> shift) & mapNodeMask) 1000 | if (n.bitmap & bit) == 0 { 1001 | return value, false 1002 | } 1003 | child := n.nodes[bits.OnesCount32(n.bitmap&(bit-1))] 1004 | return child.get(key, shift+mapNodeBits, keyHash, h) 1005 | } 1006 | 1007 | // set inserts or updates the value for the given key. If a new key is inserted 1008 | // and the size crosses the max size threshold then a hash array node is returned. 1009 | func (n *mapBitmapIndexedNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1010 | // Extract the index for the bit segment of the key hash. 1011 | keyHashFrag := (keyHash >> shift) & mapNodeMask 1012 | 1013 | // Determine the bit based on the hash index. 1014 | bit := uint32(1) << keyHashFrag 1015 | exists := (n.bitmap & bit) != 0 1016 | 1017 | // Mark as resized if the key doesn't exist. 1018 | if !exists { 1019 | *resized = true 1020 | } 1021 | 1022 | // Find index of node based on popcount of bits before it. 1023 | idx := bits.OnesCount32(n.bitmap & (bit - 1)) 1024 | 1025 | // If the node already exists, delegate set operation to it. 1026 | // If the node doesn't exist then create a simple value leaf node. 1027 | var newNode mapNode[K, V] 1028 | if exists { 1029 | newNode = n.nodes[idx].set(key, value, shift+mapNodeBits, keyHash, h, mutable, resized) 1030 | } else { 1031 | newNode = newMapValueNode(keyHash, key, value) 1032 | } 1033 | 1034 | // Convert to a hash-array node once we exceed the max bitmap size. 1035 | // Copy each node based on their bit position within the bitmap. 1036 | if !exists && len(n.nodes) > maxBitmapIndexedSize { 1037 | var other mapHashArrayNode[K, V] 1038 | for i := uint(0); i < uint(len(other.nodes)); i++ { 1039 | if n.bitmap&(uint32(1)<> shift) & mapNodeMask) 1083 | 1084 | // Return original node if key does not exist. 1085 | if (n.bitmap & bit) == 0 { 1086 | return n 1087 | } 1088 | 1089 | // Find index of node based on popcount of bits before it. 1090 | idx := bits.OnesCount32(n.bitmap & (bit - 1)) 1091 | 1092 | // Delegate delete to child node. 1093 | child := n.nodes[idx] 1094 | newChild := child.delete(key, shift+mapNodeBits, keyHash, h, mutable, resized) 1095 | 1096 | // Return original node if key doesn't exist in child. 1097 | if !*resized { 1098 | return n 1099 | } 1100 | 1101 | // Remove if returned child has been deleted. 1102 | if newChild == nil { 1103 | // If we won't have any children then return nil. 1104 | if len(n.nodes) == 1 { 1105 | return nil 1106 | } 1107 | 1108 | // Update in-place if mutable. 1109 | if mutable { 1110 | n.bitmap ^= bit 1111 | copy(n.nodes[idx:], n.nodes[idx+1:]) 1112 | n.nodes[len(n.nodes)-1] = nil 1113 | n.nodes = n.nodes[:len(n.nodes)-1] 1114 | return n 1115 | } 1116 | 1117 | // Return copy with bit removed from bitmap and node removed from node list. 1118 | other := &mapBitmapIndexedNode[K, V]{bitmap: n.bitmap ^ bit, nodes: make([]mapNode[K, V], len(n.nodes)-1)} 1119 | copy(other.nodes[:idx], n.nodes[:idx]) 1120 | copy(other.nodes[idx:], n.nodes[idx+1:]) 1121 | return other 1122 | } 1123 | 1124 | // Generate copy, if necessary. 1125 | other := n 1126 | if !mutable { 1127 | other = &mapBitmapIndexedNode[K, V]{bitmap: n.bitmap, nodes: make([]mapNode[K, V], len(n.nodes))} 1128 | copy(other.nodes, n.nodes) 1129 | } 1130 | 1131 | // Update child. 1132 | other.nodes[idx] = newChild 1133 | return other 1134 | } 1135 | 1136 | // mapHashArrayNode is a map branch node that stores nodes in a fixed length 1137 | // array. Child nodes are indexed by their index bit segment for the current depth. 1138 | type mapHashArrayNode[K, V any] struct { 1139 | count uint // number of set nodes 1140 | nodes [mapNodeSize]mapNode[K, V] // child node slots, may contain empties 1141 | } 1142 | 1143 | // clone returns a shallow copy of n. 1144 | func (n *mapHashArrayNode[K, V]) clone() *mapHashArrayNode[K, V] { 1145 | other := *n 1146 | return &other 1147 | } 1148 | 1149 | // get returns the value for the given key. 1150 | func (n *mapHashArrayNode[K, V]) get(key K, shift uint, keyHash uint32, h Hasher[K]) (value V, ok bool) { 1151 | node := n.nodes[(keyHash>>shift)&mapNodeMask] 1152 | if node == nil { 1153 | return value, false 1154 | } 1155 | return node.get(key, shift+mapNodeBits, keyHash, h) 1156 | } 1157 | 1158 | // set returns a node with the value set for the given key. 1159 | func (n *mapHashArrayNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1160 | idx := (keyHash >> shift) & mapNodeMask 1161 | node := n.nodes[idx] 1162 | 1163 | // If node at index doesn't exist, create a simple value leaf node. 1164 | // Otherwise delegate set to child node. 1165 | var newNode mapNode[K, V] 1166 | if node == nil { 1167 | *resized = true 1168 | newNode = newMapValueNode(keyHash, key, value) 1169 | } else { 1170 | newNode = node.set(key, value, shift+mapNodeBits, keyHash, h, mutable, resized) 1171 | } 1172 | 1173 | // Generate copy, if necessary. 1174 | other := n 1175 | if !mutable { 1176 | other = n.clone() 1177 | } 1178 | 1179 | // Update child node (and update size, if new). 1180 | if node == nil { 1181 | other.count++ 1182 | } 1183 | other.nodes[idx] = newNode 1184 | return other 1185 | } 1186 | 1187 | // delete returns a node with the given key removed. Returns the same node if 1188 | // the key does not exist. If node shrinks to within bitmap-indexed size then 1189 | // converts to a bitmap-indexed node. 1190 | func (n *mapHashArrayNode[K, V]) delete(key K, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1191 | idx := (keyHash >> shift) & mapNodeMask 1192 | node := n.nodes[idx] 1193 | 1194 | // Return original node if child is not found. 1195 | if node == nil { 1196 | return n 1197 | } 1198 | 1199 | // Return original node if child is unchanged. 1200 | newNode := node.delete(key, shift+mapNodeBits, keyHash, h, mutable, resized) 1201 | if !*resized { 1202 | return n 1203 | } 1204 | 1205 | // If we remove a node and drop below a threshold, convert back to bitmap indexed node. 1206 | if newNode == nil && n.count <= maxBitmapIndexedSize { 1207 | other := &mapBitmapIndexedNode[K, V]{nodes: make([]mapNode[K, V], 0, n.count-1)} 1208 | for i, child := range n.nodes { 1209 | if child != nil && uint32(i) != idx { 1210 | other.bitmap |= 1 << uint(i) 1211 | other.nodes = append(other.nodes, child) 1212 | } 1213 | } 1214 | return other 1215 | } 1216 | 1217 | // Generate copy, if necessary. 1218 | other := n 1219 | if !mutable { 1220 | other = n.clone() 1221 | } 1222 | 1223 | // Return copy of node with child updated. 1224 | other.nodes[idx] = newNode 1225 | if newNode == nil { 1226 | other.count-- 1227 | } 1228 | return other 1229 | } 1230 | 1231 | // mapValueNode represents a leaf node with a single key/value pair. 1232 | // A value node can be converted to a hash collision leaf node if a different 1233 | // key with the same keyHash is inserted. 1234 | type mapValueNode[K, V any] struct { 1235 | keyHash uint32 1236 | key K 1237 | value V 1238 | } 1239 | 1240 | // newMapValueNode returns a new instance of mapValueNode. 1241 | func newMapValueNode[K, V any](keyHash uint32, key K, value V) *mapValueNode[K, V] { 1242 | return &mapValueNode[K, V]{ 1243 | keyHash: keyHash, 1244 | key: key, 1245 | value: value, 1246 | } 1247 | } 1248 | 1249 | // keyHashValue returns the key hash for this node. 1250 | func (n *mapValueNode[K, V]) keyHashValue() uint32 { 1251 | return n.keyHash 1252 | } 1253 | 1254 | // get returns the value for the given key. 1255 | func (n *mapValueNode[K, V]) get(key K, shift uint, keyHash uint32, h Hasher[K]) (value V, ok bool) { 1256 | if !h.Equal(n.key, key) { 1257 | return value, false 1258 | } 1259 | return n.value, true 1260 | } 1261 | 1262 | // set returns a new node with the new value set for the key. If the key equals 1263 | // the node's key then a new value node is returned. If key is not equal to the 1264 | // node's key but has the same hash then a hash collision node is returned. 1265 | // Otherwise the nodes are merged into a branch node. 1266 | func (n *mapValueNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1267 | // If the keys match then return a new value node overwriting the value. 1268 | if h.Equal(n.key, key) { 1269 | // Update in-place if mutable. 1270 | if mutable { 1271 | n.value = value 1272 | return n 1273 | } 1274 | // Otherwise return a new copy. 1275 | return newMapValueNode(n.keyHash, key, value) 1276 | } 1277 | 1278 | *resized = true 1279 | 1280 | // Recursively merge nodes together if key hashes are different. 1281 | if n.keyHash != keyHash { 1282 | return mergeIntoNode[K, V](n, shift, keyHash, key, value) 1283 | } 1284 | 1285 | // Merge into collision node if hash matches. 1286 | return &mapHashCollisionNode[K, V]{keyHash: keyHash, entries: []mapEntry[K, V]{ 1287 | {key: n.key, value: n.value}, 1288 | {key: key, value: value}, 1289 | }} 1290 | } 1291 | 1292 | // delete returns nil if the key matches the node's key. Otherwise returns the original node. 1293 | func (n *mapValueNode[K, V]) delete(key K, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1294 | // Return original node if the keys do not match. 1295 | if !h.Equal(n.key, key) { 1296 | return n 1297 | } 1298 | 1299 | // Otherwise remove the node if keys do match. 1300 | *resized = true 1301 | return nil 1302 | } 1303 | 1304 | // mapHashCollisionNode represents a leaf node that contains two or more key/value 1305 | // pairs with the same key hash. Single pairs for a hash are stored as value nodes. 1306 | type mapHashCollisionNode[K, V any] struct { 1307 | keyHash uint32 // key hash for all entries 1308 | entries []mapEntry[K, V] 1309 | } 1310 | 1311 | // keyHashValue returns the key hash for all entries on the node. 1312 | func (n *mapHashCollisionNode[K, V]) keyHashValue() uint32 { 1313 | return n.keyHash 1314 | } 1315 | 1316 | // indexOf returns the index of the entry for the given key. 1317 | // Returns -1 if the key does not exist in the node. 1318 | func (n *mapHashCollisionNode[K, V]) indexOf(key K, h Hasher[K]) int { 1319 | for i := range n.entries { 1320 | if h.Equal(n.entries[i].key, key) { 1321 | return i 1322 | } 1323 | } 1324 | return -1 1325 | } 1326 | 1327 | // get returns the value for the given key. 1328 | func (n *mapHashCollisionNode[K, V]) get(key K, shift uint, keyHash uint32, h Hasher[K]) (value V, ok bool) { 1329 | for i := range n.entries { 1330 | if h.Equal(n.entries[i].key, key) { 1331 | return n.entries[i].value, true 1332 | } 1333 | } 1334 | return value, false 1335 | } 1336 | 1337 | // set returns a copy of the node with key set to the given value. 1338 | func (n *mapHashCollisionNode[K, V]) set(key K, value V, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1339 | // Merge node with key/value pair if this is not a hash collision. 1340 | if n.keyHash != keyHash { 1341 | *resized = true 1342 | return mergeIntoNode[K, V](n, shift, keyHash, key, value) 1343 | } 1344 | 1345 | // Update in-place if mutable. 1346 | if mutable { 1347 | if idx := n.indexOf(key, h); idx == -1 { 1348 | *resized = true 1349 | n.entries = append(n.entries, mapEntry[K, V]{key, value}) 1350 | } else { 1351 | n.entries[idx] = mapEntry[K, V]{key, value} 1352 | } 1353 | return n 1354 | } 1355 | 1356 | // Append to end of node if key doesn't exist & mark resized. 1357 | // Otherwise copy nodes and overwrite at matching key index. 1358 | other := &mapHashCollisionNode[K, V]{keyHash: n.keyHash} 1359 | if idx := n.indexOf(key, h); idx == -1 { 1360 | *resized = true 1361 | other.entries = make([]mapEntry[K, V], len(n.entries)+1) 1362 | copy(other.entries, n.entries) 1363 | other.entries[len(other.entries)-1] = mapEntry[K, V]{key, value} 1364 | } else { 1365 | other.entries = make([]mapEntry[K, V], len(n.entries)) 1366 | copy(other.entries, n.entries) 1367 | other.entries[idx] = mapEntry[K, V]{key, value} 1368 | } 1369 | return other 1370 | } 1371 | 1372 | // delete returns a node with the given key deleted. Returns the same node if 1373 | // the key does not exist. If removing the key would shrink the node to a single 1374 | // entry then a value node is returned. 1375 | func (n *mapHashCollisionNode[K, V]) delete(key K, shift uint, keyHash uint32, h Hasher[K], mutable bool, resized *bool) mapNode[K, V] { 1376 | idx := n.indexOf(key, h) 1377 | 1378 | // Return original node if key is not found. 1379 | if idx == -1 { 1380 | return n 1381 | } 1382 | 1383 | // Mark as resized if key exists. 1384 | *resized = true 1385 | 1386 | // Convert to value node if we move to one entry. 1387 | if len(n.entries) == 2 { 1388 | return &mapValueNode[K, V]{ 1389 | keyHash: n.keyHash, 1390 | key: n.entries[idx^1].key, 1391 | value: n.entries[idx^1].value, 1392 | } 1393 | } 1394 | 1395 | // Remove entry in-place if mutable. 1396 | if mutable { 1397 | copy(n.entries[idx:], n.entries[idx+1:]) 1398 | n.entries[len(n.entries)-1] = mapEntry[K, V]{} 1399 | n.entries = n.entries[:len(n.entries)-1] 1400 | return n 1401 | } 1402 | 1403 | // Return copy without entry if immutable. 1404 | other := &mapHashCollisionNode[K, V]{keyHash: n.keyHash, entries: make([]mapEntry[K, V], len(n.entries)-1)} 1405 | copy(other.entries[:idx], n.entries[:idx]) 1406 | copy(other.entries[idx:], n.entries[idx+1:]) 1407 | return other 1408 | } 1409 | 1410 | // mergeIntoNode merges a key/value pair into an existing node. 1411 | // Caller must verify that node's keyHash is not equal to keyHash. 1412 | func mergeIntoNode[K, V any](node mapLeafNode[K, V], shift uint, keyHash uint32, key K, value V) mapNode[K, V] { 1413 | idx1 := (node.keyHashValue() >> shift) & mapNodeMask 1414 | idx2 := (keyHash >> shift) & mapNodeMask 1415 | 1416 | // Recursively build branch nodes to combine the node and its key. 1417 | other := &mapBitmapIndexedNode[K, V]{bitmap: (1 << idx1) | (1 << idx2)} 1418 | if idx1 == idx2 { 1419 | other.nodes = []mapNode[K, V]{mergeIntoNode(node, shift+mapNodeBits, keyHash, key, value)} 1420 | } else { 1421 | if newNode := newMapValueNode(keyHash, key, value); idx1 < idx2 { 1422 | other.nodes = []mapNode[K, V]{node, newNode} 1423 | } else { 1424 | other.nodes = []mapNode[K, V]{newNode, node} 1425 | } 1426 | } 1427 | return other 1428 | } 1429 | 1430 | // mapEntry represents a single key/value pair. 1431 | type mapEntry[K, V any] struct { 1432 | key K 1433 | value V 1434 | } 1435 | 1436 | // MapIterator represents an iterator over a map's key/value pairs. Although 1437 | // map keys are not sorted, the iterator's order is deterministic. 1438 | type MapIterator[K, V any] struct { 1439 | m *Map[K, V] // source map 1440 | 1441 | stack [32]mapIteratorElem[K, V] // search stack 1442 | depth int // stack depth 1443 | } 1444 | 1445 | // Done returns true if no more elements remain in the iterator. 1446 | func (itr *MapIterator[K, V]) Done() bool { 1447 | return itr.depth == -1 1448 | } 1449 | 1450 | // First resets the iterator to the first key/value pair. 1451 | func (itr *MapIterator[K, V]) First() { 1452 | // Exit immediately if the map is empty. 1453 | if itr.m.root == nil { 1454 | itr.depth = -1 1455 | return 1456 | } 1457 | 1458 | // Initialize the stack to the left most element. 1459 | itr.stack[0] = mapIteratorElem[K, V]{node: itr.m.root} 1460 | itr.depth = 0 1461 | itr.first() 1462 | } 1463 | 1464 | // Next returns the next key/value pair. Returns a nil key when no elements remain. 1465 | func (itr *MapIterator[K, V]) Next() (key K, value V, ok bool) { 1466 | // Return nil key if iteration is done. 1467 | if itr.Done() { 1468 | return key, value, false 1469 | } 1470 | 1471 | // Retrieve current index & value. Current node is always a leaf. 1472 | elem := &itr.stack[itr.depth] 1473 | switch node := elem.node.(type) { 1474 | case *mapArrayNode[K, V]: 1475 | entry := &node.entries[elem.index] 1476 | key, value = entry.key, entry.value 1477 | case *mapValueNode[K, V]: 1478 | key, value = node.key, node.value 1479 | case *mapHashCollisionNode[K, V]: 1480 | entry := &node.entries[elem.index] 1481 | key, value = entry.key, entry.value 1482 | } 1483 | 1484 | // Move up stack until we find a node that has remaining position ahead 1485 | // and move that element forward by one. 1486 | itr.next() 1487 | return key, value, true 1488 | } 1489 | 1490 | // next moves to the next available key. 1491 | func (itr *MapIterator[K, V]) next() { 1492 | for ; itr.depth >= 0; itr.depth-- { 1493 | elem := &itr.stack[itr.depth] 1494 | 1495 | switch node := elem.node.(type) { 1496 | case *mapArrayNode[K, V]: 1497 | if elem.index < len(node.entries)-1 { 1498 | elem.index++ 1499 | return 1500 | } 1501 | 1502 | case *mapBitmapIndexedNode[K, V]: 1503 | if elem.index < len(node.nodes)-1 { 1504 | elem.index++ 1505 | itr.stack[itr.depth+1].node = node.nodes[elem.index] 1506 | itr.depth++ 1507 | itr.first() 1508 | return 1509 | } 1510 | 1511 | case *mapHashArrayNode[K, V]: 1512 | for i := elem.index + 1; i < len(node.nodes); i++ { 1513 | if node.nodes[i] != nil { 1514 | elem.index = i 1515 | itr.stack[itr.depth+1].node = node.nodes[elem.index] 1516 | itr.depth++ 1517 | itr.first() 1518 | return 1519 | } 1520 | } 1521 | 1522 | case *mapValueNode[K, V]: 1523 | continue // always the last value, traverse up 1524 | 1525 | case *mapHashCollisionNode[K, V]: 1526 | if elem.index < len(node.entries)-1 { 1527 | elem.index++ 1528 | return 1529 | } 1530 | } 1531 | } 1532 | } 1533 | 1534 | // first positions the stack left most index. 1535 | // Elements and indexes at and below the current depth are assumed to be correct. 1536 | func (itr *MapIterator[K, V]) first() { 1537 | for ; ; itr.depth++ { 1538 | elem := &itr.stack[itr.depth] 1539 | 1540 | switch node := elem.node.(type) { 1541 | case *mapBitmapIndexedNode[K, V]: 1542 | elem.index = 0 1543 | itr.stack[itr.depth+1].node = node.nodes[0] 1544 | 1545 | case *mapHashArrayNode[K, V]: 1546 | for i := 0; i < len(node.nodes); i++ { 1547 | if node.nodes[i] != nil { // find first node 1548 | elem.index = i 1549 | itr.stack[itr.depth+1].node = node.nodes[i] 1550 | break 1551 | } 1552 | } 1553 | 1554 | default: // *mapArrayNode, mapLeafNode 1555 | elem.index = 0 1556 | return 1557 | } 1558 | } 1559 | } 1560 | 1561 | // mapIteratorElem represents a node/index pair in the MapIterator stack. 1562 | type mapIteratorElem[K, V any] struct { 1563 | node mapNode[K, V] 1564 | index int 1565 | } 1566 | 1567 | // Sorted map child node limit size. 1568 | const ( 1569 | sortedMapNodeSize = 32 1570 | ) 1571 | 1572 | // SortedMap represents a map of key/value pairs sorted by key. The sort order 1573 | // is determined by the Comparer used by the map. 1574 | // 1575 | // This map is implemented as a B+tree. 1576 | type SortedMap[K, V any] struct { 1577 | size int // total number of key/value pairs 1578 | root sortedMapNode[K, V] // root of b+tree 1579 | comparer Comparer[K] 1580 | } 1581 | 1582 | // NewSortedMap returns a new instance of SortedMap. If comparer is nil then 1583 | // a default comparer is set after the first key is inserted. Default comparers 1584 | // exist for int, string, and byte slice keys. 1585 | func NewSortedMap[K, V any](comparer Comparer[K]) *SortedMap[K, V] { 1586 | return &SortedMap[K, V]{ 1587 | comparer: comparer, 1588 | } 1589 | } 1590 | 1591 | // NewSortedMapOf returns a new instance of SortedMap, containing a map of provided entries. 1592 | // 1593 | // If comparer is nil then a default comparer is set after the first key is inserted. Default comparers 1594 | // exist for int, string, and byte slice keys. 1595 | func NewSortedMapOf[K comparable, V any](comparer Comparer[K], entries map[K]V) *SortedMap[K, V] { 1596 | m := &SortedMap[K, V]{ 1597 | comparer: comparer, 1598 | } 1599 | for k, v := range entries { 1600 | m.set(k, v, true) 1601 | } 1602 | return m 1603 | } 1604 | 1605 | // Len returns the number of elements in the sorted map. 1606 | func (m *SortedMap[K, V]) Len() int { 1607 | return m.size 1608 | } 1609 | 1610 | // Get returns the value for a given key and a flag indicating if the key is set. 1611 | // The flag can be used to distinguish between a nil-set key versus an unset key. 1612 | func (m *SortedMap[K, V]) Get(key K) (V, bool) { 1613 | if m.root == nil { 1614 | var v V 1615 | return v, false 1616 | } 1617 | return m.root.get(key, m.comparer) 1618 | } 1619 | 1620 | // Set returns a copy of the map with the key set to the given value. 1621 | func (m *SortedMap[K, V]) Set(key K, value V) *SortedMap[K, V] { 1622 | return m.set(key, value, false) 1623 | } 1624 | 1625 | func (m *SortedMap[K, V]) set(key K, value V, mutable bool) *SortedMap[K, V] { 1626 | // Set a comparer on the first value if one does not already exist. 1627 | comparer := m.comparer 1628 | if comparer == nil { 1629 | comparer = NewComparer(key) 1630 | } 1631 | 1632 | // Create copy, if necessary. 1633 | other := m 1634 | if !mutable { 1635 | other = m.clone() 1636 | } 1637 | other.comparer = comparer 1638 | 1639 | // If no values are set then initialize with a leaf node. 1640 | if m.root == nil { 1641 | other.size = 1 1642 | other.root = &sortedMapLeafNode[K, V]{entries: []mapEntry[K, V]{{key: key, value: value}}} 1643 | return other 1644 | } 1645 | 1646 | // Otherwise delegate to root node. 1647 | // If a split occurs then grow the tree from the root. 1648 | var resized bool 1649 | newRoot, splitNode := m.root.set(key, value, comparer, mutable, &resized) 1650 | if splitNode != nil { 1651 | newRoot = newSortedMapBranchNode(newRoot, splitNode) 1652 | } 1653 | 1654 | // Update root and size (if resized). 1655 | other.size = m.size 1656 | other.root = newRoot 1657 | if resized { 1658 | other.size++ 1659 | } 1660 | return other 1661 | } 1662 | 1663 | // Delete returns a copy of the map with the key removed. 1664 | // Returns the original map if key does not exist. 1665 | func (m *SortedMap[K, V]) Delete(key K) *SortedMap[K, V] { 1666 | return m.delete(key, false) 1667 | } 1668 | 1669 | func (m *SortedMap[K, V]) delete(key K, mutable bool) *SortedMap[K, V] { 1670 | // Return original map if no keys exist. 1671 | if m.root == nil { 1672 | return m 1673 | } 1674 | 1675 | // If the delete did not change the node then return the original map. 1676 | var resized bool 1677 | newRoot := m.root.delete(key, m.comparer, mutable, &resized) 1678 | if !resized { 1679 | return m 1680 | } 1681 | 1682 | // Create copy, if necessary. 1683 | other := m 1684 | if !mutable { 1685 | other = m.clone() 1686 | } 1687 | 1688 | // Update root and size. 1689 | other.size = m.size - 1 1690 | other.root = newRoot 1691 | return other 1692 | } 1693 | 1694 | // clone returns a shallow copy of m. 1695 | func (m *SortedMap[K, V]) clone() *SortedMap[K, V] { 1696 | other := *m 1697 | return &other 1698 | } 1699 | 1700 | // Iterator returns a new iterator for this map positioned at the first key. 1701 | func (m *SortedMap[K, V]) Iterator() *SortedMapIterator[K, V] { 1702 | itr := &SortedMapIterator[K, V]{m: m} 1703 | itr.First() 1704 | return itr 1705 | } 1706 | 1707 | // SortedMapBuilder represents an efficient builder for creating sorted maps. 1708 | type SortedMapBuilder[K, V any] struct { 1709 | m *SortedMap[K, V] // current state 1710 | } 1711 | 1712 | // NewSortedMapBuilder returns a new instance of SortedMapBuilder. 1713 | func NewSortedMapBuilder[K, V any](comparer Comparer[K]) *SortedMapBuilder[K, V] { 1714 | return &SortedMapBuilder[K, V]{m: NewSortedMap[K, V](comparer)} 1715 | } 1716 | 1717 | // SortedMap returns the current copy of the map. 1718 | // The returned map is safe to use even if after the builder continues to be used. 1719 | func (b *SortedMapBuilder[K, V]) Map() *SortedMap[K, V] { 1720 | assert(b.m != nil, "immutable.SortedMapBuilder.Map(): duplicate call to fetch map") 1721 | m := b.m 1722 | b.m = nil 1723 | return m 1724 | } 1725 | 1726 | // Len returns the number of elements in the underlying map. 1727 | func (b *SortedMapBuilder[K, V]) Len() int { 1728 | assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") 1729 | return b.m.Len() 1730 | } 1731 | 1732 | // Get returns the value for the given key. 1733 | func (b *SortedMapBuilder[K, V]) Get(key K) (value V, ok bool) { 1734 | assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") 1735 | return b.m.Get(key) 1736 | } 1737 | 1738 | // Set sets the value of the given key. See SortedMap.Set() for additional details. 1739 | func (b *SortedMapBuilder[K, V]) Set(key K, value V) { 1740 | assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") 1741 | b.m = b.m.set(key, value, true) 1742 | } 1743 | 1744 | // Delete removes the given key. See SortedMap.Delete() for additional details. 1745 | func (b *SortedMapBuilder[K, V]) Delete(key K) { 1746 | assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") 1747 | b.m = b.m.delete(key, true) 1748 | } 1749 | 1750 | // Iterator returns a new iterator for the underlying map positioned at the first key. 1751 | func (b *SortedMapBuilder[K, V]) Iterator() *SortedMapIterator[K, V] { 1752 | assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation") 1753 | return b.m.Iterator() 1754 | } 1755 | 1756 | // sortedMapNode represents a branch or leaf node in the sorted map. 1757 | type sortedMapNode[K, V any] interface { 1758 | minKey() K 1759 | indexOf(key K, c Comparer[K]) int 1760 | get(key K, c Comparer[K]) (value V, ok bool) 1761 | set(key K, value V, c Comparer[K], mutable bool, resized *bool) (sortedMapNode[K, V], sortedMapNode[K, V]) 1762 | delete(key K, c Comparer[K], mutable bool, resized *bool) sortedMapNode[K, V] 1763 | } 1764 | 1765 | var _ sortedMapNode[string, any] = (*sortedMapBranchNode[string, any])(nil) 1766 | var _ sortedMapNode[string, any] = (*sortedMapLeafNode[string, any])(nil) 1767 | 1768 | // sortedMapBranchNode represents a branch in the sorted map. 1769 | type sortedMapBranchNode[K, V any] struct { 1770 | elems []sortedMapBranchElem[K, V] 1771 | } 1772 | 1773 | // newSortedMapBranchNode returns a new branch node with the given child nodes. 1774 | func newSortedMapBranchNode[K, V any](children ...sortedMapNode[K, V]) *sortedMapBranchNode[K, V] { 1775 | // Fetch min keys for every child. 1776 | elems := make([]sortedMapBranchElem[K, V], len(children)) 1777 | for i, child := range children { 1778 | elems[i] = sortedMapBranchElem[K, V]{ 1779 | key: child.minKey(), 1780 | node: child, 1781 | } 1782 | } 1783 | 1784 | return &sortedMapBranchNode[K, V]{elems: elems} 1785 | } 1786 | 1787 | // minKey returns the lowest key stored in this node's tree. 1788 | func (n *sortedMapBranchNode[K, V]) minKey() K { 1789 | return n.elems[0].node.minKey() 1790 | } 1791 | 1792 | // indexOf returns the index of the key within the child nodes. 1793 | func (n *sortedMapBranchNode[K, V]) indexOf(key K, c Comparer[K]) int { 1794 | if idx := sort.Search(len(n.elems), func(i int) bool { return c.Compare(n.elems[i].key, key) == 1 }); idx > 0 { 1795 | return idx - 1 1796 | } 1797 | return 0 1798 | } 1799 | 1800 | // get returns the value for the given key. 1801 | func (n *sortedMapBranchNode[K, V]) get(key K, c Comparer[K]) (value V, ok bool) { 1802 | idx := n.indexOf(key, c) 1803 | return n.elems[idx].node.get(key, c) 1804 | } 1805 | 1806 | // set returns a copy of the node with the key set to the given value. 1807 | func (n *sortedMapBranchNode[K, V]) set(key K, value V, c Comparer[K], mutable bool, resized *bool) (sortedMapNode[K, V], sortedMapNode[K, V]) { 1808 | idx := n.indexOf(key, c) 1809 | 1810 | // Delegate insert to child node. 1811 | newNode, splitNode := n.elems[idx].node.set(key, value, c, mutable, resized) 1812 | 1813 | // Update in-place, if mutable. 1814 | if mutable { 1815 | n.elems[idx] = sortedMapBranchElem[K, V]{key: newNode.minKey(), node: newNode} 1816 | if splitNode != nil { 1817 | n.elems = append(n.elems, sortedMapBranchElem[K, V]{}) 1818 | copy(n.elems[idx+1:], n.elems[idx:]) 1819 | n.elems[idx+1] = sortedMapBranchElem[K, V]{key: splitNode.minKey(), node: splitNode} 1820 | } 1821 | 1822 | // If the child splits and we have no more room then we split too. 1823 | if len(n.elems) > sortedMapNodeSize { 1824 | splitIdx := len(n.elems) / 2 1825 | newNode := &sortedMapBranchNode[K, V]{elems: n.elems[:splitIdx:splitIdx]} 1826 | splitNode := &sortedMapBranchNode[K, V]{elems: n.elems[splitIdx:]} 1827 | return newNode, splitNode 1828 | } 1829 | return n, nil 1830 | } 1831 | 1832 | // If no split occurs, copy branch and update keys. 1833 | // If the child splits, insert new key/child into copy of branch. 1834 | var other sortedMapBranchNode[K, V] 1835 | if splitNode == nil { 1836 | other.elems = make([]sortedMapBranchElem[K, V], len(n.elems)) 1837 | copy(other.elems, n.elems) 1838 | other.elems[idx] = sortedMapBranchElem[K, V]{ 1839 | key: newNode.minKey(), 1840 | node: newNode, 1841 | } 1842 | } else { 1843 | other.elems = make([]sortedMapBranchElem[K, V], len(n.elems)+1) 1844 | copy(other.elems[:idx], n.elems[:idx]) 1845 | copy(other.elems[idx+1:], n.elems[idx:]) 1846 | other.elems[idx] = sortedMapBranchElem[K, V]{ 1847 | key: newNode.minKey(), 1848 | node: newNode, 1849 | } 1850 | other.elems[idx+1] = sortedMapBranchElem[K, V]{ 1851 | key: splitNode.minKey(), 1852 | node: splitNode, 1853 | } 1854 | } 1855 | 1856 | // If the child splits and we have no more room then we split too. 1857 | if len(other.elems) > sortedMapNodeSize { 1858 | splitIdx := len(other.elems) / 2 1859 | newNode := &sortedMapBranchNode[K, V]{elems: other.elems[:splitIdx:splitIdx]} 1860 | splitNode := &sortedMapBranchNode[K, V]{elems: other.elems[splitIdx:]} 1861 | return newNode, splitNode 1862 | } 1863 | 1864 | // Otherwise return the new branch node with the updated entry. 1865 | return &other, nil 1866 | } 1867 | 1868 | // delete returns a node with the key removed. Returns the same node if the key 1869 | // does not exist. Returns nil if all child nodes are removed. 1870 | func (n *sortedMapBranchNode[K, V]) delete(key K, c Comparer[K], mutable bool, resized *bool) sortedMapNode[K, V] { 1871 | idx := n.indexOf(key, c) 1872 | 1873 | // Return original node if child has not changed. 1874 | newNode := n.elems[idx].node.delete(key, c, mutable, resized) 1875 | if !*resized { 1876 | return n 1877 | } 1878 | 1879 | // Remove child if it is now nil. 1880 | if newNode == nil { 1881 | // If this node will become empty then simply return nil. 1882 | if len(n.elems) == 1 { 1883 | return nil 1884 | } 1885 | 1886 | // If mutable, update in-place. 1887 | if mutable { 1888 | copy(n.elems[idx:], n.elems[idx+1:]) 1889 | n.elems[len(n.elems)-1] = sortedMapBranchElem[K, V]{} 1890 | n.elems = n.elems[:len(n.elems)-1] 1891 | return n 1892 | } 1893 | 1894 | // Return a copy without the given node. 1895 | other := &sortedMapBranchNode[K, V]{elems: make([]sortedMapBranchElem[K, V], len(n.elems)-1)} 1896 | copy(other.elems[:idx], n.elems[:idx]) 1897 | copy(other.elems[idx:], n.elems[idx+1:]) 1898 | return other 1899 | } 1900 | 1901 | // If mutable, update in-place. 1902 | if mutable { 1903 | n.elems[idx] = sortedMapBranchElem[K, V]{key: newNode.minKey(), node: newNode} 1904 | return n 1905 | } 1906 | 1907 | // Return a copy with the updated node. 1908 | other := &sortedMapBranchNode[K, V]{elems: make([]sortedMapBranchElem[K, V], len(n.elems))} 1909 | copy(other.elems, n.elems) 1910 | other.elems[idx] = sortedMapBranchElem[K, V]{ 1911 | key: newNode.minKey(), 1912 | node: newNode, 1913 | } 1914 | return other 1915 | } 1916 | 1917 | type sortedMapBranchElem[K, V any] struct { 1918 | key K 1919 | node sortedMapNode[K, V] 1920 | } 1921 | 1922 | // sortedMapLeafNode represents a leaf node in the sorted map. 1923 | type sortedMapLeafNode[K, V any] struct { 1924 | entries []mapEntry[K, V] 1925 | } 1926 | 1927 | // minKey returns the first key stored in this node. 1928 | func (n *sortedMapLeafNode[K, V]) minKey() K { 1929 | return n.entries[0].key 1930 | } 1931 | 1932 | // indexOf returns the index of the given key. 1933 | func (n *sortedMapLeafNode[K, V]) indexOf(key K, c Comparer[K]) int { 1934 | return sort.Search(len(n.entries), func(i int) bool { 1935 | return c.Compare(n.entries[i].key, key) != -1 // GTE 1936 | }) 1937 | } 1938 | 1939 | // get returns the value of the given key. 1940 | func (n *sortedMapLeafNode[K, V]) get(key K, c Comparer[K]) (value V, ok bool) { 1941 | idx := n.indexOf(key, c) 1942 | 1943 | // If the index is beyond the entry count or the key is not equal then return 'not found'. 1944 | if idx == len(n.entries) || c.Compare(n.entries[idx].key, key) != 0 { 1945 | return value, false 1946 | } 1947 | 1948 | // If the key matches then return its value. 1949 | return n.entries[idx].value, true 1950 | } 1951 | 1952 | // set returns a copy of node with the key set to the given value. If the update 1953 | // causes the node to grow beyond the maximum size then it is split in two. 1954 | func (n *sortedMapLeafNode[K, V]) set(key K, value V, c Comparer[K], mutable bool, resized *bool) (sortedMapNode[K, V], sortedMapNode[K, V]) { 1955 | // Find the insertion index for the key. 1956 | idx := n.indexOf(key, c) 1957 | exists := idx < len(n.entries) && c.Compare(n.entries[idx].key, key) == 0 1958 | 1959 | // Update in-place, if mutable. 1960 | if mutable { 1961 | if !exists { 1962 | *resized = true 1963 | n.entries = append(n.entries, mapEntry[K, V]{}) 1964 | copy(n.entries[idx+1:], n.entries[idx:]) 1965 | } 1966 | n.entries[idx] = mapEntry[K, V]{key: key, value: value} 1967 | 1968 | // If the key doesn't exist and we exceed our max allowed values then split. 1969 | if len(n.entries) > sortedMapNodeSize { 1970 | splitIdx := len(n.entries) / 2 1971 | newNode := &sortedMapLeafNode[K, V]{entries: n.entries[:splitIdx:splitIdx]} 1972 | splitNode := &sortedMapLeafNode[K, V]{entries: n.entries[splitIdx:]} 1973 | return newNode, splitNode 1974 | } 1975 | return n, nil 1976 | } 1977 | 1978 | // If the key matches then simply return a copy with the entry overridden. 1979 | // If there is no match then insert new entry and mark as resized. 1980 | var newEntries []mapEntry[K, V] 1981 | if exists { 1982 | newEntries = make([]mapEntry[K, V], len(n.entries)) 1983 | copy(newEntries, n.entries) 1984 | newEntries[idx] = mapEntry[K, V]{key: key, value: value} 1985 | } else { 1986 | *resized = true 1987 | newEntries = make([]mapEntry[K, V], len(n.entries)+1) 1988 | copy(newEntries[:idx], n.entries[:idx]) 1989 | newEntries[idx] = mapEntry[K, V]{key: key, value: value} 1990 | copy(newEntries[idx+1:], n.entries[idx:]) 1991 | } 1992 | 1993 | // If the key doesn't exist and we exceed our max allowed values then split. 1994 | if len(newEntries) > sortedMapNodeSize { 1995 | splitIdx := len(newEntries) / 2 1996 | newNode := &sortedMapLeafNode[K, V]{entries: newEntries[:splitIdx:splitIdx]} 1997 | splitNode := &sortedMapLeafNode[K, V]{entries: newEntries[splitIdx:]} 1998 | return newNode, splitNode 1999 | } 2000 | 2001 | // Otherwise return the new leaf node with the updated entry. 2002 | return &sortedMapLeafNode[K, V]{entries: newEntries}, nil 2003 | } 2004 | 2005 | // delete returns a copy of node with key removed. Returns the original node if 2006 | // the key does not exist. Returns nil if the removed key is the last remaining key. 2007 | func (n *sortedMapLeafNode[K, V]) delete(key K, c Comparer[K], mutable bool, resized *bool) sortedMapNode[K, V] { 2008 | idx := n.indexOf(key, c) 2009 | 2010 | // Return original node if key is not found. 2011 | if idx >= len(n.entries) || c.Compare(n.entries[idx].key, key) != 0 { 2012 | return n 2013 | } 2014 | *resized = true 2015 | 2016 | // If this is the last entry then return nil. 2017 | if len(n.entries) == 1 { 2018 | return nil 2019 | } 2020 | 2021 | // Update in-place, if mutable. 2022 | if mutable { 2023 | copy(n.entries[idx:], n.entries[idx+1:]) 2024 | n.entries[len(n.entries)-1] = mapEntry[K, V]{} 2025 | n.entries = n.entries[:len(n.entries)-1] 2026 | return n 2027 | } 2028 | 2029 | // Return copy of node with entry removed. 2030 | other := &sortedMapLeafNode[K, V]{entries: make([]mapEntry[K, V], len(n.entries)-1)} 2031 | copy(other.entries[:idx], n.entries[:idx]) 2032 | copy(other.entries[idx:], n.entries[idx+1:]) 2033 | return other 2034 | } 2035 | 2036 | // SortedMapIterator represents an iterator over a sorted map. 2037 | // Iteration can occur in natural or reverse order based on use of Next() or Prev(). 2038 | type SortedMapIterator[K, V any] struct { 2039 | m *SortedMap[K, V] // source map 2040 | 2041 | stack [32]sortedMapIteratorElem[K, V] // search stack 2042 | depth int // stack depth 2043 | } 2044 | 2045 | // Done returns true if no more key/value pairs remain in the iterator. 2046 | func (itr *SortedMapIterator[K, V]) Done() bool { 2047 | return itr.depth == -1 2048 | } 2049 | 2050 | // First moves the iterator to the first key/value pair. 2051 | func (itr *SortedMapIterator[K, V]) First() { 2052 | if itr.m.root == nil { 2053 | itr.depth = -1 2054 | return 2055 | } 2056 | itr.stack[0] = sortedMapIteratorElem[K, V]{node: itr.m.root} 2057 | itr.depth = 0 2058 | itr.first() 2059 | } 2060 | 2061 | // Last moves the iterator to the last key/value pair. 2062 | func (itr *SortedMapIterator[K, V]) Last() { 2063 | if itr.m.root == nil { 2064 | itr.depth = -1 2065 | return 2066 | } 2067 | itr.stack[0] = sortedMapIteratorElem[K, V]{node: itr.m.root} 2068 | itr.depth = 0 2069 | itr.last() 2070 | } 2071 | 2072 | // Seek moves the iterator position to the given key in the map. 2073 | // If the key does not exist then the next key is used. If no more keys exist 2074 | // then the iteartor is marked as done. 2075 | func (itr *SortedMapIterator[K, V]) Seek(key K) { 2076 | if itr.m.root == nil { 2077 | itr.depth = -1 2078 | return 2079 | } 2080 | itr.stack[0] = sortedMapIteratorElem[K, V]{node: itr.m.root} 2081 | itr.depth = 0 2082 | itr.seek(key) 2083 | } 2084 | 2085 | // Next returns the current key/value pair and moves the iterator forward. 2086 | // Returns a nil key if the there are no more elements to return. 2087 | func (itr *SortedMapIterator[K, V]) Next() (key K, value V, ok bool) { 2088 | // Return nil key if iteration is complete. 2089 | if itr.Done() { 2090 | return key, value, false 2091 | } 2092 | 2093 | // Retrieve current key/value pair. 2094 | leafElem := &itr.stack[itr.depth] 2095 | leafNode := leafElem.node.(*sortedMapLeafNode[K, V]) 2096 | leafEntry := &leafNode.entries[leafElem.index] 2097 | key, value = leafEntry.key, leafEntry.value 2098 | 2099 | // Move to the next available key/value pair. 2100 | itr.next() 2101 | 2102 | // Only occurs when iterator is done. 2103 | return key, value, true 2104 | } 2105 | 2106 | // next moves to the next key. If no keys are after then depth is set to -1. 2107 | func (itr *SortedMapIterator[K, V]) next() { 2108 | for ; itr.depth >= 0; itr.depth-- { 2109 | elem := &itr.stack[itr.depth] 2110 | 2111 | switch node := elem.node.(type) { 2112 | case *sortedMapLeafNode[K, V]: 2113 | if elem.index < len(node.entries)-1 { 2114 | elem.index++ 2115 | return 2116 | } 2117 | case *sortedMapBranchNode[K, V]: 2118 | if elem.index < len(node.elems)-1 { 2119 | elem.index++ 2120 | itr.stack[itr.depth+1].node = node.elems[elem.index].node 2121 | itr.depth++ 2122 | itr.first() 2123 | return 2124 | } 2125 | } 2126 | } 2127 | } 2128 | 2129 | // Prev returns the current key/value pair and moves the iterator backward. 2130 | // Returns a nil key if the there are no more elements to return. 2131 | func (itr *SortedMapIterator[K, V]) Prev() (key K, value V, ok bool) { 2132 | // Return nil key if iteration is complete. 2133 | if itr.Done() { 2134 | return key, value, false 2135 | } 2136 | 2137 | // Retrieve current key/value pair. 2138 | leafElem := &itr.stack[itr.depth] 2139 | leafNode := leafElem.node.(*sortedMapLeafNode[K, V]) 2140 | leafEntry := &leafNode.entries[leafElem.index] 2141 | key, value = leafEntry.key, leafEntry.value 2142 | 2143 | itr.prev() 2144 | return key, value, true 2145 | } 2146 | 2147 | // prev moves to the previous key. If no keys are before then depth is set to -1. 2148 | func (itr *SortedMapIterator[K, V]) prev() { 2149 | for ; itr.depth >= 0; itr.depth-- { 2150 | elem := &itr.stack[itr.depth] 2151 | 2152 | switch node := elem.node.(type) { 2153 | case *sortedMapLeafNode[K, V]: 2154 | if elem.index > 0 { 2155 | elem.index-- 2156 | return 2157 | } 2158 | case *sortedMapBranchNode[K, V]: 2159 | if elem.index > 0 { 2160 | elem.index-- 2161 | itr.stack[itr.depth+1].node = node.elems[elem.index].node 2162 | itr.depth++ 2163 | itr.last() 2164 | return 2165 | } 2166 | } 2167 | } 2168 | } 2169 | 2170 | // first positions the stack to the leftmost key from the current depth. 2171 | // Elements and indexes below the current depth are assumed to be correct. 2172 | func (itr *SortedMapIterator[K, V]) first() { 2173 | for { 2174 | elem := &itr.stack[itr.depth] 2175 | elem.index = 0 2176 | 2177 | switch node := elem.node.(type) { 2178 | case *sortedMapBranchNode[K, V]: 2179 | itr.stack[itr.depth+1] = sortedMapIteratorElem[K, V]{node: node.elems[elem.index].node} 2180 | itr.depth++ 2181 | case *sortedMapLeafNode[K, V]: 2182 | return 2183 | } 2184 | } 2185 | } 2186 | 2187 | // last positions the stack to the rightmost key from the current depth. 2188 | // Elements and indexes below the current depth are assumed to be correct. 2189 | func (itr *SortedMapIterator[K, V]) last() { 2190 | for { 2191 | elem := &itr.stack[itr.depth] 2192 | 2193 | switch node := elem.node.(type) { 2194 | case *sortedMapBranchNode[K, V]: 2195 | elem.index = len(node.elems) - 1 2196 | itr.stack[itr.depth+1] = sortedMapIteratorElem[K, V]{node: node.elems[elem.index].node} 2197 | itr.depth++ 2198 | case *sortedMapLeafNode[K, V]: 2199 | elem.index = len(node.entries) - 1 2200 | return 2201 | } 2202 | } 2203 | } 2204 | 2205 | // seek positions the stack to the given key from the current depth. 2206 | // Elements and indexes below the current depth are assumed to be correct. 2207 | func (itr *SortedMapIterator[K, V]) seek(key K) { 2208 | for { 2209 | elem := &itr.stack[itr.depth] 2210 | elem.index = elem.node.indexOf(key, itr.m.comparer) 2211 | 2212 | switch node := elem.node.(type) { 2213 | case *sortedMapBranchNode[K, V]: 2214 | itr.stack[itr.depth+1] = sortedMapIteratorElem[K, V]{node: node.elems[elem.index].node} 2215 | itr.depth++ 2216 | case *sortedMapLeafNode[K, V]: 2217 | if elem.index == len(node.entries) { 2218 | itr.next() 2219 | } 2220 | return 2221 | } 2222 | } 2223 | } 2224 | 2225 | // sortedMapIteratorElem represents node/index pair in the SortedMapIterator stack. 2226 | type sortedMapIteratorElem[K, V any] struct { 2227 | node sortedMapNode[K, V] 2228 | index int 2229 | } 2230 | 2231 | // Hasher hashes keys and checks them for equality. 2232 | type Hasher[K any] interface { 2233 | // Computes a hash for key. 2234 | Hash(key K) uint32 2235 | 2236 | // Returns true if a and b are equal. 2237 | Equal(a, b K) bool 2238 | } 2239 | 2240 | // NewHasher returns the built-in hasher for a given key type. 2241 | func NewHasher[K any](key K) Hasher[K] { 2242 | // Attempt to use non-reflection based hasher first. 2243 | switch (any(key)).(type) { 2244 | case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, string: 2245 | return &defaultHasher[K]{} 2246 | } 2247 | 2248 | // Fallback to reflection-based hasher otherwise. 2249 | // This is used when caller wraps a type around a primitive type. 2250 | switch reflect.TypeOf(key).Kind() { 2251 | 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: 2252 | return &reflectHasher[K]{} 2253 | } 2254 | 2255 | // If no hashers match then panic. 2256 | // This is a compile time issue so it should not return an error. 2257 | panic(fmt.Sprintf("immutable.NewHasher: must set hasher for %T type", key)) 2258 | } 2259 | 2260 | // Hash returns a hash for value. 2261 | func hashString(value string) uint32 { 2262 | var hash uint32 2263 | for i, value := 0, value; i < len(value); i++ { 2264 | hash = 31*hash + uint32(value[i]) 2265 | } 2266 | return hash 2267 | } 2268 | 2269 | // reflectIntHasher implements a reflection-based Hasher for keys. 2270 | type reflectHasher[K any] struct{} 2271 | 2272 | // Hash returns a hash for key. 2273 | func (h *reflectHasher[K]) Hash(key K) uint32 { 2274 | switch reflect.TypeOf(key).Kind() { 2275 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 2276 | return hashUint64(uint64(reflect.ValueOf(key).Int())) 2277 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 2278 | return hashUint64(reflect.ValueOf(key).Uint()) 2279 | case reflect.String: 2280 | var hash uint32 2281 | s := reflect.ValueOf(key).String() 2282 | for i := 0; i < len(s); i++ { 2283 | hash = 31*hash + uint32(s[i]) 2284 | } 2285 | return hash 2286 | } 2287 | panic(fmt.Sprintf("immutable.reflectHasher.Hash: reflectHasher does not support %T type", key)) 2288 | } 2289 | 2290 | // Equal returns true if a is equal to b. Otherwise returns false. 2291 | // Panics if a and b are not int-ish or string-ish. 2292 | func (h *reflectHasher[K]) Equal(a, b K) bool { 2293 | switch reflect.TypeOf(a).Kind() { 2294 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 2295 | return reflect.ValueOf(a).Int() == reflect.ValueOf(b).Int() 2296 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 2297 | return reflect.ValueOf(a).Uint() == reflect.ValueOf(b).Uint() 2298 | case reflect.String: 2299 | return reflect.ValueOf(a).String() == reflect.ValueOf(b).String() 2300 | } 2301 | panic(fmt.Sprintf("immutable.reflectHasher.Equal: reflectHasher does not support %T type", a)) 2302 | 2303 | } 2304 | 2305 | // hashUint64 returns a 32-bit hash for a 64-bit value. 2306 | func hashUint64(value uint64) uint32 { 2307 | hash := value 2308 | for value > 0xffffffff { 2309 | value /= 0xffffffff 2310 | hash ^= value 2311 | } 2312 | return uint32(hash) 2313 | } 2314 | 2315 | // defaultHasher implements Hasher. 2316 | type defaultHasher[K any] struct{} 2317 | 2318 | // Hash returns a hash for key. 2319 | func (h *defaultHasher[K]) Hash(key K) uint32 { 2320 | switch x := (any(key)).(type) { 2321 | case int: 2322 | return hashUint64(uint64(x)) 2323 | case int8: 2324 | return hashUint64(uint64(x)) 2325 | case int16: 2326 | return hashUint64(uint64(x)) 2327 | case int32: 2328 | return hashUint64(uint64(x)) 2329 | case int64: 2330 | return hashUint64(uint64(x)) 2331 | case uint: 2332 | return hashUint64(uint64(x)) 2333 | case uint8: 2334 | return hashUint64(uint64(x)) 2335 | case uint16: 2336 | return hashUint64(uint64(x)) 2337 | case uint32: 2338 | return hashUint64(uint64(x)) 2339 | case uint64: 2340 | return hashUint64(uint64(x)) 2341 | case uintptr: 2342 | return hashUint64(uint64(x)) 2343 | case string: 2344 | return hashString(x) 2345 | } 2346 | panic(fmt.Sprintf("immutable.defaultHasher.Hash: must set comparer for %T type", key)) 2347 | } 2348 | 2349 | // Equal returns true if a is equal to b. Otherwise returns false. 2350 | // Panics if a and b are not comparable. 2351 | func (h *defaultHasher[K]) Equal(a, b K) bool { 2352 | return any(a) == any(b) 2353 | } 2354 | 2355 | // Comparer allows the comparison of two keys for the purpose of sorting. 2356 | type Comparer[K any] interface { 2357 | // Returns -1 if a is less than b, returns 1 if a is greater than b, 2358 | // and returns 0 if a is equal to b. 2359 | Compare(a, b K) int 2360 | } 2361 | 2362 | // NewComparer returns the built-in comparer for a given key type. 2363 | // Note that only int-ish and string-ish types are supported, despite the 'comparable' constraint. 2364 | // Attempts to use other types will result in a panic - users should define their own Comparers for these cases. 2365 | func NewComparer[K any](key K) Comparer[K] { 2366 | // Attempt to use non-reflection based comparer first. 2367 | switch (any(key)).(type) { 2368 | case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, string: 2369 | return &defaultComparer[K]{} 2370 | } 2371 | // Fallback to reflection-based comparer otherwise. 2372 | // This is used when caller wraps a type around a primitive type. 2373 | switch reflect.TypeOf(key).Kind() { 2374 | 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: 2375 | return &reflectComparer[K]{} 2376 | } 2377 | // If no comparers match then panic. 2378 | // This is a compile time issue so it should not return an error. 2379 | panic(fmt.Sprintf("immutable.NewComparer: must set comparer for %T type", key)) 2380 | } 2381 | 2382 | // defaultComparer compares two values (int-ish and string-ish types are supported). Implements Comparer. 2383 | type defaultComparer[K any] struct{} 2384 | 2385 | // Compare returns -1 if a is less than b, returns 1 if a is greater than b, and 2386 | // returns 0 if a is equal to b. Panic if a or b is not a string or int* type 2387 | func (c *defaultComparer[K]) Compare(i K, j K) int { 2388 | switch x := (any(i)).(type) { 2389 | case int: 2390 | return defaultCompare(x, (any(j)).(int)) 2391 | case int8: 2392 | return defaultCompare(x, (any(j)).(int8)) 2393 | case int16: 2394 | return defaultCompare(x, (any(j)).(int16)) 2395 | case int32: 2396 | return defaultCompare(x, (any(j)).(int32)) 2397 | case int64: 2398 | return defaultCompare(x, (any(j)).(int64)) 2399 | case uint: 2400 | return defaultCompare(x, (any(j)).(uint)) 2401 | case uint8: 2402 | return defaultCompare(x, (any(j)).(uint8)) 2403 | case uint16: 2404 | return defaultCompare(x, (any(j)).(uint16)) 2405 | case uint32: 2406 | return defaultCompare(x, (any(j)).(uint32)) 2407 | case uint64: 2408 | return defaultCompare(x, (any(j)).(uint64)) 2409 | case uintptr: 2410 | return defaultCompare(x, (any(j)).(uintptr)) 2411 | case string: 2412 | return defaultCompare(x, (any(j)).(string)) 2413 | } 2414 | panic(fmt.Sprintf("immutable.defaultComparer: must set comparer for %T type", i)) 2415 | } 2416 | 2417 | // defaultCompare only operates on constraints.Ordered. 2418 | // For other types, users should bring their own comparers 2419 | func defaultCompare[K constraints.Ordered](i, j K) int { 2420 | if i < j { 2421 | return -1 2422 | } else if i > j { 2423 | return 1 2424 | } 2425 | return 0 2426 | } 2427 | 2428 | // reflectIntComparer compares two values using reflection. Implements Comparer. 2429 | type reflectComparer[K any] struct{} 2430 | 2431 | // Compare returns -1 if a is less than b, returns 1 if a is greater than b, and 2432 | // returns 0 if a is equal to b. Panic if a or b is not an int-ish or string-ish type. 2433 | func (c *reflectComparer[K]) Compare(a, b K) int { 2434 | switch reflect.TypeOf(a).Kind() { 2435 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 2436 | if i, j := reflect.ValueOf(a).Int(), reflect.ValueOf(b).Int(); i < j { 2437 | return -1 2438 | } else if i > j { 2439 | return 1 2440 | } 2441 | return 0 2442 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 2443 | if i, j := reflect.ValueOf(a).Uint(), reflect.ValueOf(b).Uint(); i < j { 2444 | return -1 2445 | } else if i > j { 2446 | return 1 2447 | } 2448 | return 0 2449 | case reflect.String: 2450 | return strings.Compare(reflect.ValueOf(a).String(), reflect.ValueOf(b).String()) 2451 | } 2452 | panic(fmt.Sprintf("immutable.reflectComparer.Compare: must set comparer for %T type", a)) 2453 | } 2454 | 2455 | func assert(condition bool, message string) { 2456 | if !condition { 2457 | panic(message) 2458 | } 2459 | } 2460 | -------------------------------------------------------------------------------- /immutable_test.go: -------------------------------------------------------------------------------- 1 | package immutable 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "math/rand" 7 | "sort" 8 | "testing" 9 | 10 | "golang.org/x/exp/constraints" 11 | ) 12 | 13 | var ( 14 | veryVerbose = flag.Bool("vv", false, "very verbose") 15 | randomN = flag.Int("random.n", 100, "number of RunRandom() iterations") 16 | ) 17 | 18 | func TestList(t *testing.T) { 19 | t.Run("Empty", func(t *testing.T) { 20 | if size := NewList[string]().Len(); size != 0 { 21 | t.Fatalf("unexpected size: %d", size) 22 | } 23 | }) 24 | 25 | t.Run("Shallow", func(t *testing.T) { 26 | list := NewList[string]() 27 | list = list.Append("foo") 28 | if v := list.Get(0); v != "foo" { 29 | t.Fatalf("unexpected value: %v", v) 30 | } 31 | 32 | other := list.Append("bar") 33 | if v := other.Get(0); v != "foo" { 34 | t.Fatalf("unexpected value: %v", v) 35 | } else if v := other.Get(1); v != "bar" { 36 | t.Fatalf("unexpected value: %v", v) 37 | } 38 | 39 | if v := list.Len(); v != 1 { 40 | t.Fatalf("unexpected value: %v", v) 41 | } 42 | }) 43 | 44 | t.Run("Deep", func(t *testing.T) { 45 | list := NewList[int]() 46 | var array []int 47 | for i := 0; i < 100000; i++ { 48 | list = list.Append(i) 49 | array = append(array, i) 50 | } 51 | 52 | if got, exp := len(array), list.Len(); got != exp { 53 | t.Fatalf("List.Len()=%d, exp %d", got, exp) 54 | } 55 | for j := range array { 56 | if got, exp := list.Get(j), array[j]; got != exp { 57 | t.Fatalf("%d. List.Get(%d)=%d, exp %d", len(array), j, got, exp) 58 | } 59 | } 60 | }) 61 | 62 | t.Run("Set", func(t *testing.T) { 63 | list := NewList[string]() 64 | list = list.Append("foo") 65 | list = list.Append("bar") 66 | 67 | if v := list.Get(0); v != "foo" { 68 | t.Fatalf("unexpected value: %v", v) 69 | } 70 | 71 | list = list.Set(0, "baz") 72 | if v := list.Get(0); v != "baz" { 73 | t.Fatalf("unexpected value: %v", v) 74 | } else if v := list.Get(1); v != "bar" { 75 | t.Fatalf("unexpected value: %v", v) 76 | } 77 | }) 78 | 79 | t.Run("GetBelowRange", func(t *testing.T) { 80 | var r string 81 | func() { 82 | defer func() { r = recover().(string) }() 83 | l := NewList[string]() 84 | l = l.Append("foo") 85 | l.Get(-1) 86 | }() 87 | if r != `immutable.List.Get: index -1 out of bounds` { 88 | t.Fatalf("unexpected panic: %q", r) 89 | } 90 | }) 91 | 92 | t.Run("GetAboveRange", func(t *testing.T) { 93 | var r string 94 | func() { 95 | defer func() { r = recover().(string) }() 96 | l := NewList[string]() 97 | l = l.Append("foo") 98 | l.Get(1) 99 | }() 100 | if r != `immutable.List.Get: index 1 out of bounds` { 101 | t.Fatalf("unexpected panic: %q", r) 102 | } 103 | }) 104 | 105 | t.Run("SetOutOfRange", func(t *testing.T) { 106 | var r string 107 | func() { 108 | defer func() { r = recover().(string) }() 109 | l := NewList[string]() 110 | l = l.Append("foo") 111 | l.Set(1, "bar") 112 | }() 113 | if r != `immutable.List.Set: index 1 out of bounds` { 114 | t.Fatalf("unexpected panic: %q", r) 115 | } 116 | }) 117 | 118 | t.Run("SliceStartOutOfRange", func(t *testing.T) { 119 | var r string 120 | func() { 121 | defer func() { r = recover().(string) }() 122 | l := NewList[string]() 123 | l = l.Append("foo") 124 | l.Slice(2, 3) 125 | }() 126 | if r != `immutable.List.Slice: start index 2 out of bounds` { 127 | t.Fatalf("unexpected panic: %q", r) 128 | } 129 | }) 130 | 131 | t.Run("SliceEndOutOfRange", func(t *testing.T) { 132 | var r string 133 | func() { 134 | defer func() { r = recover().(string) }() 135 | l := NewList[string]() 136 | l = l.Append("foo") 137 | l.Slice(1, 3) 138 | }() 139 | if r != `immutable.List.Slice: end index 3 out of bounds` { 140 | t.Fatalf("unexpected panic: %q", r) 141 | } 142 | }) 143 | 144 | t.Run("SliceInvalidIndex", func(t *testing.T) { 145 | var r string 146 | func() { 147 | defer func() { r = recover().(string) }() 148 | l := NewList[string]() 149 | l = l.Append("foo") 150 | l = l.Append("bar") 151 | l.Slice(2, 1) 152 | }() 153 | if r != `immutable.List.Slice: invalid slice index: [2:1]` { 154 | t.Fatalf("unexpected panic: %q", r) 155 | } 156 | }) 157 | 158 | t.Run("SliceBeginning", func(t *testing.T) { 159 | l := NewList[string]() 160 | l = l.Append("foo") 161 | l = l.Append("bar") 162 | l = l.Slice(1, 2) 163 | if got, exp := l.Len(), 1; got != exp { 164 | t.Fatalf("List.Len()=%d, exp %d", got, exp) 165 | } else if got, exp := l.Get(0), "bar"; got != exp { 166 | t.Fatalf("List.Get(0)=%v, exp %v", got, exp) 167 | } 168 | }) 169 | 170 | t.Run("IteratorSeekOutOfBounds", func(t *testing.T) { 171 | var r string 172 | func() { 173 | defer func() { r = recover().(string) }() 174 | l := NewList[string]() 175 | l = l.Append("foo") 176 | l.Iterator().Seek(-1) 177 | }() 178 | if r != `immutable.ListIterator.Seek: index -1 out of bounds` { 179 | t.Fatalf("unexpected panic: %q", r) 180 | } 181 | }) 182 | 183 | t.Run("TestSliceFreesReferences", func(t *testing.T) { 184 | /* Test that the leaf node in a sliced list contains zero'ed entries at 185 | * the correct positions. To do this we directly access the internal 186 | * tree structure of the list. 187 | */ 188 | l := NewList[*int]() 189 | var ints [5]int 190 | for i := 0; i < 5; i++ { 191 | l = l.Append(&ints[i]) 192 | } 193 | sl := l.Slice(2, 4) 194 | 195 | var findLeaf func(listNode[*int]) *listLeafNode[*int] 196 | findLeaf = func(n listNode[*int]) *listLeafNode[*int] { 197 | switch n := n.(type) { 198 | case *listBranchNode[*int]: 199 | if n.children[0] == nil { 200 | t.Fatal("Failed to find leaf node due to nil child") 201 | } 202 | return findLeaf(n.children[0]) 203 | case *listLeafNode[*int]: 204 | return n 205 | default: 206 | panic("Unexpected case") 207 | } 208 | } 209 | 210 | leaf := findLeaf(sl.root) 211 | if leaf.occupied != 0b1100 { 212 | t.Errorf("Expected occupied to be 1100, was %032b", leaf.occupied) 213 | } 214 | 215 | for i := 0; i < listNodeSize; i++ { 216 | if 2 <= i && i < 4 { 217 | if leaf.children[i] != &ints[i] { 218 | t.Errorf("Position %v does not contain the right pointer?", i) 219 | } 220 | } else if leaf.children[i] != nil { 221 | t.Errorf("Expected position %v to be cleared, was %v", i, leaf.children[i]) 222 | } 223 | } 224 | }) 225 | 226 | t.Run("AppendImmutable", func(t *testing.T) { 227 | outer_l := NewList[int]() 228 | for N := 0; N < 1_000; N++ { 229 | l1 := outer_l.Append(0) 230 | outer_l.Append(1) 231 | if actual := l1.Get(N); actual != 0 { 232 | t.Fatalf("Append mutates list with %d elements. Got %d instead of 0", N, actual) 233 | } 234 | 235 | outer_l = outer_l.Append(0) 236 | } 237 | }) 238 | 239 | RunRandom(t, "Random", func(t *testing.T, rand *rand.Rand) { 240 | l := NewTList() 241 | for i := 0; i < 100000; i++ { 242 | rnd := rand.Intn(70) 243 | switch { 244 | case rnd == 0: // slice 245 | start, end := l.ChooseSliceIndices(rand) 246 | l.Slice(start, end) 247 | case rnd < 10: // set 248 | if l.Len() > 0 { 249 | l.Set(l.ChooseIndex(rand), rand.Intn(10000)) 250 | } 251 | case rnd < 30: // prepend 252 | l.Prepend(rand.Intn(10000)) 253 | default: // append 254 | l.Append(rand.Intn(10000)) 255 | } 256 | } 257 | if err := l.Validate(); err != nil { 258 | t.Fatal(err) 259 | } 260 | }) 261 | } 262 | 263 | // TList represents a list that operates on a standard Go slice & immutable list. 264 | type TList struct { 265 | im, prev *List[int] 266 | builder *ListBuilder[int] 267 | std []int 268 | } 269 | 270 | // NewTList returns a new instance of TList. 271 | func NewTList() *TList { 272 | return &TList{ 273 | im: NewList[int](), 274 | builder: NewListBuilder[int](), 275 | } 276 | } 277 | 278 | // Len returns the size of the list. 279 | func (l *TList) Len() int { 280 | return len(l.std) 281 | } 282 | 283 | // ChooseIndex returns a randomly chosen, valid index from the standard slice. 284 | func (l *TList) ChooseIndex(rand *rand.Rand) int { 285 | if len(l.std) == 0 { 286 | return -1 287 | } 288 | return rand.Intn(len(l.std)) 289 | } 290 | 291 | // ChooseSliceIndices returns randomly chosen, valid indices for slicing. 292 | func (l *TList) ChooseSliceIndices(rand *rand.Rand) (start, end int) { 293 | if len(l.std) == 0 { 294 | return 0, 0 295 | } 296 | start = rand.Intn(len(l.std)) 297 | end = rand.Intn(len(l.std)-start) + start 298 | return start, end 299 | } 300 | 301 | // Append adds v to the end of slice and List. 302 | func (l *TList) Append(v int) { 303 | l.prev = l.im 304 | l.im = l.im.Append(v) 305 | l.builder.Append(v) 306 | l.std = append(l.std, v) 307 | } 308 | 309 | // Prepend adds v to the beginning of the slice and List. 310 | func (l *TList) Prepend(v int) { 311 | l.prev = l.im 312 | l.im = l.im.Prepend(v) 313 | l.builder.Prepend(v) 314 | l.std = append([]int{v}, l.std...) 315 | } 316 | 317 | // Set updates the value at index i to v in the slice and List. 318 | func (l *TList) Set(i, v int) { 319 | l.prev = l.im 320 | l.im = l.im.Set(i, v) 321 | l.builder.Set(i, v) 322 | l.std[i] = v 323 | } 324 | 325 | // Slice contracts the slice and List to the range of start/end indices. 326 | func (l *TList) Slice(start, end int) { 327 | l.prev = l.im 328 | l.im = l.im.Slice(start, end) 329 | l.builder.Slice(start, end) 330 | l.std = l.std[start:end] 331 | } 332 | 333 | // Validate returns an error if the slice and List are different. 334 | func (l *TList) Validate() error { 335 | if got, exp := l.im.Len(), len(l.std); got != exp { 336 | return fmt.Errorf("Len()=%v, expected %d", got, exp) 337 | } else if got, exp := l.builder.Len(), len(l.std); got != exp { 338 | return fmt.Errorf("Len()=%v, expected %d", got, exp) 339 | } 340 | 341 | for i := range l.std { 342 | if got, exp := l.im.Get(i), l.std[i]; got != exp { 343 | return fmt.Errorf("Get(%d)=%v, expected %v", i, got, exp) 344 | } else if got, exp := l.builder.Get(i), l.std[i]; got != exp { 345 | return fmt.Errorf("Builder.List/Get(%d)=%v, expected %v", i, got, exp) 346 | } 347 | } 348 | 349 | if err := l.validateForwardIterator("basic", l.im.Iterator()); err != nil { 350 | return err 351 | } else if err := l.validateBackwardIterator("basic", l.im.Iterator()); err != nil { 352 | return err 353 | } 354 | 355 | if err := l.validateForwardIterator("builder", l.builder.Iterator()); err != nil { 356 | return err 357 | } else if err := l.validateBackwardIterator("builder", l.builder.Iterator()); err != nil { 358 | return err 359 | } 360 | return nil 361 | } 362 | 363 | func (l *TList) validateForwardIterator(typ string, itr *ListIterator[int]) error { 364 | for i := range l.std { 365 | if j, v := itr.Next(); i != j || l.std[i] != v { 366 | return fmt.Errorf("ListIterator.Next()=<%v,%v>, expected <%v,%v> [%s]", j, v, i, l.std[i], typ) 367 | } 368 | 369 | done := i == len(l.std)-1 370 | if v := itr.Done(); v != done { 371 | return fmt.Errorf("ListIterator.Done()=%v, expected %v [%s]", v, done, typ) 372 | } 373 | } 374 | if i, v := itr.Next(); i != -1 || v != 0 { 375 | return fmt.Errorf("ListIterator.Next()=<%v,%v>, expected DONE [%s]", i, v, typ) 376 | } 377 | return nil 378 | } 379 | 380 | func (l *TList) validateBackwardIterator(typ string, itr *ListIterator[int]) error { 381 | itr.Last() 382 | for i := len(l.std) - 1; i >= 0; i-- { 383 | if j, v := itr.Prev(); i != j || l.std[i] != v { 384 | return fmt.Errorf("ListIterator.Prev()=<%v,%v>, expected <%v,%v> [%s]", j, v, i, l.std[i], typ) 385 | } 386 | 387 | done := i == 0 388 | if v := itr.Done(); v != done { 389 | return fmt.Errorf("ListIterator.Done()=%v, expected %v [%s]", v, done, typ) 390 | } 391 | } 392 | if i, v := itr.Prev(); i != -1 || v != 0 { 393 | return fmt.Errorf("ListIterator.Prev()=<%v,%v>, expected DONE [%s]", i, v, typ) 394 | } 395 | return nil 396 | } 397 | 398 | func BenchmarkList_Append(b *testing.B) { 399 | b.ReportAllocs() 400 | l := NewList[int]() 401 | for i := 0; i < b.N; i++ { 402 | l = l.Append(i) 403 | } 404 | } 405 | 406 | func BenchmarkList_Prepend(b *testing.B) { 407 | b.ReportAllocs() 408 | l := NewList[int]() 409 | for i := 0; i < b.N; i++ { 410 | l = l.Prepend(i) 411 | } 412 | } 413 | 414 | func BenchmarkList_Set(b *testing.B) { 415 | const n = 10000 416 | 417 | l := NewList[int]() 418 | for i := 0; i < 10000; i++ { 419 | l = l.Append(i) 420 | } 421 | b.ReportAllocs() 422 | b.ResetTimer() 423 | 424 | for i := 0; i < b.N; i++ { 425 | l = l.Set(i%n, i*10) 426 | } 427 | } 428 | 429 | func BenchmarkList_Iterator(b *testing.B) { 430 | const n = 10000 431 | l := NewList[int]() 432 | for i := 0; i < 10000; i++ { 433 | l = l.Append(i) 434 | } 435 | b.ReportAllocs() 436 | b.ResetTimer() 437 | 438 | b.Run("Forward", func(b *testing.B) { 439 | itr := l.Iterator() 440 | for i := 0; i < b.N; i++ { 441 | if i%n == 0 { 442 | itr.First() 443 | } 444 | itr.Next() 445 | } 446 | }) 447 | 448 | b.Run("Reverse", func(b *testing.B) { 449 | itr := l.Iterator() 450 | for i := 0; i < b.N; i++ { 451 | if i%n == 0 { 452 | itr.Last() 453 | } 454 | itr.Prev() 455 | } 456 | }) 457 | } 458 | 459 | func BenchmarkBuiltinSlice_Append(b *testing.B) { 460 | b.Run("Int", func(b *testing.B) { 461 | b.ReportAllocs() 462 | var a []int 463 | for i := 0; i < b.N; i++ { 464 | a = append(a, i) 465 | } 466 | }) 467 | b.Run("Interface", func(b *testing.B) { 468 | b.ReportAllocs() 469 | var a []interface{} 470 | for i := 0; i < b.N; i++ { 471 | a = append(a, i) 472 | } 473 | }) 474 | } 475 | 476 | func BenchmarkListBuilder_Append(b *testing.B) { 477 | b.ReportAllocs() 478 | builder := NewListBuilder[int]() 479 | for i := 0; i < b.N; i++ { 480 | builder.Append(i) 481 | } 482 | } 483 | 484 | func BenchmarkListBuilder_Prepend(b *testing.B) { 485 | b.ReportAllocs() 486 | builder := NewListBuilder[int]() 487 | for i := 0; i < b.N; i++ { 488 | builder.Prepend(i) 489 | } 490 | } 491 | 492 | func BenchmarkListBuilder_Set(b *testing.B) { 493 | const n = 10000 494 | 495 | builder := NewListBuilder[int]() 496 | for i := 0; i < 10000; i++ { 497 | builder.Append(i) 498 | } 499 | b.ReportAllocs() 500 | b.ResetTimer() 501 | 502 | for i := 0; i < b.N; i++ { 503 | builder.Set(i%n, i*10) 504 | } 505 | } 506 | 507 | func ExampleList_Append() { 508 | l := NewList[string]() 509 | l = l.Append("foo") 510 | l = l.Append("bar") 511 | l = l.Append("baz") 512 | 513 | fmt.Println(l.Get(0)) 514 | fmt.Println(l.Get(1)) 515 | fmt.Println(l.Get(2)) 516 | // Output: 517 | // foo 518 | // bar 519 | // baz 520 | } 521 | 522 | func ExampleList_Prepend() { 523 | l := NewList[string]() 524 | l = l.Prepend("foo") 525 | l = l.Prepend("bar") 526 | l = l.Prepend("baz") 527 | 528 | fmt.Println(l.Get(0)) 529 | fmt.Println(l.Get(1)) 530 | fmt.Println(l.Get(2)) 531 | // Output: 532 | // baz 533 | // bar 534 | // foo 535 | } 536 | 537 | func ExampleList_Set() { 538 | l := NewList[string]() 539 | l = l.Append("foo") 540 | l = l.Append("bar") 541 | l = l.Set(1, "baz") 542 | 543 | fmt.Println(l.Get(0)) 544 | fmt.Println(l.Get(1)) 545 | // Output: 546 | // foo 547 | // baz 548 | } 549 | 550 | func ExampleList_Slice() { 551 | l := NewList[string]() 552 | l = l.Append("foo") 553 | l = l.Append("bar") 554 | l = l.Append("baz") 555 | l = l.Slice(1, 3) 556 | 557 | fmt.Println(l.Get(0)) 558 | fmt.Println(l.Get(1)) 559 | // Output: 560 | // bar 561 | // baz 562 | } 563 | 564 | func ExampleList_Iterator() { 565 | l := NewList[string]() 566 | l = l.Append("foo") 567 | l = l.Append("bar") 568 | l = l.Append("baz") 569 | 570 | itr := l.Iterator() 571 | for !itr.Done() { 572 | i, v := itr.Next() 573 | fmt.Println(i, v) 574 | } 575 | // Output: 576 | // 0 foo 577 | // 1 bar 578 | // 2 baz 579 | } 580 | 581 | func ExampleList_Iterator_reverse() { 582 | l := NewList[string]() 583 | l = l.Append("foo") 584 | l = l.Append("bar") 585 | l = l.Append("baz") 586 | 587 | itr := l.Iterator() 588 | itr.Last() 589 | for !itr.Done() { 590 | i, v := itr.Prev() 591 | fmt.Println(i, v) 592 | } 593 | // Output: 594 | // 2 baz 595 | // 1 bar 596 | // 0 foo 597 | } 598 | 599 | func ExampleListBuilder_Append() { 600 | b := NewListBuilder[string]() 601 | b.Append("foo") 602 | b.Append("bar") 603 | b.Append("baz") 604 | 605 | l := b.List() 606 | fmt.Println(l.Get(0)) 607 | fmt.Println(l.Get(1)) 608 | fmt.Println(l.Get(2)) 609 | // Output: 610 | // foo 611 | // bar 612 | // baz 613 | } 614 | 615 | func ExampleListBuilder_Prepend() { 616 | b := NewListBuilder[string]() 617 | b.Prepend("foo") 618 | b.Prepend("bar") 619 | b.Prepend("baz") 620 | 621 | l := b.List() 622 | fmt.Println(l.Get(0)) 623 | fmt.Println(l.Get(1)) 624 | fmt.Println(l.Get(2)) 625 | // Output: 626 | // baz 627 | // bar 628 | // foo 629 | } 630 | 631 | func ExampleListBuilder_Set() { 632 | b := NewListBuilder[string]() 633 | b.Append("foo") 634 | b.Append("bar") 635 | b.Set(1, "baz") 636 | 637 | l := b.List() 638 | fmt.Println(l.Get(0)) 639 | fmt.Println(l.Get(1)) 640 | // Output: 641 | // foo 642 | // baz 643 | } 644 | 645 | func ExampleListBuilder_Slice() { 646 | b := NewListBuilder[string]() 647 | b.Append("foo") 648 | b.Append("bar") 649 | b.Append("baz") 650 | b.Slice(1, 3) 651 | 652 | l := b.List() 653 | fmt.Println(l.Get(0)) 654 | fmt.Println(l.Get(1)) 655 | // Output: 656 | // bar 657 | // baz 658 | } 659 | 660 | // Ensure node can support overwrites as it expands. 661 | func TestInternal_mapNode_Overwrite(t *testing.T) { 662 | const n = 1000 663 | var h defaultHasher[int] 664 | var node mapNode[int, int] = &mapArrayNode[int, int]{} 665 | for i := 0; i < n; i++ { 666 | var resized bool 667 | node = node.set(i, i, 0, h.Hash(i), &h, false, &resized) 668 | if !resized { 669 | t.Fatal("expected resize") 670 | } 671 | 672 | // Overwrite every node. 673 | for j := 0; j <= i; j++ { 674 | var resized bool 675 | node = node.set(j, i*j, 0, h.Hash(j), &h, false, &resized) 676 | if resized { 677 | t.Fatalf("expected no resize: i=%d, j=%d", i, j) 678 | } 679 | } 680 | 681 | // Verify not found at each branch type. 682 | if _, ok := node.get(1000000, 0, h.Hash(1000000), &h); ok { 683 | t.Fatal("expected no value") 684 | } 685 | } 686 | 687 | // Verify all key/value pairs in map. 688 | for i := 0; i < n; i++ { 689 | if v, ok := node.get(i, 0, h.Hash(i), &h); !ok || v != i*(n-1) { 690 | t.Fatalf("get(%d)=<%v,%v>", i, v, ok) 691 | } 692 | } 693 | } 694 | 695 | func TestInternal_mapArrayNode(t *testing.T) { 696 | // Ensure 8 or fewer elements stays in an array node. 697 | t.Run("Append", func(t *testing.T) { 698 | var h defaultHasher[int] 699 | n := &mapArrayNode[int, int]{} 700 | for i := 0; i < 8; i++ { 701 | var resized bool 702 | n = n.set(i*10, i, 0, h.Hash(i*10), &h, false, &resized).(*mapArrayNode[int, int]) 703 | if !resized { 704 | t.Fatal("expected resize") 705 | } 706 | 707 | for j := 0; j < i; j++ { 708 | if v, ok := n.get(j*10, 0, h.Hash(j*10), &h); !ok || v != j { 709 | t.Fatalf("get(%d)=<%v,%v>", j, v, ok) 710 | } 711 | } 712 | } 713 | }) 714 | 715 | // Ensure 8 or fewer elements stays in an array node when inserted in reverse. 716 | t.Run("Prepend", func(t *testing.T) { 717 | var h defaultHasher[int] 718 | n := &mapArrayNode[int, int]{} 719 | for i := 7; i >= 0; i-- { 720 | var resized bool 721 | n = n.set(i*10, i, 0, h.Hash(i*10), &h, false, &resized).(*mapArrayNode[int, int]) 722 | if !resized { 723 | t.Fatal("expected resize") 724 | } 725 | 726 | for j := i; j <= 7; j++ { 727 | if v, ok := n.get(j*10, 0, h.Hash(j*10), &h); !ok || v != j { 728 | t.Fatalf("get(%d)=<%v,%v>", j, v, ok) 729 | } 730 | } 731 | } 732 | }) 733 | 734 | // Ensure array can transition between node types. 735 | t.Run("Expand", func(t *testing.T) { 736 | var h defaultHasher[int] 737 | var n mapNode[int, int] = &mapArrayNode[int, int]{} 738 | for i := 0; i < 100; i++ { 739 | var resized bool 740 | n = n.set(i, i, 0, h.Hash(i), &h, false, &resized) 741 | if !resized { 742 | t.Fatal("expected resize") 743 | } 744 | 745 | for j := 0; j < i; j++ { 746 | if v, ok := n.get(j, 0, h.Hash(j), &h); !ok || v != j { 747 | t.Fatalf("get(%d)=<%v,%v>", j, v, ok) 748 | } 749 | } 750 | } 751 | }) 752 | 753 | // Ensure deleting elements returns the correct new node. 754 | RunRandom(t, "Delete", func(t *testing.T, rand *rand.Rand) { 755 | var h defaultHasher[int] 756 | var n mapNode[int, int] = &mapArrayNode[int, int]{} 757 | for i := 0; i < 8; i++ { 758 | var resized bool 759 | n = n.set(i*10, i, 0, h.Hash(i*10), &h, false, &resized) 760 | } 761 | 762 | for _, i := range rand.Perm(8) { 763 | var resized bool 764 | n = n.delete(i*10, 0, h.Hash(i*10), &h, false, &resized) 765 | } 766 | if n != nil { 767 | t.Fatal("expected nil rand") 768 | } 769 | }) 770 | } 771 | 772 | func TestInternal_mapValueNode(t *testing.T) { 773 | t.Run("Simple", func(t *testing.T) { 774 | var h defaultHasher[int] 775 | n := newMapValueNode(h.Hash(2), 2, 3) 776 | if v, ok := n.get(2, 0, h.Hash(2), &h); !ok { 777 | t.Fatal("expected ok") 778 | } else if v != 3 { 779 | t.Fatalf("unexpected value: %v", v) 780 | } 781 | }) 782 | 783 | t.Run("KeyEqual", func(t *testing.T) { 784 | var h defaultHasher[int] 785 | var resized bool 786 | n := newMapValueNode(h.Hash(2), 2, 3) 787 | other := n.set(2, 4, 0, h.Hash(2), &h, false, &resized).(*mapValueNode[int, int]) 788 | if other == n { 789 | t.Fatal("expected new node") 790 | } else if got, exp := other.keyHash, h.Hash(2); got != exp { 791 | t.Fatalf("keyHash=%v, expected %v", got, exp) 792 | } else if got, exp := other.key, 2; got != exp { 793 | t.Fatalf("key=%v, expected %v", got, exp) 794 | } else if got, exp := other.value, 4; got != exp { 795 | t.Fatalf("value=%v, expected %v", got, exp) 796 | } else if resized { 797 | t.Fatal("unexpected resize") 798 | } 799 | }) 800 | 801 | t.Run("KeyHashEqual", func(t *testing.T) { 802 | h := &mockHasher[int]{ 803 | hash: func(value int) uint32 { return 1 }, 804 | equal: func(a, b int) bool { return a == b }, 805 | } 806 | var resized bool 807 | n := newMapValueNode(h.Hash(2), 2, 3) 808 | other := n.set(4, 5, 0, h.Hash(4), h, false, &resized).(*mapHashCollisionNode[int, int]) 809 | if got, exp := other.keyHash, h.Hash(2); got != exp { 810 | t.Fatalf("keyHash=%v, expected %v", got, exp) 811 | } else if got, exp := len(other.entries), 2; got != exp { 812 | t.Fatalf("entries=%v, expected %v", got, exp) 813 | } else if !resized { 814 | t.Fatal("expected resize") 815 | } 816 | if got, exp := other.entries[0].key, 2; got != exp { 817 | t.Fatalf("key[0]=%v, expected %v", got, exp) 818 | } else if got, exp := other.entries[0].value, 3; got != exp { 819 | t.Fatalf("value[0]=%v, expected %v", got, exp) 820 | } 821 | if got, exp := other.entries[1].key, 4; got != exp { 822 | t.Fatalf("key[1]=%v, expected %v", got, exp) 823 | } else if got, exp := other.entries[1].value, 5; got != exp { 824 | t.Fatalf("value[1]=%v, expected %v", got, exp) 825 | } 826 | }) 827 | 828 | t.Run("MergeNode", func(t *testing.T) { 829 | // Inserting into a node with a different index in the mask should split into a bitmap node. 830 | t.Run("NoConflict", func(t *testing.T) { 831 | var h defaultHasher[int] 832 | var resized bool 833 | n := newMapValueNode(h.Hash(2), 2, 3) 834 | other := n.set(4, 5, 0, h.Hash(4), &h, false, &resized).(*mapBitmapIndexedNode[int, int]) 835 | if got, exp := other.bitmap, uint32(0x14); got != exp { 836 | t.Fatalf("bitmap=0x%02x, expected 0x%02x", got, exp) 837 | } else if got, exp := len(other.nodes), 2; got != exp { 838 | t.Fatalf("nodes=%v, expected %v", got, exp) 839 | } else if !resized { 840 | t.Fatal("expected resize") 841 | } 842 | if node, ok := other.nodes[0].(*mapValueNode[int, int]); !ok { 843 | t.Fatalf("node[0]=%T, unexpected type", other.nodes[0]) 844 | } else if got, exp := node.key, 2; got != exp { 845 | t.Fatalf("key[0]=%v, expected %v", got, exp) 846 | } else if got, exp := node.value, 3; got != exp { 847 | t.Fatalf("value[0]=%v, expected %v", got, exp) 848 | } 849 | if node, ok := other.nodes[1].(*mapValueNode[int, int]); !ok { 850 | t.Fatalf("node[1]=%T, unexpected type", other.nodes[1]) 851 | } else if got, exp := node.key, 4; got != exp { 852 | t.Fatalf("key[1]=%v, expected %v", got, exp) 853 | } else if got, exp := node.value, 5; got != exp { 854 | t.Fatalf("value[1]=%v, expected %v", got, exp) 855 | } 856 | 857 | // Ensure both values can be read. 858 | if v, ok := other.get(2, 0, h.Hash(2), &h); !ok || v != 3 { 859 | t.Fatalf("Get(2)=<%v,%v>", v, ok) 860 | } else if v, ok := other.get(4, 0, h.Hash(4), &h); !ok || v != 5 { 861 | t.Fatalf("Get(4)=<%v,%v>", v, ok) 862 | } 863 | }) 864 | 865 | // Reversing the nodes from NoConflict should yield the same result. 866 | t.Run("NoConflictReverse", func(t *testing.T) { 867 | var h defaultHasher[int] 868 | var resized bool 869 | n := newMapValueNode(h.Hash(4), 4, 5) 870 | other := n.set(2, 3, 0, h.Hash(2), &h, false, &resized).(*mapBitmapIndexedNode[int, int]) 871 | if got, exp := other.bitmap, uint32(0x14); got != exp { 872 | t.Fatalf("bitmap=0x%02x, expected 0x%02x", got, exp) 873 | } else if got, exp := len(other.nodes), 2; got != exp { 874 | t.Fatalf("nodes=%v, expected %v", got, exp) 875 | } else if !resized { 876 | t.Fatal("expected resize") 877 | } 878 | if node, ok := other.nodes[0].(*mapValueNode[int, int]); !ok { 879 | t.Fatalf("node[0]=%T, unexpected type", other.nodes[0]) 880 | } else if got, exp := node.key, 2; got != exp { 881 | t.Fatalf("key[0]=%v, expected %v", got, exp) 882 | } else if got, exp := node.value, 3; got != exp { 883 | t.Fatalf("value[0]=%v, expected %v", got, exp) 884 | } 885 | if node, ok := other.nodes[1].(*mapValueNode[int, int]); !ok { 886 | t.Fatalf("node[1]=%T, unexpected type", other.nodes[1]) 887 | } else if got, exp := node.key, 4; got != exp { 888 | t.Fatalf("key[1]=%v, expected %v", got, exp) 889 | } else if got, exp := node.value, 5; got != exp { 890 | t.Fatalf("value[1]=%v, expected %v", got, exp) 891 | } 892 | 893 | // Ensure both values can be read. 894 | if v, ok := other.get(2, 0, h.Hash(2), &h); !ok || v != 3 { 895 | t.Fatalf("Get(2)=<%v,%v>", v, ok) 896 | } else if v, ok := other.get(4, 0, h.Hash(4), &h); !ok || v != 5 { 897 | t.Fatalf("Get(4)=<%v,%v>", v, ok) 898 | } 899 | }) 900 | 901 | // Inserting a node with the same mask index should nest an additional level of bitmap nodes. 902 | t.Run("Conflict", func(t *testing.T) { 903 | h := &mockHasher[int]{ 904 | hash: func(value int) uint32 { return uint32(value << 5) }, 905 | equal: func(a, b int) bool { return a == b }, 906 | } 907 | var resized bool 908 | n := newMapValueNode(h.Hash(2), 2, 3) 909 | other := n.set(4, 5, 0, h.Hash(4), h, false, &resized).(*mapBitmapIndexedNode[int, int]) 910 | if got, exp := other.bitmap, uint32(0x01); got != exp { // mask is zero, expect first slot. 911 | t.Fatalf("bitmap=0x%02x, expected 0x%02x", got, exp) 912 | } else if got, exp := len(other.nodes), 1; got != exp { 913 | t.Fatalf("nodes=%v, expected %v", got, exp) 914 | } else if !resized { 915 | t.Fatal("expected resize") 916 | } 917 | child, ok := other.nodes[0].(*mapBitmapIndexedNode[int, int]) 918 | if !ok { 919 | t.Fatalf("node[0]=%T, unexpected type", other.nodes[0]) 920 | } 921 | 922 | if node, ok := child.nodes[0].(*mapValueNode[int, int]); !ok { 923 | t.Fatalf("node[0]=%T, unexpected type", child.nodes[0]) 924 | } else if got, exp := node.key, 2; got != exp { 925 | t.Fatalf("key[0]=%v, expected %v", got, exp) 926 | } else if got, exp := node.value, 3; got != exp { 927 | t.Fatalf("value[0]=%v, expected %v", got, exp) 928 | } 929 | if node, ok := child.nodes[1].(*mapValueNode[int, int]); !ok { 930 | t.Fatalf("node[1]=%T, unexpected type", child.nodes[1]) 931 | } else if got, exp := node.key, 4; got != exp { 932 | t.Fatalf("key[1]=%v, expected %v", got, exp) 933 | } else if got, exp := node.value, 5; got != exp { 934 | t.Fatalf("value[1]=%v, expected %v", got, exp) 935 | } 936 | 937 | // Ensure both values can be read. 938 | if v, ok := other.get(2, 0, h.Hash(2), h); !ok || v != 3 { 939 | t.Fatalf("Get(2)=<%v,%v>", v, ok) 940 | } else if v, ok := other.get(4, 0, h.Hash(4), h); !ok || v != 5 { 941 | t.Fatalf("Get(4)=<%v,%v>", v, ok) 942 | } else if v, ok := other.get(10, 0, h.Hash(10), h); ok { 943 | t.Fatalf("Get(10)=<%v,%v>, expected no value", v, ok) 944 | } 945 | }) 946 | }) 947 | } 948 | 949 | func TestMap_Get(t *testing.T) { 950 | t.Run("Empty", func(t *testing.T) { 951 | m := NewMap[int, string](nil) 952 | if v, ok := m.Get(100); ok { 953 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 954 | } 955 | }) 956 | } 957 | 958 | func TestMap_Set(t *testing.T) { 959 | t.Run("Simple", func(t *testing.T) { 960 | m := NewMap[int, string](nil) 961 | itr := m.Iterator() 962 | if !itr.Done() { 963 | t.Fatal("MapIterator.Done()=true, expected false") 964 | } else if k, v, ok := itr.Next(); ok { 965 | t.Fatalf("MapIterator.Next()=<%v,%v>, expected nil", k, v) 966 | } 967 | }) 968 | 969 | t.Run("Simple", func(t *testing.T) { 970 | m := NewMap[int, string](nil) 971 | m = m.Set(100, "foo") 972 | if v, ok := m.Get(100); !ok || v != "foo" { 973 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 974 | } 975 | }) 976 | 977 | t.Run("Multi", func(t *testing.T) { 978 | m := NewMapOf(nil, map[int]string{1: "foo"}) 979 | itr := m.Iterator() 980 | if itr.Done() { 981 | t.Fatal("MapIterator.Done()=false, expected true") 982 | } 983 | if k, v, ok := itr.Next(); !ok { 984 | t.Fatalf("MapIterator.Next()!=ok, expected ok") 985 | } else if k != 1 || v != "foo" { 986 | t.Fatalf("MapIterator.Next()=<%v,%v>, expected <1, \"foo\">", k, v) 987 | } 988 | if k, v, ok := itr.Next(); ok { 989 | t.Fatalf("MapIterator.Next()=<%v,%v>, expected nil", k, v) 990 | } 991 | }) 992 | 993 | t.Run("VerySmall", func(t *testing.T) { 994 | const n = 6 995 | m := NewMap[int, int](nil) 996 | for i := 0; i < n; i++ { 997 | m = m.Set(i, i+1) 998 | } 999 | for i := 0; i < n; i++ { 1000 | if v, ok := m.Get(i); !ok || v != i+1 { 1001 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1002 | } 1003 | } 1004 | 1005 | // NOTE: Array nodes store entries in insertion order. 1006 | itr := m.Iterator() 1007 | for i := 0; i < n; i++ { 1008 | if k, v, ok := itr.Next(); !ok || k != i || v != i+1 { 1009 | t.Fatalf("MapIterator.Next()=<%v,%v>, exp <%v,%v>", k, v, i, i+1) 1010 | } 1011 | } 1012 | if !itr.Done() { 1013 | t.Fatal("expected iterator done") 1014 | } 1015 | }) 1016 | 1017 | t.Run("Small", func(t *testing.T) { 1018 | const n = 1000 1019 | m := NewMap[int, int](nil) 1020 | for i := 0; i < n; i++ { 1021 | m = m.Set(i, i+1) 1022 | } 1023 | for i := 0; i < n; i++ { 1024 | if v, ok := m.Get(i); !ok || v != i+1 { 1025 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1026 | } 1027 | } 1028 | }) 1029 | 1030 | t.Run("Large", func(t *testing.T) { 1031 | if testing.Short() { 1032 | t.Skip("skipping: short") 1033 | } 1034 | 1035 | const n = 1000000 1036 | m := NewMap[int, int](nil) 1037 | for i := 0; i < n; i++ { 1038 | m = m.Set(i, i+1) 1039 | } 1040 | for i := 0; i < n; i++ { 1041 | if v, ok := m.Get(i); !ok || v != i+1 { 1042 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1043 | } 1044 | } 1045 | }) 1046 | 1047 | t.Run("StringKeys", func(t *testing.T) { 1048 | m := NewMap[string, string](nil) 1049 | m = m.Set("foo", "bar") 1050 | m = m.Set("baz", "bat") 1051 | m = m.Set("", "EMPTY") 1052 | if v, ok := m.Get("foo"); !ok || v != "bar" { 1053 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1054 | } else if v, ok := m.Get("baz"); !ok || v != "bat" { 1055 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1056 | } else if v, ok := m.Get(""); !ok || v != "EMPTY" { 1057 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1058 | } 1059 | if v, ok := m.Get("no_such_key"); ok { 1060 | t.Fatalf("expected no value: <%v,%v>", v, ok) 1061 | } 1062 | }) 1063 | 1064 | RunRandom(t, "Random", func(t *testing.T, rand *rand.Rand) { 1065 | m := NewTestMap() 1066 | for i := 0; i < 10000; i++ { 1067 | switch rand.Intn(2) { 1068 | case 1: // overwrite 1069 | m.Set(m.ExistingKey(rand), rand.Intn(10000)) 1070 | default: // set new key 1071 | m.Set(m.NewKey(rand), rand.Intn(10000)) 1072 | } 1073 | } 1074 | if err := m.Validate(); err != nil { 1075 | t.Fatal(err) 1076 | } 1077 | }) 1078 | } 1079 | 1080 | // Ensure map can support overwrites as it expands. 1081 | func TestMap_Overwrite(t *testing.T) { 1082 | if testing.Short() { 1083 | t.Skip("short mode") 1084 | } 1085 | 1086 | const n = 10000 1087 | m := NewMap[int, int](nil) 1088 | for i := 0; i < n; i++ { 1089 | // Set original value. 1090 | m = m.Set(i, i) 1091 | 1092 | // Overwrite every node. 1093 | for j := 0; j <= i; j++ { 1094 | m = m.Set(j, i*j) 1095 | } 1096 | } 1097 | 1098 | // Verify all key/value pairs in map. 1099 | for i := 0; i < n; i++ { 1100 | if v, ok := m.Get(i); !ok || v != i*(n-1) { 1101 | t.Fatalf("Get(%d)=<%v,%v>", i, v, ok) 1102 | } 1103 | } 1104 | 1105 | t.Run("Simple", func(t *testing.T) { 1106 | m := NewMap[int, string](nil) 1107 | itr := m.Iterator() 1108 | if !itr.Done() { 1109 | t.Fatal("MapIterator.Done()=true, expected false") 1110 | } else if k, v, ok := itr.Next(); ok { 1111 | t.Fatalf("MapIterator.Next()=<%v,%v>, expected nil", k, v) 1112 | } 1113 | }) 1114 | } 1115 | 1116 | func TestMap_Delete(t *testing.T) { 1117 | t.Run("Empty", func(t *testing.T) { 1118 | m := NewMap[string, int](nil) 1119 | other := m.Delete("foo") 1120 | if m != other { 1121 | t.Fatal("expected same map") 1122 | } 1123 | }) 1124 | 1125 | t.Run("Simple", func(t *testing.T) { 1126 | m := NewMap[int, string](nil) 1127 | m = m.Set(100, "foo") 1128 | if v, ok := m.Get(100); !ok || v != "foo" { 1129 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1130 | } 1131 | }) 1132 | 1133 | t.Run("Small", func(t *testing.T) { 1134 | const n = 1000 1135 | m := NewMap[int, int](nil) 1136 | for i := 0; i < n; i++ { 1137 | m = m.Set(i, i+1) 1138 | } 1139 | for i := range rand.New(rand.NewSource(0)).Perm(n) { 1140 | m = m.Delete(i) 1141 | } 1142 | if m.Len() != 0 { 1143 | t.Fatalf("expected no elements, got %d", m.Len()) 1144 | } 1145 | }) 1146 | 1147 | t.Run("Large", func(t *testing.T) { 1148 | if testing.Short() { 1149 | t.Skip("skipping: short") 1150 | } 1151 | const n = 1000000 1152 | m := NewMap[int, int](nil) 1153 | for i := 0; i < n; i++ { 1154 | m = m.Set(i, i+1) 1155 | } 1156 | for i := range rand.New(rand.NewSource(0)).Perm(n) { 1157 | m = m.Delete(i) 1158 | } 1159 | if m.Len() != 0 { 1160 | t.Fatalf("expected no elements, got %d", m.Len()) 1161 | } 1162 | }) 1163 | 1164 | RunRandom(t, "Random", func(t *testing.T, rand *rand.Rand) { 1165 | m := NewTestMap() 1166 | for i := 0; i < 10000; i++ { 1167 | switch rand.Intn(8) { 1168 | case 0: // overwrite 1169 | m.Set(m.ExistingKey(rand), rand.Intn(10000)) 1170 | case 1: // delete existing key 1171 | m.Delete(m.ExistingKey(rand)) 1172 | case 2: // delete non-existent key. 1173 | m.Delete(m.NewKey(rand)) 1174 | default: // set new key 1175 | m.Set(m.NewKey(rand), rand.Intn(10000)) 1176 | } 1177 | } 1178 | 1179 | // Delete all and verify they are gone. 1180 | keys := make([]int, len(m.keys)) 1181 | copy(keys, m.keys) 1182 | 1183 | for _, key := range keys { 1184 | m.Delete(key) 1185 | } 1186 | if err := m.Validate(); err != nil { 1187 | t.Fatal(err) 1188 | } 1189 | }) 1190 | } 1191 | 1192 | // Ensure map works even with hash conflicts. 1193 | func TestMap_LimitedHash(t *testing.T) { 1194 | if testing.Short() { 1195 | t.Skip("skipping: short") 1196 | } 1197 | 1198 | t.Run("Immutable", func(t *testing.T) { 1199 | h := mockHasher[int]{ 1200 | hash: func(value int) uint32 { return hashUint64(uint64(value)) % 0xFF }, 1201 | equal: func(a, b int) bool { return a == b }, 1202 | } 1203 | m := NewMap[int, int](&h) 1204 | 1205 | rand := rand.New(rand.NewSource(0)) 1206 | keys := rand.Perm(100000) 1207 | for _, i := range keys { 1208 | m = m.Set(i, i) // initial set 1209 | } 1210 | for i := range keys { 1211 | m = m.Set(i, i*2) // overwrite 1212 | } 1213 | if m.Len() != len(keys) { 1214 | t.Fatalf("unexpected len: %d", m.Len()) 1215 | } 1216 | 1217 | // Verify all key/value pairs in map. 1218 | for i := 0; i < m.Len(); i++ { 1219 | if v, ok := m.Get(i); !ok || v != i*2 { 1220 | t.Fatalf("Get(%d)=<%v,%v>", i, v, ok) 1221 | } 1222 | } 1223 | 1224 | // Verify iteration. 1225 | itr := m.Iterator() 1226 | for !itr.Done() { 1227 | if k, v, ok := itr.Next(); !ok || v != k*2 { 1228 | t.Fatalf("MapIterator.Next()=<%v,%v>, expected value %v", k, v, k*2) 1229 | } 1230 | } 1231 | 1232 | // Verify not found works. 1233 | if _, ok := m.Get(10000000); ok { 1234 | t.Fatal("expected no value") 1235 | } 1236 | 1237 | // Verify delete non-existent key works. 1238 | if other := m.Delete(10000000 + 1); m != other { 1239 | t.Fatal("expected no change") 1240 | } 1241 | 1242 | // Remove all keys. 1243 | for _, key := range keys { 1244 | m = m.Delete(key) 1245 | } 1246 | if m.Len() != 0 { 1247 | t.Fatalf("unexpected size: %d", m.Len()) 1248 | } 1249 | }) 1250 | 1251 | t.Run("Builder", func(t *testing.T) { 1252 | h := mockHasher[int]{ 1253 | hash: func(value int) uint32 { return hashUint64(uint64(value)) }, 1254 | equal: func(a, b int) bool { return a == b }, 1255 | } 1256 | b := NewMapBuilder[int, int](&h) 1257 | 1258 | rand := rand.New(rand.NewSource(0)) 1259 | keys := rand.Perm(100000) 1260 | for _, i := range keys { 1261 | b.Set(i, i) // initial set 1262 | } 1263 | for i := range keys { 1264 | b.Set(i, i*2) // overwrite 1265 | } 1266 | if b.Len() != len(keys) { 1267 | t.Fatalf("unexpected len: %d", b.Len()) 1268 | } 1269 | 1270 | // Verify all key/value pairs in map. 1271 | for i := 0; i < b.Len(); i++ { 1272 | if v, ok := b.Get(i); !ok || v != i*2 { 1273 | t.Fatalf("Get(%d)=<%v,%v>", i, v, ok) 1274 | } 1275 | } 1276 | 1277 | // Verify iteration. 1278 | itr := b.Iterator() 1279 | for !itr.Done() { 1280 | if k, v, ok := itr.Next(); !ok || v != k*2 { 1281 | t.Fatalf("MapIterator.Next()=<%v,%v>, expected value %v", k, v, k*2) 1282 | } 1283 | } 1284 | 1285 | // Verify not found works. 1286 | if _, ok := b.Get(10000000); ok { 1287 | t.Fatal("expected no value") 1288 | } 1289 | 1290 | // Remove all keys. 1291 | for _, key := range keys { 1292 | b.Delete(key) 1293 | } 1294 | if b.Len() != 0 { 1295 | t.Fatalf("unexpected size: %d", b.Len()) 1296 | } 1297 | }) 1298 | } 1299 | 1300 | // TMap represents a combined immutable and stdlib map. 1301 | type TMap struct { 1302 | im, prev *Map[int, int] 1303 | builder *MapBuilder[int, int] 1304 | std map[int]int 1305 | keys []int 1306 | } 1307 | 1308 | func NewTestMap() *TMap { 1309 | return &TMap{ 1310 | im: NewMap[int, int](nil), 1311 | builder: NewMapBuilder[int, int](nil), 1312 | std: make(map[int]int), 1313 | } 1314 | } 1315 | 1316 | func (m *TMap) NewKey(rand *rand.Rand) int { 1317 | for { 1318 | k := rand.Int() 1319 | if _, ok := m.std[k]; !ok { 1320 | return k 1321 | } 1322 | } 1323 | } 1324 | 1325 | func (m *TMap) ExistingKey(rand *rand.Rand) int { 1326 | if len(m.keys) == 0 { 1327 | return 0 1328 | } 1329 | return m.keys[rand.Intn(len(m.keys))] 1330 | } 1331 | 1332 | func (m *TMap) Set(k, v int) { 1333 | m.prev = m.im 1334 | m.im = m.im.Set(k, v) 1335 | m.builder.Set(k, v) 1336 | 1337 | _, exists := m.std[k] 1338 | if !exists { 1339 | m.keys = append(m.keys, k) 1340 | } 1341 | m.std[k] = v 1342 | } 1343 | 1344 | func (m *TMap) Delete(k int) { 1345 | m.prev = m.im 1346 | m.im = m.im.Delete(k) 1347 | m.builder.Delete(k) 1348 | delete(m.std, k) 1349 | 1350 | for i := range m.keys { 1351 | if m.keys[i] == k { 1352 | m.keys = append(m.keys[:i], m.keys[i+1:]...) 1353 | break 1354 | } 1355 | } 1356 | } 1357 | 1358 | func (m *TMap) Validate() error { 1359 | for _, k := range m.keys { 1360 | if v, ok := m.im.Get(k); !ok { 1361 | return fmt.Errorf("key not found: %d", k) 1362 | } else if v != m.std[k] { 1363 | return fmt.Errorf("key (%d) mismatch: immutable=%d, std=%d", k, v, m.std[k]) 1364 | } 1365 | if v, ok := m.builder.Get(k); !ok { 1366 | return fmt.Errorf("builder key not found: %d", k) 1367 | } else if v != m.std[k] { 1368 | return fmt.Errorf("builder key (%d) mismatch: immutable=%d, std=%d", k, v, m.std[k]) 1369 | } 1370 | } 1371 | if err := m.validateIterator(m.im.Iterator()); err != nil { 1372 | return fmt.Errorf("basic: %s", err) 1373 | } else if err := m.validateIterator(m.builder.Iterator()); err != nil { 1374 | return fmt.Errorf("builder: %s", err) 1375 | } 1376 | return nil 1377 | } 1378 | 1379 | func (m *TMap) validateIterator(itr *MapIterator[int, int]) error { 1380 | other := make(map[int]int) 1381 | for !itr.Done() { 1382 | k, v, _ := itr.Next() 1383 | other[k] = v 1384 | } 1385 | if len(other) != len(m.std) { 1386 | return fmt.Errorf("map iterator size mismatch: %v!=%v", len(m.std), len(other)) 1387 | } 1388 | for k, v := range m.std { 1389 | if v != other[k] { 1390 | return fmt.Errorf("map iterator mismatch: key=%v, %v!=%v", k, v, other[k]) 1391 | } 1392 | } 1393 | if k, v, ok := itr.Next(); ok { 1394 | return fmt.Errorf("map iterator returned key/value after done: <%v/%v>", k, v) 1395 | } 1396 | return nil 1397 | } 1398 | 1399 | func BenchmarkBuiltinMap_Set(b *testing.B) { 1400 | b.ReportAllocs() 1401 | m := make(map[int]int) 1402 | for i := 0; i < b.N; i++ { 1403 | m[i] = i 1404 | } 1405 | } 1406 | 1407 | func BenchmarkBuiltinMap_Delete(b *testing.B) { 1408 | const n = 10000000 1409 | 1410 | m := make(map[int]int) 1411 | for i := 0; i < n; i++ { 1412 | m[i] = i 1413 | } 1414 | b.ReportAllocs() 1415 | b.ResetTimer() 1416 | 1417 | for i := 0; i < b.N; i++ { 1418 | delete(m, i%n) 1419 | } 1420 | } 1421 | 1422 | func BenchmarkMap_Set(b *testing.B) { 1423 | b.ReportAllocs() 1424 | m := NewMap[int, int](nil) 1425 | for i := 0; i < b.N; i++ { 1426 | m = m.Set(i, i) 1427 | } 1428 | } 1429 | 1430 | func BenchmarkMap_Delete(b *testing.B) { 1431 | const n = 10000000 1432 | 1433 | builder := NewMapBuilder[int, int](nil) 1434 | for i := 0; i < n; i++ { 1435 | builder.Set(i, i) 1436 | } 1437 | b.ReportAllocs() 1438 | b.ResetTimer() 1439 | 1440 | m := builder.Map() 1441 | for i := 0; i < b.N; i++ { 1442 | m.Delete(i % n) // Do not update map, always operate on original 1443 | } 1444 | } 1445 | 1446 | func BenchmarkMap_Iterator(b *testing.B) { 1447 | const n = 10000 1448 | m := NewMap[int, int](nil) 1449 | for i := 0; i < 10000; i++ { 1450 | m = m.Set(i, i) 1451 | } 1452 | b.ReportAllocs() 1453 | b.ResetTimer() 1454 | 1455 | b.Run("Forward", func(b *testing.B) { 1456 | itr := m.Iterator() 1457 | for i := 0; i < b.N; i++ { 1458 | if i%n == 0 { 1459 | itr.First() 1460 | } 1461 | itr.Next() 1462 | } 1463 | }) 1464 | } 1465 | 1466 | func BenchmarkMapBuilder_Set(b *testing.B) { 1467 | b.ReportAllocs() 1468 | builder := NewMapBuilder[int, int](nil) 1469 | for i := 0; i < b.N; i++ { 1470 | builder.Set(i, i) 1471 | } 1472 | } 1473 | 1474 | func BenchmarkMapBuilder_Delete(b *testing.B) { 1475 | const n = 10000000 1476 | 1477 | builder := NewMapBuilder[int, int](nil) 1478 | for i := 0; i < n; i++ { 1479 | builder.Set(i, i) 1480 | } 1481 | b.ReportAllocs() 1482 | b.ResetTimer() 1483 | 1484 | for i := 0; i < b.N; i++ { 1485 | builder.Delete(i % n) 1486 | } 1487 | } 1488 | 1489 | func ExampleMap_Set() { 1490 | m := NewMap[string, any](nil) 1491 | m = m.Set("foo", "bar") 1492 | m = m.Set("baz", 100) 1493 | 1494 | v, ok := m.Get("foo") 1495 | fmt.Println("foo", v, ok) 1496 | 1497 | v, ok = m.Get("baz") 1498 | fmt.Println("baz", v, ok) 1499 | 1500 | v, ok = m.Get("bat") // does not exist 1501 | fmt.Println("bat", v, ok) 1502 | // Output: 1503 | // foo bar true 1504 | // baz 100 true 1505 | // bat false 1506 | } 1507 | 1508 | func ExampleMap_Delete() { 1509 | m := NewMap[string, any](nil) 1510 | m = m.Set("foo", "bar") 1511 | m = m.Set("baz", 100) 1512 | m = m.Delete("baz") 1513 | 1514 | v, ok := m.Get("foo") 1515 | fmt.Println("foo", v, ok) 1516 | 1517 | v, ok = m.Get("baz") 1518 | fmt.Println("baz", v, ok) 1519 | // Output: 1520 | // foo bar true 1521 | // baz false 1522 | } 1523 | 1524 | func ExampleMap_Iterator() { 1525 | m := NewMap[string, int](nil) 1526 | m = m.Set("apple", 100) 1527 | m = m.Set("grape", 200) 1528 | m = m.Set("kiwi", 300) 1529 | m = m.Set("mango", 400) 1530 | m = m.Set("orange", 500) 1531 | m = m.Set("peach", 600) 1532 | m = m.Set("pear", 700) 1533 | m = m.Set("pineapple", 800) 1534 | m = m.Set("strawberry", 900) 1535 | 1536 | itr := m.Iterator() 1537 | for !itr.Done() { 1538 | k, v, _ := itr.Next() 1539 | fmt.Println(k, v) 1540 | } 1541 | // Output: 1542 | // mango 400 1543 | // pear 700 1544 | // pineapple 800 1545 | // grape 200 1546 | // orange 500 1547 | // strawberry 900 1548 | // kiwi 300 1549 | // peach 600 1550 | // apple 100 1551 | } 1552 | 1553 | func ExampleMapBuilder_Set() { 1554 | b := NewMapBuilder[string, any](nil) 1555 | b.Set("foo", "bar") 1556 | b.Set("baz", 100) 1557 | 1558 | m := b.Map() 1559 | v, ok := m.Get("foo") 1560 | fmt.Println("foo", v, ok) 1561 | 1562 | v, ok = m.Get("baz") 1563 | fmt.Println("baz", v, ok) 1564 | 1565 | v, ok = m.Get("bat") // does not exist 1566 | fmt.Println("bat", v, ok) 1567 | // Output: 1568 | // foo bar true 1569 | // baz 100 true 1570 | // bat false 1571 | } 1572 | 1573 | func ExampleMapBuilder_Delete() { 1574 | b := NewMapBuilder[string, any](nil) 1575 | b.Set("foo", "bar") 1576 | b.Set("baz", 100) 1577 | b.Delete("baz") 1578 | 1579 | m := b.Map() 1580 | v, ok := m.Get("foo") 1581 | fmt.Println("foo", v, ok) 1582 | 1583 | v, ok = m.Get("baz") 1584 | fmt.Println("baz", v, ok) 1585 | // Output: 1586 | // foo bar true 1587 | // baz false 1588 | } 1589 | 1590 | func TestInternalSortedMapLeafNode(t *testing.T) { 1591 | RunRandom(t, "NoSplit", func(t *testing.T, rand *rand.Rand) { 1592 | var cmpr defaultComparer[int] 1593 | var node sortedMapNode[int, int] = &sortedMapLeafNode[int, int]{} 1594 | var keys []int 1595 | for _, i := range rand.Perm(32) { 1596 | var resized bool 1597 | var splitNode sortedMapNode[int, int] 1598 | node, splitNode = node.set(i, i*10, &cmpr, false, &resized) 1599 | if !resized { 1600 | t.Fatal("expected resize") 1601 | } else if splitNode != nil { 1602 | t.Fatal("expected split") 1603 | } 1604 | keys = append(keys, i) 1605 | 1606 | // Verify not found at each size. 1607 | if _, ok := node.get(rand.Int()+32, &cmpr); ok { 1608 | t.Fatal("expected no value") 1609 | } 1610 | 1611 | // Verify min key is always the lowest. 1612 | sort.Ints(keys) 1613 | if got, exp := node.minKey(), keys[0]; got != exp { 1614 | t.Fatalf("minKey()=%d, expected %d", got, exp) 1615 | } 1616 | } 1617 | 1618 | // Verify all key/value pairs in node. 1619 | for i := range keys { 1620 | if v, ok := node.get(i, &cmpr); !ok || v != i*10 { 1621 | t.Fatalf("get(%d)=<%v,%v>", i, v, ok) 1622 | } 1623 | } 1624 | }) 1625 | 1626 | RunRandom(t, "Overwrite", func(t *testing.T, rand *rand.Rand) { 1627 | var cmpr defaultComparer[int] 1628 | var node sortedMapNode[int, int] = &sortedMapLeafNode[int, int]{} 1629 | 1630 | for _, i := range rand.Perm(32) { 1631 | var resized bool 1632 | node, _ = node.set(i, i*2, &cmpr, false, &resized) 1633 | } 1634 | for _, i := range rand.Perm(32) { 1635 | var resized bool 1636 | node, _ = node.set(i, i*3, &cmpr, false, &resized) 1637 | if resized { 1638 | t.Fatal("expected no resize") 1639 | } 1640 | } 1641 | 1642 | // Verify all overwritten key/value pairs in node. 1643 | for i := 0; i < 32; i++ { 1644 | if v, ok := node.get(i, &cmpr); !ok || v != i*3 { 1645 | t.Fatalf("get(%d)=<%v,%v>", i, v, ok) 1646 | } 1647 | } 1648 | }) 1649 | 1650 | t.Run("Split", func(t *testing.T) { 1651 | // Fill leaf node. var cmpr defaultComparer[int] 1652 | var cmpr defaultComparer[int] 1653 | var node sortedMapNode[int, int] = &sortedMapLeafNode[int, int]{} 1654 | for i := 0; i < 32; i++ { 1655 | var resized bool 1656 | node, _ = node.set(i, i*10, &cmpr, false, &resized) 1657 | } 1658 | 1659 | // Add one more and expect split. 1660 | var resized bool 1661 | newNode, splitNode := node.set(32, 320, &cmpr, false, &resized) 1662 | 1663 | // Verify node contents. 1664 | newLeafNode, ok := newNode.(*sortedMapLeafNode[int, int]) 1665 | if !ok { 1666 | t.Fatalf("unexpected node type: %T", newLeafNode) 1667 | } else if n := len(newLeafNode.entries); n != 16 { 1668 | t.Fatalf("unexpected node len: %d", n) 1669 | } 1670 | for i := range newLeafNode.entries { 1671 | if entry := newLeafNode.entries[i]; entry.key != i || entry.value != i*10 { 1672 | t.Fatalf("%d. unexpected entry: %v=%v", i, entry.key, entry.value) 1673 | } 1674 | } 1675 | 1676 | // Verify split node contents. 1677 | splitLeafNode, ok := splitNode.(*sortedMapLeafNode[int, int]) 1678 | if !ok { 1679 | t.Fatalf("unexpected split node type: %T", splitLeafNode) 1680 | } else if n := len(splitLeafNode.entries); n != 17 { 1681 | t.Fatalf("unexpected split node len: %d", n) 1682 | } 1683 | for i := range splitLeafNode.entries { 1684 | if entry := splitLeafNode.entries[i]; entry.key != (i+16) || entry.value != (i+16)*10 { 1685 | t.Fatalf("%d. unexpected split node entry: %v=%v", i, entry.key, entry.value) 1686 | } 1687 | } 1688 | }) 1689 | } 1690 | 1691 | func TestInternalSortedMapBranchNode(t *testing.T) { 1692 | RunRandom(t, "NoSplit", func(t *testing.T, rand *rand.Rand) { 1693 | keys := make([]int, 32*16) 1694 | for i := range keys { 1695 | keys[i] = rand.Intn(10000) 1696 | } 1697 | keys = uniqueIntSlice(keys) 1698 | sort.Ints(keys[:2]) // ensure first two keys are sorted for initial insert. 1699 | 1700 | // Initialize branch with two leafs. 1701 | var cmpr defaultComparer[int] 1702 | leaf0 := &sortedMapLeafNode[int, int]{entries: []mapEntry[int, int]{{key: keys[0], value: keys[0] * 10}}} 1703 | leaf1 := &sortedMapLeafNode[int, int]{entries: []mapEntry[int, int]{{key: keys[1], value: keys[1] * 10}}} 1704 | var node sortedMapNode[int, int] = newSortedMapBranchNode[int, int](leaf0, leaf1) 1705 | 1706 | sort.Ints(keys) 1707 | for _, i := range rand.Perm(len(keys)) { 1708 | key := keys[i] 1709 | 1710 | var resized bool 1711 | var splitNode sortedMapNode[int, int] 1712 | node, splitNode = node.set(key, key*10, &cmpr, false, &resized) 1713 | if key == leaf0.entries[0].key || key == leaf1.entries[0].key { 1714 | if resized { 1715 | t.Fatalf("expected no resize: key=%d", key) 1716 | } 1717 | } else { 1718 | if !resized { 1719 | t.Fatalf("expected resize: key=%d", key) 1720 | } 1721 | } 1722 | if splitNode != nil { 1723 | t.Fatal("unexpected split") 1724 | } 1725 | } 1726 | 1727 | // Verify all key/value pairs in node. 1728 | for _, key := range keys { 1729 | if v, ok := node.get(key, &cmpr); !ok || v != key*10 { 1730 | t.Fatalf("get(%d)=<%v,%v>", key, v, ok) 1731 | } 1732 | } 1733 | 1734 | // Verify min key is the lowest key. 1735 | if got, exp := node.minKey(), keys[0]; got != exp { 1736 | t.Fatalf("minKey()=%d, expected %d", got, exp) 1737 | } 1738 | }) 1739 | 1740 | t.Run("Split", func(t *testing.T) { 1741 | // Generate leaf nodes. 1742 | var cmpr defaultComparer[int] 1743 | children := make([]sortedMapNode[int, int], 32) 1744 | for i := range children { 1745 | leaf := &sortedMapLeafNode[int, int]{entries: make([]mapEntry[int, int], 32)} 1746 | for j := range leaf.entries { 1747 | leaf.entries[j] = mapEntry[int, int]{key: (i * 32) + j, value: ((i * 32) + j) * 100} 1748 | } 1749 | children[i] = leaf 1750 | } 1751 | var node sortedMapNode[int, int] = newSortedMapBranchNode(children...) 1752 | 1753 | // Add one more and expect split. 1754 | var resized bool 1755 | newNode, splitNode := node.set((32 * 32), (32*32)*100, &cmpr, false, &resized) 1756 | 1757 | // Verify node contents. 1758 | var idx int 1759 | newBranchNode, ok := newNode.(*sortedMapBranchNode[int, int]) 1760 | if !ok { 1761 | t.Fatalf("unexpected node type: %T", newBranchNode) 1762 | } else if n := len(newBranchNode.elems); n != 16 { 1763 | t.Fatalf("unexpected child elems len: %d", n) 1764 | } 1765 | for i, elem := range newBranchNode.elems { 1766 | child, ok := elem.node.(*sortedMapLeafNode[int, int]) 1767 | if !ok { 1768 | t.Fatalf("unexpected child type") 1769 | } 1770 | for j, entry := range child.entries { 1771 | if entry.key != idx || entry.value != idx*100 { 1772 | t.Fatalf("%d/%d. unexpected entry: %v=%v", i, j, entry.key, entry.value) 1773 | } 1774 | idx++ 1775 | } 1776 | } 1777 | 1778 | // Verify split node contents. 1779 | splitBranchNode, ok := splitNode.(*sortedMapBranchNode[int, int]) 1780 | if !ok { 1781 | t.Fatalf("unexpected split node type: %T", splitBranchNode) 1782 | } else if n := len(splitBranchNode.elems); n != 17 { 1783 | t.Fatalf("unexpected split node elem len: %d", n) 1784 | } 1785 | for i, elem := range splitBranchNode.elems { 1786 | child, ok := elem.node.(*sortedMapLeafNode[int, int]) 1787 | if !ok { 1788 | t.Fatalf("unexpected split node child type") 1789 | } 1790 | for j, entry := range child.entries { 1791 | if entry.key != idx || entry.value != idx*100 { 1792 | t.Fatalf("%d/%d. unexpected split node entry: %v=%v", i, j, entry.key, entry.value) 1793 | } 1794 | idx++ 1795 | } 1796 | } 1797 | }) 1798 | } 1799 | 1800 | func TestSortedMap_Get(t *testing.T) { 1801 | t.Run("Empty", func(t *testing.T) { 1802 | m := NewSortedMap[int, int](nil) 1803 | if v, ok := m.Get(100); ok { 1804 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1805 | } 1806 | }) 1807 | } 1808 | 1809 | func TestSortedMap_Set(t *testing.T) { 1810 | t.Run("Simple", func(t *testing.T) { 1811 | m := NewSortedMap[int, string](nil) 1812 | m = m.Set(100, "foo") 1813 | if v, ok := m.Get(100); !ok || v != "foo" { 1814 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1815 | } else if got, exp := m.Len(), 1; got != exp { 1816 | t.Fatalf("SortedMap.Len()=%d, exp %d", got, exp) 1817 | } 1818 | }) 1819 | 1820 | t.Run("Small", func(t *testing.T) { 1821 | const n = 1000 1822 | m := NewSortedMap[int, int](nil) 1823 | for i := 0; i < n; i++ { 1824 | m = m.Set(i, i+1) 1825 | } 1826 | for i := 0; i < n; i++ { 1827 | if v, ok := m.Get(i); !ok || v != i+1 { 1828 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1829 | } 1830 | } 1831 | }) 1832 | 1833 | t.Run("Large", func(t *testing.T) { 1834 | if testing.Short() { 1835 | t.Skip("skipping: short") 1836 | } 1837 | 1838 | const n = 1000000 1839 | m := NewSortedMap[int, int](nil) 1840 | for i := 0; i < n; i++ { 1841 | m = m.Set(i, i+1) 1842 | } 1843 | for i := 0; i < n; i++ { 1844 | if v, ok := m.Get(i); !ok || v != i+1 { 1845 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1846 | } 1847 | } 1848 | }) 1849 | 1850 | t.Run("StringKeys", func(t *testing.T) { 1851 | m := NewSortedMap[string, string](nil) 1852 | m = m.Set("foo", "bar") 1853 | m = m.Set("baz", "bat") 1854 | m = m.Set("", "EMPTY") 1855 | if v, ok := m.Get("foo"); !ok || v != "bar" { 1856 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1857 | } else if v, ok := m.Get("baz"); !ok || v != "bat" { 1858 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1859 | } else if v, ok := m.Get(""); !ok || v != "EMPTY" { 1860 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1861 | } 1862 | if v, ok := m.Get("no_such_key"); ok { 1863 | t.Fatalf("expected no value: <%v,%v>", v, ok) 1864 | } 1865 | }) 1866 | 1867 | t.Run("NoDefaultComparer", func(t *testing.T) { 1868 | var r string 1869 | func() { 1870 | defer func() { r = recover().(string) }() 1871 | m := NewSortedMap[float64, string](nil) 1872 | m = m.Set(float64(100), "bar") 1873 | }() 1874 | if r != `immutable.NewComparer: must set comparer for float64 type` { 1875 | t.Fatalf("unexpected panic: %q", r) 1876 | } 1877 | }) 1878 | 1879 | RunRandom(t, "Random", func(t *testing.T, rand *rand.Rand) { 1880 | m := NewTSortedMap() 1881 | for j := 0; j < 10000; j++ { 1882 | switch rand.Intn(2) { 1883 | case 1: // overwrite 1884 | m.Set(m.ExistingKey(rand), rand.Intn(10000)) 1885 | default: // set new key 1886 | m.Set(m.NewKey(rand), rand.Intn(10000)) 1887 | } 1888 | } 1889 | if err := m.Validate(); err != nil { 1890 | t.Fatal(err) 1891 | } 1892 | }) 1893 | } 1894 | 1895 | // Ensure map can support overwrites as it expands. 1896 | func TestSortedMap_Overwrite(t *testing.T) { 1897 | const n = 1000 1898 | m := NewSortedMap[int, int](nil) 1899 | for i := 0; i < n; i++ { 1900 | // Set original value. 1901 | m = m.Set(i, i) 1902 | 1903 | // Overwrite every node. 1904 | for j := 0; j <= i; j++ { 1905 | m = m.Set(j, i*j) 1906 | } 1907 | } 1908 | 1909 | // Verify all key/value pairs in map. 1910 | for i := 0; i < n; i++ { 1911 | if v, ok := m.Get(i); !ok || v != i*(n-1) { 1912 | t.Fatalf("Get(%d)=<%v,%v>", i, v, ok) 1913 | } 1914 | } 1915 | } 1916 | 1917 | func TestSortedMap_Delete(t *testing.T) { 1918 | t.Run("Empty", func(t *testing.T) { 1919 | m := NewSortedMap[int, int](nil) 1920 | m = m.Delete(100) 1921 | if n := m.Len(); n != 0 { 1922 | t.Fatalf("SortedMap.Len()=%d, expected 0", n) 1923 | } 1924 | }) 1925 | 1926 | t.Run("Simple", func(t *testing.T) { 1927 | m := NewSortedMap[int, string](nil) 1928 | m = m.Set(100, "foo") 1929 | if v, ok := m.Get(100); !ok || v != "foo" { 1930 | t.Fatalf("unexpected value: <%v,%v>", v, ok) 1931 | } 1932 | m = m.Delete(100) 1933 | if v, ok := m.Get(100); ok { 1934 | t.Fatalf("unexpected no value: <%v,%v>", v, ok) 1935 | } 1936 | }) 1937 | 1938 | t.Run("Small", func(t *testing.T) { 1939 | const n = 1000 1940 | m := NewSortedMap[int, int](nil) 1941 | for i := 0; i < n; i++ { 1942 | m = m.Set(i, i+1) 1943 | } 1944 | for i := 0; i < n; i++ { 1945 | if v, ok := m.Get(i); !ok || v != i+1 { 1946 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1947 | } 1948 | } 1949 | 1950 | for i := 0; i < n; i++ { 1951 | m = m.Delete(i) 1952 | } 1953 | for i := 0; i < n; i++ { 1954 | if v, ok := m.Get(i); ok { 1955 | t.Fatalf("expected no value for key=%v: <%v,%v>", i, v, ok) 1956 | } 1957 | } 1958 | }) 1959 | 1960 | t.Run("Large", func(t *testing.T) { 1961 | if testing.Short() { 1962 | t.Skip("skipping: short") 1963 | } 1964 | 1965 | const n = 1000000 1966 | m := NewSortedMap[int, int](nil) 1967 | for i := 0; i < n; i++ { 1968 | m = m.Set(i, i+1) 1969 | } 1970 | for i := 0; i < n; i++ { 1971 | if v, ok := m.Get(i); !ok || v != i+1 { 1972 | t.Fatalf("unexpected value for key=%v: <%v,%v>", i, v, ok) 1973 | } 1974 | } 1975 | 1976 | for i := 0; i < n; i++ { 1977 | m = m.Delete(i) 1978 | } 1979 | for i := 0; i < n; i++ { 1980 | if v, ok := m.Get(i); ok { 1981 | t.Fatalf("unexpected no value for key=%v: <%v,%v>", i, v, ok) 1982 | } 1983 | } 1984 | }) 1985 | 1986 | RunRandom(t, "Random", func(t *testing.T, rand *rand.Rand) { 1987 | m := NewTSortedMap() 1988 | for j := 0; j < 10000; j++ { 1989 | switch rand.Intn(8) { 1990 | case 0: // overwrite 1991 | m.Set(m.ExistingKey(rand), rand.Intn(10000)) 1992 | case 1: // delete existing key 1993 | m.Delete(m.ExistingKey(rand)) 1994 | case 2: // delete non-existent key. 1995 | m.Delete(m.NewKey(rand)) 1996 | default: // set new key 1997 | m.Set(m.NewKey(rand), rand.Intn(10000)) 1998 | } 1999 | } 2000 | if err := m.Validate(); err != nil { 2001 | t.Fatal(err) 2002 | } 2003 | 2004 | // Delete all keys. 2005 | keys := make([]int, len(m.keys)) 2006 | copy(keys, m.keys) 2007 | for _, k := range keys { 2008 | m.Delete(k) 2009 | } 2010 | if err := m.Validate(); err != nil { 2011 | t.Fatal(err) 2012 | } 2013 | }) 2014 | } 2015 | 2016 | func TestSortedMap_Iterator(t *testing.T) { 2017 | t.Run("Empty", func(t *testing.T) { 2018 | t.Run("First", func(t *testing.T) { 2019 | itr := NewSortedMap[int, int](nil).Iterator() 2020 | itr.First() 2021 | if k, v, ok := itr.Next(); ok { 2022 | t.Fatalf("SortedMapIterator.Next()=<%v,%v>, expected nil", k, v) 2023 | } 2024 | }) 2025 | 2026 | t.Run("Last", func(t *testing.T) { 2027 | itr := NewSortedMap[int, int](nil).Iterator() 2028 | itr.Last() 2029 | if k, v, ok := itr.Prev(); ok { 2030 | t.Fatalf("SortedMapIterator.Prev()=<%v,%v>, expected nil", k, v) 2031 | } 2032 | }) 2033 | 2034 | t.Run("Seek", func(t *testing.T) { 2035 | itr := NewSortedMap[string, int](nil).Iterator() 2036 | itr.Seek("foo") 2037 | if k, v, ok := itr.Next(); ok { 2038 | t.Fatalf("SortedMapIterator.Next()=<%v,%v>, expected nil", k, v) 2039 | } 2040 | }) 2041 | }) 2042 | 2043 | t.Run("Seek", func(t *testing.T) { 2044 | const n = 100 2045 | m := NewSortedMap[string, int](nil) 2046 | for i := 0; i < n; i += 2 { 2047 | m = m.Set(fmt.Sprintf("%04d", i), i) 2048 | } 2049 | 2050 | t.Run("Exact", func(t *testing.T) { 2051 | itr := m.Iterator() 2052 | for i := 0; i < n; i += 2 { 2053 | itr.Seek(fmt.Sprintf("%04d", i)) 2054 | for j := i; j < n; j += 2 { 2055 | if k, _, ok := itr.Next(); !ok || k != fmt.Sprintf("%04d", j) { 2056 | t.Fatalf("%d/%d. SortedMapIterator.Next()=%v, expected key %04d", i, j, k, j) 2057 | } 2058 | } 2059 | if !itr.Done() { 2060 | t.Fatalf("SortedMapIterator.Done()=true, expected false") 2061 | } 2062 | } 2063 | }) 2064 | 2065 | t.Run("Miss", func(t *testing.T) { 2066 | itr := m.Iterator() 2067 | for i := 1; i < n-2; i += 2 { 2068 | itr.Seek(fmt.Sprintf("%04d", i)) 2069 | for j := i + 1; j < n; j += 2 { 2070 | if k, _, ok := itr.Next(); !ok || k != fmt.Sprintf("%04d", j) { 2071 | t.Fatalf("%d/%d. SortedMapIterator.Next()=%v, expected key %04d", i, j, k, j) 2072 | } 2073 | } 2074 | if !itr.Done() { 2075 | t.Fatalf("SortedMapIterator.Done()=true, expected false") 2076 | } 2077 | } 2078 | }) 2079 | 2080 | t.Run("BeforeFirst", func(t *testing.T) { 2081 | itr := m.Iterator() 2082 | itr.Seek("") 2083 | for i := 0; i < n; i += 2 { 2084 | if k, _, ok := itr.Next(); !ok || k != fmt.Sprintf("%04d", i) { 2085 | t.Fatalf("%d. SortedMapIterator.Next()=%v, expected key %04d", i, k, i) 2086 | } 2087 | } 2088 | if !itr.Done() { 2089 | t.Fatalf("SortedMapIterator.Done()=true, expected false") 2090 | } 2091 | }) 2092 | t.Run("AfterLast", func(t *testing.T) { 2093 | itr := m.Iterator() 2094 | itr.Seek("1000") 2095 | if k, _, ok := itr.Next(); ok { 2096 | t.Fatalf("0. SortedMapIterator.Next()=%v, expected nil key", k) 2097 | } else if !itr.Done() { 2098 | t.Fatalf("SortedMapIterator.Done()=true, expected false") 2099 | } 2100 | }) 2101 | }) 2102 | } 2103 | 2104 | func TestNewHasher(t *testing.T) { 2105 | t.Run("builtin", func(t *testing.T) { 2106 | t.Run("int", func(t *testing.T) { testNewHasher(t, int(100)) }) 2107 | t.Run("int8", func(t *testing.T) { testNewHasher(t, int8(100)) }) 2108 | t.Run("int16", func(t *testing.T) { testNewHasher(t, int16(100)) }) 2109 | t.Run("int32", func(t *testing.T) { testNewHasher(t, int32(100)) }) 2110 | t.Run("int64", func(t *testing.T) { testNewHasher(t, int64(100)) }) 2111 | 2112 | t.Run("uint", func(t *testing.T) { testNewHasher(t, uint(100)) }) 2113 | t.Run("uint8", func(t *testing.T) { testNewHasher(t, uint8(100)) }) 2114 | t.Run("uint16", func(t *testing.T) { testNewHasher(t, uint16(100)) }) 2115 | t.Run("uint32", func(t *testing.T) { testNewHasher(t, uint32(100)) }) 2116 | t.Run("uint64", func(t *testing.T) { testNewHasher(t, uint64(100)) }) 2117 | 2118 | t.Run("string", func(t *testing.T) { testNewHasher(t, "foo") }) 2119 | //t.Run("byteSlice", func(t *testing.T) { testNewHasher(t, []byte("foo")) }) 2120 | }) 2121 | 2122 | t.Run("reflection", func(t *testing.T) { 2123 | type Int int 2124 | t.Run("int", func(t *testing.T) { testNewHasher(t, Int(100)) }) 2125 | 2126 | type Uint uint 2127 | t.Run("uint", func(t *testing.T) { testNewHasher(t, Uint(100)) }) 2128 | 2129 | type String string 2130 | t.Run("string", func(t *testing.T) { testNewHasher(t, String("foo")) }) 2131 | }) 2132 | } 2133 | 2134 | func testNewHasher[V constraints.Ordered](t *testing.T, v V) { 2135 | t.Helper() 2136 | h := NewHasher(v) 2137 | h.Hash(v) 2138 | if !h.Equal(v, v) { 2139 | t.Fatal("expected hash equality") 2140 | } 2141 | } 2142 | 2143 | func TestNewComparer(t *testing.T) { 2144 | t.Run("builtin", func(t *testing.T) { 2145 | t.Run("int", func(t *testing.T) { testNewComparer(t, int(100), int(101)) }) 2146 | t.Run("int8", func(t *testing.T) { testNewComparer(t, int8(100), int8(101)) }) 2147 | t.Run("int16", func(t *testing.T) { testNewComparer(t, int16(100), int16(101)) }) 2148 | t.Run("int32", func(t *testing.T) { testNewComparer(t, int32(100), int32(101)) }) 2149 | t.Run("int64", func(t *testing.T) { testNewComparer(t, int64(100), int64(101)) }) 2150 | 2151 | t.Run("uint", func(t *testing.T) { testNewComparer(t, uint(100), uint(101)) }) 2152 | t.Run("uint8", func(t *testing.T) { testNewComparer(t, uint8(100), uint8(101)) }) 2153 | t.Run("uint16", func(t *testing.T) { testNewComparer(t, uint16(100), uint16(101)) }) 2154 | t.Run("uint32", func(t *testing.T) { testNewComparer(t, uint32(100), uint32(101)) }) 2155 | t.Run("uint64", func(t *testing.T) { testNewComparer(t, uint64(100), uint64(101)) }) 2156 | 2157 | t.Run("string", func(t *testing.T) { testNewComparer(t, "bar", "foo") }) 2158 | //t.Run("byteSlice", func(t *testing.T) { testNewComparer(t, []byte("bar"), []byte("foo")) }) 2159 | }) 2160 | 2161 | t.Run("reflection", func(t *testing.T) { 2162 | type Int int 2163 | t.Run("int", func(t *testing.T) { testNewComparer(t, Int(100), Int(101)) }) 2164 | 2165 | type Uint uint 2166 | t.Run("uint", func(t *testing.T) { testNewComparer(t, Uint(100), Uint(101)) }) 2167 | 2168 | type String string 2169 | t.Run("string", func(t *testing.T) { testNewComparer(t, String("bar"), String("foo")) }) 2170 | }) 2171 | } 2172 | 2173 | func testNewComparer[T constraints.Ordered](t *testing.T, x, y T) { 2174 | t.Helper() 2175 | c := NewComparer(x) 2176 | if c.Compare(x, y) != -1 { 2177 | t.Fatal("expected comparer LT") 2178 | } else if c.Compare(x, x) != 0 { 2179 | t.Fatal("expected comparer EQ") 2180 | } else if c.Compare(y, x) != 1 { 2181 | t.Fatal("expected comparer GT") 2182 | } 2183 | } 2184 | 2185 | // TSortedMap represents a combined immutable and stdlib sorted map. 2186 | type TSortedMap struct { 2187 | im, prev *SortedMap[int, int] 2188 | builder *SortedMapBuilder[int, int] 2189 | std map[int]int 2190 | keys []int 2191 | } 2192 | 2193 | func NewTSortedMap() *TSortedMap { 2194 | return &TSortedMap{ 2195 | im: NewSortedMap[int, int](nil), 2196 | builder: NewSortedMapBuilder[int, int](nil), 2197 | std: make(map[int]int), 2198 | } 2199 | } 2200 | 2201 | func (m *TSortedMap) NewKey(rand *rand.Rand) int { 2202 | for { 2203 | k := rand.Int() 2204 | if _, ok := m.std[k]; !ok { 2205 | return k 2206 | } 2207 | } 2208 | } 2209 | 2210 | func (m *TSortedMap) ExistingKey(rand *rand.Rand) int { 2211 | if len(m.keys) == 0 { 2212 | return 0 2213 | } 2214 | return m.keys[rand.Intn(len(m.keys))] 2215 | } 2216 | 2217 | func (m *TSortedMap) Set(k, v int) { 2218 | m.prev = m.im 2219 | m.im = m.im.Set(k, v) 2220 | m.builder.Set(k, v) 2221 | 2222 | if _, ok := m.std[k]; !ok { 2223 | m.keys = append(m.keys, k) 2224 | sort.Ints(m.keys) 2225 | } 2226 | m.std[k] = v 2227 | } 2228 | 2229 | func (m *TSortedMap) Delete(k int) { 2230 | m.prev = m.im 2231 | m.im = m.im.Delete(k) 2232 | m.builder.Delete(k) 2233 | delete(m.std, k) 2234 | 2235 | for i := range m.keys { 2236 | if m.keys[i] == k { 2237 | m.keys = append(m.keys[:i], m.keys[i+1:]...) 2238 | break 2239 | } 2240 | } 2241 | } 2242 | 2243 | func (m *TSortedMap) Validate() error { 2244 | for _, k := range m.keys { 2245 | if v, ok := m.im.Get(k); !ok { 2246 | return fmt.Errorf("key not found: %d", k) 2247 | } else if v != m.std[k] { 2248 | return fmt.Errorf("key (%d) mismatch: immutable=%d, std=%d", k, v, m.std[k]) 2249 | } 2250 | if v, ok := m.builder.Get(k); !ok { 2251 | return fmt.Errorf("builder key not found: %d", k) 2252 | } else if v != m.std[k] { 2253 | return fmt.Errorf("builder key (%d) mismatch: immutable=%d, std=%d", k, v, m.std[k]) 2254 | } 2255 | } 2256 | 2257 | if got, exp := m.builder.Len(), len(m.std); got != exp { 2258 | return fmt.Errorf("SortedMapBuilder.Len()=%d, expected %d", got, exp) 2259 | } 2260 | 2261 | sort.Ints(m.keys) 2262 | if err := m.validateForwardIterator(m.im.Iterator()); err != nil { 2263 | return fmt.Errorf("basic: %s", err) 2264 | } else if err := m.validateBackwardIterator(m.im.Iterator()); err != nil { 2265 | return fmt.Errorf("basic: %s", err) 2266 | } 2267 | 2268 | if err := m.validateForwardIterator(m.builder.Iterator()); err != nil { 2269 | return fmt.Errorf("basic: %s", err) 2270 | } else if err := m.validateBackwardIterator(m.builder.Iterator()); err != nil { 2271 | return fmt.Errorf("basic: %s", err) 2272 | } 2273 | return nil 2274 | } 2275 | 2276 | func (m *TSortedMap) validateForwardIterator(itr *SortedMapIterator[int, int]) error { 2277 | for i, k0 := range m.keys { 2278 | v0 := m.std[k0] 2279 | if k1, v1, ok := itr.Next(); !ok || k0 != k1 || v0 != v1 { 2280 | return fmt.Errorf("%d. SortedMapIterator.Next()=<%v,%v>, expected <%v,%v>", i, k1, v1, k0, v0) 2281 | } 2282 | 2283 | done := i == len(m.keys)-1 2284 | if v := itr.Done(); v != done { 2285 | return fmt.Errorf("%d. SortedMapIterator.Done()=%v, expected %v", i, v, done) 2286 | } 2287 | } 2288 | if k, v, ok := itr.Next(); ok { 2289 | return fmt.Errorf("SortedMapIterator.Next()=<%v,%v>, expected nil after done", k, v) 2290 | } 2291 | return nil 2292 | } 2293 | 2294 | func (m *TSortedMap) validateBackwardIterator(itr *SortedMapIterator[int, int]) error { 2295 | itr.Last() 2296 | for i := len(m.keys) - 1; i >= 0; i-- { 2297 | k0 := m.keys[i] 2298 | v0 := m.std[k0] 2299 | if k1, v1, ok := itr.Prev(); !ok || k0 != k1 || v0 != v1 { 2300 | return fmt.Errorf("%d. SortedMapIterator.Prev()=<%v,%v>, expected <%v,%v>", i, k1, v1, k0, v0) 2301 | } 2302 | 2303 | done := i == 0 2304 | if v := itr.Done(); v != done { 2305 | return fmt.Errorf("%d. SortedMapIterator.Done()=%v, expected %v", i, v, done) 2306 | } 2307 | } 2308 | if k, v, ok := itr.Prev(); ok { 2309 | return fmt.Errorf("SortedMapIterator.Prev()=<%v,%v>, expected nil after done", k, v) 2310 | } 2311 | return nil 2312 | } 2313 | 2314 | func BenchmarkSortedMap_Set(b *testing.B) { 2315 | b.ReportAllocs() 2316 | m := NewSortedMap[int, int](nil) 2317 | for i := 0; i < b.N; i++ { 2318 | m = m.Set(i, i) 2319 | } 2320 | } 2321 | 2322 | func BenchmarkSortedMap_Delete(b *testing.B) { 2323 | const n = 10000 2324 | 2325 | m := NewSortedMap[int, int](nil) 2326 | for i := 0; i < n; i++ { 2327 | m = m.Set(i, i) 2328 | } 2329 | b.ReportAllocs() 2330 | b.ResetTimer() 2331 | 2332 | for i := 0; i < b.N; i++ { 2333 | m.Delete(i % n) // Do not update map, always operate on original 2334 | } 2335 | } 2336 | 2337 | func BenchmarkSortedMap_Iterator(b *testing.B) { 2338 | const n = 10000 2339 | m := NewSortedMap[int, int](nil) 2340 | for i := 0; i < 10000; i++ { 2341 | m = m.Set(i, i) 2342 | } 2343 | b.ReportAllocs() 2344 | b.ResetTimer() 2345 | 2346 | b.Run("Forward", func(b *testing.B) { 2347 | itr := m.Iterator() 2348 | for i := 0; i < b.N; i++ { 2349 | if i%n == 0 { 2350 | itr.First() 2351 | } 2352 | itr.Next() 2353 | } 2354 | }) 2355 | 2356 | b.Run("Reverse", func(b *testing.B) { 2357 | itr := m.Iterator() 2358 | for i := 0; i < b.N; i++ { 2359 | if i%n == 0 { 2360 | itr.Last() 2361 | } 2362 | itr.Prev() 2363 | } 2364 | }) 2365 | } 2366 | 2367 | func BenchmarkSortedMapBuilder_Set(b *testing.B) { 2368 | b.ReportAllocs() 2369 | builder := NewSortedMapBuilder[int, int](nil) 2370 | for i := 0; i < b.N; i++ { 2371 | builder.Set(i, i) 2372 | } 2373 | } 2374 | 2375 | func BenchmarkSortedMapBuilder_Delete(b *testing.B) { 2376 | const n = 1000000 2377 | 2378 | builder := NewSortedMapBuilder[int, int](nil) 2379 | for i := 0; i < n; i++ { 2380 | builder.Set(i, i) 2381 | } 2382 | b.ReportAllocs() 2383 | b.ResetTimer() 2384 | 2385 | for i := 0; i < b.N; i++ { 2386 | builder.Delete(i % n) 2387 | } 2388 | } 2389 | 2390 | func ExampleSortedMap_Set() { 2391 | m := NewSortedMap[string, any](nil) 2392 | m = m.Set("foo", "bar") 2393 | m = m.Set("baz", 100) 2394 | 2395 | v, ok := m.Get("foo") 2396 | fmt.Println("foo", v, ok) 2397 | 2398 | v, ok = m.Get("baz") 2399 | fmt.Println("baz", v, ok) 2400 | 2401 | v, ok = m.Get("bat") // does not exist 2402 | fmt.Println("bat", v, ok) 2403 | // Output: 2404 | // foo bar true 2405 | // baz 100 true 2406 | // bat false 2407 | } 2408 | 2409 | func ExampleSortedMap_Delete() { 2410 | m := NewSortedMap[string, any](nil) 2411 | m = m.Set("foo", "bar") 2412 | m = m.Set("baz", 100) 2413 | m = m.Delete("baz") 2414 | 2415 | v, ok := m.Get("foo") 2416 | fmt.Println("foo", v, ok) 2417 | 2418 | v, ok = m.Get("baz") 2419 | fmt.Println("baz", v, ok) 2420 | // Output: 2421 | // foo bar true 2422 | // baz false 2423 | } 2424 | 2425 | func ExampleSortedMap_Iterator() { 2426 | m := NewSortedMap[string, any](nil) 2427 | m = m.Set("strawberry", 900) 2428 | m = m.Set("kiwi", 300) 2429 | m = m.Set("apple", 100) 2430 | m = m.Set("pear", 700) 2431 | m = m.Set("pineapple", 800) 2432 | m = m.Set("peach", 600) 2433 | m = m.Set("orange", 500) 2434 | m = m.Set("grape", 200) 2435 | m = m.Set("mango", 400) 2436 | 2437 | itr := m.Iterator() 2438 | for !itr.Done() { 2439 | k, v, _ := itr.Next() 2440 | fmt.Println(k, v) 2441 | } 2442 | // Output: 2443 | // apple 100 2444 | // grape 200 2445 | // kiwi 300 2446 | // mango 400 2447 | // orange 500 2448 | // peach 600 2449 | // pear 700 2450 | // pineapple 800 2451 | // strawberry 900 2452 | } 2453 | 2454 | func ExampleSortedMapBuilder_Set() { 2455 | b := NewSortedMapBuilder[string, any](nil) 2456 | b.Set("foo", "bar") 2457 | b.Set("baz", 100) 2458 | 2459 | m := b.Map() 2460 | v, ok := m.Get("foo") 2461 | fmt.Println("foo", v, ok) 2462 | 2463 | v, ok = m.Get("baz") 2464 | fmt.Println("baz", v, ok) 2465 | 2466 | v, ok = m.Get("bat") // does not exist 2467 | fmt.Println("bat", v, ok) 2468 | // Output: 2469 | // foo bar true 2470 | // baz 100 true 2471 | // bat false 2472 | } 2473 | 2474 | func ExampleSortedMapBuilder_Delete() { 2475 | b := NewSortedMapBuilder[string, any](nil) 2476 | b.Set("foo", "bar") 2477 | b.Set("baz", 100) 2478 | b.Delete("baz") 2479 | 2480 | m := b.Map() 2481 | v, ok := m.Get("foo") 2482 | fmt.Println("foo", v, ok) 2483 | 2484 | v, ok = m.Get("baz") 2485 | fmt.Println("baz", v, ok) 2486 | // Output: 2487 | // foo bar true 2488 | // baz false 2489 | } 2490 | 2491 | // RunRandom executes fn multiple times with a different rand. 2492 | func RunRandom(t *testing.T, name string, fn func(t *testing.T, rand *rand.Rand)) { 2493 | if testing.Short() { 2494 | t.Skip("short mode") 2495 | } 2496 | t.Run(name, func(t *testing.T) { 2497 | for i := 0; i < *randomN; i++ { 2498 | i := i 2499 | t.Run(fmt.Sprintf("%08d", i), func(t *testing.T) { 2500 | t.Parallel() 2501 | fn(t, rand.New(rand.NewSource(int64(i)))) 2502 | }) 2503 | } 2504 | }) 2505 | } 2506 | 2507 | func uniqueIntSlice(a []int) []int { 2508 | m := make(map[int]struct{}) 2509 | other := make([]int, 0, len(a)) 2510 | for _, v := range a { 2511 | if _, ok := m[v]; ok { 2512 | continue 2513 | } 2514 | m[v] = struct{}{} 2515 | other = append(other, v) 2516 | } 2517 | return other 2518 | } 2519 | 2520 | // mockHasher represents a mock implementation of immutable.Hasher. 2521 | type mockHasher[K constraints.Ordered] struct { 2522 | hash func(value K) uint32 2523 | equal func(a, b K) bool 2524 | } 2525 | 2526 | // Hash executes the mocked HashFn function. 2527 | func (h *mockHasher[K]) Hash(value K) uint32 { 2528 | return h.hash(value) 2529 | } 2530 | 2531 | // Equal executes the mocked EqualFn function. 2532 | func (h *mockHasher[K]) Equal(a, b K) bool { 2533 | return h.equal(a, b) 2534 | } 2535 | 2536 | // mockComparer represents a mock implementation of immutable.Comparer. 2537 | type mockComparer[K constraints.Ordered] struct { 2538 | compare func(a, b K) int 2539 | } 2540 | 2541 | // Compare executes the mocked CompreFn function. 2542 | func (h *mockComparer[K]) Compare(a, b K) int { 2543 | return h.compare(a, b) 2544 | } 2545 | -------------------------------------------------------------------------------- /sets.go: -------------------------------------------------------------------------------- 1 | package immutable 2 | 3 | // Set represents a collection of unique values. The set uses a Hasher 4 | // to generate hashes and check for equality of key values. 5 | // 6 | // Internally, the Set stores values as keys of a Map[T,struct{}] 7 | type Set[T any] struct { 8 | m *Map[T, struct{}] 9 | } 10 | 11 | // NewSet returns a new instance of Set. 12 | // 13 | // If hasher is nil, a default hasher implementation will automatically be chosen based on the first key added. 14 | // Default hasher implementations only exist for int, string, and byte slice types. 15 | // NewSet can also take some initial values as varargs. 16 | func NewSet[T any](hasher Hasher[T], values ...T) Set[T] { 17 | m := NewMap[T, struct{}](hasher) 18 | for _, value := range values { 19 | m = m.set(value, struct{}{}, true) 20 | } 21 | return Set[T]{m} 22 | } 23 | 24 | // Add returns a set containing the new value. 25 | // 26 | // This function will return a new set even if the set already contains the value. 27 | func (s Set[T]) Add(value T) Set[T] { 28 | return Set[T]{s.m.Set(value, struct{}{})} 29 | } 30 | 31 | // Delete returns a set with the given key removed. 32 | func (s Set[T]) Delete(value T) Set[T] { 33 | return Set[T]{s.m.Delete(value)} 34 | } 35 | 36 | // Has returns true when the set contains the given value 37 | func (s Set[T]) Has(val T) bool { 38 | _, ok := s.m.Get(val) 39 | return ok 40 | } 41 | 42 | // Len returns the number of elements in the underlying map. 43 | func (s Set[K]) Len() int { 44 | return s.m.Len() 45 | } 46 | 47 | // Items returns a slice of the items inside the set 48 | func (s Set[T]) Items() []T { 49 | r := make([]T, 0, s.Len()) 50 | itr := s.Iterator() 51 | for !itr.Done() { 52 | v, _ := itr.Next() 53 | r = append(r, v) 54 | } 55 | return r 56 | } 57 | 58 | // Iterator returns a new iterator for this set positioned at the first value. 59 | func (s Set[T]) Iterator() *SetIterator[T] { 60 | itr := &SetIterator[T]{mi: s.m.Iterator()} 61 | itr.mi.First() 62 | return itr 63 | } 64 | 65 | // SetIterator represents an iterator over a set. 66 | // Iteration can occur in natural or reverse order based on use of Next() or Prev(). 67 | type SetIterator[T any] struct { 68 | mi *MapIterator[T, struct{}] 69 | } 70 | 71 | // Done returns true if no more values remain in the iterator. 72 | func (itr *SetIterator[T]) Done() bool { 73 | return itr.mi.Done() 74 | } 75 | 76 | // First moves the iterator to the first value. 77 | func (itr *SetIterator[T]) First() { 78 | itr.mi.First() 79 | } 80 | 81 | // Next moves the iterator to the next value. 82 | func (itr *SetIterator[T]) Next() (val T, ok bool) { 83 | val, _, ok = itr.mi.Next() 84 | return 85 | } 86 | 87 | type SetBuilder[T any] struct { 88 | s Set[T] 89 | } 90 | 91 | func NewSetBuilder[T any](hasher Hasher[T]) *SetBuilder[T] { 92 | return &SetBuilder[T]{s: NewSet(hasher)} 93 | } 94 | 95 | func (s SetBuilder[T]) Set(val T) { 96 | s.s.m = s.s.m.set(val, struct{}{}, true) 97 | } 98 | 99 | func (s SetBuilder[T]) Delete(val T) { 100 | s.s.m = s.s.m.delete(val, true) 101 | } 102 | 103 | func (s SetBuilder[T]) Has(val T) bool { 104 | return s.s.Has(val) 105 | } 106 | 107 | func (s SetBuilder[T]) Len() int { 108 | return s.s.Len() 109 | } 110 | 111 | type SortedSet[T any] struct { 112 | m *SortedMap[T, struct{}] 113 | } 114 | 115 | // NewSortedSet returns a new instance of SortedSet. 116 | // 117 | // If comparer is nil then 118 | // a default comparer is set after the first key is inserted. Default comparers 119 | // exist for int, string, and byte slice keys. 120 | // NewSortedSet can also take some initial values as varargs. 121 | func NewSortedSet[T any](comparer Comparer[T], values ...T) SortedSet[T] { 122 | m := NewSortedMap[T, struct{}](comparer) 123 | for _, value := range values { 124 | m = m.set(value, struct{}{}, true) 125 | } 126 | return SortedSet[T]{m} 127 | } 128 | 129 | // Add returns a set containing the new value. 130 | // 131 | // This function will return a new set even if the set already contains the value. 132 | func (s SortedSet[T]) Add(value T) SortedSet[T] { 133 | return SortedSet[T]{s.m.Set(value, struct{}{})} 134 | } 135 | 136 | // Delete returns a set with the given key removed. 137 | func (s SortedSet[T]) Delete(value T) SortedSet[T] { 138 | return SortedSet[T]{s.m.Delete(value)} 139 | } 140 | 141 | // Has returns true when the set contains the given value 142 | func (s SortedSet[T]) Has(val T) bool { 143 | _, ok := s.m.Get(val) 144 | return ok 145 | } 146 | 147 | // Len returns the number of elements in the underlying map. 148 | func (s SortedSet[K]) Len() int { 149 | return s.m.Len() 150 | } 151 | 152 | // Items returns a slice of the items inside the set 153 | func (s SortedSet[T]) Items() []T { 154 | r := make([]T, 0, s.Len()) 155 | itr := s.Iterator() 156 | for !itr.Done() { 157 | v, _ := itr.Next() 158 | r = append(r, v) 159 | } 160 | return r 161 | } 162 | 163 | // Iterator returns a new iterator for this set positioned at the first value. 164 | func (s SortedSet[T]) Iterator() *SortedSetIterator[T] { 165 | itr := &SortedSetIterator[T]{mi: s.m.Iterator()} 166 | itr.mi.First() 167 | return itr 168 | } 169 | 170 | // SortedSetIterator represents an iterator over a sorted set. 171 | // Iteration can occur in natural or reverse order based on use of Next() or Prev(). 172 | type SortedSetIterator[T any] struct { 173 | mi *SortedMapIterator[T, struct{}] 174 | } 175 | 176 | // Done returns true if no more values remain in the iterator. 177 | func (itr *SortedSetIterator[T]) Done() bool { 178 | return itr.mi.Done() 179 | } 180 | 181 | // First moves the iterator to the first value. 182 | func (itr *SortedSetIterator[T]) First() { 183 | itr.mi.First() 184 | } 185 | 186 | // Last moves the iterator to the last value. 187 | func (itr *SortedSetIterator[T]) Last() { 188 | itr.mi.Last() 189 | } 190 | 191 | // Next moves the iterator to the next value. 192 | func (itr *SortedSetIterator[T]) Next() (val T, ok bool) { 193 | val, _, ok = itr.mi.Next() 194 | return 195 | } 196 | 197 | // Prev moves the iterator to the previous value. 198 | func (itr *SortedSetIterator[T]) Prev() (val T, ok bool) { 199 | val, _, ok = itr.mi.Prev() 200 | return 201 | } 202 | 203 | // Seek moves the iterator to the given value. 204 | // 205 | // If the value does not exist then the next value is used. If no more keys exist 206 | // then the iterator is marked as done. 207 | func (itr *SortedSetIterator[T]) Seek(val T) { 208 | itr.mi.Seek(val) 209 | } 210 | 211 | type SortedSetBuilder[T any] struct { 212 | s *SortedSet[T] 213 | } 214 | 215 | func NewSortedSetBuilder[T any](comparer Comparer[T]) *SortedSetBuilder[T] { 216 | s := NewSortedSet(comparer) 217 | return &SortedSetBuilder[T]{s: &s} 218 | } 219 | 220 | func (s SortedSetBuilder[T]) Set(val T) { 221 | s.s.m = s.s.m.set(val, struct{}{}, true) 222 | } 223 | 224 | func (s SortedSetBuilder[T]) Delete(val T) { 225 | s.s.m = s.s.m.delete(val, true) 226 | } 227 | 228 | func (s SortedSetBuilder[T]) Has(val T) bool { 229 | return s.s.Has(val) 230 | } 231 | 232 | func (s SortedSetBuilder[T]) Len() int { 233 | return s.s.Len() 234 | } 235 | 236 | // SortedSet returns the current copy of the set. 237 | // The builder should not be used again after the list after this call. 238 | func (s SortedSetBuilder[T]) SortedSet() SortedSet[T] { 239 | assert(s.s != nil, "immutable.SortedSetBuilder.SortedSet(): duplicate call to fetch sorted set") 240 | set := s.s 241 | s.s = nil 242 | return *set 243 | } 244 | -------------------------------------------------------------------------------- /sets_test.go: -------------------------------------------------------------------------------- 1 | package immutable 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSetsPut(t *testing.T) { 8 | s := NewSet[string](nil) 9 | s2 := s.Add("1").Add("1") 10 | s2.Add("2") 11 | if s.Len() != 0 { 12 | t.Fatalf("Unexpected mutation of set") 13 | } 14 | if s.Has("1") { 15 | t.Fatalf("Unexpected set element") 16 | } 17 | if s2.Len() != 1 { 18 | t.Fatalf("Unexpected non-mutation of set") 19 | } 20 | if !s2.Has("1") { 21 | t.Fatalf("Set element missing") 22 | } 23 | itr := s2.Iterator() 24 | counter := 0 25 | for !itr.Done() { 26 | i, v := itr.Next() 27 | t.Log(i, v) 28 | counter++ 29 | } 30 | if counter != 1 { 31 | t.Fatalf("iterator wrong length") 32 | } 33 | } 34 | 35 | func TestSetsDelete(t *testing.T) { 36 | s := NewSet[string](nil) 37 | s2 := s.Add("1") 38 | s3 := s.Delete("1") 39 | if s2.Len() != 1 { 40 | t.Fatalf("Unexpected non-mutation of set") 41 | } 42 | if !s2.Has("1") { 43 | t.Fatalf("Set element missing") 44 | } 45 | if s3.Len() != 0 { 46 | t.Fatalf("Unexpected set length after delete") 47 | } 48 | if s3.Has("1") { 49 | t.Fatalf("Unexpected set element after delete") 50 | } 51 | } 52 | 53 | func TestSortedSetsPut(t *testing.T) { 54 | s := NewSortedSet[string](nil) 55 | s2 := s.Add("1").Add("1").Add("0") 56 | if s.Len() != 0 { 57 | t.Fatalf("Unexpected mutation of set") 58 | } 59 | if s.Has("1") { 60 | t.Fatalf("Unexpected set element") 61 | } 62 | if s2.Len() != 2 { 63 | t.Fatalf("Unexpected non-mutation of set") 64 | } 65 | if !s2.Has("1") { 66 | t.Fatalf("Set element missing") 67 | } 68 | 69 | itr := s2.Iterator() 70 | counter := 0 71 | for !itr.Done() { 72 | i, v := itr.Next() 73 | t.Log(i, v) 74 | if counter == 0 && i != "0" { 75 | t.Fatalf("sort did not work for first el") 76 | } 77 | if counter == 1 && i != "1" { 78 | t.Fatalf("sort did not work for second el") 79 | } 80 | counter++ 81 | } 82 | if counter != 2 { 83 | t.Fatalf("iterator wrong length") 84 | } 85 | } 86 | 87 | func TestSortedSetsDelete(t *testing.T) { 88 | s := NewSortedSet[string](nil) 89 | s2 := s.Add("1") 90 | s3 := s.Delete("1") 91 | if s2.Len() != 1 { 92 | t.Fatalf("Unexpected non-mutation of set") 93 | } 94 | if !s2.Has("1") { 95 | t.Fatalf("Set element missing") 96 | } 97 | if s3.Len() != 0 { 98 | t.Fatalf("Unexpected set length after delete") 99 | } 100 | if s3.Has("1") { 101 | t.Fatalf("Unexpected set element after delete") 102 | } 103 | } 104 | 105 | func TestSortedSetBuilder(t *testing.T) { 106 | b := NewSortedSetBuilder[string](nil) 107 | b.Set("test3") 108 | b.Set("test1") 109 | b.Set("test2") 110 | 111 | s := b.SortedSet() 112 | items := s.Items() 113 | 114 | if len(items) != 3 { 115 | t.Fatalf("Set has wrong number of items") 116 | } 117 | if items[0] != "test1" { 118 | t.Fatalf("First item incorrectly sorted") 119 | } 120 | if items[1] != "test2" { 121 | t.Fatalf("Second item incorrectly sorted") 122 | } 123 | if items[2] != "test3" { 124 | t.Fatalf("Third item incorrectly sorted") 125 | } 126 | } 127 | --------------------------------------------------------------------------------