| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | package mangler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | 	"unsafe" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func append_uint16(b []byte, u uint16) []byte { | 
					
						
							|  |  |  | 	return append(b, // LE | 
					
						
							|  |  |  | 		byte(u), | 
					
						
							|  |  |  | 		byte(u>>8), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func append_uint32(b []byte, u uint32) []byte { | 
					
						
							|  |  |  | 	return append(b, // LE | 
					
						
							|  |  |  | 		byte(u), | 
					
						
							|  |  |  | 		byte(u>>8), | 
					
						
							|  |  |  | 		byte(u>>16), | 
					
						
							|  |  |  | 		byte(u>>24), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func append_uint64(b []byte, u uint64) []byte { | 
					
						
							|  |  |  | 	return append(b, // LE | 
					
						
							|  |  |  | 		byte(u), | 
					
						
							|  |  |  | 		byte(u>>8), | 
					
						
							|  |  |  | 		byte(u>>16), | 
					
						
							|  |  |  | 		byte(u>>24), | 
					
						
							|  |  |  | 		byte(u>>32), | 
					
						
							|  |  |  | 		byte(u>>40), | 
					
						
							|  |  |  | 		byte(u>>48), | 
					
						
							|  |  |  | 		byte(u>>56), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | type typecontext struct { | 
					
						
							|  |  |  | 	ntype reflect.Type | 
					
						
							|  |  |  | 	rtype reflect.Type | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func deref_ptr_mangler(ctx typecontext, mangle Mangler, n uint) Mangler { | 
					
						
							|  |  |  | 	if mangle == nil || n == 0 { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		panic("bad input") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// Non-nested value types, | 
					
						
							|  |  |  | 	// i.e. just direct ptrs to | 
					
						
							|  |  |  | 	// primitives require one | 
					
						
							|  |  |  | 	// less dereference to ptr. | 
					
						
							|  |  |  | 	if ctx.ntype == nil { | 
					
						
							|  |  |  | 		n-- | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	return func(buf []byte, ptr unsafe.Pointer) []byte { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		// Deref n number times. | 
					
						
							|  |  |  | 		for i := n; i > 0; i-- { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if ptr == nil { | 
					
						
							|  |  |  | 				// Check for nil values | 
					
						
							|  |  |  | 				buf = append(buf, '0') | 
					
						
							|  |  |  | 				return buf | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Further deref ptr | 
					
						
							|  |  |  | 			buf = append(buf, '1') | 
					
						
							|  |  |  | 			ptr = *(*unsafe.Pointer)(ptr) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ptr == nil { | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 			// Check for nil values | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 			buf = append(buf, '0') | 
					
						
							|  |  |  | 			return buf | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		// Mangle fully deref'd | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		buf = append(buf, '1') | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		buf = mangle(buf, ptr) | 
					
						
							|  |  |  | 		return buf | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func iter_slice_mangler(ctx typecontext, mangle Mangler) Mangler { | 
					
						
							|  |  |  | 	if ctx.rtype == nil || mangle == nil { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		panic("bad input") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// memory size of elem. | 
					
						
							|  |  |  | 	esz := ctx.rtype.Size() | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	return func(buf []byte, ptr unsafe.Pointer) []byte { | 
					
						
							|  |  |  | 		// Get data as slice hdr. | 
					
						
							|  |  |  | 		hdr := (*slice_header)(ptr) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		for i := 0; i < hdr.len; i++ { | 
					
						
							|  |  |  | 			// Mangle data at slice index. | 
					
						
							|  |  |  | 			eptr := array_at(hdr.data, esz, i) | 
					
						
							|  |  |  | 			buf = mangle(buf, eptr) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 			buf = append(buf, ',') | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		if hdr.len > 0 { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 			// Drop final comma. | 
					
						
							|  |  |  | 			buf = buf[:len(buf)-1] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return buf | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func iter_array_mangler(ctx typecontext, mangle Mangler) Mangler { | 
					
						
							|  |  |  | 	if ctx.rtype == nil || mangle == nil { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		panic("bad input") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// no. array elements. | 
					
						
							|  |  |  | 	n := ctx.ntype.Len() | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// memory size of elem. | 
					
						
							|  |  |  | 	esz := ctx.rtype.Size() | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	return func(buf []byte, ptr unsafe.Pointer) []byte { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		for i := 0; i < n; i++ { | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 			// Mangle data at array index. | 
					
						
							|  |  |  | 			offset := esz * uintptr(i) | 
					
						
							|  |  |  | 			eptr := add(ptr, offset) | 
					
						
							|  |  |  | 			buf = mangle(buf, eptr) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 			buf = append(buf, ',') | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if n > 0 { | 
					
						
							|  |  |  | 			// Drop final comma. | 
					
						
							|  |  |  | 			buf = buf[:len(buf)-1] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return buf | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func iter_struct_mangler(ctx typecontext, manglers []Mangler) Mangler { | 
					
						
							|  |  |  | 	if ctx.rtype == nil || len(manglers) != ctx.rtype.NumField() { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		panic("bad input") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	type field struct { | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		offset uintptr | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		mangle Mangler | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Bundle together the fields and manglers. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	fields := make([]field, ctx.rtype.NumField()) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	for i := range fields { | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		rfield := ctx.rtype.FieldByIndex([]int{i}) | 
					
						
							|  |  |  | 		fields[i].offset = rfield.Offset | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		fields[i].mangle = manglers[i] | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		if fields[i].mangle == nil { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 			panic("bad input") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	return func(buf []byte, ptr unsafe.Pointer) []byte { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		for i := range fields { | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 			// Get struct field ptr via offset. | 
					
						
							|  |  |  | 			fptr := add(ptr, fields[i].offset) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Mangle the struct field data. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 			buf = fields[i].mangle(buf, fptr) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 			buf = append(buf, ',') | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if len(fields) > 0 { | 
					
						
							|  |  |  | 			// Drop final comma. | 
					
						
							|  |  |  | 			buf = buf[:len(buf)-1] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return buf | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | // array_at returns ptr to index in array at ptr, given element size. | 
					
						
							|  |  |  | func array_at(ptr unsafe.Pointer, esz uintptr, i int) unsafe.Pointer { | 
					
						
							|  |  |  | 	return unsafe.Pointer(uintptr(ptr) + esz*uintptr(i)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // add returns the ptr addition of starting ptr and a delta. | 
					
						
							|  |  |  | func add(ptr unsafe.Pointer, delta uintptr) unsafe.Pointer { | 
					
						
							|  |  |  | 	return unsafe.Pointer(uintptr(ptr) + delta) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type slice_header struct { | 
					
						
							|  |  |  | 	data unsafe.Pointer | 
					
						
							|  |  |  | 	len  int | 
					
						
							|  |  |  | 	cap  int | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func eface_data(a any) unsafe.Pointer { | 
					
						
							|  |  |  | 	type eface struct{ _, data unsafe.Pointer } | 
					
						
							|  |  |  | 	return (*eface)(unsafe.Pointer(&a)).data | 
					
						
							|  |  |  | } |