]> Cypherpunks repositories - gostls13.git/commitdiff
gob: add DecodeValue and EncodeValue
authorRob Pike <r@golang.org>
Tue, 29 Jun 2010 00:11:54 +0000 (17:11 -0700)
committerRob Pike <r@golang.org>
Tue, 29 Jun 2010 00:11:54 +0000 (17:11 -0700)
R=rsc
CC=golang-dev
https://golang.org/cl/1698045

src/pkg/gob/codec_test.go
src/pkg/gob/decode.go
src/pkg/gob/decoder.go
src/pkg/gob/encode.go
src/pkg/gob/encoder.go

index 49a13e84d71299d4032ac0b11bc5ae1260b20911..2caaaa43f8ddcd643fc70e9f259c3fb5be4b0817 100644 (file)
@@ -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 {
index 51e439900035929d64c45b785490b53a87640a5b..a70799e9a729997d4770fc670629df3756f98180 100644 (file)
@@ -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() {
index caec517121c98d072164fb90df08cc816b228549..5ba2750d276bb17abcca238406339a27a2b75dd0 100644 (file)
@@ -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
index a7d44ecc2b0ca5549ed26471a6a57bf32595358a..57af146c04f94defee002b4b31308701c973a553 100644 (file)
@@ -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())
 }
index 28cf6f6e0cf022aaccc3da347869c5bdf320eba7..aba8d0e5c51d616986cf71971e01ba4d92ca02ac 100644 (file)
@@ -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 {