goki.dev/laser@v0.1.34/ptrs_test.go (about)

     1  // Copyright (c) 2023, The Goki Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package laser
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  	"unsafe"
    11  )
    12  
    13  // structs are in embeds_test.go
    14  
    15  type PtrTstSub struct {
    16  	Mbr1 string
    17  	Mbr2 int
    18  }
    19  
    20  type PtrTst struct {
    21  	Mbr1     string
    22  	Mbr2     int
    23  	SubField PtrTstSub
    24  }
    25  
    26  var pt = PtrTst{}
    27  
    28  func InitPtrTst() {
    29  	pt.Mbr1 = "mbr1 string"
    30  	pt.Mbr2 = 2
    31  }
    32  
    33  func FieldValue(obj any, fld reflect.StructField) reflect.Value {
    34  	ov := reflect.ValueOf(obj)
    35  	f := unsafe.Pointer(ov.Pointer() + fld.Offset)
    36  	nw := reflect.NewAt(fld.Type, f)
    37  	return UnhideAnyValue(nw).Elem()
    38  }
    39  
    40  func SubFieldValue(obj any, fld reflect.StructField, sub reflect.StructField) reflect.Value {
    41  	ov := reflect.ValueOf(obj)
    42  	f := unsafe.Pointer(ov.Pointer() + fld.Offset + sub.Offset)
    43  	nw := reflect.NewAt(sub.Type, f)
    44  	return UnhideAnyValue(nw).Elem()
    45  }
    46  
    47  // test ability to create an addressable pointer value to fields of a struct
    48  func TestNewAt(t *testing.T) {
    49  	InitPtrTst()
    50  	typ := reflect.TypeOf(pt)
    51  	fld, _ := typ.FieldByName("Mbr2")
    52  	vf := FieldValue(&pt, fld)
    53  
    54  	// fmt.Printf("Fld: %v Typ: %v vf: %v vfi: %v vfT: %v vfp: %v canaddr: %v canset: %v caninterface: %v\n", fld.Name, vf.Type().String(), vf.String(), vf.Interface(), vf.Interface(), vf.Interface(), vf.CanAddr(), vf.CanSet(), vf.CanInterface())
    55  
    56  	vf.Elem().Set(reflect.ValueOf(int(10)))
    57  
    58  	if pt.Mbr2 != 10 {
    59  		t.Errorf("Mbr2 should be 10, is: %v\n", pt.Mbr2)
    60  	}
    61  
    62  	fld, _ = typ.FieldByName("Mbr1")
    63  	vf = FieldValue(&pt, fld)
    64  
    65  	// fmt.Printf("Fld: %v Typ: %v vf: %v vfi: %v vfT: %v vfp: %v canaddr: %v canset: %v caninterface: %v\n", fld.Name, vf.Type().String(), vf.String(), vf.Interface(), vf.Interface(), vf.Interface(), vf.CanAddr(), vf.CanSet(), vf.CanInterface())
    66  
    67  	vf.Elem().Set(reflect.ValueOf("this is a new string"))
    68  
    69  	if pt.Mbr1 != "this is a new string" {
    70  		t.Errorf("Mbr1 should be 'this is a new string': %v\n", pt.Mbr1)
    71  	}
    72  }