goprotobuf: Avoid reflect+interface conversion for Marshaler/Unmarshaler check.
R=r
CC=golang-dev, rsc
http://codereview.appspot.com/5824045
diff --git a/proto/encode.go b/proto/encode.go
index a1a9f1d..a64de1f 100644
--- a/proto/encode.go
+++ b/proto/encode.go
@@ -272,12 +272,16 @@
// Encode a message struct.
func (o *Buffer) enc_struct_message(p *Properties, base uintptr) error {
+ structp := *(*unsafe.Pointer)(unsafe.Pointer(base + p.offset))
+ if structp == nil {
+ return ErrNil
+ }
+
+ typ := p.stype.Elem()
+
// Can the object marshal itself?
- iv := reflect.NewAt(p.stype, unsafe.Pointer(base+p.offset)).Elem().Interface()
- if m, ok := iv.(Marshaler); ok {
- if isNil(reflect.ValueOf(iv)) {
- return ErrNil
- }
+ if p.isMarshaler {
+ m := reflect.NewAt(typ, structp).Interface().(Marshaler)
data, err := m.Marshal()
if err != nil {
return err
@@ -286,19 +290,13 @@
o.EncodeRawBytes(data)
return nil
}
- v := *(**struct{})(unsafe.Pointer(base + p.offset))
- if v == nil {
- return ErrNil
- }
// need the length before we can write out the message itself,
// so marshal into a separate byte buffer first.
obuf := o.buf
o.buf = o.bufalloc()
- b := uintptr(unsafe.Pointer(v))
- typ := p.stype.Elem()
- err := o.enc_struct(typ, b)
+ err := o.enc_struct(typ, uintptr(structp))
nbuf := o.buf
o.buf = obuf
@@ -473,22 +471,19 @@
// Encode a slice of message structs ([]*struct).
func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) error {
- s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
+ s := *(*[]unsafe.Pointer)(unsafe.Pointer(base + p.offset))
l := len(s)
typ := p.stype.Elem()
for i := 0; i < l; i++ {
- v := s[i]
- if v == nil {
+ structp := s[i]
+ if structp == nil {
return ErrRepeatedHasNil
}
// Can the object marshal itself?
- iv := reflect.NewAt(p.stype, unsafe.Pointer(&s[i])).Elem().Interface()
- if m, ok := iv.(Marshaler); ok {
- if isNil(reflect.ValueOf(iv)) {
- return ErrNil
- }
+ if p.isMarshaler {
+ m := reflect.NewAt(typ, structp).Interface().(Marshaler)
data, err := m.Marshal()
if err != nil {
return err
@@ -501,8 +496,7 @@
obuf := o.buf
o.buf = o.bufalloc()
- b := uintptr(unsafe.Pointer(v))
- err := o.enc_struct(typ, b)
+ err := o.enc_struct(typ, uintptr(structp))
nbuf := o.buf
o.buf = obuf