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 | 147 |
1 files changed, 81 insertions, 66 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 index cf86c7c30..5e10e6fa1 100644 --- a/vendor/codeberg.org/gruf/go-cache/v3/result/key.go +++ b/vendor/codeberg.org/gruf/go-cache/v3/result/key.go @@ -47,27 +47,32 @@ func (sk structKeys) generate(a any) []cacheKey { buf := getBuf() defer putBuf(buf) +outer: for i := range sk { // Reset buffer - buf.B = buf.B[:0] + buf.Reset() // Append each field value to buffer. for _, field := range sk[i].fields { fv := v.Field(field.index) fi := fv.Interface() - buf.B = field.mangle(buf.B, fi) + + // 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) - // Don't generate keys for zero values - if allowZero := sk[i].zero == ""; // nocollapse - !allowZero && buf.String() == sk[i].zero { - continue - } - // Append new cached key to slice keys = append(keys, cacheKey{ info: &sk[i], @@ -114,14 +119,6 @@ type structKey struct { // period ('.') separated struct field names. name string - // zero is the possible zero value for this key. - // if set, this will _always_ be non-empty, as - // the mangled cache key will never be empty. - // - // i.e. zero = "" --> allow zero value keys - // zero != "" --> don't allow zero value keys - zero string - // unique determines whether this structKey supports // multiple or just the singular unique result. unique bool @@ -135,47 +132,10 @@ type structKey struct { pkeys map[string][]int64 } -type structField struct { - // index is the reflect index of this struct field. - index int - - // mangle is the mangler function for - // serializing values of this struct field. - mangle mangler.Mangler -} - -// 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 byte buffer - buf := getBuf() - defer putBuf(buf) - buf.Reset() - - // Encode each key part - for i, part := range parts { - buf.B = sk.fields[i].mangle(buf.B, part) - buf.B = append(buf.B, '.') - } - - // Drop last '.' - buf.Truncate(1) - - // Return string copy - return string(buf.B) -} - // 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 - zeros []any - ) + var sk structKey // Set the lookup name sk.name = lk.Name @@ -183,9 +143,6 @@ func newStructKey(lk Lookup, t reflect.Type) structKey { // Split dot-separated lookup to get // the individual struct field names names := strings.Split(lk.Name, ".") - if len(names) == 0 { - panic("no key fields specified") - } // Allocate the mangler and field indices slice. sk.fields = make([]structField, len(names)) @@ -213,16 +170,12 @@ func newStructKey(lk Lookup, t reflect.Type) structKey { sk.fields[i].mangle = mangler.Get(ft.Type) if !lk.AllowZero { - // Append the zero value interface - zeros = append(zeros, v.Interface()) + // Append the mangled zero value interface + zero := sk.fields[i].mangle(nil, v.Interface()) + sk.fields[i].zero = string(zero) } } - if len(zeros) > 0 { - // Generate zero value string - sk.zero = sk.genKey(zeros) - } - // Set unique lookup flag. sk.unique = !lk.Multi @@ -232,6 +185,68 @@ func newStructKey(lk Lookup, t reflect.Type) structKey { 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 byte buffer + buf := getBuf() + defer putBuf(buf) + 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) + + // Return string copy + return string(buf.B) +} + +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) @@ -246,12 +261,12 @@ var bufPool = sync.Pool{ }, } -// getBuf ... +// getBuf acquires a byte buffer from memory pool. func getBuf() *byteutil.Buffer { return bufPool.Get().(*byteutil.Buffer) } -// putBuf ... +// putBuf replaces a byte buffer back in memory pool. func putBuf(buf *byteutil.Buffer) { if buf.Cap() > int(^uint16(0)) { return // drop large bufs |