diff options
author | Rob Pike <r@golang.org> | 2010-06-28 17:11:54 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2010-06-28 17:11:54 -0700 |
commit | 6d251a8db9f75e1cca23bb031d23df6900b19bbd (patch) | |
tree | 4635de83a193a36c91bafd5e62197e8be1657854 /src | |
parent | d612cf93ad4543b75f8b206bf35406ef2dbb2cdc (diff) | |
download | golang-6d251a8db9f75e1cca23bb031d23df6900b19bbd.tar.gz |
gob: add DecodeValue and EncodeValue
R=rsc
CC=golang-dev
http://codereview.appspot.com/1698045
Diffstat (limited to 'src')
-rw-r--r-- | src/pkg/gob/codec_test.go | 2 | ||||
-rw-r--r-- | src/pkg/gob/decode.go | 8 | ||||
-rw-r--r-- | src/pkg/gob/decoder.go | 13 | ||||
-rw-r--r-- | src/pkg/gob/encode.go | 13 | ||||
-rw-r--r-- | src/pkg/gob/encoder.go | 12 |
5 files changed, 30 insertions, 18 deletions
diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go index 49a13e84d..2caaaa43f 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 51e439900..a70799e9a 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 caec51712..5ba2750d2 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 a7d44ecc2..57af146c0 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 28cf6f6e0..aba8d0e5c 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 { |