Commit 1399badb authored by Rob Pike's avatar Rob Pike

- allow wire type and receive type to differ.

- still TODO: ignoring struct fields.

R=rsc
DELTA=309  (240 added, 2 deleted, 67 changed)
OCL=31750
CL=31750
parent f3ffd93a
...@@ -523,7 +523,6 @@ func TestScalarDecInstructions(t *testing.T) { ...@@ -523,7 +523,6 @@ func TestScalarDecInstructions(t *testing.T) {
} }
} }
func TestEndToEnd(t *testing.T) { func TestEndToEnd(t *testing.T) {
type T2 struct { type T2 struct {
t string t string
...@@ -553,7 +552,7 @@ func TestEndToEnd(t *testing.T) { ...@@ -553,7 +552,7 @@ func TestEndToEnd(t *testing.T) {
b := new(bytes.Buffer); b := new(bytes.Buffer);
encode(b, t1); encode(b, t1);
var _t1 T1; var _t1 T1;
decode(b, &_t1); decode(b, getTypeInfo(reflect.Typeof(_t1)).typeId, &_t1);
if !reflect.DeepEqual(t1, &_t1) { if !reflect.DeepEqual(t1, &_t1) {
t.Errorf("encode expected %v got %v", *t1, _t1); t.Errorf("encode expected %v got %v", *t1, _t1);
} }
...@@ -571,7 +570,7 @@ func TestNesting(t *testing.T) { ...@@ -571,7 +570,7 @@ func TestNesting(t *testing.T) {
b := new(bytes.Buffer); b := new(bytes.Buffer);
encode(b, rt); encode(b, rt);
var drt RT; var drt RT;
decode(b, &drt); decode(b, getTypeInfo(reflect.Typeof(drt)).typeId, &drt);
if drt.a != rt.a { if drt.a != rt.a {
t.Errorf("nesting: encode expected %v got %v", *rt, drt); t.Errorf("nesting: encode expected %v got %v", *rt, drt);
} }
...@@ -613,7 +612,8 @@ func TestAutoIndirection(t *testing.T) { ...@@ -613,7 +612,8 @@ func TestAutoIndirection(t *testing.T) {
b := new(bytes.Buffer); b := new(bytes.Buffer);
encode(b, t1); encode(b, t1);
var t0 T0; var t0 T0;
decode(b, &t0); t0Id := getTypeInfo(reflect.Typeof(t0)).typeId;
decode(b, t0Id, &t0);
if t0.a != 17 || t0.b != 177 || t0.c != 1777 || t0.d != 17777 { 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); t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0);
} }
...@@ -627,7 +627,7 @@ func TestAutoIndirection(t *testing.T) { ...@@ -627,7 +627,7 @@ func TestAutoIndirection(t *testing.T) {
b.Reset(); b.Reset();
encode(b, t2); encode(b, t2);
t0 = T0{}; t0 = T0{};
decode(b, &t0); decode(b, t0Id, &t0);
if t0.a != 17 || t0.b != 177 || t0.c != 1777 || t0.d != 17777 { if t0.a != 17 || t0.b != 177 || t0.c != 1777 || t0.d != 17777 {
t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0); t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0);
} }
...@@ -637,7 +637,8 @@ func TestAutoIndirection(t *testing.T) { ...@@ -637,7 +637,8 @@ func TestAutoIndirection(t *testing.T) {
b.Reset(); b.Reset();
encode(b, t0); encode(b, t0);
t1 = T1{}; t1 = T1{};
decode(b, &t1); t1Id := getTypeInfo(reflect.Typeof(t1)).typeId;
decode(b, t1Id, &t1);
if t1.a != 17 || *t1.b != 177 || **t1.c != 1777 || ***t1.d != 17777 { 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); t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.a, *t1.b, **t1.c, ***t1.d);
} }
...@@ -646,7 +647,8 @@ func TestAutoIndirection(t *testing.T) { ...@@ -646,7 +647,8 @@ func TestAutoIndirection(t *testing.T) {
b.Reset(); b.Reset();
encode(b, t0); encode(b, t0);
t2 = T2{}; t2 = T2{};
decode(b, &t2); t2Id := getTypeInfo(reflect.Typeof(t2)).typeId;
decode(b, t2Id, &t2);
if ***t2.a != 17 || **t2.b != 177 || *t2.c != 1777 || t2.d != 17777 { 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); t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.a, **t2.b, *t2.c, t2.d);
} }
...@@ -658,8 +660,72 @@ func TestAutoIndirection(t *testing.T) { ...@@ -658,8 +660,72 @@ func TestAutoIndirection(t *testing.T) {
**t2.b = 0; **t2.b = 0;
*t2.c = 0; *t2.c = 0;
t2.d = 0; t2.d = 0;
decode(b, &t2); decode(b, t2Id, &t2);
if ***t2.a != 17 || **t2.b != 177 || *t2.c != 1777 || t2.d != 17777 { 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); t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.a, **t2.b, *t2.c, t2.d);
} }
} }
type RT0 struct {
a int;
b string;
c float;
}
type RT1 struct {
c float;
b string;
a int;
notSet string;
}
func TestReorderedFields(t *testing.T) {
var rt0 RT0;
rt0.a = 17;
rt0.b = "hello";
rt0.c = 3.14159;
b := new(bytes.Buffer);
encode(b, rt0);
rt0Id := getTypeInfo(reflect.Typeof(rt0)).typeId;
var rt1 RT1;
// Wire type is RT0, local type is RT1.
decode(b, rt0Id, &rt1);
if rt0.a != rt1.a || rt0.b != rt1.b || rt0.c != rt1.c {
t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1);
}
}
// Like an RT0 but with fields we'll ignore on the decode side.
type IT0 struct {
a int64;
b string;
ignore_d []int;
ignore_e [3]float;
ignore_f bool;
ignore_g string;
ignore_h []byte;
c float;
}
func TestIgnoredFields(t *testing.T) {
var it0 IT0;
it0.a = 17;
it0.b = "hello";
it0.c = 3.14159;
it0.ignore_d = []int{ 1, 2, 3 };
it0.ignore_e[0] = 1.0;
it0.ignore_e[1] = 2.0;
it0.ignore_e[2] = 3.0;
it0.ignore_f = true;
it0.ignore_g = "pay no attention";
it0.ignore_h = strings.Bytes("to the curtain");
b := new(bytes.Buffer);
encode(b, it0);
rt0Id := getTypeInfo(reflect.Typeof(it0)).typeId;
var rt1 RT1;
// Wire type is IT0, local type is RT1.
decode(b, rt0Id, &rt1);
if int(it0.a) != rt1.a || it0.b != rt1.b || it0.c != rt1.c {
t.Errorf("rt1->rt0: expected %v; got %v", it0, rt1);
}
}
This diff is collapsed.
...@@ -42,7 +42,7 @@ func (dec *Decoder) recvType(id TypeId) { ...@@ -42,7 +42,7 @@ func (dec *Decoder) recvType(id TypeId) {
// Type: // Type:
wire := new(wireType); wire := new(wireType);
decode(dec.state.b, wire); decode(dec.state.b, tWireType, wire);
// Remember we've seen this type. // Remember we've seen this type.
dec.seen[id] = wire; dec.seen[id] = wire;
} }
...@@ -86,7 +86,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error { ...@@ -86,7 +86,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
return dec.state.err return dec.state.err
} }
// Is it a type? // Is it a new type?
if id < 0 { // 0 is the error state, handled above if id < 0 { // 0 is the error state, handled above
// If the id is negative, we have a type. // If the id is negative, we have a type.
dec.recvType(-id); dec.recvType(-id);
...@@ -97,7 +97,9 @@ func (dec *Decoder) Decode(e interface{}) os.Error { ...@@ -97,7 +97,9 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
} }
// No, it's a value. // No, it's a value.
typeLock.Lock();
info := getTypeInfo(rt); info := getTypeInfo(rt);
typeLock.Unlock();
// Check type compatibility. // Check type compatibility.
// TODO(r): need to make the decoder work correctly if the wire type is compatible // TODO(r): need to make the decoder work correctly if the wire type is compatible
...@@ -108,7 +110,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error { ...@@ -108,7 +110,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
} }
// Receive a value. // Receive a value.
decode(dec.state.b, e); decode(dec.state.b, id, e);
return dec.state.err return dec.state.err
} }
......
...@@ -86,7 +86,9 @@ func (enc *Encoder) sendType(origt reflect.Type) { ...@@ -86,7 +86,9 @@ func (enc *Encoder) sendType(origt reflect.Type) {
} }
// Need to send it. // Need to send it.
typeLock.Lock();
info := getTypeInfo(rt); info := getTypeInfo(rt);
typeLock.Unlock();
// Send the pair (-id, type) // Send the pair (-id, type)
// Id: // Id:
encodeInt(enc.state, -int64(info.typeId)); encodeInt(enc.state, -int64(info.typeId));
......
...@@ -72,7 +72,7 @@ func TestBasicEncoder(t *testing.T) { ...@@ -72,7 +72,7 @@ func TestBasicEncoder(t *testing.T) {
} }
// 2) The wireType for ET1 // 2) The wireType for ET1
wire1 := new(wireType); wire1 := new(wireType);
err := decode(b, wire1); err := decode(b, tWireType, wire1);
if err != nil { if err != nil {
t.Fatal("error decoding ET1 type:", err); t.Fatal("error decoding ET1 type:", err);
} }
...@@ -93,7 +93,7 @@ func TestBasicEncoder(t *testing.T) { ...@@ -93,7 +93,7 @@ func TestBasicEncoder(t *testing.T) {
} }
// 5) The wireType for ET2 // 5) The wireType for ET2
wire2 := new(wireType); wire2 := new(wireType);
err = decode(b, wire2); err = decode(b, tWireType, wire2);
if err != nil { if err != nil {
t.Fatal("error decoding ET2 type:", err); t.Fatal("error decoding ET2 type:", err);
} }
...@@ -114,7 +114,8 @@ func TestBasicEncoder(t *testing.T) { ...@@ -114,7 +114,8 @@ func TestBasicEncoder(t *testing.T) {
} }
// 8) The value of et1 // 8) The value of et1
newEt1 := new(ET1); newEt1 := new(ET1);
err = decode(b, newEt1); et1Id := getTypeInfo(reflect.Typeof(*newEt1)).typeId;
err = decode(b, et1Id, newEt1);
if err != nil { if err != nil {
t.Fatal("error decoding ET1 value:", err); t.Fatal("error decoding ET1 value:", err);
} }
...@@ -144,7 +145,7 @@ func TestBasicEncoder(t *testing.T) { ...@@ -144,7 +145,7 @@ func TestBasicEncoder(t *testing.T) {
} }
// 6a) The value of et1 // 6a) The value of et1
newEt1 = new(ET1); newEt1 = new(ET1);
err = decode(b, newEt1); err = decode(b, et1Id, newEt1);
if err != nil { if err != nil {
t.Fatal("2nd round: error decoding ET1 value:", err); t.Fatal("2nd round: error decoding ET1 value:", err);
} }
......
...@@ -81,6 +81,9 @@ var tFloat TypeId ...@@ -81,6 +81,9 @@ var tFloat TypeId
var tString TypeId var tString TypeId
var tBytes TypeId var tBytes TypeId
// Predefined because it's needed by the Decoder
var tWireType TypeId
// Array type // Array type
type arrayType struct { type arrayType struct {
commonType; commonType;
...@@ -322,7 +325,9 @@ type decEngine struct // defined in decode.go ...@@ -322,7 +325,9 @@ type decEngine struct // defined in decode.go
type encEngine struct // defined in encode.go type encEngine struct // defined in encode.go
type typeInfo struct { type typeInfo struct {
typeId TypeId; typeId TypeId;
decoder *decEngine; // Decoder engine to convert TypeId.Type() to this type. Stored as a pointer to a
// pointer to aid construction of recursive types. Protected by typeLock.
decoderPtr map[TypeId] **decEngine;
encoder *encEngine; encoder *encEngine;
wire *wireType; wire *wireType;
} }
...@@ -330,6 +335,7 @@ type typeInfo struct { ...@@ -330,6 +335,7 @@ type typeInfo struct {
var typeInfoMap = make(map[reflect.Type] *typeInfo) // protected by typeLock var typeInfoMap = make(map[reflect.Type] *typeInfo) // protected by typeLock
// The reflection type must have all its indirections processed out. // The reflection type must have all its indirections processed out.
// typeLock must be held.
func getTypeInfo(rt reflect.Type) *typeInfo { func getTypeInfo(rt reflect.Type) *typeInfo {
if pt, ok := rt.(*reflect.PtrType); ok { if pt, ok := rt.(*reflect.PtrType); ok {
panicln("pointer type in getTypeInfo:", rt.String()) panicln("pointer type in getTypeInfo:", rt.String())
...@@ -339,6 +345,7 @@ func getTypeInfo(rt reflect.Type) *typeInfo { ...@@ -339,6 +345,7 @@ func getTypeInfo(rt reflect.Type) *typeInfo {
info = new(typeInfo); info = new(typeInfo);
path, name := rt.Name(); path, name := rt.Name();
info.typeId = getType(name, rt).id(); info.typeId = getType(name, rt).id();
info.decoderPtr = make(map[TypeId] **decEngine);
// assume it's a struct type // assume it's a struct type
info.wire = &wireType{info.typeId.gobType().(*structType)}; info.wire = &wireType{info.typeId.gobType().(*structType)};
typeInfoMap[rt] = info; typeInfoMap[rt] = info;
...@@ -347,11 +354,12 @@ func getTypeInfo(rt reflect.Type) *typeInfo { ...@@ -347,11 +354,12 @@ func getTypeInfo(rt reflect.Type) *typeInfo {
} }
func init() { func init() {
tBool= bootstrapType("bool", false); tBool = bootstrapType("bool", false);
tInt = bootstrapType("int", int(0)); tInt = bootstrapType("int", int(0));
tUint = bootstrapType("uint", uint(0)); tUint = bootstrapType("uint", uint(0));
tFloat = bootstrapType("float", float64(0)); tFloat = bootstrapType("float", float64(0));
// The string for tBytes is "bytes" not "[]byte" to signify its specialness. // The string for tBytes is "bytes" not "[]byte" to signify its specialness.
tBytes = bootstrapType("bytes", make([]byte, 0)); tBytes = bootstrapType("bytes", make([]byte, 0));
tString= bootstrapType("string", ""); tString= bootstrapType("string", "");
tWireType = getTypeInfo(reflect.Typeof(wireType{})).typeId;
} }
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