diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-structr/runtime.go')
| -rw-r--r-- | vendor/codeberg.org/gruf/go-structr/runtime.go | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/vendor/codeberg.org/gruf/go-structr/runtime.go b/vendor/codeberg.org/gruf/go-structr/runtime.go index 6e8af83dd..cd7f8d7a1 100644 --- a/vendor/codeberg.org/gruf/go-structr/runtime.go +++ b/vendor/codeberg.org/gruf/go-structr/runtime.go @@ -1,3 +1,5 @@ +//go:build go1.22 || go1.23 + package structr import ( @@ -36,6 +38,11 @@ type struct_field struct { // offsets defines whereabouts in // memory this field is located. offsets []next_offset + + // determines whether field type + // is ptr-like in-memory, and so + // requires a further dereference. + likeptr bool } // next_offset defines a next offset location @@ -107,6 +114,9 @@ func find_field(t reflect.Type, names []string) (sfield struct_field) { t = field.Type } + // Check if ptr-like in-memory. + sfield.likeptr = like_ptr(t) + // Set final type. sfield.rtype = t @@ -126,10 +136,14 @@ func find_field(t reflect.Type, names []string) (sfield struct_field) { // extract_fields extracts given structfields from the provided value type, // this is done using predetermined struct field memory offset locations. func extract_fields(ptr unsafe.Pointer, fields []struct_field) []unsafe.Pointer { + // Prepare slice of field value pointers. ptrs := make([]unsafe.Pointer, len(fields)) - for i, field := range fields { + if len(ptrs) != len(fields) { + panic("BCE") + } + for i, field := range fields { // loop scope. fptr := ptr @@ -145,7 +159,7 @@ func extract_fields(ptr unsafe.Pointer, fields []struct_field) []unsafe.Pointer offset.offset) } - if like_ptr(field.rtype) && fptr != nil { + if field.likeptr && fptr != nil { // Further dereference value ptr. fptr = *(*unsafe.Pointer)(fptr) } @@ -162,9 +176,63 @@ func extract_fields(ptr unsafe.Pointer, fields []struct_field) []unsafe.Pointer return ptrs } -// like_ptr returns whether type's kind is ptr-like. +// pkey_field contains pre-prepared type +// information about a primary key struct's +// field member, including memory offset. +type pkey_field struct { + rtype reflect.Type + + // offsets defines whereabouts in + // memory this field is located. + offsets []next_offset + + // determines whether field type + // is ptr-like in-memory, and so + // requires a further dereference. + likeptr bool +} + +// extract_pkey will extract a pointer from 'ptr', to +// the primary key struct field defined by 'field'. +func extract_pkey(ptr unsafe.Pointer, field pkey_field) unsafe.Pointer { + for _, offset := range field.offsets { + // Dereference any ptrs to offset. + ptr = deref(ptr, offset.derefs) + if ptr == nil { + return nil + } + + // Jump forward by offset to next ptr. + ptr = unsafe.Pointer(uintptr(ptr) + + offset.offset) + } + + if field.likeptr && ptr != nil { + // Further dereference value ptr. + ptr = *(*unsafe.Pointer)(ptr) + } + + return ptr +} + +// like_ptr returns whether type's kind is ptr-like in-memory, +// which indicates it may need a final additional dereference. func like_ptr(t reflect.Type) bool { switch t.Kind() { + case reflect.Array: + switch n := t.Len(); n { + case 1: + // specifically single elem arrays + // follow like_ptr for contained type. + return like_ptr(t.Elem()) + } + case reflect.Struct: + switch n := t.NumField(); n { + case 1: + // specifically single field structs + // follow like_ptr for contained type. + return like_ptr(t.Field(0).Type) + } case reflect.Pointer, reflect.Map, reflect.Chan, @@ -201,7 +269,7 @@ func panicf(format string, args ...any) { // else it prints callsite info with a BUG report. // //go:noinline -func should_not_reach() { +func should_not_reach(exit bool) { pcs := make([]uintptr, 1) _ = runtime.Callers(2, pcs) fn := runtime.FuncForPC(pcs[0]) @@ -212,5 +280,9 @@ func should_not_reach() { funcname = funcname[i+1:] } } - os.Stderr.WriteString("BUG: assertion failed in " + funcname + "\n") + if exit { + panic("BUG: assertion failed in " + funcname) + } else { + os.Stderr.WriteString("BUG: assertion failed in " + funcname + "\n") + } } |
