Commit 369c48ca authored by Rob Pike's avatar Rob Pike

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
parent bfd3d81b
...@@ -13,9 +13,7 @@ import ( ...@@ -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 ...@@ -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 { ...@@ -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 ( ...@@ -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 { ...@@ -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. ...@@ -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. ...@@ -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. ...@@ -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) { ...@@ -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)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment