aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2010-06-28 17:11:54 -0700
committerRob Pike <r@golang.org>2010-06-28 17:11:54 -0700
commit12a4d84371d6d60b715d2fca3fe9bb45d5ca7454 (patch)
tree2564bbc0f2bb6174c0fc54ec6b02277d9e5056c3
parent6d61da6350cce067305be8e03c7dac182214440d (diff)
downloadgo-12a4d84371d6d60b715d2fca3fe9bb45d5ca7454.tar.gz
go-12a4d84371d6d60b715d2fca3fe9bb45d5ca7454.zip
gob: add DecodeValue and EncodeValue
R=rsc CC=golang-dev https://golang.org/cl/1698045
-rw-r--r--src/pkg/gob/codec_test.go2
-rw-r--r--src/pkg/gob/decode.go8
-rw-r--r--src/pkg/gob/decoder.go13
-rw-r--r--src/pkg/gob/encode.go13
-rw-r--r--src/pkg/gob/encoder.go12
5 files changed, 30 insertions, 18 deletions
diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go
index 49a13e84d7..2caaaa43f8 100644
--- a/src/pkg/gob/codec_test.go
+++ b/src/pkg/gob/codec_test.go
@@ -1028,7 +1028,7 @@ func TestInvalidField(t *testing.T) {
var bad0 Bad0
bad0.inter = 17
b := new(bytes.Buffer)
- err := encode(b, &bad0)
+ err := encode(b, reflect.NewValue(&bad0))
if err == nil {
t.Error("expected error; got none")
} else if strings.Index(err.String(), "interface") < 0 {
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
index 51e4399000..a70799e9a7 100644
--- a/src/pkg/gob/decode.go
+++ b/src/pkg/gob/decode.go
@@ -918,9 +918,9 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er
return
}
-func (dec *Decoder) decode(wireId typeId, e interface{}) os.Error {
+func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error {
// Dereference down to the underlying struct type.
- rt, indir := indirect(reflect.Typeof(e))
+ rt, indir := indirect(val.Type())
enginePtr, err := dec.getDecEnginePtr(wireId, rt)
if err != nil {
return err
@@ -931,9 +931,9 @@ func (dec *Decoder) decode(wireId typeId, e interface{}) os.Error {
name := rt.Name()
return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name)
}
- return decodeStruct(engine, st, dec.state.b, uintptr(reflect.NewValue(e).Addr()), indir)
+ return decodeStruct(engine, st, dec.state.b, uintptr(val.Addr()), indir)
}
- return decodeSingle(engine, rt, dec.state.b, uintptr(reflect.NewValue(e).Addr()), indir)
+ return decodeSingle(engine, rt, dec.state.b, uintptr(val.Addr()), indir)
}
func init() {
diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go
index caec517121..5ba2750d27 100644
--- a/src/pkg/gob/decoder.go
+++ b/src/pkg/gob/decoder.go
@@ -47,7 +47,7 @@ func (dec *Decoder) recvType(id typeId) {
// Type:
wire := new(wireType)
- dec.state.err = dec.decode(tWireType, wire)
+ dec.state.err = dec.decode(tWireType, reflect.NewValue(wire))
// Remember we've seen this type.
dec.wireType[id] = wire
}
@@ -55,7 +55,7 @@ func (dec *Decoder) recvType(id typeId) {
// 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
-// data item received.
+// data item received, which must be a pointer.
func (dec *Decoder) Decode(e interface{}) os.Error {
// If e represents a value, the answer won't get back to the
// caller. Make sure it's a pointer.
@@ -63,7 +63,14 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
dec.state.err = os.ErrorString("gob: attempt to decode into a non-pointer")
return dec.state.err
}
+ return dec.DecodeValue(reflect.NewValue(e))
+}
+// DecodeValue reads the next value from the connection and stores
+// it in the data represented by the reflection value.
+// The value must be the correct type for the next
+// data item received.
+func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
// Make sure we're single-threaded through here.
dec.mutex.Lock()
defer dec.mutex.Unlock()
@@ -114,7 +121,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
dec.state.err = errBadType
break
}
- dec.state.err = dec.decode(id, e)
+ dec.state.err = dec.decode(id, value)
break
}
return dec.state.err
diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go
index a7d44ecc2b..57af146c04 100644
--- a/src/pkg/gob/encode.go
+++ b/src/pkg/gob/encode.go
@@ -798,12 +798,11 @@ func getEncEngine(rt reflect.Type) (*encEngine, os.Error) {
return info.encoder, err
}
-func encode(b *bytes.Buffer, e interface{}) os.Error {
+func encode(b *bytes.Buffer, value reflect.Value) os.Error {
// Dereference down to the underlying object.
- rt, indir := indirect(reflect.Typeof(e))
- v := reflect.NewValue(e)
+ rt, indir := indirect(value.Type())
for i := 0; i < indir; i++ {
- v = reflect.Indirect(v)
+ value = reflect.Indirect(value)
}
typeLock.Lock()
engine, err := getEncEngine(rt)
@@ -811,8 +810,8 @@ func encode(b *bytes.Buffer, e interface{}) os.Error {
if err != nil {
return err
}
- if _, ok := v.(*reflect.StructValue); ok {
- return encodeStruct(engine, b, v.Addr())
+ if _, ok := value.(*reflect.StructValue); ok {
+ return encodeStruct(engine, b, value.Addr())
}
- return encodeSingle(engine, b, v.Addr())
+ return encodeSingle(engine, b, value.Addr())
}
diff --git a/src/pkg/gob/encoder.go b/src/pkg/gob/encoder.go
index 28cf6f6e0c..aba8d0e5c5 100644
--- a/src/pkg/gob/encoder.go
+++ b/src/pkg/gob/encoder.go
@@ -115,7 +115,7 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) {
// Id:
encodeInt(enc.state, -int64(info.id))
// Type:
- encode(enc.state.b, info.wire)
+ encode(enc.state.b, reflect.NewValue(info.wire))
enc.send()
if enc.state.err != nil {
return
@@ -140,13 +140,19 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) {
// Encode transmits the data item represented by the empty interface value,
// guaranteeing that all necessary type information has been transmitted first.
func (enc *Encoder) Encode(e interface{}) os.Error {
+ return enc.EncodeValue(reflect.NewValue(e))
+}
+
+// EncodeValue transmits the data item represented by the reflection value,
+// guaranteeing that all necessary type information has been transmitted first.
+func (enc *Encoder) EncodeValue(value reflect.Value) os.Error {
// Make sure we're single-threaded through here, so multiple
// goroutines can share an encoder.
enc.mutex.Lock()
defer enc.mutex.Unlock()
enc.state.err = nil
- rt, _ := indirect(reflect.Typeof(e))
+ rt, _ := indirect(value.Type())
// Sanity check only: encoder should never come in with data present.
if enc.state.b.Len() > 0 || enc.countState.b.Len() > 0 {
@@ -181,7 +187,7 @@ func (enc *Encoder) Encode(e interface{}) os.Error {
encodeInt(enc.state, int64(enc.sent[rt]))
// Encode the object.
- err := encode(enc.state.b, e)
+ err := encode(enc.state.b, value)
if err != nil {
enc.setError(err)
} else {