summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-mangler/mangle.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2022-11-11 12:18:38 +0100
committerLibravatar GitHub <noreply@github.com>2022-11-11 12:18:38 +0100
commitedcee14d07bae129e2d1a06d99c30fc6f659ff5e (patch)
tree5b9d605654347fe104c55bf4b0e7fb1e1533e2a0 /vendor/codeberg.org/gruf/go-mangler/mangle.go
parent[feature] S3: add config flag to proxy S3 media (#1014) (diff)
downloadgotosocial-edcee14d07bae129e2d1a06d99c30fc6f659ff5e.tar.xz
[feature] Read + Write tombstones for deleted Actors (#1005)
* [feature] Read + Write tombstones for deleted Actors * copyTombstone * update to use resultcache instead of old ttl cache Signed-off-by: kim <grufwub@gmail.com> * update go-cache library to fix result cache capacity / ordering bugs Signed-off-by: kim <grufwub@gmail.com> * bump go-cache/v3 to v3.1.6 to fix bugs Signed-off-by: kim <grufwub@gmail.com> * switch on status code * better explain ErrGone reasoning Signed-off-by: kim <grufwub@gmail.com> Co-authored-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-mangler/mangle.go')
-rw-r--r--vendor/codeberg.org/gruf/go-mangler/mangle.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-mangler/mangle.go b/vendor/codeberg.org/gruf/go-mangler/mangle.go
new file mode 100644
index 000000000..7158893ae
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-mangler/mangle.go
@@ -0,0 +1,132 @@
+package mangler
+
+import (
+ "encoding/binary"
+ "reflect"
+ "unsafe"
+
+ "github.com/cespare/xxhash"
+ "github.com/cornelk/hashmap"
+)
+
+var (
+ // manglers is a map of runtime type ptrs => Mangler functions.
+ manglers = hashmap.New[uintptr, Mangler]()
+
+ // bin is a short-hand for our chosen byteorder encoding.
+ bin = binary.LittleEndian
+)
+
+// Mangled is an interface that allows any type to implement a custom
+// Mangler function to improve performance when mangling this type.
+type Mangled interface {
+ Mangle(buf []byte) []byte
+}
+
+// Mangler is a function that will take an input interface value of known
+// type, and append it in mangled serialized form to the given byte buffer.
+// While the value type is an interface, the Mangler functions are accessed
+// by the value's runtime type pointer, allowing the input value type to be known.
+type Mangler func(buf []byte, value any) []byte
+
+// rMangler is functionally the same as a Mangler function, but it
+// takes the value input in reflected form. By specifying these differences
+// in mangler function types, it allows us to cut back on new calls to
+// `reflect.ValueOf()` and instead pass by existing reflected values.
+type rMangler func(buf []byte, value reflect.Value) []byte
+
+// Get will fetch the Mangler function for given runtime type.
+func Get(t reflect.Type) (Mangler, bool) {
+ if t == nil {
+ return nil, false
+ }
+ uptr := uintptr(iface_value(t))
+ return manglers.Get(uptr)
+}
+
+// Register will register the given Mangler function for use with vars of given runtime type. This allows
+// registering performant manglers for existing types not implementing Mangled (e.g. std library types).
+// NOTE: panics if there already exists a Mangler function for given type. Register on init().
+func Register(t reflect.Type, m Mangler) {
+ if t == nil {
+ // Nil interface{} types cannot be searched by, do not accept
+ panic("cannot register mangler for nil interface{} type")
+ }
+
+ // Get raw runtime type ptr
+ uptr := uintptr(iface_value(t))
+
+ // Ensure this is a unique encoder
+ if _, ok := manglers.Get(uptr); ok {
+ panic("already registered mangler for type: " + t.String())
+ }
+
+ // Cache this encoder func
+ manglers.Set(uptr, m)
+}
+
+// Append will append the mangled form of input value 'a' to buffer 'b'.
+// See mangler.String() for more information on mangled output.
+func Append(b []byte, a any) []byte {
+ // Get reflect type of 'a'
+ t := reflect.TypeOf(a)
+
+ // Get raw runtime type ptr
+ uptr := uintptr(iface_value(t))
+
+ // Look for a cached mangler
+ mng, ok := manglers.Get(uptr)
+
+ if !ok {
+ // Load mangler into cache
+ mng = loadMangler(a, t)
+ manglers.Set(uptr, mng)
+ }
+
+ // First write the type ptr (this adds
+ // a unique prefix for each runtime type).
+ b = mangle_platform_int(b, uptr)
+
+ // Finally, mangle value
+ return mng(b, a)
+}
+
+// String will return the mangled format of input value 'a'. This
+// mangled output will be unique for all default supported input types
+// during a single runtime instance. Uniqueness cannot be guaranteed
+// between separate runtime instances (whether running concurrently, or
+// the same application running at different times).
+//
+// The exact formatting of the output data should not be relied upon,
+// only that it is unique given the above constraints. Generally though,
+// the mangled output is the binary formatted text of given input data.
+//
+// Uniqueness is guaranteed for similar input data of differing types
+// (e.g. string("hello world") vs. []byte("hello world")) by prefixing
+// mangled output with the input data's runtime type pointer.
+//
+// Default supported types include:
+// - string
+// - bool
+// - int,int8,int16,int32,int64
+// - uint,uint8,uint16,uint32,uint64,uintptr
+// - float32,float64
+// - complex64,complex128
+// - all type aliases of above
+// - time.Time{}, *url.URL{}
+// - mangler.Mangled{}
+// - encoding.BinaryMarshaler{}
+// - all pointers to the above
+// - all slices / arrays of the above
+// - all map keys / values of the above
+func String(a any) string {
+ b := Append(make([]byte, 0, 32), a)
+ return *(*string)(unsafe.Pointer(&b))
+}
+
+// Hash returns the xxHash digest of the result of mangler.Append(nil, 'a').
+func Hash(a any) uint64 {
+ b := make([]byte, 0, 32)
+ b = Append(b, a)
+ return xxhash.Sum64(b)
+}