diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-cache/v3/result/key.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-cache/v3/result/key.go | 282 |
1 files changed, 0 insertions, 282 deletions
diff --git a/vendor/codeberg.org/gruf/go-cache/v3/result/key.go b/vendor/codeberg.org/gruf/go-cache/v3/result/key.go deleted file mode 100644 index 5508936ba..000000000 --- a/vendor/codeberg.org/gruf/go-cache/v3/result/key.go +++ /dev/null @@ -1,282 +0,0 @@ -package result - -import ( - "fmt" - "reflect" - "strings" - "sync" - "unicode" - "unicode/utf8" - - "codeberg.org/gruf/go-byteutil" - "codeberg.org/gruf/go-mangler" -) - -// structKeys provides convience methods for a list -// of structKey field combinations used for cache keys. -type structKeys []structKey - -// get fetches the structKey info for given lookup name (else, panics). -func (sk structKeys) get(name string) *structKey { - for i := range sk { - if sk[i].name == name { - return &sk[i] - } - } - panic("unknown lookup: \"" + name + "\"") -} - -// generate will calculate and produce a slice of cache keys the given value -// can be stored under in the, as determined by receiving struct keys. -func (sk structKeys) generate(a any) []cacheKey { - var keys []cacheKey - - // Get reflected value in order - // to access the struct fields - v := reflect.ValueOf(a) - - // Iteratively deref pointer value - for v.Kind() == reflect.Pointer { - if v.IsNil() { - panic("nil ptr") - } - v = v.Elem() - } - - // Acquire buffer - buf := getBuf() - -outer: - for i := range sk { - // Reset buffer - buf.Reset() - - // Append each field value to buffer. - for _, field := range sk[i].fields { - fv := v.Field(field.index) - fi := fv.Interface() - - // Mangle this key part into buffer. - ok := field.manglePart(buf, fi) - - if !ok { - // don't generate keys - // for zero value parts. - continue outer - } - - // Append part separator. - buf.B = append(buf.B, '.') - } - - // Drop last '.' - buf.Truncate(1) - - // Append new cached key to slice - keys = append(keys, cacheKey{ - info: &sk[i], - key: string(buf.B), // copy - }) - } - - // Release buf - putBuf(buf) - - return keys -} - -type cacheKeys []cacheKey - -// drop will drop the cachedKey with lookup name from receiving cacheKeys slice. -func (ck *cacheKeys) drop(name string) { - _ = *ck // move out of loop - for i := range *ck { - if (*ck)[i].info.name == name { - (*ck) = append((*ck)[:i], (*ck)[i+1:]...) - break - } - } -} - -// cacheKey represents an actual cached key. -type cacheKey struct { - // info is a reference to the structKey this - // cacheKey is representing. This is a shared - // reference and as such only the structKey.pkeys - // lookup map is expecting to be modified. - info *structKey - - // value is the actual string representing - // this cache key for hashmap lookups. - key string -} - -// structKey represents a list of struct fields -// encompassing a single cache key, the string name -// of the lookup, the lookup map to primary cache -// keys, and the key's possible zero value string. -type structKey struct { - // name is the provided cache lookup name for - // this particular struct key, consisting of - // period ('.') separated struct field names. - name string - - // unique determines whether this structKey supports - // multiple or just the singular unique result. - unique bool - - // fields is a slice of runtime struct field - // indices, of fields encompassed by this key. - fields []structField - - // pkeys is a lookup of stored struct key values - // to the primary cache lookup key (int64). this - // is protected by the main cache mutex. - pkeys map[string][]int64 -} - -// newStructKey will generate a structKey{} information object for user-given lookup -// key information, and the receiving generic paramter's type information. Panics on error. -func newStructKey(lk Lookup, t reflect.Type) structKey { - var sk structKey - - // Set the lookup name - sk.name = lk.Name - - // Split dot-separated lookup to get - // the individual struct field names - names := strings.Split(lk.Name, ".") - - // Allocate the mangler and field indices slice. - sk.fields = make([]structField, len(names)) - - for i, name := range names { - // Get field info for given name - ft, ok := t.FieldByName(name) - if !ok { - panic("no field found for name: \"" + name + "\"") - } - - // Check field is usable - if !isExported(name) { - panic("field must be exported") - } - - // Set the runtime field index - sk.fields[i].index = ft.Index[0] - - // Allocate new instance of field - v := reflect.New(ft.Type) - v = v.Elem() - - // Fetch mangler for field type. - sk.fields[i].mangle = mangler.Get(ft.Type) - - if !lk.AllowZero { - // Append the mangled zero value interface - zero := sk.fields[i].mangle(nil, v.Interface()) - sk.fields[i].zero = string(zero) - } - } - - // Set unique lookup flag. - sk.unique = !lk.Multi - - // Allocate primary lookup map - sk.pkeys = make(map[string][]int64) - - return sk -} - -// genKey generates a cache key string for given key parts (i.e. serializes them using "go-mangler"). -func (sk *structKey) genKey(parts []any) string { - // Check this expected no. key parts. - if len(parts) != len(sk.fields) { - panic(fmt.Sprintf("incorrect no. key parts provided: want=%d received=%d", len(parts), len(sk.fields))) - } - - // Acquire buffer - buf := getBuf() - buf.Reset() - - for i, part := range parts { - // Mangle this key part into buffer. - // specifically ignoring whether this - // is returning a zero value key part. - _ = sk.fields[i].manglePart(buf, part) - - // Append part separator. - buf.B = append(buf.B, '.') - } - - // Drop last '.' - buf.Truncate(1) - - // Create str copy - str := string(buf.B) - - // Release buf - putBuf(buf) - - return str -} - -type structField struct { - // index is the reflect index of this struct field. - index int - - // zero is the possible zero value for this - // key part. if set, this will _always_ be - // non-empty due to how the mangler works. - // - // i.e. zero = "" --> allow zero value keys - // zero != "" --> don't allow zero value keys - zero string - - // mangle is the mangler function for - // serializing values of this struct field. - mangle mangler.Mangler -} - -// manglePart ... -func (field *structField) manglePart(buf *byteutil.Buffer, part any) bool { - // Start of part bytes. - start := len(buf.B) - - // Mangle this key part into buffer. - buf.B = field.mangle(buf.B, part) - - // End of part bytes. - end := len(buf.B) - - // Return whether this is zero value. - return (field.zero == "" || - string(buf.B[start:end]) != field.zero) -} - -// isExported checks whether function name is exported. -func isExported(fnName string) bool { - r, _ := utf8.DecodeRuneInString(fnName) - return unicode.IsUpper(r) -} - -// bufpool provides a memory pool of byte -// buffers use when encoding key types. -var bufPool = sync.Pool{ - New: func() any { - return &byteutil.Buffer{B: make([]byte, 0, 512)} - }, -} - -// getBuf acquires a byte buffer from memory pool. -func getBuf() *byteutil.Buffer { - return bufPool.Get().(*byteutil.Buffer) -} - -// putBuf replaces a byte buffer back in memory pool. -func putBuf(buf *byteutil.Buffer) { - if buf.Cap() > int(^uint16(0)) { - return // drop large bufs - } - bufPool.Put(buf) -} |