// 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
+// If e is nil, the value will be discarded. Otherwise,
+// the value underlying e must either be the correct type for the next
// data item received, and must be a pointer.
func (dec *Decoder) Decode(e interface{}) os.Error {
+ if e == nil {
+ return dec.DecodeValue(nil)
+ }
value := reflect.NewValue(e)
// If e represents a value as opposed to a pointer, the answer won't
// get back to the caller. Make sure it's a pointer.
// 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.
+// data item received, or it may be nil, which means the
+// value will be discarded.
func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
// Make sure we're single-threaded through here.
dec.mutex.Lock()
dec.err = nil
id := dec.decodeTypeSequence(false)
if id >= 0 {
- dec.err = dec.decodeValue(id, value)
+ // A nil value means "ignore the data". Since it's already read into
+ // the decoder's buffer, all we need to do is not bother to decode it.
+ if value != nil {
+ dec.err = dec.decodeValue(id, value)
+ }
}
return dec.err
}
}
}
+func TestDecodeIntoEmptyStruct(t *testing.T) {
+ type Empty struct{}
+ empty := &Empty{}
+ b := new(bytes.Buffer)
+ enc := NewEncoder(b)
+ err := enc.Encode(&struct{ A int }{23})
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+ dec := NewDecoder(b)
+ err = dec.Decode(empty)
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+}
+
+func TestStructDecodeIntoNil(t *testing.T) {
+ nonempty := &struct{ A int }{23}
+ b := new(bytes.Buffer)
+ enc := NewEncoder(b)
+ err := enc.Encode(nonempty)
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+ dec := NewDecoder(b)
+ err = dec.Decode(nil)
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+ if b.Len() != 0 {
+ t.Fatalf("%d bytes remain after decode", b.Len())
+ }
+}
+
+func TestSingletonDecodeIntoNil(t *testing.T) {
+ b := new(bytes.Buffer)
+ enc := NewEncoder(b)
+ err := enc.Encode("hello world")
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+ dec := NewDecoder(b)
+ err = dec.Decode(nil)
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+ if b.Len() != 0 {
+ t.Fatalf("%d bytes remain after decode", b.Len())
+ }
+}
+
// Another bug from golang-nuts, involving nested interfaces.
type Bug0Outer struct {
Bug0Field interface{}