Commit 3036604b authored by Rob Pike's avatar Rob Pike

gob: do not encode or decode unexported fields

Such fields are simply ignored.

R=rsc, r2
CC=golang-dev
https://golang.org/cl/3889043
parent feb8d0b2
This diff is collapsed.
...@@ -137,32 +137,32 @@ func (dec *Decoder) debugRecvType(id typeId) { ...@@ -137,32 +137,32 @@ func (dec *Decoder) debugRecvType(id typeId) {
func printWireType(wire *wireType) { func printWireType(wire *wireType) {
fmt.Printf("type definition {\n") fmt.Printf("type definition {\n")
switch { switch {
case wire.arrayT != nil: case wire.ArrayT != nil:
printCommonType("array", &wire.arrayT.commonType) printCommonType("array", &wire.ArrayT.CommonType)
fmt.Printf("\tlen %d\n\telemid %d\n", wire.arrayT.Len, wire.arrayT.Elem) fmt.Printf("\tlen %d\n\telemid %d\n", wire.ArrayT.Len, wire.ArrayT.Elem)
case wire.mapT != nil: case wire.MapT != nil:
printCommonType("map", &wire.mapT.commonType) printCommonType("map", &wire.MapT.CommonType)
fmt.Printf("\tkeyid %d\n", wire.mapT.Key) fmt.Printf("\tkeyid %d\n", wire.MapT.Key)
fmt.Printf("\telemid %d\n", wire.mapT.Elem) fmt.Printf("\telemid %d\n", wire.MapT.Elem)
case wire.sliceT != nil: case wire.SliceT != nil:
printCommonType("slice", &wire.sliceT.commonType) printCommonType("slice", &wire.SliceT.CommonType)
fmt.Printf("\telemid %d\n", wire.sliceT.Elem) fmt.Printf("\telemid %d\n", wire.SliceT.Elem)
case wire.structT != nil: case wire.StructT != nil:
printCommonType("struct", &wire.structT.commonType) printCommonType("struct", &wire.StructT.CommonType)
for i, field := range wire.structT.field { for i, field := range wire.StructT.Field {
fmt.Printf("\tfield %d:\t%s\tid=%d\n", i, field.name, field.id) fmt.Printf("\tfield %d:\t%s\tid=%d\n", i, field.Name, field.Id)
} }
} }
fmt.Printf("}\n") fmt.Printf("}\n")
} }
func printCommonType(kind string, common *commonType) { func printCommonType(kind string, common *CommonType) {
fmt.Printf("\t%s %q\n\tid: %d\n", kind, common.name, common._id) fmt.Printf("\t%s %q\n\tid: %d\n", kind, common.Name, common.Id)
} }
func (dec *Decoder) debugPrint(indent int, id typeId) { func (dec *Decoder) debugPrint(indent int, id typeId) {
wire, ok := dec.wireType[id] wire, ok := dec.wireType[id]
if ok && wire.structT != nil { if ok && wire.StructT != nil {
dec.debugStruct(indent+1, id, wire) dec.debugStruct(indent+1, id, wire)
} else { } else {
dec.debugSingle(indent+1, id, wire) dec.debugSingle(indent+1, id, wire)
...@@ -193,32 +193,32 @@ func (dec *Decoder) printItem(indent int, id typeId) { ...@@ -193,32 +193,32 @@ func (dec *Decoder) printItem(indent int, id typeId) {
errorf("type id %d not defined\n", id) errorf("type id %d not defined\n", id)
} }
switch { switch {
case wire.arrayT != nil: case wire.ArrayT != nil:
dec.printArray(indent, wire) dec.printArray(indent, wire)
case wire.mapT != nil: case wire.MapT != nil:
dec.printMap(indent, wire) dec.printMap(indent, wire)
case wire.sliceT != nil: case wire.SliceT != nil:
dec.printSlice(indent, wire) dec.printSlice(indent, wire)
case wire.structT != nil: case wire.StructT != nil:
dec.debugStruct(indent, id, wire) dec.debugStruct(indent, id, wire)
} }
} }
func (dec *Decoder) printArray(indent int, wire *wireType) { func (dec *Decoder) printArray(indent int, wire *wireType) {
elemId := wire.arrayT.Elem elemId := wire.ArrayT.Elem
n := int(decodeUint(dec.state)) n := int(decodeUint(dec.state))
for i := 0; i < n && dec.err == nil; i++ { for i := 0; i < n && dec.err == nil; i++ {
dec.printItem(indent, elemId) dec.printItem(indent, elemId)
} }
if n != wire.arrayT.Len { if n != wire.ArrayT.Len {
tab(indent) tab(indent)
fmt.Printf("(wrong length for array: %d should be %d)\n", n, wire.arrayT.Len) fmt.Printf("(wrong length for array: %d should be %d)\n", n, wire.ArrayT.Len)
} }
} }
func (dec *Decoder) printMap(indent int, wire *wireType) { func (dec *Decoder) printMap(indent int, wire *wireType) {
keyId := wire.mapT.Key keyId := wire.MapT.Key
elemId := wire.mapT.Elem elemId := wire.MapT.Elem
n := int(decodeUint(dec.state)) n := int(decodeUint(dec.state))
for i := 0; i < n && dec.err == nil; i++ { for i := 0; i < n && dec.err == nil; i++ {
dec.printItem(indent, keyId) dec.printItem(indent, keyId)
...@@ -227,7 +227,7 @@ func (dec *Decoder) printMap(indent int, wire *wireType) { ...@@ -227,7 +227,7 @@ func (dec *Decoder) printMap(indent int, wire *wireType) {
} }
func (dec *Decoder) printSlice(indent int, wire *wireType) { func (dec *Decoder) printSlice(indent int, wire *wireType) {
elemId := wire.sliceT.Elem elemId := wire.SliceT.Elem
n := int(decodeUint(dec.state)) n := int(decodeUint(dec.state))
for i := 0; i < n && dec.err == nil; i++ { for i := 0; i < n && dec.err == nil; i++ {
dec.printItem(indent, elemId) dec.printItem(indent, elemId)
...@@ -273,8 +273,8 @@ func (dec *Decoder) printBuiltin(indent int, id typeId) { ...@@ -273,8 +273,8 @@ func (dec *Decoder) printBuiltin(indent int, id typeId) {
func (dec *Decoder) debugStruct(indent int, id typeId, wire *wireType) { func (dec *Decoder) debugStruct(indent int, id typeId, wire *wireType) {
tab(indent) tab(indent)
fmt.Printf("%s struct {\n", id.Name()) fmt.Printf("%s struct {\n", id.name())
strct := wire.structT strct := wire.StructT
state := newDecodeState(dec, dec.state.b) state := newDecodeState(dec, dec.state.b)
state.fieldnum = -1 state.fieldnum = -1
for dec.err == nil { for dec.err == nil {
...@@ -286,17 +286,17 @@ func (dec *Decoder) debugStruct(indent int, id typeId, wire *wireType) { ...@@ -286,17 +286,17 @@ func (dec *Decoder) debugStruct(indent int, id typeId, wire *wireType) {
break break
} }
fieldNum := state.fieldnum + delta fieldNum := state.fieldnum + delta
if fieldNum < 0 || fieldNum >= len(strct.field) { if fieldNum < 0 || fieldNum >= len(strct.Field) {
errorf("field number out of range") errorf("field number out of range")
break break
} }
tab(indent) tab(indent)
fmt.Printf("%s(%d):\n", wire.structT.field[fieldNum].name, fieldNum) fmt.Printf("%s(%d):\n", wire.StructT.Field[fieldNum].Name, fieldNum)
dec.printItem(indent+1, strct.field[fieldNum].id) dec.printItem(indent+1, strct.Field[fieldNum].Id)
state.fieldnum = fieldNum state.fieldnum = fieldNum
} }
tab(indent) tab(indent)
fmt.Printf(" } // end %s struct\n", id.Name()) fmt.Printf(" } // end %s struct\n", id.name())
} }
func tab(indent int) { func tab(indent int) {
......
...@@ -13,7 +13,9 @@ import ( ...@@ -13,7 +13,9 @@ import (
"math" "math"
"os" "os"
"reflect" "reflect"
"unicode"
"unsafe" "unsafe"
"utf8"
) )
var ( var (
...@@ -684,7 +686,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp ...@@ -684,7 +686,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
switch t := typ.(type) { switch t := typ.(type) {
case *reflect.ArrayType: case *reflect.ArrayType:
name = "element of " + name name = "element of " + name
elemId := dec.wireType[wireId].arrayT.Elem elemId := dec.wireType[wireId].ArrayT.Elem
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name) elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name) ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
...@@ -693,8 +695,8 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp ...@@ -693,8 +695,8 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
case *reflect.MapType: case *reflect.MapType:
name = "element of " + name name = "element of " + name
keyId := dec.wireType[wireId].mapT.Key keyId := dec.wireType[wireId].MapT.Key
elemId := dec.wireType[wireId].mapT.Elem elemId := dec.wireType[wireId].MapT.Elem
keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name) keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name)
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name) elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name) ovfl := overflow(name)
...@@ -713,7 +715,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp ...@@ -713,7 +715,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
if tt, ok := builtinIdToType[wireId]; ok { if tt, ok := builtinIdToType[wireId]; ok {
elemId = tt.(*sliceType).Elem elemId = tt.(*sliceType).Elem
} else { } else {
elemId = dec.wireType[wireId].sliceT.Elem elemId = dec.wireType[wireId].SliceT.Elem
} }
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name) elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name) ovfl := overflow(name)
...@@ -763,30 +765,30 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { ...@@ -763,30 +765,30 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
switch { switch {
case wire == nil: case wire == nil:
panic("internal error: can't find ignore op for type " + wireId.string()) panic("internal error: can't find ignore op for type " + wireId.string())
case wire.arrayT != nil: case wire.ArrayT != nil:
elemId := wire.arrayT.Elem elemId := wire.ArrayT.Elem
elemOp := dec.decIgnoreOpFor(elemId) elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
state.dec.ignoreArray(state, elemOp, wire.arrayT.Len) state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
} }
case wire.mapT != nil: case wire.MapT != nil:
keyId := dec.wireType[wireId].mapT.Key keyId := dec.wireType[wireId].MapT.Key
elemId := dec.wireType[wireId].mapT.Elem elemId := dec.wireType[wireId].MapT.Elem
keyOp := dec.decIgnoreOpFor(keyId) keyOp := dec.decIgnoreOpFor(keyId)
elemOp := dec.decIgnoreOpFor(elemId) elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
state.dec.ignoreMap(state, keyOp, elemOp) state.dec.ignoreMap(state, keyOp, elemOp)
} }
case wire.sliceT != nil: case wire.SliceT != nil:
elemId := wire.sliceT.Elem elemId := wire.SliceT.Elem
elemOp := dec.decIgnoreOpFor(elemId) elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) { op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
state.dec.ignoreSlice(state, elemOp) state.dec.ignoreSlice(state, elemOp)
} }
case wire.structT != nil: case wire.StructT != nil:
// Generate a closure that calls out to the engine for the nested type. // Generate a closure that calls out to the engine for the nested type.
enginePtr, err := dec.getIgnoreEnginePtr(wireId) enginePtr, err := dec.getIgnoreEnginePtr(wireId)
if err != nil { if err != nil {
...@@ -829,18 +831,18 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool { ...@@ -829,18 +831,18 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
return fw == tInterface return fw == tInterface
case *reflect.ArrayType: case *reflect.ArrayType:
wire, ok := dec.wireType[fw] wire, ok := dec.wireType[fw]
if !ok || wire.arrayT == nil { if !ok || wire.ArrayT == nil {
return false return false
} }
array := wire.arrayT array := wire.ArrayT
return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem) return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem)
case *reflect.MapType: case *reflect.MapType:
wire, ok := dec.wireType[fw] wire, ok := dec.wireType[fw]
if !ok || wire.mapT == nil { if !ok || wire.MapT == nil {
return false return false
} }
mapType := wire.mapT MapType := wire.MapT
return dec.compatibleType(t.Key(), mapType.Key) && dec.compatibleType(t.Elem(), mapType.Elem) return dec.compatibleType(t.Key(), MapType.Key) && dec.compatibleType(t.Elem(), MapType.Elem)
case *reflect.SliceType: case *reflect.SliceType:
// Is it an array of bytes? // Is it an array of bytes?
if t.Elem().Kind() == reflect.Uint8 { if t.Elem().Kind() == reflect.Uint8 {
...@@ -851,7 +853,7 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool { ...@@ -851,7 +853,7 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
if tt, ok := builtinIdToType[fw]; ok { if tt, ok := builtinIdToType[fw]; ok {
sw = tt.(*sliceType) sw = tt.(*sliceType)
} else { } else {
sw = dec.wireType[fw].sliceT sw = dec.wireType[fw].SliceT
} }
elem, _ := indirect(t.Elem()) elem, _ := indirect(t.Elem())
return sw != nil && dec.compatibleType(elem, sw.Elem) return sw != nil && dec.compatibleType(elem, sw.Elem)
...@@ -885,6 +887,12 @@ func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *dec ...@@ -885,6 +887,12 @@ func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *dec
return return
} }
// Is this an exported - upper case - name?
func isExported(name string) bool {
rune, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(rune)
}
func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) { func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
defer catchError(&err) defer catchError(&err)
srt, ok := rt.(*reflect.StructType) srt, ok := rt.(*reflect.StructType)
...@@ -897,29 +905,32 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng ...@@ -897,29 +905,32 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng
if t, ok := builtinIdToType[remoteId]; ok { if t, ok := builtinIdToType[remoteId]; ok {
wireStruct, _ = t.(*structType) wireStruct, _ = t.(*structType)
} else { } else {
wireStruct = dec.wireType[remoteId].structT wireStruct = dec.wireType[remoteId].StructT
} }
if wireStruct == nil { if wireStruct == nil {
errorf("gob: type mismatch in decoder: want struct type %s; got non-struct", rt.String()) errorf("gob: type mismatch in decoder: want struct type %s; got non-struct", rt.String())
} }
engine = new(decEngine) engine = new(decEngine)
engine.instr = make([]decInstr, len(wireStruct.field)) engine.instr = make([]decInstr, len(wireStruct.Field))
// Loop over the fields of the wire type. // Loop over the fields of the wire type.
for fieldnum := 0; fieldnum < len(wireStruct.field); fieldnum++ { for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ {
wireField := wireStruct.field[fieldnum] wireField := wireStruct.Field[fieldnum]
if wireField.Name == "" {
errorf("gob: empty name for remote field of type %s", wireStruct.Name)
}
ovfl := overflow(wireField.Name)
// Find the field of the local type with the same name. // Find the field of the local type with the same name.
localField, present := srt.FieldByName(wireField.name) localField, present := srt.FieldByName(wireField.Name)
ovfl := overflow(wireField.name)
// TODO(r): anonymous names // TODO(r): anonymous names
if !present { if !present || !isExported(wireField.Name) {
op := dec.decIgnoreOpFor(wireField.id) op := dec.decIgnoreOpFor(wireField.Id)
engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl} engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
continue continue
} }
if !dec.compatibleType(localField.Type, wireField.id) { if !dec.compatibleType(localField.Type, wireField.Id) {
errorf("gob: wrong type (%s) for received field %s.%s", localField.Type, wireStruct.name, wireField.name) errorf("gob: wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
} }
op, indir := dec.decOpFor(wireField.id, localField.Type, localField.Name) op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name)
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(localField.Offset), ovfl} engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(localField.Offset), ovfl}
engine.numInstr++ engine.numInstr++
} }
...@@ -972,7 +983,7 @@ func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error { ...@@ -972,7 +983,7 @@ func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error {
} }
engine := *enginePtr engine := *enginePtr
if st, ok := rt.(*reflect.StructType); ok { if st, ok := rt.(*reflect.StructType); ok {
if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].structT.field) > 0 { if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
name := rt.Name() name := rt.Name()
return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name) return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name)
} }
......
...@@ -149,31 +149,34 @@ pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireTy ...@@ -149,31 +149,34 @@ pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireTy
description, constructed from these types: description, constructed from these types:
type wireType struct { type wireType struct {
s structType ArrayT *ArrayType
SliceT *SliceType
StructT *StructType
MapT *MapType
} }
type arrayType struct { type ArrayType struct {
commonType CommonType
Elem typeId Elem typeId
Len int Len int
} }
type commonType { type CommonType {
name string // the name of the struct type Name string // the name of the struct type
_id int // the id of the type, repeated for so it's inside the type Id int // the id of the type, repeated so it's inside the type
} }
type sliceType struct { type SliceType struct {
commonType CommonType
Elem typeId Elem typeId
} }
type structType struct { type StructType struct {
commonType CommonType
field []*fieldType // the fields of the struct. Field []*fieldType // the fields of the struct.
} }
type fieldType struct { type FieldType struct {
name string // the name of the field. Name string // the name of the field.
id int // the type id of the field, which must be already defined Id int // the type id of the field, which must be already defined
} }
type mapType struct { type MapType struct {
commonType CommonType
Key typeId Key typeId
Elem typeId Elem typeId
} }
...@@ -193,14 +196,14 @@ priori, as well as the basic gob types int, uint, etc. Their ids are: ...@@ -193,14 +196,14 @@ priori, as well as the basic gob types int, uint, etc. Their ids are:
complex 7 complex 7
interface 8 interface 8
// gap for reserved ids. // gap for reserved ids.
wireType 16 WireType 16
arrayType 17 ArrayType 17
commonType 18 CommonType 18
sliceType 19 SliceType 19
structType 20 StructType 20
fieldType 21 FieldType 21
// 22 is slice of fieldType. // 22 is slice of fieldType.
mapType 23 MapType 23
Finally, each message created by a call to Encode is preceded by an encoded Finally, each message created by a call to Encode is preceded by an encoded
unsigned integer count of the number of bytes remaining in the message. After unsigned integer count of the number of bytes remaining in the message. After
......
...@@ -284,6 +284,9 @@ func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { ...@@ -284,6 +284,9 @@ func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
} }
} }
func encNoOp(i *encInstr, state *encoderState, p unsafe.Pointer) {
}
// Byte arrays are encoded as an unsigned count followed by the raw bytes. // Byte arrays are encoded as an unsigned count followed by the raw bytes.
func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) { func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
b := *(*[]byte)(p) b := *(*[]byte)(p)
...@@ -539,6 +542,9 @@ func (enc *Encoder) compileEnc(rt reflect.Type) *encEngine { ...@@ -539,6 +542,9 @@ func (enc *Encoder) compileEnc(rt reflect.Type) *encEngine {
for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ { for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
f := srt.Field(fieldnum) f := srt.Field(fieldnum)
op, indir := enc.encOpFor(f.Type) op, indir := enc.encOpFor(f.Type)
if !isExported(f.Name) {
op = encNoOp
}
engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)} engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)}
} }
engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0} engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0}
......
...@@ -14,35 +14,35 @@ import ( ...@@ -14,35 +14,35 @@ import (
) )
type ET2 struct { type ET2 struct {
x string X string
} }
type ET1 struct { type ET1 struct {
a int A int
et2 *ET2 Et2 *ET2
next *ET1 Next *ET1
} }
// Like ET1 but with a different name for a field // Like ET1 but with a different name for a field
type ET3 struct { type ET3 struct {
a int A int
et2 *ET2 Et2 *ET2
differentNext *ET1 DifferentNext *ET1
} }
// Like ET1 but with a different type for a field // Like ET1 but with a different type for a field
type ET4 struct { type ET4 struct {
a int A int
et2 float Et2 float
next int Next int
} }
func TestEncoderDecoder(t *testing.T) { func TestEncoderDecoder(t *testing.T) {
b := new(bytes.Buffer) b := new(bytes.Buffer)
enc := NewEncoder(b) enc := NewEncoder(b)
et1 := new(ET1) et1 := new(ET1)
et1.a = 7 et1.A = 7
et1.et2 = new(ET2) et1.Et2 = new(ET2)
err := enc.Encode(et1) err := enc.Encode(et1)
if err != nil { if err != nil {
t.Error("encoder fail:", err) t.Error("encoder fail:", err)
...@@ -92,8 +92,8 @@ func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) { ...@@ -92,8 +92,8 @@ func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) {
b := new(bytes.Buffer) b := new(bytes.Buffer)
enc := NewEncoder(b) enc := NewEncoder(b)
et1 := new(ET1) et1 := new(ET1)
et1.a = 7 et1.A = 7
et1.et2 = new(ET2) et1.Et2 = new(ET2)
err := enc.Encode(et1) err := enc.Encode(et1)
if err != nil { if err != nil {
t.Error("encoder fail:", err) t.Error("encoder fail:", err)
...@@ -166,7 +166,7 @@ func encAndDec(in, out interface{}) os.Error { ...@@ -166,7 +166,7 @@ func encAndDec(in, out interface{}) os.Error {
func TestTypeToPtrType(t *testing.T) { func TestTypeToPtrType(t *testing.T) {
// Encode a T, decode a *T // Encode a T, decode a *T
type Type0 struct { type Type0 struct {
a int A int
} }
t0 := Type0{7} t0 := Type0{7}
t0p := (*Type0)(nil) t0p := (*Type0)(nil)
...@@ -178,7 +178,7 @@ func TestTypeToPtrType(t *testing.T) { ...@@ -178,7 +178,7 @@ func TestTypeToPtrType(t *testing.T) {
func TestPtrTypeToType(t *testing.T) { func TestPtrTypeToType(t *testing.T) {
// Encode a *T, decode a T // Encode a *T, decode a T
type Type1 struct { type Type1 struct {
a uint A uint
} }
t1p := &Type1{17} t1p := &Type1{17}
var t1 Type1 var t1 Type1
...@@ -189,26 +189,26 @@ func TestPtrTypeToType(t *testing.T) { ...@@ -189,26 +189,26 @@ func TestPtrTypeToType(t *testing.T) {
func TestTypeToPtrPtrPtrPtrType(t *testing.T) { func TestTypeToPtrPtrPtrPtrType(t *testing.T) {
type Type2 struct { type Type2 struct {
a ****float A ****float
} }
t2 := Type2{} t2 := Type2{}
t2.a = new(***float) t2.A = new(***float)
*t2.a = new(**float) *t2.A = new(**float)
**t2.a = new(*float) **t2.A = new(*float)
***t2.a = new(float) ***t2.A = new(float)
****t2.a = 27.4 ****t2.A = 27.4
t2pppp := new(***Type2) t2pppp := new(***Type2)
if err := encAndDec(t2, t2pppp); err != nil { if err := encAndDec(t2, t2pppp); err != nil {
t.Error(err) t.Fatal(err)
} }
if ****(****t2pppp).a != ****t2.a { if ****(****t2pppp).A != ****t2.A {
t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).a, ****t2.a) t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A)
} }
} }
func TestSlice(t *testing.T) { func TestSlice(t *testing.T) {
type Type3 struct { type Type3 struct {
a []string A []string
} }
t3p := &Type3{[]string{"hello", "world"}} t3p := &Type3{[]string{"hello", "world"}}
var t3 Type3 var t3 Type3
...@@ -231,11 +231,11 @@ func TestValueError(t *testing.T) { ...@@ -231,11 +231,11 @@ func TestValueError(t *testing.T) {
func TestArray(t *testing.T) { func TestArray(t *testing.T) {
type Type5 struct { type Type5 struct {
a [3]string A [3]string
b [3]byte B [3]byte
} }
type Type6 struct { type Type6 struct {
a [2]string // can't hold t5.a A [2]string // can't hold t5.a
} }
t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}} t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}}
var t5p Type5 var t5p Type5
...@@ -251,10 +251,10 @@ func TestArray(t *testing.T) { ...@@ -251,10 +251,10 @@ func TestArray(t *testing.T) {
// Regression test for bug: must send zero values inside arrays // Regression test for bug: must send zero values inside arrays
func TestDefaultsInArray(t *testing.T) { func TestDefaultsInArray(t *testing.T) {
type Type7 struct { type Type7 struct {
b []bool B []bool
i []int I []int
s []string S []string
f []float F []float
} }
t7 := Type7{ t7 := Type7{
[]bool{false, false, true}, []bool{false, false, true},
...@@ -329,7 +329,7 @@ func TestSingletons(t *testing.T) { ...@@ -329,7 +329,7 @@ func TestSingletons(t *testing.T) {
func TestStructNonStruct(t *testing.T) { func TestStructNonStruct(t *testing.T) {
type Struct struct { type Struct struct {
a string A string
} }
type NonStruct string type NonStruct string
s := Struct{"hello"} s := Struct{"hello"}
......
...@@ -29,7 +29,7 @@ const firstUserId = 64 // lowest id number granted to user ...@@ -29,7 +29,7 @@ const firstUserId = 64 // lowest id number granted to user
type gobType interface { type gobType interface {
id() typeId id() typeId
setId(id typeId) setId(id typeId)
Name() string name() string
string() string // not public; only for debugging string() string // not public; only for debugging
safeString(seen map[typeId]bool) string safeString(seen map[typeId]bool) string
} }
...@@ -60,30 +60,30 @@ func (t typeId) string() string { ...@@ -60,30 +60,30 @@ func (t typeId) string() string {
} }
// Name returns the name of the type associated with the typeId. // Name returns the name of the type associated with the typeId.
func (t typeId) Name() string { func (t typeId) name() string {
if t.gobType() == nil { if t.gobType() == nil {
return "<nil>" return "<nil>"
} }
return t.gobType().Name() return t.gobType().name()
} }
// Common elements of all types. // Common elements of all types.
type commonType struct { type CommonType struct {
name string Name string
_id typeId Id typeId
} }
func (t *commonType) id() typeId { return t._id } func (t *CommonType) id() typeId { return t.Id }
func (t *commonType) setId(id typeId) { t._id = id } func (t *CommonType) setId(id typeId) { t.Id = id }
func (t *commonType) string() string { return t.name } func (t *CommonType) string() string { return t.Name }
func (t *commonType) safeString(seen map[typeId]bool) string { func (t *CommonType) safeString(seen map[typeId]bool) string {
return t.name return t.Name
} }
func (t *commonType) Name() string { return t.name } func (t *CommonType) name() string { return t.Name }
// Create and check predefined types // Create and check predefined types
// The string for tBytes is "bytes" not "[]byte" to signify its specialness. // The string for tBytes is "bytes" not "[]byte" to signify its specialness.
...@@ -115,7 +115,7 @@ func init() { ...@@ -115,7 +115,7 @@ func init() {
// Some magic numbers to make sure there are no surprises. // Some magic numbers to make sure there are no surprises.
checkId(16, tWireType) checkId(16, tWireType)
checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id) checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id)
checkId(18, mustGetTypeInfo(reflect.Typeof(commonType{})).id) checkId(18, mustGetTypeInfo(reflect.Typeof(CommonType{})).id)
checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id) checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id)
checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id) checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id)
checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id) checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id)
...@@ -137,22 +137,22 @@ func init() { ...@@ -137,22 +137,22 @@ func init() {
// Array type // Array type
type arrayType struct { type arrayType struct {
commonType CommonType
Elem typeId Elem typeId
Len int Len int
} }
func newArrayType(name string, elem gobType, length int) *arrayType { func newArrayType(name string, elem gobType, length int) *arrayType {
a := &arrayType{commonType{name: name}, elem.id(), length} a := &arrayType{CommonType{Name: name}, elem.id(), length}
setTypeId(a) setTypeId(a)
return a return a
} }
func (a *arrayType) safeString(seen map[typeId]bool) string { func (a *arrayType) safeString(seen map[typeId]bool) string {
if seen[a._id] { if seen[a.Id] {
return a.name return a.Name
} }
seen[a._id] = true seen[a.Id] = true
return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
} }
...@@ -160,22 +160,22 @@ func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) ...@@ -160,22 +160,22 @@ func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool))
// Map type // Map type
type mapType struct { type mapType struct {
commonType CommonType
Key typeId Key typeId
Elem typeId Elem typeId
} }
func newMapType(name string, key, elem gobType) *mapType { func newMapType(name string, key, elem gobType) *mapType {
m := &mapType{commonType{name: name}, key.id(), elem.id()} m := &mapType{CommonType{Name: name}, key.id(), elem.id()}
setTypeId(m) setTypeId(m)
return m return m
} }
func (m *mapType) safeString(seen map[typeId]bool) string { func (m *mapType) safeString(seen map[typeId]bool) string {
if seen[m._id] { if seen[m.Id] {
return m.name return m.Name
} }
seen[m._id] = true seen[m.Id] = true
key := m.Key.gobType().safeString(seen) key := m.Key.gobType().safeString(seen)
elem := m.Elem.gobType().safeString(seen) elem := m.Elem.gobType().safeString(seen)
return fmt.Sprintf("map[%s]%s", key, elem) return fmt.Sprintf("map[%s]%s", key, elem)
...@@ -185,21 +185,21 @@ func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } ...@@ -185,21 +185,21 @@ func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
// Slice type // Slice type
type sliceType struct { type sliceType struct {
commonType CommonType
Elem typeId Elem typeId
} }
func newSliceType(name string, elem gobType) *sliceType { func newSliceType(name string, elem gobType) *sliceType {
s := &sliceType{commonType{name: name}, elem.id()} s := &sliceType{CommonType{Name: name}, elem.id()}
setTypeId(s) setTypeId(s)
return s return s
} }
func (s *sliceType) safeString(seen map[typeId]bool) string { func (s *sliceType) safeString(seen map[typeId]bool) string {
if seen[s._id] { if seen[s.Id] {
return s.name return s.Name
} }
seen[s._id] = true seen[s.Id] = true
return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
} }
...@@ -207,26 +207,26 @@ func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) ...@@ -207,26 +207,26 @@ func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool))
// Struct type // Struct type
type fieldType struct { type fieldType struct {
name string Name string
id typeId Id typeId
} }
type structType struct { type structType struct {
commonType CommonType
field []*fieldType Field []*fieldType
} }
func (s *structType) safeString(seen map[typeId]bool) string { func (s *structType) safeString(seen map[typeId]bool) string {
if s == nil { if s == nil {
return "<nil>" return "<nil>"
} }
if _, ok := seen[s._id]; ok { if _, ok := seen[s.Id]; ok {
return s.name return s.Name
} }
seen[s._id] = true seen[s.Id] = true
str := s.name + " = struct { " str := s.Name + " = struct { "
for _, f := range s.field { for _, f := range s.Field {
str += fmt.Sprintf("%s %s; ", f.name, f.id.gobType().safeString(seen)) str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
} }
str += "}" str += "}"
return str return str
...@@ -235,7 +235,7 @@ func (s *structType) safeString(seen map[typeId]bool) string { ...@@ -235,7 +235,7 @@ func (s *structType) safeString(seen map[typeId]bool) string {
func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
func newStructType(name string) *structType { func newStructType(name string) *structType {
s := &structType{commonType{name: name}, nil} s := &structType{CommonType{Name: name}, nil}
setTypeId(s) setTypeId(s)
return s return s
} }
...@@ -329,7 +329,7 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) { ...@@ -329,7 +329,7 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) {
} }
field[i] = &fieldType{f.Name, gt.id()} field[i] = &fieldType{f.Name, gt.id()}
} }
strType.field = field strType.Field = field
return strType, nil return strType, nil
default: default:
...@@ -356,7 +356,7 @@ func getType(name string, rt reflect.Type) (gobType, os.Error) { ...@@ -356,7 +356,7 @@ func getType(name string, rt reflect.Type) (gobType, os.Error) {
func checkId(want, got typeId) { func checkId(want, got typeId) {
if want != got { if want != got {
fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(want), int(got)) fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(want), int(got))
panic("bootstrap type wrong id: " + got.Name() + " " + got.string() + " not " + want.string()) panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
} }
} }
...@@ -367,7 +367,7 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId { ...@@ -367,7 +367,7 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId {
if present { if present {
panic("bootstrap type already present: " + name + ", " + rt.String()) panic("bootstrap type already present: " + name + ", " + rt.String())
} }
typ := &commonType{name: name} typ := &CommonType{Name: name}
types[rt] = typ types[rt] = typ
setTypeId(typ) setTypeId(typ)
checkId(expect, nextId) checkId(expect, nextId)
...@@ -386,10 +386,10 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId { ...@@ -386,10 +386,10 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId {
// To maintain binary compatibility, if you extend this type, always put // To maintain binary compatibility, if you extend this type, always put
// the new fields last. // the new fields last.
type wireType struct { type wireType struct {
arrayT *arrayType ArrayT *arrayType
sliceT *sliceType SliceT *sliceType
structT *structType StructT *structType
mapT *mapType MapT *mapType
} }
func (w *wireType) string() string { func (w *wireType) string() string {
...@@ -398,14 +398,14 @@ func (w *wireType) string() string { ...@@ -398,14 +398,14 @@ func (w *wireType) string() string {
return unknown return unknown
} }
switch { switch {
case w.arrayT != nil: case w.ArrayT != nil:
return w.arrayT.name return w.ArrayT.Name
case w.sliceT != nil: case w.SliceT != nil:
return w.sliceT.name return w.SliceT.Name
case w.structT != nil: case w.StructT != nil:
return w.structT.name return w.StructT.Name
case w.mapT != nil: case w.MapT != nil:
return w.mapT.name return w.MapT.Name
} }
return unknown return unknown
} }
...@@ -436,16 +436,16 @@ func getTypeInfo(rt reflect.Type) (*typeInfo, os.Error) { ...@@ -436,16 +436,16 @@ func getTypeInfo(rt reflect.Type) (*typeInfo, os.Error) {
t := info.id.gobType() t := info.id.gobType()
switch typ := rt.(type) { switch typ := rt.(type) {
case *reflect.ArrayType: case *reflect.ArrayType:
info.wire = &wireType{arrayT: t.(*arrayType)} info.wire = &wireType{ArrayT: t.(*arrayType)}
case *reflect.MapType: case *reflect.MapType:
info.wire = &wireType{mapT: t.(*mapType)} info.wire = &wireType{MapT: t.(*mapType)}
case *reflect.SliceType: case *reflect.SliceType:
// []byte == []uint8 is a special case handled separately // []byte == []uint8 is a special case handled separately
if typ.Elem().Kind() != reflect.Uint8 { if typ.Elem().Kind() != reflect.Uint8 {
info.wire = &wireType{sliceT: t.(*sliceType)} info.wire = &wireType{SliceT: t.(*sliceType)}
} }
case *reflect.StructType: case *reflect.StructType:
info.wire = &wireType{structT: t.(*structType)} info.wire = &wireType{StructT: t.(*structType)}
} }
typeInfoMap[rt] = info typeInfoMap[rt] = info
} }
......
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