mirror of
https://github.com/golang/go
synced 2024-11-21 18:34:44 -07:00
gob: don't send type information about unexported fields.
A change a while back stop sending data for unexported fields but due to an oversight the type info was being sent also. It's inconsequential but wrong to do that. R=rsc, rh CC=golang-dev https://golang.org/cl/4252058
This commit is contained in:
parent
bfd3d81b92
commit
369c48cafb
@ -13,9 +13,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unicode"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"utf8"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1073,12 +1071,6 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// isExported reports whether this is an exported - upper case - name.
|
|
||||||
func isExported(name string) bool {
|
|
||||||
rune, _ := utf8.DecodeRuneInString(name)
|
|
||||||
return unicode.IsUpper(rune)
|
|
||||||
}
|
|
||||||
|
|
||||||
// compileDec compiles the decoder engine for a value. If the value is not a struct,
|
// compileDec compiles the decoder engine for a value. If the value is not a struct,
|
||||||
// it calls out to compileSingle.
|
// it calls out to compileSingle.
|
||||||
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
|
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
|
||||||
|
@ -606,13 +606,14 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
|
|||||||
rt = ut.user
|
rt = ut.user
|
||||||
}
|
}
|
||||||
if !ut.isGobEncoder && isStruct {
|
if !ut.isGobEncoder && isStruct {
|
||||||
for fieldNum := 0; fieldNum < srt.NumField(); fieldNum++ {
|
for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
|
||||||
f := srt.Field(fieldNum)
|
f := srt.Field(fieldNum)
|
||||||
if !isExported(f.Name) {
|
if !isExported(f.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
op, indir := enc.encOpFor(f.Type, seen)
|
op, indir := enc.encOpFor(f.Type, seen)
|
||||||
engine.instr = append(engine.instr, encInstr{*op, fieldNum, indir, uintptr(f.Offset)})
|
engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)})
|
||||||
|
wireFieldNum++
|
||||||
}
|
}
|
||||||
if srt.NumField() > 0 && len(engine.instr) == 0 {
|
if srt.NumField() > 0 && len(engine.instr) == 0 {
|
||||||
errorf("type %s has no exported fields", rt)
|
errorf("type %s has no exported fields", rt)
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
"unicode"
|
||||||
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// userTypeInfo stores the information associated with a type the user has handed
|
// userTypeInfo stores the information associated with a type the user has handed
|
||||||
@ -418,10 +420,6 @@ func newStructType(name string) *structType {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *structType) init(field []*fieldType) {
|
|
||||||
s.Field = field
|
|
||||||
}
|
|
||||||
|
|
||||||
// newTypeObject allocates a gobType for the reflection type rt.
|
// newTypeObject allocates a gobType for the reflection type rt.
|
||||||
// Unless ut represents a GobEncoder, rt should be the base type
|
// Unless ut represents a GobEncoder, rt should be the base type
|
||||||
// of ut.
|
// of ut.
|
||||||
@ -514,10 +512,11 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.
|
|||||||
st := newStructType(name)
|
st := newStructType(name)
|
||||||
types[rt] = st
|
types[rt] = st
|
||||||
idToType[st.id()] = st
|
idToType[st.id()] = st
|
||||||
field := make([]*fieldType, t.NumField())
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
// TODO: don't send unexported fields.
|
|
||||||
f := t.Field(i)
|
f := t.Field(i)
|
||||||
|
if !isExported(f.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
typ := userType(f.Type).base
|
typ := userType(f.Type).base
|
||||||
tname := typ.Name()
|
tname := typ.Name()
|
||||||
if tname == "" {
|
if tname == "" {
|
||||||
@ -528,9 +527,8 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
field[i] = &fieldType{f.Name, gt.id()}
|
st.Field = append(st.Field, &fieldType{f.Name, gt.id()})
|
||||||
}
|
}
|
||||||
st.init(field)
|
|
||||||
return st, nil
|
return st, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -539,6 +537,12 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isExported reports whether this is an exported - upper case - name.
|
||||||
|
func isExported(name string) bool {
|
||||||
|
rune, _ := utf8.DecodeRuneInString(name)
|
||||||
|
return unicode.IsUpper(rune)
|
||||||
|
}
|
||||||
|
|
||||||
// getBaseType returns the Gob type describing the given reflect.Type's base type.
|
// getBaseType returns the Gob type describing the given reflect.Type's base type.
|
||||||
// typeLock must be held.
|
// typeLock must be held.
|
||||||
func getBaseType(name string, rt reflect.Type) (gobType, os.Error) {
|
func getBaseType(name string, rt reflect.Type) (gobType, os.Error) {
|
||||||
|
@ -126,27 +126,27 @@ func TestMapType(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Bar struct {
|
type Bar struct {
|
||||||
x string
|
X string
|
||||||
}
|
}
|
||||||
|
|
||||||
// This structure has pointers and refers to itself, making it a good test case.
|
// This structure has pointers and refers to itself, making it a good test case.
|
||||||
type Foo struct {
|
type Foo struct {
|
||||||
a int
|
A int
|
||||||
b int32 // will become int
|
B int32 // will become int
|
||||||
c string
|
C string
|
||||||
d []byte
|
D []byte
|
||||||
e *float64 // will become float64
|
E *float64 // will become float64
|
||||||
f ****float64 // will become float64
|
F ****float64 // will become float64
|
||||||
g *Bar
|
G *Bar
|
||||||
h *Bar // should not interpolate the definition of Bar again
|
H *Bar // should not interpolate the definition of Bar again
|
||||||
i *Foo // will not explode
|
I *Foo // will not explode
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructType(t *testing.T) {
|
func TestStructType(t *testing.T) {
|
||||||
sstruct := getTypeUnlocked("Foo", reflect.Typeof(Foo{}))
|
sstruct := getTypeUnlocked("Foo", reflect.Typeof(Foo{}))
|
||||||
str := sstruct.string()
|
str := sstruct.string()
|
||||||
// If we can print it correctly, we built it correctly.
|
// If we can print it correctly, we built it correctly.
|
||||||
expected := "Foo = struct { a int; b int; c string; d bytes; e float; f float; g Bar = struct { x string; }; h Bar; i Foo; }"
|
expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
|
||||||
if str != expected {
|
if str != expected {
|
||||||
t.Errorf("struct printed as %q; expected %q", str, expected)
|
t.Errorf("struct printed as %q; expected %q", str, expected)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user