mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 23:52:26 -06:00 
			
		
		
		
	
		
			
	
	
		
			76 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			76 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package mangler
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"unsafe"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"codeberg.org/gruf/go-xunsafe"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// field stores the minimum necessary
							 | 
						||
| 
								 | 
							
								// data for iterating and mangling
							 | 
						||
| 
								 | 
							
								// each field in a given struct.
							 | 
						||
| 
								 | 
							
								type field struct {
							 | 
						||
| 
								 | 
							
									mangle Mangler
							 | 
						||
| 
								 | 
							
									offset uintptr
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// iterStructType returns a Mangler capable of iterating
							 | 
						||
| 
								 | 
							
								// and mangling the given struct type currently in TypeIter{}.
							 | 
						||
| 
								 | 
							
								// note this will fetch sub-Manglers for each struct field.
							 | 
						||
| 
								 | 
							
								func iterStructType(t xunsafe.TypeIter) Mangler {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Number of struct fields.
							 | 
						||
| 
								 | 
							
									n := t.Type.NumField()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Gather mangler functions.
							 | 
						||
| 
								 | 
							
									fields := make([]field, n)
							 | 
						||
| 
								 | 
							
									for i := 0; i < n; i++ {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Get struct field at index.
							 | 
						||
| 
								 | 
							
										sfield := t.Type.Field(i)
							 | 
						||
| 
								 | 
							
										rtype := sfield.Type
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Get nested field TypeIter with appropriate flags.
							 | 
						||
| 
								 | 
							
										flags := xunsafe.ReflectStructFieldFlags(t.Flag, rtype)
							 | 
						||
| 
								 | 
							
										ft := t.Child(sfield.Type, flags)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Get field mangler.
							 | 
						||
| 
								 | 
							
										fn := loadOrGet(ft)
							 | 
						||
| 
								 | 
							
										if fn == nil {
							 | 
						||
| 
								 | 
							
											return nil
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Set field info.
							 | 
						||
| 
								 | 
							
										fields[i] = field{
							 | 
						||
| 
								 | 
							
											mangle: fn,
							 | 
						||
| 
								 | 
							
											offset: sfield.Offset,
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Handle no. fields.
							 | 
						||
| 
								 | 
							
									switch len(fields) {
							 | 
						||
| 
								 | 
							
									case 0:
							 | 
						||
| 
								 | 
							
										return empty_mangler
							 | 
						||
| 
								 | 
							
									case 1:
							 | 
						||
| 
								 | 
							
										return fields[0].mangle
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										return func(buf []byte, ptr unsafe.Pointer) []byte {
							 | 
						||
| 
								 | 
							
											for i := range fields {
							 | 
						||
| 
								 | 
							
												// Get struct field ptr via offset.
							 | 
						||
| 
								 | 
							
												fptr := add(ptr, fields[i].offset)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Mangle the struct field data.
							 | 
						||
| 
								 | 
							
												buf = fields[i].mangle(buf, fptr)
							 | 
						||
| 
								 | 
							
												buf = append(buf, ',')
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if len(fields) > 0 {
							 | 
						||
| 
								 | 
							
												// Drop final comma.
							 | 
						||
| 
								 | 
							
												buf = buf[:len(buf)-1]
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return buf
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |