mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-04 03:52:24 -06:00 
			
		
		
		
	
		
			
	
	
		
			151 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			151 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package mangler
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"reflect"
							 | 
						||
| 
								 | 
							
									"unsafe"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"codeberg.org/gruf/go-xunsafe"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// loadOrStore first checks the cache for a Mangler
							 | 
						||
| 
								 | 
							
								// function, else generates one by calling get().
							 | 
						||
| 
								 | 
							
								// note: this does store generated funcs in cache.
							 | 
						||
| 
								 | 
							
								func loadOrStore(t xunsafe.TypeIter) Mangler {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get cache key.
							 | 
						||
| 
								 | 
							
									key := t.TypeInfo
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Check cache for func.
							 | 
						||
| 
								 | 
							
									fn := manglers.Get(key)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if fn == nil {
							 | 
						||
| 
								 | 
							
										// Generate new mangler
							 | 
						||
| 
								 | 
							
										// func for this type.
							 | 
						||
| 
								 | 
							
										fn = get(t)
							 | 
						||
| 
								 | 
							
										if fn == nil {
							 | 
						||
| 
								 | 
							
											return nil
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Store func in cache.
							 | 
						||
| 
								 | 
							
										manglers.Put(key, fn)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return fn
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// loadOrGet first checks the cache for a Mangler
							 | 
						||
| 
								 | 
							
								// function, else generates one by calling get().
							 | 
						||
| 
								 | 
							
								// note: it does not store the function in cache.
							 | 
						||
| 
								 | 
							
								func loadOrGet(t xunsafe.TypeIter) Mangler {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Check cache for mangler func.
							 | 
						||
| 
								 | 
							
									fn := manglers.Get(t.TypeInfo)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if fn == nil {
							 | 
						||
| 
								 | 
							
										// Generate new mangler
							 | 
						||
| 
								 | 
							
										// func for this type.
							 | 
						||
| 
								 | 
							
										fn = get(t)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return fn
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var (
							 | 
						||
| 
								 | 
							
									// reflectTypeType is the reflected type of the reflect type,
							 | 
						||
| 
								 | 
							
									// used in fmt.get() to prevent iter of internal ABI structs.
							 | 
						||
| 
								 | 
							
									reflectTypeType = reflect.TypeOf(reflect.TypeOf(0))
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// get attempts to generate a new Mangler function
							 | 
						||
| 
								 | 
							
								// capable of mangling a ptr of given type information.
							 | 
						||
| 
								 | 
							
								func get(t xunsafe.TypeIter) (fn Mangler) {
							 | 
						||
| 
								 | 
							
									defer func() {
							 | 
						||
| 
								 | 
							
										if fn == nil {
							 | 
						||
| 
								 | 
							
											// nothing more
							 | 
						||
| 
								 | 
							
											// we can do.
							 | 
						||
| 
								 | 
							
											return
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if t.Parent != nil {
							 | 
						||
| 
								 | 
							
											// We're only interested
							 | 
						||
| 
								 | 
							
											// in wrapping top-level.
							 | 
						||
| 
								 | 
							
											return
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Get reflected type ptr for prefix.
							 | 
						||
| 
								 | 
							
										ptr := xunsafe.ReflectTypeData(t.Type)
							 | 
						||
| 
								 | 
							
										uptr := uintptr(ptr)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Outer fn.
							 | 
						||
| 
								 | 
							
										mng := fn
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Wrap the mangler func to prepend type pointer.
							 | 
						||
| 
								 | 
							
										fn = func(buf []byte, ptr unsafe.Pointer) []byte {
							 | 
						||
| 
								 | 
							
											buf = append_uint64(buf, uint64(uptr))
							 | 
						||
| 
								 | 
							
											return mng(buf, ptr)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if t.Type == nil {
							 | 
						||
| 
								 | 
							
										// nil type.
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if t.Type == reflectTypeType {
							 | 
						||
| 
								 | 
							
										// DO NOT iterate down internal ABI
							 | 
						||
| 
								 | 
							
										// types, some are in non-GC memory.
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Check supports known method receiver.
							 | 
						||
| 
								 | 
							
									if fn := getMethodType(t); fn != nil {
							 | 
						||
| 
								 | 
							
										return fn
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if !visit(t) {
							 | 
						||
| 
								 | 
							
										// On type recursion simply
							 | 
						||
| 
								 | 
							
										// mangle as raw pointer.
							 | 
						||
| 
								 | 
							
										return mangle_int
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get func for type kind.
							 | 
						||
| 
								 | 
							
									switch t.Type.Kind() {
							 | 
						||
| 
								 | 
							
									case reflect.Pointer:
							 | 
						||
| 
								 | 
							
										return derefPointerType(t)
							 | 
						||
| 
								 | 
							
									case reflect.Struct:
							 | 
						||
| 
								 | 
							
										return iterStructType(t)
							 | 
						||
| 
								 | 
							
									case reflect.Array:
							 | 
						||
| 
								 | 
							
										return iterArrayType(t)
							 | 
						||
| 
								 | 
							
									case reflect.Slice:
							 | 
						||
| 
								 | 
							
										return iterSliceType(t)
							 | 
						||
| 
								 | 
							
									case reflect.Map:
							 | 
						||
| 
								 | 
							
										return iterMapType(t)
							 | 
						||
| 
								 | 
							
									case reflect.String:
							 | 
						||
| 
								 | 
							
										return mangle_string
							 | 
						||
| 
								 | 
							
									case reflect.Bool:
							 | 
						||
| 
								 | 
							
										return mangle_bool
							 | 
						||
| 
								 | 
							
									case reflect.Int,
							 | 
						||
| 
								 | 
							
										reflect.Uint,
							 | 
						||
| 
								 | 
							
										reflect.Uintptr:
							 | 
						||
| 
								 | 
							
										return mangle_int
							 | 
						||
| 
								 | 
							
									case reflect.Int8, reflect.Uint8:
							 | 
						||
| 
								 | 
							
										return mangle_8bit
							 | 
						||
| 
								 | 
							
									case reflect.Int16, reflect.Uint16:
							 | 
						||
| 
								 | 
							
										return mangle_16bit
							 | 
						||
| 
								 | 
							
									case reflect.Int32, reflect.Uint32:
							 | 
						||
| 
								 | 
							
										return mangle_32bit
							 | 
						||
| 
								 | 
							
									case reflect.Int64, reflect.Uint64:
							 | 
						||
| 
								 | 
							
										return mangle_64bit
							 | 
						||
| 
								 | 
							
									case reflect.Float32:
							 | 
						||
| 
								 | 
							
										return mangle_32bit
							 | 
						||
| 
								 | 
							
									case reflect.Float64:
							 | 
						||
| 
								 | 
							
										return mangle_64bit
							 | 
						||
| 
								 | 
							
									case reflect.Complex64:
							 | 
						||
| 
								 | 
							
										return mangle_64bit
							 | 
						||
| 
								 | 
							
									case reflect.Complex128:
							 | 
						||
| 
								 | 
							
										return mangle_128bit
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										return nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |