summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-mangler/mangle.go
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2024-04-02 11:03:40 +0100
committerLibravatar GitHub <noreply@github.com>2024-04-02 12:03:40 +0200
commitadf345f1ec0cb76a0df94a4505143d891659cba9 (patch)
treee0cca289c0a50f30191d4b65a2c336704570e470 /vendor/codeberg.org/gruf/go-mangler/mangle.go
parent[feature] Option to hide followers/following (#2788) (diff)
downloadgotosocial-adf345f1ec0cb76a0df94a4505143d891659cba9.tar.xz
[chore] bump go structr cache version -> v0.6.0 (#2773)
* update go-structr library -> v0.6.0, add necessary wrapping types + code changes to support these changes * update readme with go-structr package changes * improved wrapping of the SliceCache type * add code comments for the cache wrapper types * remove test.out :innocent: --------- Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-mangler/mangle.go')
-rw-r--r--vendor/codeberg.org/gruf/go-mangler/mangle.go154
1 files changed, 154 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..b44d26dc5
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-mangler/mangle.go
@@ -0,0 +1,154 @@
+package mangler
+
+import (
+ "reflect"
+ "sync"
+ "unsafe"
+)
+
+// manglers is a map of runtime
+// type ptrs => Mangler functions.
+var manglers sync.Map
+
+// 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
+
+// Get will fetch the Mangler function for given runtime type.
+// Note that the returned mangler will be a no-op in the case
+// that an incorrect type is passed as the value argument.
+func Get(t reflect.Type) Mangler {
+ var mng Mangler
+
+ // Get raw runtime type ptr
+ uptr := uintptr(eface_data(t))
+
+ // Look for a cached mangler
+ v, ok := manglers.Load(uptr)
+
+ if !ok {
+ // Load mangler function
+ mng = loadMangler(nil, t)
+ } else {
+ // cast cached value
+ mng = v.(Mangler)
+ }
+
+ // Get platform int mangler func.
+ mangle_int := mangle_platform_int()
+
+ return func(buf []byte, value any) []byte {
+ // Type check passed against original type.
+ if vt := reflect.TypeOf(value); vt != t {
+ return buf
+ }
+
+ // First write the type ptr (this adds
+ // a unique prefix for each runtime type).
+ buf = mangle_int(buf, uptr)
+
+ // Finally, mangle value
+ return mng(buf, value)
+ }
+}
+
+// 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(eface_data(t))
+
+ // Ensure this is a unique encoder
+ if _, ok := manglers.Load(uptr); ok {
+ panic("already registered mangler for type: " + t.String())
+ }
+
+ // Cache this encoder func
+ manglers.Store(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 {
+ var mng Mangler
+
+ // Get reflect type of 'a'
+ t := reflect.TypeOf(a)
+
+ // Get raw runtime type ptr
+ uptr := uintptr(eface_data(t))
+
+ // Look for a cached mangler
+ v, ok := manglers.Load(uptr)
+
+ if !ok {
+ // Load mangler into cache
+ mng = loadMangler(nil, t)
+ manglers.Store(uptr, mng)
+ } else {
+ // cast cached value
+ mng = v.(Mangler)
+ }
+
+ // Get platform int mangler func.
+ mangle_int := mangle_platform_int()
+
+ // First write the type ptr (this adds
+ // a unique prefix for each runtime type).
+ b = mangle_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
+// - arbitrary structs
+// - all type aliases of above
+// - time.Time{}
+// - url.URL{}
+// - net.IPAddr{}
+// - netip.Addr{}, netip.AddrPort{}
+// - mangler.Mangled{}
+// - fmt.Stringer{}
+// - json.Marshaler{}
+// - encoding.BinaryMarshaler{}
+// - encoding.TextMarshaler{}
+// - 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))
+}