mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-05-31 22:58:32 +00:00
[chore]: Bump codeberg.org/gruf/go-structr from 0.3.0 to 0.5.0
Bumps codeberg.org/gruf/go-structr from 0.3.0 to 0.5.0. --- updated-dependencies: - dependency-name: codeberg.org/gruf/go-structr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
parent
0362d49da0
commit
e7226a6361
2
go.mod
2
go.mod
|
@ -19,7 +19,7 @@ require (
|
|||
codeberg.org/gruf/go-runners v1.6.2
|
||||
codeberg.org/gruf/go-sched v1.2.3
|
||||
codeberg.org/gruf/go-store/v2 v2.2.4
|
||||
codeberg.org/gruf/go-structr v0.3.0
|
||||
codeberg.org/gruf/go-structr v0.5.0
|
||||
codeberg.org/superseriousbusiness/exif-terminator v0.7.0
|
||||
github.com/DmitriyVTitov/size v1.5.0
|
||||
github.com/KimMachineGun/automemlimit v0.5.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -68,8 +68,8 @@ codeberg.org/gruf/go-sched v1.2.3 h1:H5ViDxxzOBR3uIyGBCf0eH8b1L8wMybOXcdtUUTXZHk
|
|||
codeberg.org/gruf/go-sched v1.2.3/go.mod h1:vT9uB6KWFIIwnG9vcPY2a0alYNoqdL1mSzRM8I+PK7A=
|
||||
codeberg.org/gruf/go-store/v2 v2.2.4 h1:8HO1Jh2gg7boQKA3hsDAIXd9zwieu5uXwDXEcTOD9js=
|
||||
codeberg.org/gruf/go-store/v2 v2.2.4/go.mod h1:zI4VWe5CpXAktYMtaBMrgA5QmO0sQH53LBRvfn1huys=
|
||||
codeberg.org/gruf/go-structr v0.3.0 h1:qaQz40LVm6dWDDp0pGsHbsbO0+XbqsXZ9N5YgqMmG78=
|
||||
codeberg.org/gruf/go-structr v0.3.0/go.mod h1:v9TsGsCBNNSVm/qeOuiblAeIS72YyxEIUoRpW8j4xm8=
|
||||
codeberg.org/gruf/go-structr v0.5.0 h1:DBoT7EuP7Gne2ecO91BZiWqIQlJ84oNbISIwWkhKbkg=
|
||||
codeberg.org/gruf/go-structr v0.5.0/go.mod h1:v9TsGsCBNNSVm/qeOuiblAeIS72YyxEIUoRpW8j4xm8=
|
||||
codeberg.org/superseriousbusiness/exif-terminator v0.7.0 h1:Y6VApSXhKqExG0H2hZ2JelRK4xmWdjDQjn13CpEfzko=
|
||||
codeberg.org/superseriousbusiness/exif-terminator v0.7.0/go.mod h1:gCWKduudUWFzsnixoMzu0FYVdxHWG+AbXnZ50DqxsUE=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
|
|
2
vendor/codeberg.org/gruf/go-structr/README.md
generated
vendored
2
vendor/codeberg.org/gruf/go-structr/README.md
generated
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
A performant struct caching library with automated indexing by arbitrary combinations of fields, including support for negative results (errors!). An example use case is in database lookups.
|
||||
|
||||
Under the hood, go-structr maintains a hashmap per index, where each hashmap is a hashmap keyed with either 32bit, 48bit or 64bit (default) hash checksum of the inputted raw index keys. The hash checksum size can be controlled by the following Go build-tags: `structr_32bit_hash` `structr_48bit_hash`
|
||||
Under the hood, go-structr maintains a hashmap per index, where each hashmap is a hashmap keyed with either 32bit or 64bit (default) hash checksum of the inputted raw index keys. The hash checksum size can be controlled by the following Go build-tags: `structr_32bit_hash`
|
||||
|
||||
Some example code of how you can use `go-structr` in your application:
|
||||
```golang
|
||||
|
|
224
vendor/codeberg.org/gruf/go-structr/cache.go
generated
vendored
224
vendor/codeberg.org/gruf/go-structr/cache.go
generated
vendored
|
@ -124,20 +124,14 @@ func (c *Cache[T]) Index(name string) *Index[T] {
|
|||
panic("unknown index: " + name)
|
||||
}
|
||||
|
||||
// GetOne fetches one value from the cache stored under index, using key generated from key parts.
|
||||
// Note that given number of key parts MUST match expected number and types of the given index name.
|
||||
func (c *Cache[T]) GetOne(index string, key ...any) (T, bool) {
|
||||
return c.GetOneBy(c.Index(index), key...)
|
||||
}
|
||||
|
||||
// GetOneBy fetches value from cache stored under index, using precalculated index key.
|
||||
func (c *Cache[T]) GetOneBy(index *Index[T], key ...any) (T, bool) {
|
||||
// GetOne fetches value from cache stored under index, using precalculated index key.
|
||||
func (c *Cache[T]) GetOne(index *Index[T], key Key) (T, bool) {
|
||||
if index == nil {
|
||||
panic("no index given")
|
||||
} else if !is_unique(index.flags) {
|
||||
panic("cannot get one by non-unique index")
|
||||
}
|
||||
values := c.GetBy(index, key)
|
||||
values := c.Get(index, key)
|
||||
if len(values) == 0 {
|
||||
var zero T
|
||||
return zero, false
|
||||
|
@ -145,20 +139,14 @@ func (c *Cache[T]) GetOneBy(index *Index[T], key ...any) (T, bool) {
|
|||
return values[0], true
|
||||
}
|
||||
|
||||
// Get fetches values from the cache stored under index, using keys generated from given key parts.
|
||||
// Note that each number of key parts MUST match expected number and types of the given index name.
|
||||
func (c *Cache[T]) Get(index string, keys ...[]any) []T {
|
||||
return c.GetBy(c.Index(index), keys...)
|
||||
}
|
||||
|
||||
// GetBy fetches values from the cache stored under index, using precalculated index keys.
|
||||
func (c *Cache[T]) GetBy(index *Index[T], keys ...[]any) []T {
|
||||
// Get fetches values from the cache stored under index, using precalculated index keys.
|
||||
func (c *Cache[T]) Get(index *Index[T], keys ...Key) []T {
|
||||
if index == nil {
|
||||
panic("no index given")
|
||||
}
|
||||
|
||||
// Acquire hasher.
|
||||
h := get_hasher()
|
||||
// Preallocate expected ret slice.
|
||||
values := make([]T, 0, len(keys))
|
||||
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
@ -169,19 +157,10 @@ func (c *Cache[T]) GetBy(index *Index[T], keys ...[]any) []T {
|
|||
panic("not initialized")
|
||||
}
|
||||
|
||||
// Preallocate expected ret slice.
|
||||
values := make([]T, 0, len(keys))
|
||||
|
||||
for _, key := range keys {
|
||||
|
||||
// Generate sum from provided key.
|
||||
sum, ok := index_hash(index, h, key)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for i := range keys {
|
||||
|
||||
// Get indexed results list at key.
|
||||
list := index_get(index, sum, key)
|
||||
list := index_get(index, keys[i])
|
||||
if list == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -213,17 +192,12 @@ func (c *Cache[T]) GetBy(index *Index[T], keys ...[]any) []T {
|
|||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
|
||||
// Done with h.
|
||||
hash_pool.Put(h)
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
// Put will insert the given values into cache,
|
||||
// calling any invalidate hook on each value.
|
||||
func (c *Cache[T]) Put(values ...T) {
|
||||
var z Hash
|
||||
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
|
@ -236,9 +210,9 @@ func (c *Cache[T]) Put(values ...T) {
|
|||
panic("not initialized")
|
||||
}
|
||||
|
||||
// Store all the passed values.
|
||||
for _, value := range values {
|
||||
c.store_value(nil, z, nil, value)
|
||||
// Store all passed values.
|
||||
for i := range values {
|
||||
c.store_value(nil, Key{}, values[i])
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
|
@ -253,16 +227,9 @@ func (c *Cache[T]) Put(values ...T) {
|
|||
}
|
||||
}
|
||||
|
||||
// LoadOne fetches one result from the cache stored under index, using key generated from key parts.
|
||||
// In the case that no result is found, the provided load callback will be used to hydrate the cache.
|
||||
// Note that given number of key parts MUST match expected number and types of the given index name.
|
||||
func (c *Cache[T]) LoadOne(index string, load func() (T, error), key ...any) (T, error) {
|
||||
return c.LoadOneBy(c.Index(index), load, key...)
|
||||
}
|
||||
|
||||
// LoadOneBy fetches one result from the cache stored under index, using precalculated index key.
|
||||
// In the case that no result is found, provided load callback will be used to hydrate the cache.
|
||||
func (c *Cache[T]) LoadOneBy(index *Index[T], load func() (T, error), key ...any) (T, error) {
|
||||
func (c *Cache[T]) LoadOne(index *Index[T], key Key, load func() (T, error)) (T, error) {
|
||||
if index == nil {
|
||||
panic("no index given")
|
||||
} else if !is_unique(index.flags) {
|
||||
|
@ -281,15 +248,6 @@ func (c *Cache[T]) LoadOneBy(index *Index[T], load func() (T, error), key ...any
|
|||
err error
|
||||
)
|
||||
|
||||
// Acquire hasher.
|
||||
h := get_hasher()
|
||||
|
||||
// Generate sum from provided key.
|
||||
sum, _ := index_hash(index, h, key)
|
||||
|
||||
// Done with h.
|
||||
hash_pool.Put(h)
|
||||
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
|
@ -303,8 +261,8 @@ func (c *Cache[T]) LoadOneBy(index *Index[T], load func() (T, error), key ...any
|
|||
panic("not initialized")
|
||||
}
|
||||
|
||||
// Get indexed list at hash key.
|
||||
list := index_get(index, sum, key)
|
||||
// Get indexed result list at key.
|
||||
list := index_get(index, key)
|
||||
|
||||
if ok = (list != nil); ok {
|
||||
entry := (*index_entry)(list.head.data)
|
||||
|
@ -350,9 +308,9 @@ func (c *Cache[T]) LoadOneBy(index *Index[T], load func() (T, error), key ...any
|
|||
// the provided value, so it is
|
||||
// safe for us to return as-is.
|
||||
if err != nil {
|
||||
c.store_error(index, sum, key, err)
|
||||
c.store_error(index, key, err)
|
||||
} else {
|
||||
c.store_value(index, sum, key, val)
|
||||
c.store_value(index, key, val)
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
|
@ -361,29 +319,16 @@ func (c *Cache[T]) LoadOneBy(index *Index[T], load func() (T, error), key ...any
|
|||
return val, err
|
||||
}
|
||||
|
||||
// Load fetches values from the cache stored under index, using keys generated from given key parts. The provided get callback is used
|
||||
// to load groups of values from the cache by the key generated from the key parts provided to the inner callback func, where the returned
|
||||
// boolean indicates whether any values are currently stored. After the get callback has returned, the cache will then call provided load
|
||||
// callback to hydrate the cache with any other values. Example usage here is that you may see which values are cached using 'get', and load
|
||||
// the remaining uncached values using 'load', to minimize database queries. Cached error results are not included or returned by this func.
|
||||
// Note that given number of key parts MUST match expected number and types of the given index name, in those provided to the get callback.
|
||||
func (c *Cache[T]) Load(index string, get func(load func(key ...any) bool), load func() ([]T, error)) (values []T, err error) {
|
||||
return c.LoadBy(c.Index(index), get, load)
|
||||
}
|
||||
|
||||
// LoadBy fetches values from the cache stored under index, using precalculated index key. The provided get callback is used to load
|
||||
// groups of values from the cache by the key generated from the key parts provided to the inner callback func, where the returned boolea
|
||||
// indicates whether any values are currently stored. After the get callback has returned, the cache will then call provided load callback
|
||||
// to hydrate the cache with any other values. Example usage here is that you may see which values are cached using 'get', and load the
|
||||
// remaining uncached values using 'load', to minimize database queries. Cached error results are not included or returned by this func.
|
||||
// Note that given number of key parts MUST match expected number and types of the given index name, in those provided to the get callback.
|
||||
func (c *Cache[T]) LoadBy(index *Index[T], get func(load func(key ...any) bool), load func() ([]T, error)) (values []T, err error) {
|
||||
// Load fetches values from the cache stored under index, using precalculated index keys. The cache will attempt to
|
||||
// results with values stored under keys, passing keys with uncached results to the provider load callback to further
|
||||
// hydrate the cache with missing results. Cached error results not included or returned by this function.
|
||||
func (c *Cache[T]) Load(index *Index[T], keys []Key, load func([]Key) ([]T, error)) ([]T, error) {
|
||||
if index == nil {
|
||||
panic("no index given")
|
||||
}
|
||||
|
||||
// Acquire hasher.
|
||||
h := get_hasher()
|
||||
// Preallocate expected ret slice.
|
||||
values := make([]T, 0, len(keys))
|
||||
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
@ -394,35 +339,19 @@ func (c *Cache[T]) LoadBy(index *Index[T], get func(load func(key ...any) bool),
|
|||
panic("not initialized")
|
||||
}
|
||||
|
||||
var unlocked bool
|
||||
defer func() {
|
||||
// Deferred unlock to catch
|
||||
// any user function panics.
|
||||
if !unlocked {
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
}()
|
||||
for i := 0; i < len(keys); i++ {
|
||||
|
||||
// Pass loader to user func.
|
||||
get(func(key ...any) bool {
|
||||
|
||||
// Generate sum from provided key.
|
||||
sum, ok := index_hash(index, h, key)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
// Get indexed results at hash key.
|
||||
list := index_get(index, sum, key)
|
||||
// Get indexed results at key.
|
||||
list := index_get(index, keys[i])
|
||||
if list == nil {
|
||||
return false
|
||||
continue
|
||||
}
|
||||
|
||||
// Value length before
|
||||
// any below appends.
|
||||
before := len(values)
|
||||
|
||||
// Concatenate all *values* from non-err cached results.
|
||||
// Concat all *values* from cached results.
|
||||
list_rangefn(list, func(e *list_elem) {
|
||||
entry := (*index_entry)(e.data)
|
||||
res := entry.result
|
||||
|
@ -447,18 +376,20 @@ func (c *Cache[T]) LoadBy(index *Index[T], get func(load func(key ...any) bool),
|
|||
|
||||
// Only if values changed did
|
||||
// we actually find anything.
|
||||
return len(values) != before
|
||||
})
|
||||
if len(values) != before {
|
||||
|
||||
// We found values at key,
|
||||
// drop key from the slice.
|
||||
copy(keys[i:], keys[i+1:])
|
||||
keys = keys[:len(keys)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
unlocked = true
|
||||
|
||||
// Done with h.
|
||||
hash_pool.Put(h)
|
||||
|
||||
// Load uncached values.
|
||||
uncached, err := load()
|
||||
uncached, err := load(keys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -469,7 +400,7 @@ func (c *Cache[T]) LoadBy(index *Index[T], get func(load func(key ...any) bool),
|
|||
// Append uncached to return values.
|
||||
values = append(values, uncached...)
|
||||
|
||||
return
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// Store will call the given store callback, on non-error then
|
||||
|
@ -501,51 +432,36 @@ func (c *Cache[T]) Store(value T, store func() error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Invalidate generates index key from parts and invalidates all stored under it.
|
||||
func (c *Cache[T]) Invalidate(index string, key ...any) {
|
||||
c.InvalidateBy(c.Index(index), key...)
|
||||
}
|
||||
|
||||
// InvalidateBy invalidates all results stored under index key.
|
||||
func (c *Cache[T]) InvalidateBy(index *Index[T], key ...any) {
|
||||
// Invalidate invalidates all results stored under index keys.
|
||||
func (c *Cache[T]) Invalidate(index *Index[T], keys ...Key) {
|
||||
if index == nil {
|
||||
panic("no index given")
|
||||
}
|
||||
|
||||
// Acquire hasher.
|
||||
h := get_hasher()
|
||||
|
||||
// Generate sum from provided key.
|
||||
sum, ok := index_hash(index, h, key)
|
||||
|
||||
// Done with h.
|
||||
hash_pool.Put(h)
|
||||
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var values []T
|
||||
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
// Preallocate expected ret slice.
|
||||
values := make([]T, 0, len(keys))
|
||||
|
||||
for i := range keys {
|
||||
// Delete all results under key from index, collecting
|
||||
// value results and dropping them from all their indices.
|
||||
index_delete(index, keys[i], func(del *result) {
|
||||
switch value := del.data.(type) {
|
||||
case T:
|
||||
// Append value COPY.
|
||||
value = c.copy(value)
|
||||
values = append(values, value)
|
||||
case error:
|
||||
}
|
||||
c.delete(del)
|
||||
})
|
||||
}
|
||||
|
||||
// Get func ptrs.
|
||||
invalid := c.invalid
|
||||
|
||||
// Delete all results under key from index, collecting
|
||||
// value results and dropping them from all their indices.
|
||||
index_delete(c, index, sum, key, func(del *result) {
|
||||
switch value := del.data.(type) {
|
||||
case T:
|
||||
// Append value COPY.
|
||||
value = c.copy(value)
|
||||
values = append(values, value)
|
||||
case error:
|
||||
}
|
||||
c.delete(del)
|
||||
})
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
|
||||
|
@ -614,14 +530,14 @@ func (c *Cache[T]) Cap() int {
|
|||
return m
|
||||
}
|
||||
|
||||
func (c *Cache[T]) store_value(index *Index[T], hash Hash, key []any, value T) {
|
||||
func (c *Cache[T]) store_value(index *Index[T], key Key, value T) {
|
||||
// Acquire new result.
|
||||
res := result_acquire(c)
|
||||
|
||||
if index != nil {
|
||||
// Append result to the provided index
|
||||
// with precalculated key / its hash.
|
||||
index_append(c, index, hash, key, res)
|
||||
index_append(c, index, key, res)
|
||||
}
|
||||
|
||||
// Create COPY of value.
|
||||
|
@ -641,14 +557,18 @@ func (c *Cache[T]) store_value(index *Index[T], hash Hash, key []any, value T) {
|
|||
continue
|
||||
}
|
||||
|
||||
// Get key and hash sum for this index.
|
||||
key, sum, ok := index_key(idx, h, value)
|
||||
if !ok {
|
||||
// Extract struct fields comprising
|
||||
// key parts configured for this index.
|
||||
parts := extract_fields(value, idx.fields)
|
||||
|
||||
// Calculate key for this index.
|
||||
key := index_key(idx, h, parts)
|
||||
if key.Zero() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Append result to index at key.
|
||||
index_append(c, idx, sum, key, res)
|
||||
index_append(c, idx, key, res)
|
||||
}
|
||||
|
||||
// Done with h.
|
||||
|
@ -663,7 +583,7 @@ func (c *Cache[T]) store_value(index *Index[T], hash Hash, key []any, value T) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Cache[T]) store_error(index *Index[T], hash Hash, key []any, err error) {
|
||||
func (c *Cache[T]) store_error(index *Index[T], key Key, err error) {
|
||||
if index == nil {
|
||||
// nothing we
|
||||
// can do here.
|
||||
|
@ -676,7 +596,7 @@ func (c *Cache[T]) store_error(index *Index[T], hash Hash, key []any, err error)
|
|||
|
||||
// Append result to the provided index
|
||||
// with precalculated key / its hash.
|
||||
index_append(c, index, hash, key, res)
|
||||
index_append(c, index, key, res)
|
||||
|
||||
if c.lruList.len > c.maxSize {
|
||||
// Cache has hit max size!
|
||||
|
@ -687,8 +607,6 @@ func (c *Cache[T]) store_error(index *Index[T], hash Hash, key []any, err error)
|
|||
}
|
||||
}
|
||||
|
||||
// delete will delete the given result from the cache, deleting
|
||||
// it from all indices it is stored under, and main LRU list.
|
||||
func (c *Cache[T]) delete(res *result) {
|
||||
for len(res.indexed) != 0 {
|
||||
|
||||
|
@ -697,7 +615,7 @@ func (c *Cache[T]) delete(res *result) {
|
|||
res.indexed = res.indexed[:len(res.indexed)-1]
|
||||
|
||||
// Drop entry from index.
|
||||
index_delete_entry(c, entry)
|
||||
index_delete_entry[T](entry)
|
||||
|
||||
// Release to memory pool.
|
||||
index_entry_release(entry)
|
||||
|
|
2
vendor/codeberg.org/gruf/go-structr/hash_32.go
generated
vendored
2
vendor/codeberg.org/gruf/go-structr/hash_32.go
generated
vendored
|
@ -8,7 +8,7 @@ package structr
|
|||
// checksum type. Here; uint32.
|
||||
type Hash uint32
|
||||
|
||||
// uint64ToHash converts uint64 to currently Hash type.
|
||||
// uint64ToHash converts uint64 to current Hash type.
|
||||
func uint64ToHash(u uint64) Hash {
|
||||
return Hash(u >> 32)
|
||||
}
|
||||
|
|
21
vendor/codeberg.org/gruf/go-structr/hash_48.go
generated
vendored
21
vendor/codeberg.org/gruf/go-structr/hash_48.go
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
//go:build structr_48bit_hash
|
||||
// +build structr_48bit_hash
|
||||
|
||||
package structr
|
||||
|
||||
// Hash is the current compiler
|
||||
// flag defined cache key hash
|
||||
// checksum type. Here; uint48.
|
||||
type Hash [6]byte
|
||||
|
||||
// uint64ToHash converts uint64 to currently Hash type.
|
||||
func uint64ToHash(u uint64) Hash {
|
||||
return Hash{
|
||||
0: byte(u),
|
||||
1: byte(u >> 8),
|
||||
2: byte(u >> 16),
|
||||
3: byte(u >> 24),
|
||||
4: byte(u >> 32),
|
||||
5: byte(u >> 40),
|
||||
}
|
||||
}
|
2
vendor/codeberg.org/gruf/go-structr/hash_64.go
generated
vendored
2
vendor/codeberg.org/gruf/go-structr/hash_64.go
generated
vendored
|
@ -8,7 +8,7 @@ package structr
|
|||
// checksum type. Here; uint64.
|
||||
type Hash uint64
|
||||
|
||||
// uint64ToHash converts uint64 to currently Hash type.
|
||||
// uint64ToHash converts uint64 to current Hash type.
|
||||
func uint64ToHash(u uint64) Hash {
|
||||
return Hash(u)
|
||||
}
|
||||
|
|
192
vendor/codeberg.org/gruf/go-structr/index.go
generated
vendored
192
vendor/codeberg.org/gruf/go-structr/index.go
generated
vendored
|
@ -9,6 +9,43 @@ import (
|
|||
"github.com/zeebo/xxh3"
|
||||
)
|
||||
|
||||
// Key represents one key to
|
||||
// lookup (potentially) stored
|
||||
// entries in an Index.
|
||||
type Key struct {
|
||||
raw []any
|
||||
sum Hash
|
||||
}
|
||||
|
||||
// Equal returns whether keys are equal.
|
||||
func (k Key) Equal(o Key) bool {
|
||||
if len(k.raw) != len(o.raw) {
|
||||
return false
|
||||
}
|
||||
for i := range k.raw {
|
||||
if k.raw[i] != o.raw[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Sum returns the hashsum of Key.
|
||||
func (k Key) Sum() Hash {
|
||||
return k.sum
|
||||
}
|
||||
|
||||
// Value returns the raw slice of
|
||||
// values that comprise this Key.
|
||||
func (k Key) Values() []any {
|
||||
return k.raw
|
||||
}
|
||||
|
||||
// Zero indicates a zero value key.
|
||||
func (k Key) Zero() bool {
|
||||
return k.raw == nil
|
||||
}
|
||||
|
||||
// IndexConfig defines config variables
|
||||
// for initializing a struct index.
|
||||
type IndexConfig struct {
|
||||
|
@ -79,32 +116,36 @@ type Index[StructType any] struct {
|
|||
flags uint8
|
||||
}
|
||||
|
||||
// Key returns the configured fields as key, and hash sum of key.
|
||||
func (i *Index[T]) Key(value T) ([]any, Hash, bool) {
|
||||
// Name returns the receiving Index name.
|
||||
func (i *Index[T]) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
// Key generates Key{} from given parts for
|
||||
// the type of lookup this Index uses in cache.
|
||||
// NOTE: panics on incorrect no. parts / types given.
|
||||
func (i *Index[T]) ToKey(parts ...any) Key {
|
||||
h := get_hasher()
|
||||
key, sum, ok := index_key(i, h, value)
|
||||
key := index_key(i, h, parts)
|
||||
hash_pool.Put(h)
|
||||
return key, sum, ok
|
||||
return key
|
||||
}
|
||||
|
||||
func is_unique(f uint8) bool {
|
||||
const mask = uint8(1) << 0
|
||||
return f&mask != 0
|
||||
}
|
||||
|
||||
func set_is_unique(f *uint8) {
|
||||
const mask = uint8(1) << 0
|
||||
(*f) |= mask
|
||||
}
|
||||
|
||||
func allow_zero(f uint8) bool {
|
||||
const mask = uint8(1) << 1
|
||||
return f&mask != 0
|
||||
}
|
||||
|
||||
func set_allow_zero(f *uint8) {
|
||||
const mask = uint8(1) << 1
|
||||
(*f) |= mask
|
||||
// ToKeys generates []Key{} from given (multiple) parts
|
||||
// for the type of lookup this Index uses in the cache.
|
||||
// NOTE: panics on incorrect no. parts / types given.
|
||||
func (i *Index[T]) ToKeys(parts ...[]any) []Key {
|
||||
keys := make([]Key, 0, len(parts))
|
||||
h := get_hasher()
|
||||
for _, parts := range parts {
|
||||
key := index_key(i, h, parts)
|
||||
if key.Zero() {
|
||||
continue
|
||||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
hash_pool.Put(h)
|
||||
return keys
|
||||
}
|
||||
|
||||
func init_index[T any](i *Index[T], config IndexConfig, max int) {
|
||||
|
@ -141,52 +182,44 @@ func init_index[T any](i *Index[T], config IndexConfig, max int) {
|
|||
i.data = make(map[Hash]*list, max+1)
|
||||
}
|
||||
|
||||
func index_key[T any](i *Index[T], h *xxh3.Hasher, value T) ([]any, Hash, bool) {
|
||||
key := extract_fields(value, i.fields)
|
||||
sum, zero := hash_sum(i.fields, h, key)
|
||||
func index_key[T any](i *Index[T], h *xxh3.Hasher, parts []any) Key {
|
||||
sum, zero := hash_sum(i.fields, h, parts)
|
||||
if zero && !allow_zero(i.flags) {
|
||||
var zero Hash
|
||||
return nil, zero, false
|
||||
return Key{}
|
||||
}
|
||||
return Key{
|
||||
raw: parts,
|
||||
sum: sum,
|
||||
}
|
||||
return key, sum, true
|
||||
}
|
||||
|
||||
func index_hash[T any](i *Index[T], h *xxh3.Hasher, key []any) (Hash, bool) {
|
||||
sum, zero := hash_sum(i.fields, h, key)
|
||||
if zero && !allow_zero(i.flags) {
|
||||
var zero Hash
|
||||
return zero, false
|
||||
}
|
||||
return sum, true
|
||||
}
|
||||
|
||||
func index_get[T any](i *Index[T], hash Hash, key []any) *list {
|
||||
l := i.data[hash]
|
||||
func index_get[T any](i *Index[T], key Key) *list {
|
||||
l := i.data[key.sum]
|
||||
if l == nil {
|
||||
return nil
|
||||
}
|
||||
entry := (*index_entry)(l.head.data)
|
||||
if !is_equal(entry.key, key) {
|
||||
if !entry.key.Equal(key) {
|
||||
return l
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func index_append[T any](c *Cache[T], i *Index[T], hash Hash, key []any, res *result) {
|
||||
func index_append[T any](c *Cache[T], i *Index[T], key Key, res *result) {
|
||||
// Get list at key.
|
||||
l := i.data[hash]
|
||||
l := i.data[key.sum]
|
||||
|
||||
if l == nil {
|
||||
|
||||
// Allocate new list.
|
||||
l = list_acquire()
|
||||
i.data[hash] = l
|
||||
i.data[key.sum] = l
|
||||
|
||||
} else if entry := (*index_entry)(l.head.data); //nocollapse
|
||||
!is_equal(entry.key, key) {
|
||||
!entry.key.Equal(key) {
|
||||
|
||||
// Collision! Drop all.
|
||||
delete(i.data, hash)
|
||||
delete(i.data, key.sum)
|
||||
|
||||
// Iterate entries in list.
|
||||
for x := 0; x < l.len; x++ {
|
||||
|
@ -236,7 +269,6 @@ func index_append[T any](c *Cache[T], i *Index[T], hash Hash, key []any, res *re
|
|||
entry.index = unsafe.Pointer(i)
|
||||
entry.result = res
|
||||
entry.key = key
|
||||
entry.hash = hash
|
||||
|
||||
// Append to result's indexed entries.
|
||||
res.indexed = append(res.indexed, entry)
|
||||
|
@ -245,26 +277,27 @@ func index_append[T any](c *Cache[T], i *Index[T], hash Hash, key []any, res *re
|
|||
list_push_front(l, &entry.elem)
|
||||
}
|
||||
|
||||
func index_delete[T any](c *Cache[T], i *Index[T], hash Hash, key []any, fn func(*result)) {
|
||||
func index_delete[T any](i *Index[T], key Key, fn func(*result)) {
|
||||
if fn == nil {
|
||||
panic("nil fn")
|
||||
}
|
||||
|
||||
// Get list at hash.
|
||||
l := i.data[hash]
|
||||
l := i.data[key.sum]
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Extract entry from first list elem.
|
||||
entry := (*index_entry)(l.head.data)
|
||||
|
||||
// Check contains expected key for hash.
|
||||
if !is_equal(entry.key, key) {
|
||||
// Check contains expected key.
|
||||
if !entry.key.Equal(key) {
|
||||
return
|
||||
}
|
||||
|
||||
// Delete data at hash.
|
||||
delete(i.data, hash)
|
||||
delete(i.data, key.sum)
|
||||
|
||||
// Iterate entries in list.
|
||||
for x := 0; x < l.len; x++ {
|
||||
|
@ -287,12 +320,12 @@ func index_delete[T any](c *Cache[T], i *Index[T], hash Hash, key []any, fn func
|
|||
list_release(l)
|
||||
}
|
||||
|
||||
func index_delete_entry[T any](c *Cache[T], entry *index_entry) {
|
||||
// Get from entry.
|
||||
func index_delete_entry[T any](entry *index_entry) {
|
||||
// Get index from entry.
|
||||
i := (*Index[T])(entry.index)
|
||||
|
||||
// Get list at hash sum.
|
||||
l := i.data[entry.hash]
|
||||
l := i.data[entry.key.sum]
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
|
@ -301,8 +334,8 @@ func index_delete_entry[T any](c *Cache[T], entry *index_entry) {
|
|||
list_remove(l, &entry.elem)
|
||||
if l.len == 0 {
|
||||
|
||||
// Remove list from map.
|
||||
delete(i.data, entry.hash)
|
||||
// Remove entry list from map.
|
||||
delete(i.data, entry.key.sum)
|
||||
|
||||
// Release to pool.
|
||||
list_release(l)
|
||||
|
@ -337,15 +370,10 @@ type index_entry struct {
|
|||
// is currently stored under.
|
||||
result *result
|
||||
|
||||
// key contains the actual
|
||||
// key this item was stored
|
||||
// under, used for collision
|
||||
// check.
|
||||
key []any
|
||||
|
||||
// hash contains computed
|
||||
// hash checksum of .key.
|
||||
hash Hash
|
||||
// key contains the raw key
|
||||
// data this was stored under,
|
||||
// and the hash checksum.
|
||||
key Key
|
||||
}
|
||||
|
||||
func index_entry_acquire() *index_entry {
|
||||
|
@ -365,28 +393,32 @@ func index_entry_acquire() *index_entry {
|
|||
}
|
||||
|
||||
func index_entry_release(entry *index_entry) {
|
||||
var zero Hash
|
||||
|
||||
// Reset index entry.
|
||||
entry.elem.data = nil
|
||||
entry.index = nil
|
||||
entry.result = nil
|
||||
entry.key = nil
|
||||
entry.hash = zero
|
||||
entry.key = Key{}
|
||||
|
||||
// Release to pool.
|
||||
entry_pool.Put(entry)
|
||||
}
|
||||
|
||||
// is_equal returns whether 2 key slices are equal.
|
||||
func is_equal(k1, k2 []any) bool {
|
||||
if len(k1) != len(k2) {
|
||||
return false
|
||||
}
|
||||
for i := range k1 {
|
||||
if k1[i] != k2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
func is_unique(f uint8) bool {
|
||||
const mask = uint8(1) << 0
|
||||
return f&mask != 0
|
||||
}
|
||||
|
||||
func set_is_unique(f *uint8) {
|
||||
const mask = uint8(1) << 0
|
||||
(*f) |= mask
|
||||
}
|
||||
|
||||
func allow_zero(f uint8) bool {
|
||||
const mask = uint8(1) << 1
|
||||
return f&mask != 0
|
||||
}
|
||||
|
||||
func set_allow_zero(f *uint8) {
|
||||
const mask = uint8(1) << 1
|
||||
(*f) |= mask
|
||||
}
|
||||
|
|
8
vendor/codeberg.org/gruf/go-structr/runtime.go
generated
vendored
8
vendor/codeberg.org/gruf/go-structr/runtime.go
generated
vendored
|
@ -12,10 +12,10 @@ import (
|
|||
)
|
||||
|
||||
type structfield struct {
|
||||
// _type is the runtime type pointer
|
||||
// type2 is the runtime type pointer
|
||||
// underlying the struct field type.
|
||||
// used for repacking our own erfaces.
|
||||
_type reflect2.Type
|
||||
type2 reflect2.Type
|
||||
|
||||
// offset is the offset in memory
|
||||
// of this struct field from the
|
||||
|
@ -92,7 +92,7 @@ func find_field(t reflect.Type, names []string) (sfield structfield) {
|
|||
}
|
||||
|
||||
// Get field type as reflect2.
|
||||
sfield._type = reflect2.Type2(t)
|
||||
sfield.type2 = reflect2.Type2(t)
|
||||
|
||||
// Find hasher for type.
|
||||
sfield.hasher = hasher(t)
|
||||
|
@ -117,7 +117,7 @@ func extract_fields[T any](value T, fields []structfield) []any {
|
|||
for i := 0; i < len(fields); i++ {
|
||||
// Manually access field at memory offset and pack eface.
|
||||
ptr := unsafe.Pointer(uintptr(ptr) + fields[i].offset)
|
||||
ifaces[i] = fields[i]._type.UnsafeIndirect(ptr)
|
||||
ifaces[i] = fields[i].type2.UnsafeIndirect(ptr)
|
||||
}
|
||||
|
||||
return ifaces
|
||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -56,7 +56,7 @@ codeberg.org/gruf/go-sched
|
|||
## explicit; go 1.19
|
||||
codeberg.org/gruf/go-store/v2/storage
|
||||
codeberg.org/gruf/go-store/v2/util
|
||||
# codeberg.org/gruf/go-structr v0.3.0
|
||||
# codeberg.org/gruf/go-structr v0.5.0
|
||||
## explicit; go 1.21
|
||||
codeberg.org/gruf/go-structr
|
||||
# codeberg.org/superseriousbusiness/exif-terminator v0.7.0
|
||||
|
|
Loading…
Reference in a new issue