Commit 5aa17455 authored by Rob Pike's avatar Rob Pike

clean up for public use: make some stuff private, add doc comments.

R=rsc
DELTA=298  (202 added, 0 deleted, 96 changed)
OCL=32006
CL=32224
parent 3ff5e727
......@@ -36,6 +36,7 @@ var encodeT = []EncodeT {
EncodeT{ 1<<63, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81} },
}
// Test basic encode/decode routines for unsigned integers
func TestUintCodec(t *testing.T) {
b := new(bytes.Buffer);
......@@ -552,7 +553,7 @@ func TestEndToEnd(t *testing.T) {
b := new(bytes.Buffer);
encode(b, t1);
var _t1 T1;
decode(b, getTypeInfo(reflect.Typeof(_t1)).typeId, &_t1);
decode(b, getTypeInfo(reflect.Typeof(_t1)).id, &_t1);
if !reflect.DeepEqual(t1, &_t1) {
t.Errorf("encode expected %v got %v", *t1, _t1);
}
......@@ -570,7 +571,7 @@ func TestNesting(t *testing.T) {
b := new(bytes.Buffer);
encode(b, rt);
var drt RT;
decode(b, getTypeInfo(reflect.Typeof(drt)).typeId, &drt);
decode(b, getTypeInfo(reflect.Typeof(drt)).id, &drt);
if drt.a != rt.a {
t.Errorf("nesting: encode expected %v got %v", *rt, drt);
}
......@@ -612,7 +613,7 @@ func TestAutoIndirection(t *testing.T) {
b := new(bytes.Buffer);
encode(b, t1);
var t0 T0;
t0Id := getTypeInfo(reflect.Typeof(t0)).typeId;
t0Id := getTypeInfo(reflect.Typeof(t0)).id;
decode(b, t0Id, &t0);
if t0.a != 17 || t0.b != 177 || t0.c != 1777 || t0.d != 17777 {
t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0);
......@@ -637,7 +638,7 @@ func TestAutoIndirection(t *testing.T) {
b.Reset();
encode(b, t0);
t1 = T1{};
t1Id := getTypeInfo(reflect.Typeof(t1)).typeId;
t1Id := getTypeInfo(reflect.Typeof(t1)).id;
decode(b, t1Id, &t1);
if t1.a != 17 || *t1.b != 177 || **t1.c != 1777 || ***t1.d != 17777 {
t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.a, *t1.b, **t1.c, ***t1.d);
......@@ -647,7 +648,7 @@ func TestAutoIndirection(t *testing.T) {
b.Reset();
encode(b, t0);
t2 = T2{};
t2Id := getTypeInfo(reflect.Typeof(t2)).typeId;
t2Id := getTypeInfo(reflect.Typeof(t2)).id;
decode(b, t2Id, &t2);
if ***t2.a != 17 || **t2.b != 177 || *t2.c != 1777 || t2.d != 17777 {
t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.a, **t2.b, *t2.c, t2.d);
......@@ -685,7 +686,7 @@ func TestReorderedFields(t *testing.T) {
rt0.c = 3.14159;
b := new(bytes.Buffer);
encode(b, rt0);
rt0Id := getTypeInfo(reflect.Typeof(rt0)).typeId;
rt0Id := getTypeInfo(reflect.Typeof(rt0)).id;
var rt1 RT1;
// Wire type is RT0, local type is RT1.
decode(b, rt0Id, &rt1);
......@@ -723,7 +724,7 @@ func TestIgnoredFields(t *testing.T) {
b := new(bytes.Buffer);
encode(b, it0);
rt0Id := getTypeInfo(reflect.Typeof(it0)).typeId;
rt0Id := getTypeInfo(reflect.Typeof(it0)).id;
var rt1 RT1;
// Wire type is IT0, local type is RT1.
err := decode(b, rt0Id, &rt1);
......
......@@ -18,8 +18,8 @@ import (
)
var (
ErrRange = os.ErrorString("gob: internal error: field numbers out of bounds");
ErrNotStruct = os.ErrorString("gob: TODO: can only handle structs")
errRange = os.ErrorString("gob: internal error: field numbers out of bounds");
errNotStruct = os.ErrorString("gob: TODO: can only handle structs")
)
// The global execution state of an instance of the decoder.
......@@ -347,7 +347,7 @@ func decodeStruct(engine *decEngine, rtyp *reflect.StructType, b *bytes.Buffer,
}
fieldnum := state.fieldnum + delta;
if fieldnum >= len(engine.instr) {
state.err = ErrRange;
state.err = errRange;
break;
}
instr := &engine.instr[fieldnum];
......@@ -376,7 +376,7 @@ func ignoreStruct(engine *decEngine, b *bytes.Buffer) os.Error {
}
fieldnum := state.fieldnum + delta;
if fieldnum >= len(engine.instr) {
state.err = ErrRange;
state.err = errRange;
break;
}
instr := &engine.instr[fieldnum];
......@@ -474,7 +474,7 @@ var decOpMap = map[reflect.Type] decOp {
reflect.Typeof((*reflect.StringType)(nil)): decString,
}
var decIgnoreOpMap = map[TypeId] decOp {
var decIgnoreOpMap = map[typeId] decOp {
tBool: ignoreUint,
tInt: ignoreUint,
tUint: ignoreUint,
......@@ -483,12 +483,12 @@ var decIgnoreOpMap = map[TypeId] decOp {
tString: ignoreUint8Array,
}
func getDecEnginePtr(wireId TypeId, rt reflect.Type) (enginePtr **decEngine, err os.Error)
func getIgnoreEnginePtr(wireId TypeId) (enginePtr **decEngine, err os.Error)
func getDecEnginePtr(wireId typeId, rt reflect.Type) (enginePtr **decEngine, err os.Error)
func getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err os.Error)
// Return the decoding op for the base type under rt and
// the indirection count to reach it.
func decOpFor(wireId TypeId, rt reflect.Type) (decOp, int, os.Error) {
func decOpFor(wireId typeId, rt reflect.Type) (decOp, int, os.Error) {
typ, indir := indirect(rt);
op, ok := decOpMap[reflect.Typeof(typ)];
if !ok {
......@@ -537,7 +537,7 @@ func decOpFor(wireId TypeId, rt reflect.Type) (decOp, int, os.Error) {
}
// Return the decoding op for a field that has no destination.
func decIgnoreOpFor(wireId TypeId) (decOp, os.Error) {
func decIgnoreOpFor(wireId typeId) (decOp, os.Error) {
op, ok := decIgnoreOpMap[wireId];
if !ok {
// Special cases
......@@ -583,7 +583,7 @@ func decIgnoreOpFor(wireId TypeId) (decOp, os.Error) {
// Are these two gob Types compatible?
// Answers the question for basic types, arrays, and slices.
// Structs are considered ok; fields will be checked later.
func compatibleType(fr reflect.Type, fw TypeId) bool {
func compatibleType(fr reflect.Type, fw typeId) bool {
for {
if pt, ok := fr.(*reflect.PtrType); ok {
fr = pt.Elem();
......@@ -645,11 +645,11 @@ func compatibleType(fr reflect.Type, fw TypeId) bool {
return true;
}
func compileDec(wireId TypeId, rt reflect.Type) (engine *decEngine, err os.Error) {
func compileDec(wireId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
srt, ok1 := rt.(*reflect.StructType);
wireStruct, ok2 := wireId.gobType().(*structType);
if !ok1 || !ok2 {
return nil, ErrNotStruct
return nil, errNotStruct
}
engine = new(decEngine);
engine.instr = make([]decInstr, len(wireStruct.field));
......@@ -660,17 +660,17 @@ func compileDec(wireId TypeId, rt reflect.Type) (engine *decEngine, err os.Error
localField, present := srt.FieldByName(wireField.name);
// TODO(r): anonymous names
if !present || localField.Anonymous {
op, err := decIgnoreOpFor(wireField.typeId);
op, err := decIgnoreOpFor(wireField.id);
if err != nil {
return nil, err
}
engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0};
continue;
}
if !compatibleType(localField.Type, wireField.typeId) {
if !compatibleType(localField.Type, wireField.id) {
return nil, os.ErrorString("gob: wrong type for field " + wireField.name + " in type " + wireId.Name());
}
op, indir, err := decOpFor(wireField.typeId, localField.Type);
op, indir, err := decOpFor(wireField.id, localField.Type);
if err != nil {
return nil, err
}
......@@ -680,14 +680,14 @@ func compileDec(wireId TypeId, rt reflect.Type) (engine *decEngine, err os.Error
return;
}
var decoderCache = make(map[reflect.Type] map[TypeId] **decEngine)
var ignorerCache = make(map[TypeId] **decEngine)
var decoderCache = make(map[reflect.Type] map[typeId] **decEngine)
var ignorerCache = make(map[typeId] **decEngine)
// typeLock must be held.
func getDecEnginePtr(wireId TypeId, rt reflect.Type) (enginePtr **decEngine, err os.Error) {
func getDecEnginePtr(wireId typeId, rt reflect.Type) (enginePtr **decEngine, err os.Error) {
decoderMap, ok := decoderCache[rt];
if !ok {
decoderMap = make(map[TypeId] **decEngine);
decoderMap = make(map[typeId] **decEngine);
decoderCache[rt] = decoderMap;
}
if enginePtr, ok = decoderMap[wireId]; !ok {
......@@ -707,7 +707,7 @@ type emptyStruct struct {}
var emptyStructType = reflect.Typeof(emptyStruct{})
// typeLock must be held.
func getIgnoreEnginePtr(wireId TypeId) (enginePtr **decEngine, err os.Error) {
func getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err os.Error) {
var ok bool;
if enginePtr, ok = ignorerCache[wireId]; !ok {
// To handle recursive types, mark this engine as underway before compiling.
......@@ -721,7 +721,7 @@ func getIgnoreEnginePtr(wireId TypeId) (enginePtr **decEngine, err os.Error) {
return
}
func decode(b *bytes.Buffer, wireId TypeId, e interface{}) os.Error {
func decode(b *bytes.Buffer, wireId typeId, e interface{}) os.Error {
// Dereference down to the underlying object.
rt, indir := indirect(reflect.Typeof(e));
v := reflect.NewValue(e);
......
......@@ -13,27 +13,30 @@ import (
"sync";
)
// A Decoder manages the receipt of type and data information read from the
// remote side of a connection.
type Decoder struct {
sync.Mutex; // each item must be received atomically
mutex sync.Mutex; // each item must be received atomically
r io.Reader; // source of the data
seen map[TypeId] *wireType; // which types we've already seen described
seen map[typeId] *wireType; // which types we've already seen described
state *decodeState; // reads data from in-memory buffer
countState *decodeState; // reads counts from wire
buf []byte;
oneByte []byte;
}
// NewDecoder returns a new decoder that reads from the io.Reader.
func NewDecoder(r io.Reader) *Decoder {
dec := new(Decoder);
dec.r = r;
dec.seen = make(map[TypeId] *wireType);
dec.seen = make(map[typeId] *wireType);
dec.state = new(decodeState); // buffer set in Decode(); rest is unimportant
dec.oneByte = make([]byte, 1);
return dec;
}
func (dec *Decoder) recvType(id TypeId) {
func (dec *Decoder) recvType(id typeId) {
// Have we already seen this type? That's an error
if wt_, alreadySeen := dec.seen[id]; alreadySeen {
dec.state.err = os.ErrorString("gob: duplicate type received");
......@@ -47,14 +50,16 @@ func (dec *Decoder) recvType(id TypeId) {
dec.seen[id] = wire;
}
// Decode reads the next value from the connection and stores
// it in the data represented by the empty interface value.
// The value underlying e must be the correct type for the next
// value to be received for this decoder.
// data item received.
func (dec *Decoder) Decode(e interface{}) os.Error {
rt, indir := indirect(reflect.Typeof(e));
// Make sure we're single-threaded through here.
dec.Lock();
defer dec.Unlock();
dec.mutex.Lock();
defer dec.mutex.Unlock();
dec.state.err = nil;
for {
......@@ -81,7 +86,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
}
// Receive a type id.
id := TypeId(decodeInt(dec.state));
id := typeId(decodeInt(dec.state));
if dec.state.err != nil {
break;
}
......
This diff is collapsed.
......@@ -70,7 +70,7 @@ func TestBasicEncoder(t *testing.T) {
t.Fatal("error decoding ET1 type:", err);
}
info := getTypeInfo(reflect.Typeof(ET1{}));
trueWire1 := &wireType{s: info.typeId.gobType().(*structType)};
trueWire1 := &wireType{s: info.id.gobType().(*structType)};
if !reflect.DeepEqual(wire1, trueWire1) {
t.Fatalf("invalid wireType for ET1: expected %+v; got %+v\n", *trueWire1, *wire1);
}
......@@ -91,7 +91,7 @@ func TestBasicEncoder(t *testing.T) {
t.Fatal("error decoding ET2 type:", err);
}
info = getTypeInfo(reflect.Typeof(ET2{}));
trueWire2 := &wireType{s: info.typeId.gobType().(*structType)};
trueWire2 := &wireType{s: info.id.gobType().(*structType)};
if !reflect.DeepEqual(wire2, trueWire2) {
t.Fatalf("invalid wireType for ET2: expected %+v; got %+v\n", *trueWire2, *wire2);
}
......@@ -107,7 +107,7 @@ func TestBasicEncoder(t *testing.T) {
}
// 8) The value of et1
newEt1 := new(ET1);
et1Id := getTypeInfo(reflect.Typeof(*newEt1)).typeId;
et1Id := getTypeInfo(reflect.Typeof(*newEt1)).id;
err = decode(b, et1Id, newEt1);
if err != nil {
t.Fatal("error decoding ET1 value:", err);
......
......@@ -13,23 +13,23 @@ import (
"unicode";
)
// Types are identified by an integer TypeId. These can be passed on the wire.
// Internally, they are used as keys to a map to recover the underlying type info.
type TypeId int32
// A typeId represents a gob Type as an integer that can be passed on the wire.
// Internally, typeIds are used as keys to a map to recover the underlying type info.
type typeId int32
var nextId TypeId // incremented for each new type we build
var nextId typeId // incremented for each new type we build
var typeLock sync.Mutex // set while building a type
type gobType interface {
id() TypeId;
setId(id TypeId);
id() typeId;
setId(id typeId);
Name() string;
String() string;
safeString(seen map[TypeId] bool) string;
safeString(seen map[typeId] bool) string;
}
var types = make(map[reflect.Type] gobType)
var idToType = make(map[TypeId] gobType)
var idToType = make(map[typeId] gobType)
func setTypeId(typ gobType) {
nextId++;
......@@ -37,32 +37,34 @@ func setTypeId(typ gobType) {
idToType[nextId] = typ;
}
func (t TypeId) gobType() gobType {
func (t typeId) gobType() gobType {
if t == 0 {
return nil
}
return idToType[t]
}
func (t TypeId) String() string {
// String returns the string representation of the type associated with the typeId.
func (t typeId) String() string {
return t.gobType().String()
}
func (t TypeId) Name() string {
// Name returns the name of the type associated with the typeId.
func (t typeId) Name() string {
return t.gobType().Name()
}
// Common elements of all types.
type commonType struct {
name string;
_id TypeId;
_id typeId;
}
func (t *commonType) id() TypeId {
func (t *commonType) id() typeId {
return t._id
}
func (t *commonType) setId(id TypeId) {
func (t *commonType) setId(id typeId) {
t._id = id
}
......@@ -79,20 +81,20 @@ func (t *commonType) Name() string {
}
// Basic type identifiers, predefined.
var tBool TypeId
var tInt TypeId
var tUint TypeId
var tFloat TypeId
var tString TypeId
var tBytes TypeId
var tBool typeId
var tInt typeId
var tUint typeId
var tFloat typeId
var tString typeId
var tBytes typeId
// Predefined because it's needed by the Decoder
var tWireType TypeId
var tWireType typeId
// Array type
type arrayType struct {
commonType;
Elem TypeId;
Elem typeId;
Len int;
}
......@@ -102,7 +104,7 @@ func newArrayType(name string, elem gobType, length int) *arrayType {
return a;
}
func (a *arrayType) safeString(seen map[TypeId] bool) string {
func (a *arrayType) safeString(seen map[typeId] bool) string {
if _, ok := seen[a._id]; ok {
return a.name
}
......@@ -117,7 +119,7 @@ func (a *arrayType) String() string {
// Slice type
type sliceType struct {
commonType;
Elem TypeId;
Elem typeId;
}
func newSliceType(name string, elem gobType) *sliceType {
......@@ -126,7 +128,7 @@ func newSliceType(name string, elem gobType) *sliceType {
return s;
}
func (s *sliceType) safeString(seen map[TypeId] bool) string {
func (s *sliceType) safeString(seen map[typeId] bool) string {
if _, ok := seen[s._id]; ok {
return s.name
}
......@@ -135,13 +137,13 @@ func (s *sliceType) safeString(seen map[TypeId] bool) string {
}
func (s *sliceType) String() string {
return s.safeString(make(map[TypeId] bool))
return s.safeString(make(map[typeId] bool))
}
// Struct type
type fieldType struct {
name string;
typeId TypeId;
id typeId;
}
type structType struct {
......@@ -149,7 +151,7 @@ type structType struct {
field []*fieldType;
}
func (s *structType) safeString(seen map[TypeId] bool) string {
func (s *structType) safeString(seen map[typeId] bool) string {
if s == nil {
return "<nil>"
}
......@@ -159,14 +161,14 @@ func (s *structType) safeString(seen map[TypeId] bool) string {
seen[s._id] = true;
str := s.name + " = struct { ";
for _, f := range s.field {
str += fmt.Sprintf("%s %s; ", f.name, f.typeId.gobType().safeString(seen));
str += fmt.Sprintf("%s %s; ", f.name, f.id.gobType().safeString(seen));
}
str += "}";
return str;
}
func (s *structType) String() string {
return s.safeString(make(map[TypeId] bool))
return s.safeString(make(map[typeId] bool))
}
func newStructType(name string) *structType {
......@@ -294,8 +296,14 @@ func getType(name string, rt reflect.Type) gobType {
return t;
}
func checkId(want, got typeId) {
if want != got {
panicln("bootstrap type wrong id:", got.Name(), got, "not", want);
}
}
// used for building the basic types; called only from init()
func bootstrapType(name string, e interface{}) TypeId {
func bootstrapType(name string, e interface{}, expect typeId) typeId {
rt := reflect.Typeof(e);
_, present := types[rt];
if present {
......@@ -304,6 +312,7 @@ func bootstrapType(name string, e interface{}) TypeId {
typ := &commonType{ name: name };
types[rt] = typ;
setTypeId(typ);
checkId(expect, nextId);
return nextId
}
......@@ -329,7 +338,7 @@ func (w *wireType) name() string {
type decEngine struct // defined in decode.go
type encEngine struct // defined in encode.go
type typeInfo struct {
typeId TypeId;
id typeId;
encoder *encEngine;
wire *wireType;
}
......@@ -346,21 +355,26 @@ func getTypeInfo(rt reflect.Type) *typeInfo {
if !ok {
info = new(typeInfo);
name := rt.Name();
info.typeId = getType(name, rt).id();
info.id = getType(name, rt).id();
// assume it's a struct type
info.wire = &wireType{info.typeId.gobType().(*structType)};
info.wire = &wireType{info.id.gobType().(*structType)};
typeInfoMap[rt] = info;
}
return info;
}
func init() {
tBool = bootstrapType("bool", false);
tInt = bootstrapType("int", int(0));
tUint = bootstrapType("uint", uint(0));
tFloat = bootstrapType("float", float64(0));
// Create and check predefined types
tBool = bootstrapType("bool", false, 1);
tInt = bootstrapType("int", int(0), 2);
tUint = bootstrapType("uint", uint(0), 3);
tFloat = bootstrapType("float", float64(0), 4);
// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
tBytes = bootstrapType("bytes", make([]byte, 0));
tString= bootstrapType("string", "");
tWireType = getTypeInfo(reflect.Typeof(wireType{})).typeId;
tBytes = bootstrapType("bytes", make([]byte, 0), 5);
tString= bootstrapType("string", "", 6);
tWireType = getTypeInfo(reflect.Typeof(wireType{})).id;
checkId(7, tWireType);
checkId(8, getTypeInfo(reflect.Typeof(structType{})).id);
checkId(9, getTypeInfo(reflect.Typeof(commonType{})).id);
checkId(10, getTypeInfo(reflect.Typeof(fieldType{})).id);
}
......@@ -12,7 +12,7 @@ import (
)
type typeT struct {
typeId TypeId;
id typeId;
str string;
}
var basicTypes = []typeT {
......@@ -33,10 +33,10 @@ func getTypeUnlocked(name string, rt reflect.Type) gobType {
// Sanity checks
func TestBasic(t *testing.T) {
for _, tt := range basicTypes {
if tt.typeId.String() != tt.str {
t.Errorf("checkType: expected %q got %s", tt.str, tt.typeId.String())
if tt.id.String() != tt.str {
t.Errorf("checkType: expected %q got %s", tt.str, tt.id.String())
}
if tt.typeId == 0 {
if tt.id == 0 {
t.Errorf("id for %q is zero", tt.str)
}
}
......
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