diff --git a/wmo/reflection.go b/wmo/reflection.go index 2997eb3..6646332 100644 --- a/wmo/reflection.go +++ b/wmo/reflection.go @@ -25,7 +25,7 @@ func (c *Coll[TData]) EnsureInitializedReflection(v TData) { m := make(map[string]fullTypeRef) - c.initFields("", rval, m, make([]int, 0)) + c.initFields("", rval.Type(), m, make([]int, 0)) c.implDataTypeMap[rval.Type()] = m } @@ -50,20 +50,17 @@ func (c *Coll[TData]) init() { c.implDataTypeMap = make(map[reflect.Type]map[string]fullTypeRef) v := reflect.ValueOf(example) - c.initFields("", v, c.dataTypeMap, make([]int, 0)) + c.initFields("", v.Type(), c.dataTypeMap, make([]int, 0)) } } -func (c *Coll[TData]) initFields(prefix string, rval reflect.Value, m map[string]fullTypeRef, idxarr []int) { - - rtyp := rval.Type() +func (c *Coll[TData]) initFields(prefix string, rtyp reflect.Type, m map[string]fullTypeRef, idxarr []int) { for i := 0; i < rtyp.NumField(); i++ { rsfield := rtyp.Field(i) - rvfield := rval.Field(i) if !rsfield.IsExported() { continue @@ -91,21 +88,21 @@ func (c *Coll[TData]) initFields(prefix string, rval reflect.Value, m map[string newIdxArr := langext.ArrCopy(idxarr) newIdxArr = append(newIdxArr, i) - if langext.InArray("inline", bsontags) && rvfield.Kind() == reflect.Struct { + if langext.InArray("inline", bsontags) && rsfield.Type.Kind() == reflect.Struct { // pass-through field - c.initFields(prefix, rvfield, m, newIdxArr) + c.initFields(prefix, rsfield.Type, m, newIdxArr) } else { - if rvfield.Type().Kind() == reflect.Pointer { + if rsfield.Type.Kind() == reflect.Pointer { m[fullKey] = fullTypeRef{ IsPointer: true, - RealType: rvfield.Type(), - Kind: rvfield.Type().Elem().Kind(), - Type: rvfield.Type().Elem(), - UnderlyingType: reflectext.Underlying(rvfield.Type().Elem()), + RealType: rsfield.Type, + Kind: rsfield.Type.Elem().Kind(), + Type: rsfield.Type.Elem(), + UnderlyingType: reflectext.Underlying(rsfield.Type.Elem()), Name: rsfield.Name, Index: newIdxArr, } @@ -114,20 +111,23 @@ func (c *Coll[TData]) initFields(prefix string, rval reflect.Value, m map[string m[fullKey] = fullTypeRef{ IsPointer: false, - RealType: rvfield.Type(), - Kind: rvfield.Type().Kind(), - Type: rvfield.Type(), - UnderlyingType: reflectext.Underlying(rvfield.Type()), + RealType: rsfield.Type, + Kind: rsfield.Type.Kind(), + Type: rsfield.Type, + UnderlyingType: reflectext.Underlying(rsfield.Type), Name: rsfield.Name, Index: newIdxArr, } } - if rvfield.Kind() == reflect.Struct { - c.initFields(fullKey+".", rvfield, m, newIdxArr) + if rsfield.Type.Kind() == reflect.Struct { + c.initFields(fullKey+".", rsfield.Type, m, newIdxArr) } + if rsfield.Type.Kind() == reflect.Pointer && rsfield.Type.Elem().Kind() == reflect.Struct { + c.initFields(fullKey+".", rsfield.Type.Elem(), m, newIdxArr) + } } } diff --git a/wmo/reflection_test.go b/wmo/reflection_test.go index 7347664..0a1de71 100644 --- a/wmo/reflection_test.go +++ b/wmo/reflection_test.go @@ -23,6 +23,9 @@ func TestReflectionGetFieldType(t *testing.T) { Sub struct { A string `bson:"a"` } `bson:"sub"` + SubPtr *struct { + A string `bson:"a"` + } `bson:"subPtr"` Str string `bson:"str"` Ptr *int `bson:"ptr"` MDate rfctime.RFC3339NanoTime `bson:"mdate"` @@ -43,6 +46,11 @@ func TestReflectionGetFieldType(t *testing.T) { }{ A: "2", }, + SubPtr: &struct { + A string `bson:"a"` + }{ + A: "4", + }, Str: "3", Ptr: langext.Ptr(4), MDate: t1, @@ -82,6 +90,12 @@ func TestReflectionGetFieldType(t *testing.T) { tst.AssertEqual(t, gft("sub.a").IsPointer, false) tst.AssertEqual(t, gfv("sub.a").(string), "2") + tst.AssertEqual(t, gft("subPtr.a").Kind.String(), "string") + tst.AssertEqual(t, gft("subPtr.a").Type.String(), "string") + tst.AssertEqual(t, gft("subPtr.a").Name, "A") + tst.AssertEqual(t, gft("subPtr.a").IsPointer, false) + tst.AssertEqual(t, gfv("subPtr.a").(string), "4") + tst.AssertEqual(t, gft("str").Kind.String(), "string") tst.AssertEqual(t, gft("str").Type.String(), "string") tst.AssertEqual(t, gft("str").Name, "Str") @@ -105,6 +119,9 @@ func TestReflectionGetTokenValueAsMongoType(t *testing.T) { Sub struct { A string `bson:"a"` } `bson:"sub"` + SubPtr struct { + A string `bson:"a"` + } `bson:"subPtr"` Str string `bson:"str"` Ptr *int `bson:"ptr"` Num int `bson:"num"` @@ -130,6 +147,8 @@ func TestReflectionGetTokenValueAsMongoType(t *testing.T) { } tst.AssertEqual(t, gtvasmt("hello", "str").(string), "hello") + tst.AssertEqual(t, gtvasmt("hello", "sub.a").(string), "hello") + tst.AssertEqual(t, gtvasmt("hello", "subPtr.a").(string), "hello") tst.AssertEqual(t, gtvasmt("4", "num").(int), 4) tst.AssertEqual(t, gtvasmt("asdf", "_id").(IDType), "asdf") tst.AssertEqual(t, gtvasmt("", "ptr").(*int), nil)