コード例 #1
0
ファイル: helper.go プロジェクト: dropbox/goprotoc
func (g *Generator) transformCustomByteToString(file *FileDescriptor) {
	//TODO(andrei) fix this hacky code
	for _, message := range g.file.desc {
		for _, field := range message.Field {
			if !gogoproto.IsCustomType(field) {
				continue
			}
			_, ctype, _ := GetCustomType(field)
			fieldtype, _ := g.GoBaseType(field)
			if ctype == "string" && fieldtype == "[]byte" {
				stringType := descriptor.FieldDescriptorProto_Type(descriptor.FieldDescriptorProto_TYPE_STRING)
				field.Type = &stringType
			}
		}
	}
}
コード例 #2
0
ファイル: stringer.go プロジェクト: dropbox/goprotoc
func (p *stringer) Generate(file *generator.FileDescriptor) {
	p.PluginImports = generator.NewPluginImports(p.Generator)
	p.atleastOne = false

	p.localName = generator.FileName(file)

	stringsPkg := p.NewImport("strings")
	for _, message := range file.Messages() {
		if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
			continue
		}
		p.atleastOne = true
		ccTypeName := generator.CamelCaseSlice(message.TypeName())
		p.P(`func (this *`, ccTypeName, `) String() string {`)
		p.In()
		p.P(`if this == nil {`)
		p.In()
		p.P(`return "nil"`)
		p.Out()
		p.P(`}`)
		p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
		for _, field := range message.Field {
			fieldname := p.GetFieldName(message, field)
			if field.IsMessage() || p.IsGroup(field) {
				desc := p.ObjectNamed(field.GetTypeName())
				msgname := p.TypeName(desc)
				msgnames := strings.Split(msgname, ".")
				typeName := msgnames[len(msgnames)-1]
				if field.IsRepeated() {
					p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, p.Pkg["fmt"],
						`.Sprintf("%v", this.`, fieldname, `[:this.`, generator.SizerName(fieldname),
						`]), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
				} else {
					fieldValue := "this.Get" + generator.CamelCase(fieldname) + "()"
					if gogoproto.IsCustomType(field) || gogoproto.IsEmbed(field) {
						fieldValue = "this." + fieldname
					}
					p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, p.Pkg["fmt"],
						`.Sprintf("%v", `, fieldValue, `), "`, typeName, `","`, msgname, `"`,
						", 1) + `,", "`,")
				}
			} else if field.IsRepeated() {
				p.P("`", fieldname, ":`", ` + `, p.Pkg["fmt"], `.Sprintf("%v", this.`, fieldname,
					"[:this.", generator.SizerName(fieldname), "]) + `,", "`,")
			} else {
				fieldValue := "this.Get" + generator.CamelCase(fieldname) + "()"
				if gogoproto.IsCustomType(field) || gogoproto.IsEmbed(field) {
					fieldValue = "this." + fieldname
				}
				p.P("`", fieldname, ":`", ` + `, p.Pkg["fmt"], `.Sprintf("%v", `, fieldValue, ") + `,", "`,")
			}
		}
		if message.DescriptorProto.HasExtension() {
			if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
				p.P("`XXX_extensions:` + proto.StringFromExtensionsMap(this.XXX_extensions) + `,`,")
			} else {
				p.P("`XXX_extensions:` + proto.StringFromExtensionsBytes(this.XXX_extensions) + `,`,")
			}
		}
		p.P("`XXX_unrecognized:` + ", p.Pkg["fmt"], `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,")
		p.P("`}`,")
		p.P(`}`, `,""`, ")")
		p.P(`return s`)
		p.Out()
		p.P(`}`)
	}

	if !p.atleastOne {
		return
	}

}
コード例 #3
0
ファイル: testgen.go プロジェクト: dropbox/goprotoc
func (p *testAPI) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
	used := false
	testingPkg := imports.NewImport("testing")
	randPkg := imports.NewImport("math/rand")
	timePkg := imports.NewImport("time")
	for _, message := range file.Messages() {
		ccTypeName := generator.CamelCaseSlice(message.TypeName())
		if !gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
			continue
		}
		used = true
		p.P(`func Test`, ccTypeName, `API(t *`, testingPkg.Use(), `.T) {`)
		p.In()
		p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(),
			`.Now().UnixNano()))`)
		p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
		p.P(`msg := &`, ccTypeName, `{}`)
		p.P(`if !apiEmpty`, ccTypeName, `(msg, t) {`)
		p.In()
		p.P(`t.Fatalf("`, ccTypeName, ` should be empty")`)
		p.Out()
		p.P(`}`)
		p.P(`apiCopy`, ccTypeName, `(msg, p, t)`)
		if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
			p.P(`if err := p.VerboseEqual(msg); err != nil {`)
			p.In()
			p.P(`t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)`)
			p.Out()
			p.P(`}`)
		}
		p.P(`if apiEmpty`, ccTypeName, `(p, t) != apiEmpty`, ccTypeName, `(msg, t) {`)
		p.In()
		p.P(`t.Fatalf("`, ccTypeName, ` should not be empty")`)
		p.Out()
		p.P(`}`)
		p.P(`if !p.Equal(msg) {`)
		p.In()
		p.P(`t.Fatalf("%#v !Proto %#v", msg, p)`)
		p.Out()
		p.P(`}`)
		p.P(`msg.Clear()`)
		p.P(`if !apiEmpty`, ccTypeName, `(msg, t) {`)
		p.In()
		p.P(`t.Fatalf("`, ccTypeName, ` should be empty")`)
		p.Out()
		p.P(`}`)
		p.Out()
		p.P(`}`)
		p.P()

		p.P(`func apiCopy`, ccTypeName, `(dst *`, ccTypeName, `, src *`, ccTypeName, `, t *`,
			testingPkg.Use(), `.T) {`)
		p.In()
		p.P(`if dst == nil || src == nil {`)
		p.In()
		p.P(`t.Fatalf("Cannot copy to(%v) or from(%v) nil message", dst, src)`)
		p.Out()
		p.P(`}`)
		for _, field := range message.Field {
			if gogoproto.IsEmbed(field) {
				p.P(`t.Skip("Cannot copy embed field")`)
				break
			}
			if gogoproto.IsCustomType(field) {
				p.P(`t.Skip("Cannot copy costum field")`)
				break
			}
			fieldName := generator.CamelCase(p.GetFieldName(message, field))
			fieldType, _ := p.GoType(message, field)
			fieldTypeName := generator.GoTypeToName(fieldType)
			if generator.IsRepeated(field) {
				p.P(`for i := 0; i < src.`, fieldName, `Size(); i++ {`)
				p.In()
				if generator.IsMessageType(field) {
					p.P(`src`, fieldName, `, _ := src.Get`, fieldName, `(i)`)
					p.P(`dst`, fieldName, `, _ := dst.Add`, fieldName, `()`)
					p.P(`apiCopy`, fieldTypeName, `(dst`, fieldName, `, src`, fieldName, `, t)`)
				} else {
					p.P(`value, _ := src.Get`, fieldName, `(i)`)
					p.P(`dst.Add`, fieldName, `(value)`)
				}
				p.Out()
				p.P(`}`)
			} else {
				p.P(`if src.Has`, fieldName, `() {`)
				p.In()
				if generator.IsMessageType(field) {
					p.P(`src`, fieldName, ` := src.Get`, fieldName, `()`)
					p.P(`dst`, fieldName, `, _ := dst.Mutate`, fieldName, `()`)
					p.P(`apiCopy`, fieldTypeName, `(dst`, fieldName, `, src`, fieldName, `, t)`)
				} else {
					p.P(`dst.Set`, fieldName, `(src.Get`, fieldName, `())`)
				}
				p.Out()
				p.P(`}`)
			}
		}
		p.P(`src.XXX_unrecognized = dst.XXX_unrecognized`)
		if len(message.ExtensionRange) > 0 {
			p.P(`src.XXX_extensions = dst.XXX_extensions`)
		}
		p.Out()
		p.P(`}`)
		p.P()

		p.P(`func apiEmpty`, ccTypeName, `(msg *`, ccTypeName, `, t *`, testingPkg.Use(), `.T) bool {`)
		p.In()
		p.P(`if msg == nil {`)
		p.In()
		p.P(`return true`)
		p.Out()
		p.P(`}`)
		for _, field := range message.Field {
			if gogoproto.IsEmbed(field) {
				p.P(`t.Skip("Cannot check embed field")`)
				break
			}
			if gogoproto.IsCustomType(field) {
				p.P(`t.Skip("Cannot check costum field")`)
				break
			}
			fieldName := generator.CamelCase(p.GetFieldName(message, field))
			if generator.IsRepeated(field) {
				p.P(`if msg.`, fieldName, `Size() != 0 {`)
			} else {
				p.P(`if msg.Has`, fieldName, `() {`)
			}
			p.In()
			p.P(`return false`)
			p.Out()
			p.P(`}`)
		}
		p.P(`return true`)
		p.Out()
		p.P(`}`)
		p.P()
	}
	return used
}
コード例 #4
0
ファイル: populate.go プロジェクト: dropbox/goprotoc
func (p *plugin) GenerateField(message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
	goTyp, _ := p.GoType(message, field)
	fieldname := p.GetFieldName(message, field)
	goTypName := generator.GoTypeToName(goTyp)
	ctype := ""
	if gogoproto.IsCustomType(field) {
		_, typ, err := generator.GetCustomType(field)
		if err != nil {
			panic(err)
		}
		ctype = typ
	}
	if field.IsMessage() || p.IsGroup(field) {
		funcName := "NewPopulated" + goTypName
		goTypNames := strings.Split(goTypName, ".")
		if len(goTypNames) == 2 {
			funcName = goTypNames[0] + ".NewPopulated" + goTypNames[1]
		} else if len(goTypNames) != 1 {
			panic(fmt.Errorf("unreachable: too many dots in %v", goTypName))
		}
		funcCall := funcName + "(r, easy)"
		if field.IsRepeated() {
			p.P(p.varGen.Next(), ` := r.Intn(10)`)
			p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
			p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
			p.In()
			p.P(p.varGen.Next(), `:= `, funcCall)
			p.P(`this.`, generator.SizerName(fieldname), ` += 1`)
			p.P(`this.`, fieldname, `[i] = `, p.varGen.Current())
			p.Out()
			p.P(`}`)
		} else {
			p.P(p.varGen.Next(), `:= `, funcCall)
			p.P(`this.`, generator.SetterName(fieldname), ` = true`)
			p.P(`this.`, fieldname, ` = `, p.varGen.Current())
		}
	} else {
		if field.IsEnum() {
			enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
			l := len(enum.Value)
			values := make([]string, l)
			for i := range enum.Value {
				values[i] = strconv.Itoa(int(*enum.Value[i].Number))
			}
			arr := "[]int32{" + strings.Join(values, ",") + "}"
			val := strings.Join([]string{generator.GoTypeToName(goTyp), `(`, arr, `[r.Intn(`, fmt.Sprintf("%d", l), `)])`}, "")
			if field.IsRepeated() {
				p.P(p.varGen.Next(), ` := r.Intn(10)`)
				p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
				p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
				p.In()
				p.P(`this.`, generator.SizerName(fieldname), ` += 1`)
				p.P(`this.`, fieldname, `[i] = `, val)
				p.Out()
				p.P(`}`)
			} else {
				p.P(`this.`, generator.SetterName(fieldname), ` = true`)
				p.P(`this.`, fieldname, ` = `, val)
			}
		} else if field.IsString() {
			val := fmt.Sprintf("randString%v(r)", p.localName)
			if field.IsRepeated() {
				p.P(p.varGen.Next(), ` := r.Intn(10)`)
				p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
				p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
				p.In()
				p.P(`this.`, generator.SizerName(fieldname), ` += 1`)
				p.P(`this.`, fieldname, `[i] = `, ctype, `(`, val, `)`)
				p.Out()
				p.P(`}`)
			} else {
				p.P(`this.`, generator.SetterName(fieldname), ` = true`)
				p.P(`this.`, fieldname, ` = `, ctype, `(`, val, `)`)
			}
		} else if field.IsBytes() {
			if field.IsRepeated() {
				p.P(p.varGen.Next(), ` := r.Intn(100)`)
				p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
				p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
				p.In()
				p.P(p.varGen.Next(), ` := r.Intn(100)`)
				p.P(`this.`, generator.SizerName(fieldname), ` += 1`)
				p.P(`this.`, fieldname, `[i] = make([]byte,`, p.varGen.Current(), `)`)
				p.P(`for j := 0; j < `, p.varGen.Current(), `; j++ {`)
				p.In()
				p.P(`this.`, fieldname, `[i][j] = byte(r.Intn(256))`)
				p.Out()
				p.P(`}`)
				p.Out()
				p.P(`}`)
			} else {
				p.P(p.varGen.Next(), ` := r.Intn(100)`)
				p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
				p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
				p.In()
				p.P(`this.`, generator.SetterName(fieldname), ` = true`)
				p.P(`this.`, fieldname, `[i] = byte(r.Intn(256))`)
				p.Out()
				p.P(`}`)
			}
		} else {
			if field.IsRepeated() {
				p.P(p.varGen.Next(), ` := r.Intn(100)`)
				p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
				p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
				p.In()
				p.P(`this.`, generator.SizerName(fieldname), ` += 1`)
				p.P(`this.`, fieldname, `[i] = `, ctype, `(`, value(field), `)`)
				if negative(field) {
					p.P(`if r.Intn(2) == 0 {`)
					p.In()
					p.P(`this.`, fieldname, `[i] *= `, ctype, `(-1)`)
					p.Out()
					p.P(`}`)
				}
				p.Out()
				p.P(`}`)
			} else {
				p.P(`this.`, generator.SetterName(fieldname), ` = true`)
				p.P(`this.`, fieldname, ` = `, ctype, `(`, value(field), `)`)
				if negative(field) {
					p.P(`if r.Intn(2) == 0 {`)
					p.In()
					p.P(`this.`, fieldname, ` *= `, ctype, `(-1)`)
					p.Out()
					p.P(`}`)
				}
			}
		}
	}
}
コード例 #5
0
ファイル: unmarshal.go プロジェクト: dropbox/goprotoc
func (g *Generator) field(field *descriptor.FieldDescriptorProto, fieldname string) {
	repeated := field.IsRepeated()
	gotype, _ := g.GoType(nil, field)
	fieldtype := GoTypeToName(gotype)
	if repeated {
		g.P(`m.`, SizerName(fieldname), ` += 1`)
	} else {
		g.P(`m.`, SetterName(fieldname), ` = true`)
	}
	if gogoproto.IsCustomType(field) {
		_, typ, err := GetCustomType(field)
		if err != nil {
			panic(err)
		}
		fieldtype = typ
	}
	switch *field.Type {
	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
		if repeated {
			g.P(`var v uint64`)
			g.decodeFixed64("v", "uint64")
			g.P(`v2 := `, g.Pkg["math"], `.Float64frombits(v)`)
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v2))`)
		} else {
			g.P(`var v uint64`)
			g.decodeFixed64("v", "uint64")
			g.P(`m.`, fieldname, ` = `, fieldtype, `(`, g.Pkg["math"], `.Float64frombits(v))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
		if repeated {
			g.P(`var v uint32`)
			g.decodeFixed32("v", "uint32")
			g.P(`v2 := `, g.Pkg["math"], `.Float32frombits(v)`)
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v2))`)
		} else {
			g.P(`var v uint32`)
			g.decodeFixed32("v", "uint32")
			g.P(`m.`, fieldname, ` = `, fieldtype, `(`, g.Pkg["math"], `.Float32frombits(v))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_INT64:
		if repeated {
			g.P(`var v int64`)
			g.decodeVarint("v", "int64")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeVarint("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_UINT64:
		if repeated {
			g.P(`var v uint64`)
			g.decodeVarint("v", "uint64")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeVarint("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_INT32:
		if repeated {
			g.P(`var v int32`)
			g.decodeVarint("v", "int32")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeVarint("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
		if repeated {
			g.P(`var v uint64`)
			g.decodeFixed64("v", "uint64")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeFixed64("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
		if repeated {
			g.P(`var v uint32`)
			g.decodeFixed32("v", "uint32")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeFixed32("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_BOOL:
		if repeated {
			g.P(`var v int`)
			g.decodeVarint("v", "int")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(bool(v != 0)))`)
		} else {
			g.P(`var v int`)
			g.decodeVarint("v", "int")
			g.P(`m.`, fieldname, ` = `, fieldtype, `(bool(v != 0))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_STRING:
		g.P(`var stringLen uint64`)
		g.decodeVarint("stringLen", "uint64")
		g.P(`postIndex := index + int(stringLen)`)
		g.P(`if postIndex > l {`)
		g.In()
		g.P(`return `, g.Pkg["io"], `.ErrUnexpectedEOF`)
		g.Out()
		g.P(`}`)
		if repeated {
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(data[index:postIndex]))`)
		} else {
			g.P(`m.`, fieldname, ` = `, fieldtype, `(data[index:postIndex])`)
		}
		g.P(`index = postIndex`)
	case descriptor.FieldDescriptorProto_TYPE_GROUP:
		panic(fmt.Errorf("unmarshaler does not support group %v", fieldname))
	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
		desc := g.ObjectNamed(field.GetTypeName())
		msgname := g.TypeName(desc)
		g.P(`var msglen int`)
		g.decodeVarint("msglen", "int")
		g.P(`postIndex := index + msglen`)
		g.P(`if postIndex > l {`)
		g.In()
		g.P(`return `, g.Pkg["io"], `.ErrUnexpectedEOF`)
		g.Out()
		g.P(`}`)
		if repeated {
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, &`, msgname, `{})`)
			g.P(`m.`, fieldname, `[len(m.`, fieldname, `)-1].Unmarshal(data[index:postIndex])`)
		} else {
			g.P(`m.`, fieldname, ` = &`, msgname, `{}`)
			g.P(`if err := m.`, fieldname, `.Unmarshal(data[index:postIndex]); err != nil {`)
			g.In()
			g.P(`return err`)
			g.Out()
			g.P(`}`)
		}
		g.P(`index = postIndex`)
	case descriptor.FieldDescriptorProto_TYPE_BYTES:
		g.P(`var byteLen int`)
		g.decodeVarint("byteLen", "int")
		g.P(`postIndex := index + byteLen`)
		g.P(`if postIndex > l {`)
		g.In()
		g.P(`return `, g.Pkg["io"], `.ErrUnexpectedEOF`)
		g.Out()
		g.P(`}`)
		if !gogoproto.IsCustomType(field) {
			if repeated {
				g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, make([]byte, postIndex-index))`)
				g.P(`copy(m.`, fieldname, `[len(m.`, fieldname, `)-1], data[index:postIndex])`)
			} else {
				g.P(`m.`, fieldname, ` = append([]byte{}, data[index:postIndex]...)`)
			}
		} else {
			if repeated {
				g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, make(([]byte), postIndex-index))`)
				g.P(`copy(m.`, fieldname, `[len(m.`, fieldname, `)-1], data[index:postIndex])`)
			} else {
				g.P(`m.`, fieldname, ` = append([]byte{}, data[index:postIndex]...)`)
			}
		}
		g.P(`index = postIndex`)
	case descriptor.FieldDescriptorProto_TYPE_UINT32:
		if repeated {
			g.P(`var v uint32`)
			g.decodeVarint("v", "uint32")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeVarint("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_ENUM:
		if !gogoproto.IsCustomType(field) {
			typName := g.TypeName(g.ObjectNamed(field.GetTypeName()))
			if repeated {
				g.P(`var v `, typName)
				g.decodeVarint("v", typName)
				g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else {
				g.decodeVarint("m."+fieldname, typName)
			}
		} else {
			panic("Enum custom types is not supported!")
		}
	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
		if repeated {
			g.P(`var v int32`)
			g.decodeFixed32("v", "int32")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeFixed32("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
		if repeated {
			g.P(`var v int64`)
			g.decodeFixed64("v", "int64")
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.decodeFixed64("m."+fieldname, fieldtype)
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT32:
		g.P(`var v int32`)
		g.decodeVarint("v", "int32")
		g.P(`v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))`)
		if repeated {
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(v))`)
		} else {
			g.P(`m.`, fieldname, ` = `, fieldtype, `(v)`)
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT64:
		g.P(`var v uint64`)
		g.decodeVarint("v", "uint64")
		g.P(`v = (v >> 1) ^ uint64((int64(v&1)<<63)>>63)`)
		if repeated {
			g.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, fieldtype, `(int64(v)))`)
		} else {
			g.P(`m.`, fieldname, ` = `, fieldtype, `(int64(v))`)
		}
	default:
		panic("not implemented")
	}
}