diff --git a/jsonpointer/resolve.go b/jsonpointer/resolve.go index dcf7958..2d2f284 100644 --- a/jsonpointer/resolve.go +++ b/jsonpointer/resolve.go @@ -33,7 +33,7 @@ func findByLabel(base reflect.Value, jsonLabel string) (reflect.Value, bool) { return reflect.Value{}, false } - for base.Kind() == reflect.Ptr || base.Kind() == reflect.Interface { + for base.Kind() == reflect.Pointer || base.Kind() == reflect.Interface { if base.IsNil() { return reflect.Value{}, false } diff --git a/reference.go b/reference.go index 1e96f0b..7897f1e 100644 --- a/reference.go +++ b/reference.go @@ -10,14 +10,14 @@ import ( "golang.org/x/exp/slices" ) -// NewReference creates a new reference to a field of a Object. +// NewReference creates a new reference to a field of an Object. // The base must be a pointer to a struct implementing Object. // The field must be a pointer to a field within the base. func NewReference(base Object, field any) *Reference { - if reflect.ValueOf(base).Kind() != reflect.Ptr { + if reflect.ValueOf(base).Kind() != reflect.Pointer { panic("Base must be a pointer to a struct implementing Object") } - if reflect.ValueOf(field).Kind() != reflect.Ptr { + if reflect.ValueOf(field).Kind() != reflect.Pointer { panic("field must be a pointer to a field within base") } return &Reference{ @@ -26,9 +26,9 @@ func NewReference(base Object, field any) *Reference { } } -// Reference is a reference to a field of a Object +// Reference is a reference to a field of an Object type Reference struct { - Base any // Must be a pointer to a Object + Base any // Must be a pointer to an Object PointedField any // Must be a pointer to a (possibly nested) field of Base textLabel string @@ -42,7 +42,7 @@ func (r *Reference) ToJsonPointer() jsonpointer.Pointer { } baseValue := reflect.ValueOf(r.Base) pointedValue := reflect.ValueOf(r.PointedField) - if pointedValue.Kind() != reflect.Ptr { + if pointedValue.Kind() != reflect.Pointer { panic("PointedField must be a pointer") } r.jsonPointer = findRelativeJsonPointer(baseValue, pointedValue) @@ -52,8 +52,12 @@ func (r *Reference) ToJsonPointer() jsonpointer.Pointer { return r.jsonPointer } -var referenceType = reflect.TypeFor[Reference]() +var referenceType = reflect.TypeOf((*Reference)(nil)).Elem() +// findRelativeJsonPointer finds a JSON pointer from base to pointedField. The +// base must be pointer. The pointed field should be a pointer to a field +// within the base; if the pointed field is not found within the base, nil is +// returned. func findRelativeJsonPointer(base reflect.Value, pointedField reflect.Value) jsonpointer.Pointer { for { if base.Equal(pointedField) { @@ -65,7 +69,7 @@ func findRelativeJsonPointer(base reflect.Value, pointedField reflect.Value) jso if base.Type() == referenceType { // Don't recurse into other references return nil } - if base.Kind() == reflect.Ptr || base.Kind() == reflect.Interface { + if base.Kind() == reflect.Pointer || base.Kind() == reflect.Interface { if base.IsNil() { return nil } @@ -123,7 +127,7 @@ func (r *Reference) ToTextLabel() string { } baseValue := reflect.ValueOf(r.Base).Elem() pointedValue := reflect.ValueOf(r.PointedField) - if pointedValue.Kind() != reflect.Ptr { + if pointedValue.Kind() != reflect.Pointer { panic("PointedField must be a pointer") } r.textLabel, _ = findTextLabel(baseValue, reflect.ValueOf(r.PointedField)) @@ -143,7 +147,7 @@ func findTextLabel(base reflect.Value, pointedField reflect.Value) (string, bool if base.Addr().Equal(pointedField) { return "", true } - if base.Kind() == reflect.Ptr || base.Kind() == reflect.Interface { + if base.Kind() == reflect.Pointer || base.Kind() == reflect.Interface { base = base.Elem() } if base.Kind() != reflect.Struct { @@ -156,7 +160,7 @@ func findTextLabel(base reflect.Value, pointedField reflect.Value) (string, bool continue } var fieldPointer = field - if field.Kind() != reflect.Ptr { + if field.Kind() != reflect.Pointer { fieldPointer = field.Addr() } var label string diff --git a/reference_test.go b/reference_test.go index 372761d..d7613f2 100644 --- a/reference_test.go +++ b/reference_test.go @@ -111,6 +111,8 @@ func TestReference_ToJsonPointer(t *testing.T) { {&test.Valuer.Subfield7, "/valuer/subfield7"}, {&test.SubObject, "/subobject"}, {&test.SubObject.Subfield8, "/subobject/subfield8"}, + // test.Recursive not required here: if there is a flaw in the pointer + // search logic, it will panic when encountering this cycle. } for _, tt := range tests { t.Run(tt.want, func(t *testing.T) { diff --git a/textlog.go b/textlog.go index cc22125..338a44b 100644 --- a/textlog.go +++ b/textlog.go @@ -86,7 +86,7 @@ func withUppercaseKeys(entry TextlogEntry) TextlogEntry { } func (t TextlogFormatter) toEntry(object reflect.Value) TextlogEntry { - for object.Kind() == reflect.Ptr || object.Kind() == reflect.Interface { + for object.Kind() == reflect.Pointer || object.Kind() == reflect.Interface { if object.IsNil() { return nil } @@ -138,7 +138,7 @@ func (t TextlogFormatter) toEntry(object reflect.Value) TextlogEntry { } else { // Add the field as a single value key := logfield - if field.Kind() == reflect.Ptr { + if field.Kind() == reflect.Pointer { field = field.Elem() } details = append(details, TextlogValuePair{