From c8d0b87a678bcb772b4a36f5911eb3e4b10d0c64 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Sat, 8 Mar 2025 15:45:37 -0800 Subject: [PATCH] internal/reflectlite, reflect: handle different StructField --- src/internal/reflectlite/type.go | 2 +- src/reflect/deepequal.go | 7 ++++ src/reflect/type.go | 63 ++++++++++++++++++++++++++++++-- src/reflect/visiblefields.go | 8 +++- 4 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 src/reflect/deepequal.go diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go index b81468de4..10350676c 100644 --- a/src/internal/reflectlite/type.go +++ b/src/internal/reflectlite/type.go @@ -294,7 +294,6 @@ func (t *RawType) String() string { } return s } - switch t.Kind() { case Chan: elem := t.elem().String() @@ -977,6 +976,7 @@ func (t *RawType) FieldByIndex(index []int) StructField { } // A StructField describes a single field in a struct. +// This must be kept in sync with [reflect.StructField]. type StructField struct { // Name indicates the field name. Name string diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go new file mode 100644 index 000000000..362385aed --- /dev/null +++ b/src/reflect/deepequal.go @@ -0,0 +1,7 @@ +package reflect + +import "internal/reflectlite" + +func DeepEqual(x, y interface{}) bool { + return reflectlite.DeepEqual(x, y) +} diff --git a/src/reflect/type.go b/src/reflect/type.go index 08c73bb2e..5116108dc 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -342,6 +342,9 @@ type rawType struct { } func toType(t reflectlite.Type) Type { + if t == nil { + return nil + } return (*rawType)(unsafe.Pointer(t.(*reflectlite.RawType))) } @@ -395,6 +398,30 @@ func (t *rawType) ConvertibleTo(u Type) bool { panic("unimplemented: (reflect.Type).ConvertibleTo()") } +func (t *rawType) Elem() Type { + return toType(t.RawType.Elem()) +} + +func (t *rawType) Field(i int) StructField { + f := t.RawType.Field(i) + return toStructField(f) +} + +func (t *rawType) FieldByIndex(index []int) StructField { + f := t.RawType.FieldByIndex(index) + return toStructField(f) +} + +func (t *rawType) FieldByName(name string) (StructField, bool) { + f, ok := t.RawType.FieldByName(name) + return toStructField(f), ok +} + +func (t *rawType) FieldByNameFunc(match func(string) bool) (StructField, bool) { + f, ok := t.RawType.FieldByNameFunc(match) + return toStructField(f), ok +} + func (t *rawType) Implements(u Type) bool { return t.RawType.Implements(&(u.(*rawType).RawType)) } @@ -431,11 +458,41 @@ func (t *rawType) Out(i int) Type { panic("unimplemented: (reflect.Type).Out()") } -func (t *rawType) Elem() Type { - return toType(t.RawType.Elem()) +// A StructField describes a single field in a struct. +// This must be kept in sync with [reflectlite.StructField]. +type StructField struct { + // Name indicates the field name. + Name string + + // PkgPath is the package path where the struct containing this field is + // declared for unexported fields, or the empty string for exported fields. + PkgPath string + + Type Type + Tag StructTag // field tag string + Offset uintptr + Index []int // index sequence for Type.FieldByIndex + Anonymous bool } -type StructField = reflectlite.StructField +func toStructField(f reflectlite.StructField) StructField { + return StructField{ + Name: f.Name, + PkgPath: f.PkgPath, + Type: toType(f.Type), + Tag: f.Tag, + Offset: f.Offset, + Index: f.Index, + Anonymous: f.Anonymous, + } +} + +// IsExported reports whether the field is exported. +func (f StructField) IsExported() bool { + return f.PkgPath == "" +} + +type StructTag = reflectlite.StructTag func TypeFor[T any]() Type { return toType(reflectlite.TypeFor[T]()) diff --git a/src/reflect/visiblefields.go b/src/reflect/visiblefields.go index ea7a0fd00..ac722da07 100644 --- a/src/reflect/visiblefields.go +++ b/src/reflect/visiblefields.go @@ -1,7 +1,11 @@ package reflect -import "internal/reflectlite" +import ( + "internal/reflectlite" + "unsafe" +) func VisibleFields(t Type) []StructField { - return reflectlite.VisibleFields(toRawType(t)) + fields := reflectlite.VisibleFields(toRawType(t)) + return *(*[]StructField)(unsafe.Pointer(&fields)) }