mirror of
https://github.com/golang/go
synced 2024-11-22 01:04:40 -07:00
gob: allow Decode(nil) and have it just discard the next value.
Fixes #1489. R=rsc CC=golang-dev https://golang.org/cl/4187046
This commit is contained in:
parent
bab5536af6
commit
ea46bda72b
@ -153,9 +153,13 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
|
|||||||
|
|
||||||
// Decode reads the next value from the connection and stores
|
// Decode reads the next value from the connection and stores
|
||||||
// it in the data represented by the empty interface value.
|
// 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.
|
// data item received, and must be a pointer.
|
||||||
func (dec *Decoder) Decode(e interface{}) os.Error {
|
func (dec *Decoder) Decode(e interface{}) os.Error {
|
||||||
|
if e == nil {
|
||||||
|
return dec.DecodeValue(nil)
|
||||||
|
}
|
||||||
value := reflect.NewValue(e)
|
value := reflect.NewValue(e)
|
||||||
// If e represents a value as opposed to a pointer, the answer won't
|
// 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.
|
// get back to the caller. Make sure it's a pointer.
|
||||||
@ -169,7 +173,8 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
|
|||||||
// DecodeValue reads the next value from the connection and stores
|
// DecodeValue reads the next value from the connection and stores
|
||||||
// it in the data represented by the reflection value.
|
// it in the data represented by the reflection value.
|
||||||
// The value must be the correct type for the next
|
// 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 {
|
func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
|
||||||
// Make sure we're single-threaded through here.
|
// Make sure we're single-threaded through here.
|
||||||
dec.mutex.Lock()
|
dec.mutex.Lock()
|
||||||
@ -179,8 +184,12 @@ func (dec *Decoder) DecodeValue(value reflect.Value) os.Error {
|
|||||||
dec.err = nil
|
dec.err = nil
|
||||||
id := dec.decodeTypeSequence(false)
|
id := dec.decodeTypeSequence(false)
|
||||||
if id >= 0 {
|
if id >= 0 {
|
||||||
|
// 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)
|
dec.err = dec.decodeValue(id, value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return dec.err
|
return dec.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +384,57 @@ func TestInterfaceIndirect(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
// Another bug from golang-nuts, involving nested interfaces.
|
||||||
type Bug0Outer struct {
|
type Bug0Outer struct {
|
||||||
Bug0Field interface{}
|
Bug0Field interface{}
|
||||||
|
Loading…
Reference in New Issue
Block a user