github.com/m3db/m3@v1.5.0/src/m3ninx/index/segment/builder/ids_map_gen.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all 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, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 // This file was automatically generated by genny. 22 // Any changes will be lost if this file is regenerated. 23 // see https://github.com/mauricelam/genny 24 25 package builder 26 27 // Copyright (c) 2021 Uber Technologies, Inc. 28 // 29 // Permission is hereby granted, free of charge, to any person obtaining a copy 30 // of this software and associated documentation files (the "Software"), to deal 31 // in the Software without restriction, including without limitation the rights 32 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 // copies of the Software, and to permit persons to whom the Software is 34 // furnished to do so, subject to the following conditions: 35 // 36 // The above copyright notice and this permission notice shall be included in 37 // all copies or substantial portions of the Software. 38 // 39 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45 // THE SOFTWARE. 46 47 // This file was automatically generated by genny. 48 // Any changes will be lost if this file is regenerated. 49 // see https://github.com/mauricelam/genny 50 51 // Copyright (c) 2018 Uber Technologies, Inc. 52 // 53 // Permission is hereby granted, free of charge, to any person obtaining a copy 54 // of this software and associated documentation files (the "Software"), to deal 55 // in the Software without restriction, including without limitation the rights 56 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57 // copies of the Software, and to permit persons to whom the Software is 58 // furnished to do so, subject to the following conditions: 59 // 60 // The above copyright notice and this permission notice shall be included in 61 // all copies or substantial portions of the Software. 62 // 63 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 66 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 68 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 69 // THE SOFTWARE. 70 71 // IDsMapHash is the hash for a given map entry, this is public to support 72 // iterating over the map using a native Go for loop. 73 type IDsMapHash uint64 74 75 // IDsMapHashFn is the hash function to execute when hashing a key. 76 type IDsMapHashFn func([]byte) IDsMapHash 77 78 // IDsMapEqualsFn is the equals key function to execute when detecting equality of a key. 79 type IDsMapEqualsFn func([]byte, []byte) bool 80 81 // IDsMapCopyFn is the copy key function to execute when copying the key. 82 type IDsMapCopyFn func([]byte) []byte 83 84 // IDsMapFinalizeFn is the finalize key function to execute when finished with a key. 85 type IDsMapFinalizeFn func([]byte) 86 87 // IDsMap uses the genny package to provide a generic hash map that can be specialized 88 // by running the following command from this root of the repository: 89 // ``` 90 // make hashmap-gen pkg=outpkg key_type=Type value_type=Type out_dir=/tmp 91 // ``` 92 // Or if you would like to use bytes or ident.ID as keys you can use the 93 // partially specialized maps to generate your own maps as well: 94 // ``` 95 // make byteshashmap-gen pkg=outpkg value_type=Type out_dir=/tmp 96 // make idhashmap-gen pkg=outpkg value_type=Type out_dir=/tmp 97 // ``` 98 // This will output to stdout the generated source file to use for your map. 99 // It uses linear probing by incrementing the number of the hash created when 100 // hashing the identifier if there is a collision. 101 // IDsMap is a value type and not an interface to allow for less painful 102 // upgrades when adding/removing methods, it is not likely to need mocking so 103 // an interface would not be super useful either. 104 type IDsMap struct { 105 _IDsMapOptions 106 107 // lookup uses hash of the identifier for the key and the MapEntry value 108 // wraps the value type and the key (used to ensure lookup is correct 109 // when dealing with collisions), we use uint64 for the hash partially 110 // because lookups of maps with uint64 keys has a fast path for Go. 111 lookup map[IDsMapHash]IDsMapEntry 112 } 113 114 // _IDsMapOptions is a set of options used when creating an identifier map, it is kept 115 // private so that implementers of the generated map can specify their own options 116 // that partially fulfill these options. 117 type _IDsMapOptions struct { 118 // hash is the hash function to execute when hashing a key. 119 hash IDsMapHashFn 120 // equals is the equals key function to execute when detecting equality. 121 equals IDsMapEqualsFn 122 // copy is the copy key function to execute when copying the key. 123 copy IDsMapCopyFn 124 // finalize is the finalize key function to execute when finished with a 125 // key, this is optional to specify. 126 finalize IDsMapFinalizeFn 127 // initialSize is the initial size for the map, use zero to use Go's std map 128 // initial size and consequently is optional to specify. 129 initialSize int 130 } 131 132 // IDsMapEntry is an entry in the map, this is public to support iterating 133 // over the map using a native Go for loop. 134 type IDsMapEntry struct { 135 // key is used to check equality on lookups to resolve collisions 136 key _IDsMapKey 137 // value type stored 138 value struct{} 139 } 140 141 type _IDsMapKey struct { 142 key []byte 143 finalize bool 144 } 145 146 // Key returns the map entry key. 147 func (e IDsMapEntry) Key() []byte { 148 return e.key.key 149 } 150 151 // Value returns the map entry value. 152 func (e IDsMapEntry) Value() struct{} { 153 return e.value 154 } 155 156 // _IDsMapAlloc is a non-exported function so that when generating the source code 157 // for the map you can supply a public constructor that sets the correct 158 // hash, equals, copy, finalize options without users of the map needing to 159 // implement them themselves. 160 func _IDsMapAlloc(opts _IDsMapOptions) *IDsMap { 161 m := &IDsMap{_IDsMapOptions: opts} 162 m.Reallocate() 163 return m 164 } 165 166 func (m *IDsMap) newMapKey(k []byte, opts _IDsMapKeyOptions) _IDsMapKey { 167 key := _IDsMapKey{key: k, finalize: opts.finalizeKey} 168 if !opts.copyKey { 169 return key 170 } 171 172 key.key = m.copy(k) 173 return key 174 } 175 176 func (m *IDsMap) removeMapKey(hash IDsMapHash, key _IDsMapKey) { 177 delete(m.lookup, hash) 178 if key.finalize { 179 m.finalize(key.key) 180 } 181 } 182 183 // Get returns a value in the map for an identifier if found. 184 func (m *IDsMap) Get(k []byte) (struct{}, bool) { 185 hash := m.hash(k) 186 for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] { 187 if m.equals(entry.key.key, k) { 188 return entry.value, true 189 } 190 // Linear probe to "next" to this entry (really a rehash) 191 hash++ 192 } 193 var empty struct{} 194 return empty, false 195 } 196 197 // Set will set the value for an identifier. 198 func (m *IDsMap) Set(k []byte, v struct{}) { 199 m.set(k, v, _IDsMapKeyOptions{ 200 copyKey: true, 201 finalizeKey: m.finalize != nil, 202 }) 203 } 204 205 // IDsMapSetUnsafeOptions is a set of options to use when setting a value with 206 // the SetUnsafe method. 207 type IDsMapSetUnsafeOptions struct { 208 NoCopyKey bool 209 NoFinalizeKey bool 210 } 211 212 // SetUnsafe will set the value for an identifier with unsafe options for how 213 // the map treats the key. 214 func (m *IDsMap) SetUnsafe(k []byte, v struct{}, opts IDsMapSetUnsafeOptions) { 215 m.set(k, v, _IDsMapKeyOptions{ 216 copyKey: !opts.NoCopyKey, 217 finalizeKey: !opts.NoFinalizeKey, 218 }) 219 } 220 221 type _IDsMapKeyOptions struct { 222 copyKey bool 223 finalizeKey bool 224 } 225 226 func (m *IDsMap) set(k []byte, v struct{}, opts _IDsMapKeyOptions) { 227 hash := m.hash(k) 228 for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] { 229 if m.equals(entry.key.key, k) { 230 m.lookup[hash] = IDsMapEntry{ 231 key: entry.key, 232 value: v, 233 } 234 return 235 } 236 // Linear probe to "next" to this entry (really a rehash) 237 hash++ 238 } 239 240 m.lookup[hash] = IDsMapEntry{ 241 key: m.newMapKey(k, opts), 242 value: v, 243 } 244 } 245 246 // Iter provides the underlying map to allow for using a native Go for loop 247 // to iterate the map, however callers should only ever read and not write 248 // the map. 249 func (m *IDsMap) Iter() map[IDsMapHash]IDsMapEntry { 250 return m.lookup 251 } 252 253 // Len returns the number of map entries in the map. 254 func (m *IDsMap) Len() int { 255 return len(m.lookup) 256 } 257 258 // Contains returns true if value exists for key, false otherwise, it is 259 // shorthand for a call to Get that doesn't return the value. 260 func (m *IDsMap) Contains(k []byte) bool { 261 _, ok := m.Get(k) 262 return ok 263 } 264 265 // Delete will remove a value set in the map for the specified key. 266 func (m *IDsMap) Delete(k []byte) { 267 hash := m.hash(k) 268 for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] { 269 if m.equals(entry.key.key, k) { 270 m.removeMapKey(hash, entry.key) 271 return 272 } 273 // Linear probe to "next" to this entry (really a rehash) 274 hash++ 275 } 276 } 277 278 // Reset will reset the map by simply deleting all keys to avoid 279 // allocating a new map. 280 func (m *IDsMap) Reset() { 281 for hash, entry := range m.lookup { 282 m.removeMapKey(hash, entry.key) 283 } 284 } 285 286 // Reallocate will avoid deleting all keys and reallocate a new 287 // map, this is useful if you believe you have a large map and 288 // will not need to grow back to a similar size. 289 func (m *IDsMap) Reallocate() { 290 if m.initialSize > 0 { 291 m.lookup = make(map[IDsMapHash]IDsMapEntry, m.initialSize) 292 } else { 293 m.lookup = make(map[IDsMapHash]IDsMapEntry) 294 } 295 }