Просмотр исходного кода

goprotobuf: update for new Set semantics for reflect.Value.

R=rsc
CC=dsymonds, golang-dev
http://codereview.appspot.com/4432051
Rob Pike 15 лет назад
Родитель
Сommit
ccd260cb48
2 измененных файлов с 17 добавлено и 2 удалено
  1. 16 1
      proto/extensions.go
  2. 1 1
      proto/text_parser.go

+ 16 - 1
proto/extensions.go

@@ -169,9 +169,24 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
 
 	p := NewBuffer(nil)
 	v := reflect.NewValue(value)
-	if err := props.enc(p, props, v.UnsafeAddr()); err != nil {
+	if err := props.enc(p, props, unsafeAddr(v)); err != nil {
 		return err
 	}
 	pb.ExtensionMap()[extension.Field] = p.buf
 	return nil
 }
+
+// SetExtension assumes it can call UnsafeAddr on any Value
+// in order to get a pointer it can copy data from.
+// Values that have just been created and do not point
+// into existing structs or slices cannot be addressed,
+// so simulate it by returning a pointer to a copy.
+// Each call allocates once.
+func unsafeAddr(v reflect.Value) uintptr {
+	if v.CanAddr() {
+		return v.UnsafeAddr()
+	}
+	x := reflect.New(v.Type()).Elem()
+	x.Set(v)
+	return x.UnsafeAddr()
+}

+ 1 - 1
proto/text_parser.go

@@ -412,7 +412,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) *ParseError {
 	case reflect.Ptr:
 		// A basic field (indirected through pointer), or a repeated message/group
 		p.back()
-		fv.Set(reflect.Zero(fv.Type().Elem()).Addr())
+		fv.Set(reflect.New(fv.Type().Elem()))
 		return p.readAny(fv.Elem(), props)
 	case reflect.String:
 		if tok.value[0] == '"' {