mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[performance] cache library performance enhancements (updates go-structr => v0.2.0) (#2575)
* update go-structr => v0.2.0 * update readme * whoops, fix the link
This commit is contained in:
204
vendor/codeberg.org/gruf/go-structr/key.go
generated
vendored
204
vendor/codeberg.org/gruf/go-structr/key.go
generated
vendored
@ -1,204 +0,0 @@
|
||||
package structr
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"codeberg.org/gruf/go-byteutil"
|
||||
"codeberg.org/gruf/go-mangler"
|
||||
)
|
||||
|
||||
// KeyGen is the underlying index key generator
|
||||
// used within Index, and therefore Cache itself.
|
||||
type KeyGen[StructType any] struct {
|
||||
|
||||
// fields contains our representation of
|
||||
// the struct fields contained in the
|
||||
// creation of keys by this generator.
|
||||
fields []structfield
|
||||
|
||||
// zero specifies whether zero
|
||||
// value fields are permitted.
|
||||
zero bool
|
||||
}
|
||||
|
||||
// NewKeyGen returns a new initialized KeyGen for the receiving generic
|
||||
// parameter type, comprising of the given field strings, and whether to
|
||||
// allow zero values to be included within generated output strings.
|
||||
func NewKeyGen[T any](fields []string, allowZero bool) KeyGen[T] {
|
||||
var kgen KeyGen[T]
|
||||
|
||||
// Preallocate expected struct field slice.
|
||||
kgen.fields = make([]structfield, len(fields))
|
||||
|
||||
// Get the reflected struct ptr type.
|
||||
t := reflect.TypeOf((*T)(nil)).Elem()
|
||||
|
||||
for i, fieldName := range fields {
|
||||
// Split name to account for nesting.
|
||||
names := strings.Split(fieldName, ".")
|
||||
|
||||
// Look for a usable struct field from type.
|
||||
sfield, ok := findField(t, names, allowZero)
|
||||
if !ok {
|
||||
panicf("failed finding field: %s", fieldName)
|
||||
}
|
||||
|
||||
// Set parsed struct field.
|
||||
kgen.fields[i] = sfield
|
||||
}
|
||||
|
||||
// Set config flags.
|
||||
kgen.zero = allowZero
|
||||
|
||||
return kgen
|
||||
}
|
||||
|
||||
// FromParts generates key string from individual key parts.
|
||||
func (kgen *KeyGen[T]) FromParts(parts ...any) (key string, ok bool) {
|
||||
buf := getBuf()
|
||||
if ok = kgen.AppendFromParts(buf, parts...); ok {
|
||||
key = string(buf.B)
|
||||
}
|
||||
putBuf(buf)
|
||||
return
|
||||
}
|
||||
|
||||
// FromValue generates key string from a value, via reflection.
|
||||
func (kgen *KeyGen[T]) FromValue(value T) (key string, ok bool) {
|
||||
buf := getBuf()
|
||||
rvalue := reflect.ValueOf(value)
|
||||
if ok = kgen.appendFromRValue(buf, rvalue); ok {
|
||||
key = string(buf.B)
|
||||
}
|
||||
putBuf(buf)
|
||||
return
|
||||
}
|
||||
|
||||
// AppendFromParts generates key string into provided buffer, from individual key parts.
|
||||
func (kgen *KeyGen[T]) AppendFromParts(buf *byteutil.Buffer, parts ...any) bool {
|
||||
if len(parts) != len(kgen.fields) {
|
||||
// User must provide correct number of parts for key.
|
||||
panicf("incorrect number key parts: want=%d received=%d",
|
||||
len(parts),
|
||||
len(kgen.fields),
|
||||
)
|
||||
}
|
||||
|
||||
if kgen.zero {
|
||||
// Zero values are permitted,
|
||||
// mangle all values and ignore
|
||||
// zero value return booleans.
|
||||
for i, part := range parts {
|
||||
|
||||
// Mangle this value into buffer.
|
||||
_ = kgen.fields[i].Mangle(buf, part)
|
||||
|
||||
// Append part separator.
|
||||
buf.B = append(buf.B, '.')
|
||||
}
|
||||
} else {
|
||||
// Zero values are NOT permitted.
|
||||
for i, part := range parts {
|
||||
|
||||
// Mangle this value into buffer.
|
||||
z := kgen.fields[i].Mangle(buf, part)
|
||||
|
||||
if z {
|
||||
// The value was zero for
|
||||
// this type, return early.
|
||||
return false
|
||||
}
|
||||
|
||||
// Append part separator.
|
||||
buf.B = append(buf.B, '.')
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the last separator.
|
||||
buf.B = buf.B[:len(buf.B)-1]
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// AppendFromValue generates key string into provided buffer, from a value via reflection.
|
||||
func (kgen *KeyGen[T]) AppendFromValue(buf *byteutil.Buffer, value T) bool {
|
||||
return kgen.appendFromRValue(buf, reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
// appendFromRValue is the underlying generator function for the exported ___FromValue() functions,
|
||||
// accepting a reflected input. We do not expose this as the reflected value is EXPECTED to be right.
|
||||
func (kgen *KeyGen[T]) appendFromRValue(buf *byteutil.Buffer, rvalue reflect.Value) bool {
|
||||
// Follow any ptrs leading to value.
|
||||
for rvalue.Kind() == reflect.Pointer {
|
||||
rvalue = rvalue.Elem()
|
||||
}
|
||||
|
||||
if kgen.zero {
|
||||
// Zero values are permitted,
|
||||
// mangle all values and ignore
|
||||
// zero value return booleans.
|
||||
for i := range kgen.fields {
|
||||
|
||||
// Get the reflect value's field at idx.
|
||||
fv := rvalue.FieldByIndex(kgen.fields[i].index)
|
||||
fi := fv.Interface()
|
||||
|
||||
// Mangle this value into buffer.
|
||||
_ = kgen.fields[i].Mangle(buf, fi)
|
||||
|
||||
// Append part separator.
|
||||
buf.B = append(buf.B, '.')
|
||||
}
|
||||
} else {
|
||||
// Zero values are NOT permitted.
|
||||
for i := range kgen.fields {
|
||||
|
||||
// Get the reflect value's field at idx.
|
||||
fv := rvalue.FieldByIndex(kgen.fields[i].index)
|
||||
fi := fv.Interface()
|
||||
|
||||
// Mangle this value into buffer.
|
||||
z := kgen.fields[i].Mangle(buf, fi)
|
||||
|
||||
if z {
|
||||
// The value was zero for
|
||||
// this type, return early.
|
||||
return false
|
||||
}
|
||||
|
||||
// Append part separator.
|
||||
buf.B = append(buf.B, '.')
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the last separator.
|
||||
buf.B = buf.B[:len(buf.B)-1]
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type structfield struct {
|
||||
// index is the reflected index
|
||||
// of this field (this takes into
|
||||
// account struct nesting).
|
||||
index []int
|
||||
|
||||
// zero is the possible mangled
|
||||
// zero value for this field.
|
||||
zero string
|
||||
|
||||
// mangler is the mangler function for
|
||||
// serializing values of this field.
|
||||
mangler mangler.Mangler
|
||||
}
|
||||
|
||||
// Mangle mangles the given value, using the determined type-appropriate
|
||||
// field's type. The returned boolean indicates whether this is a zero value.
|
||||
func (f *structfield) Mangle(buf *byteutil.Buffer, value any) (isZero bool) {
|
||||
s := len(buf.B) // start pos.
|
||||
buf.B = f.mangler(buf.B, value)
|
||||
e := len(buf.B) // end pos.
|
||||
isZero = (f.zero == string(buf.B[s:e]))
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user