Ejemplo n.º 1
0
func (p *plugin) Generate(file *generator.FileDescriptor) {
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	for _, msg := range file.Messages() {
		getters := gogoproto.HasGoGetters(file.FileDescriptorProto, msg.DescriptorProto)
		face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
		for _, field := range msg.GetField() {
			if len(field.GetDefaultValue()) > 0 {
				if !getters {
					fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
					os.Exit(1)
				}
				if face {
					fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
					os.Exit(1)
				}
			}
			if gogoproto.IsNullable(field) {
				continue
			}
			if len(field.GetDefaultValue()) > 0 {
				fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				os.Exit(1)
			}
			if !field.IsMessage() && !gogoproto.IsCustomType(field) {
				if field.IsRepeated() {
					fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				} else if proto3 {
					fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
					os.Exit(1)
				}
				if field.IsBytes() {
					fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				}
			}
			if !field.IsEnum() {
				continue
			}
			enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
			if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 {
				fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName())
				os.Exit(1)
			}
		}
	}
	for _, e := range file.GetExtension() {
		if !gogoproto.IsNullable(e) {
			fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name))
			os.Exit(1)
		}
	}
}
Ejemplo n.º 2
0
func (p *size) std(field *descriptor.FieldDescriptorProto, name string) (string, bool) {
	if gogoproto.IsStdTime(field) {
		if gogoproto.IsNullable(field) {
			return p.typesPkg.Use() + `.SizeOfStdTime(*` + name + `)`, true
		} else {
			return p.typesPkg.Use() + `.SizeOfStdTime(` + name + `)`, true
		}
	} else if gogoproto.IsStdDuration(field) {
		if gogoproto.IsNullable(field) {
			return p.typesPkg.Use() + `.SizeOfStdDuration(*` + name + `)`, true
		} else {
			return p.typesPkg.Use() + `.SizeOfStdDuration(` + name + `)`, true
		}
	}
	return "", false
}
Ejemplo n.º 3
0
func (p *plugin) Generate(file *generator.FileDescriptor) {
	for _, msg := range file.Messages() {
		face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
		for _, field := range msg.GetField() {
			if field.OneofIndex == nil {
				continue
			}
			if face {
				fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				os.Exit(1)
			}
			if gogoproto.IsEmbed(field) {
				fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				os.Exit(1)
			}
			if !gogoproto.IsNullable(field) {
				fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				os.Exit(1)
			}
			if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) {
				fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
				os.Exit(1)
			}
		}
	}
}
Ejemplo n.º 4
0
// GoMapValueTypes returns the map value Go type and the alias map value Go type (for casting), taking into
// account whether the map is nullable or the value is a message.
func GoMapValueTypes(mapField, valueField *descriptor.FieldDescriptorProto, goValueType, goValueAliasType string) (nullable bool, outGoType string, outGoAliasType string) {
	nullable = gogoproto.IsNullable(mapField) && (valueField.IsMessage() || gogoproto.IsCustomType(mapField))
	if nullable {
		// ensure the non-aliased Go value type is a pointer for consistency
		if strings.HasPrefix(goValueType, "*") {
			outGoType = goValueType
		} else {
			outGoType = "*" + goValueType
		}
		outGoAliasType = goValueAliasType
	} else {
		outGoType = strings.Replace(goValueType, "*", "", 1)
		outGoAliasType = strings.Replace(goValueAliasType, "*", "", 1)
	}
	return
}
Ejemplo n.º 5
0
func (g *Generator) GetMapValueField(field, valField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
	if gogoproto.IsCustomType(field) && gogoproto.IsCastValue(field) {
		g.Fail("cannot have a customtype and casttype: ", field.String())
	}
	valField = proto.Clone(valField).(*descriptor.FieldDescriptorProto)
	if valField.Options == nil {
		valField.Options = &descriptor.FieldOptions{}
	}

	stdtime := gogoproto.IsStdTime(field)
	if stdtime {
		if err := proto.SetExtension(valField.Options, gogoproto.E_Stdtime, &stdtime); err != nil {
			g.Fail(err.Error())
		}
	}

	stddur := gogoproto.IsStdDuration(field)
	if stddur {
		if err := proto.SetExtension(valField.Options, gogoproto.E_Stdduration, &stddur); err != nil {
			g.Fail(err.Error())
		}
	}

	if valType := gogoproto.GetCastValue(field); len(valType) > 0 {
		if err := proto.SetExtension(valField.Options, gogoproto.E_Casttype, &valType); err != nil {
			g.Fail(err.Error())
		}
	}
	if valType := gogoproto.GetCustomType(field); len(valType) > 0 {
		if err := proto.SetExtension(valField.Options, gogoproto.E_Customtype, &valType); err != nil {
			g.Fail(err.Error())
		}
	}

	nullable := gogoproto.IsNullable(field)
	if err := proto.SetExtension(valField.Options, gogoproto.E_Nullable, &nullable); err != nil {
		g.Fail(err.Error())
	}
	return valField
}
Ejemplo n.º 6
0
func (p *plugin) Generate(file *generator.FileDescriptor) {
	p.atleastOne = false
	p.PluginImports = generator.NewPluginImports(p.Generator)
	p.varGen = NewVarGen()
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	p.typesPkg = p.NewImport("github.com/maditya/protobuf/types")
	p.localName = generator.FileName(file)
	protoPkg := p.NewImport("github.com/maditya/protobuf/proto")
	if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
		protoPkg = p.NewImport("github.com/golang/protobuf/proto")
	}

	for _, message := range file.Messages() {
		if !gogoproto.HasPopulate(file.FileDescriptorProto, message.DescriptorProto) {
			continue
		}
		if message.DescriptorProto.GetOptions().GetMapEntry() {
			continue
		}
		p.atleastOne = true
		ccTypeName := generator.CamelCaseSlice(message.TypeName())
		loopLevels := make([]int, len(message.Field))
		maxLoopLevel := 0
		for i, field := range message.Field {
			loopLevels[i] = p.loops(field, message)
			if loopLevels[i] > maxLoopLevel {
				maxLoopLevel = loopLevels[i]
			}
		}
		ranTotal := 0
		for i := range loopLevels {
			ranTotal += int(math.Pow10(maxLoopLevel - loopLevels[i]))
		}
		p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
		p.In()
		p.P(`this := &`, ccTypeName, `{}`)
		if gogoproto.IsUnion(message.File(), message.DescriptorProto) && len(message.Field) > 0 {
			p.P(`fieldNum := r.Intn(`, fmt.Sprintf("%d", ranTotal), `)`)
			p.P(`switch fieldNum {`)
			k := 0
			for i, field := range message.Field {
				is := []string{}
				ran := int(math.Pow10(maxLoopLevel - loopLevels[i]))
				for j := 0; j < ran; j++ {
					is = append(is, fmt.Sprintf("%d", j+k))
				}
				k += ran
				p.P(`case `, strings.Join(is, ","), `:`)
				p.In()
				p.GenerateField(file, message, field)
				p.Out()
			}
			p.P(`}`)
		} else {
			var maxFieldNumber int32
			oneofs := make(map[string]struct{})
			for fieldIndex, field := range message.Field {
				if field.GetNumber() > maxFieldNumber {
					maxFieldNumber = field.GetNumber()
				}
				oneof := field.OneofIndex != nil
				if !oneof {
					if field.IsRequired() || (!gogoproto.IsNullable(field) && !field.IsRepeated()) || (proto3 && !field.IsMessage()) {
						p.GenerateField(file, message, field)
					} else {
						if loopLevels[fieldIndex] > 0 {
							p.P(`if r.Intn(10) == 0 {`)
						} else {
							p.P(`if r.Intn(10) != 0 {`)
						}
						p.In()
						p.GenerateField(file, message, field)
						p.Out()
						p.P(`}`)
					}
				} else {
					fieldname := p.GetFieldName(message, field)
					if _, ok := oneofs[fieldname]; ok {
						continue
					} else {
						oneofs[fieldname] = struct{}{}
					}
					fieldNumbers := []int32{}
					for _, f := range message.Field {
						fname := p.GetFieldName(message, f)
						if fname == fieldname {
							fieldNumbers = append(fieldNumbers, f.GetNumber())
						}
					}

					p.P(`oneofNumber_`, fieldname, ` := `, fmt.Sprintf("%#v", fieldNumbers), `[r.Intn(`, strconv.Itoa(len(fieldNumbers)), `)]`)
					p.P(`switch oneofNumber_`, fieldname, ` {`)
					for _, f := range message.Field {
						fname := p.GetFieldName(message, f)
						if fname != fieldname {
							continue
						}
						p.P(`case `, strconv.Itoa(int(f.GetNumber())), `:`)
						p.In()
						ccTypeName := p.OneOfTypeName(message, f)
						p.P(`this.`, fname, ` = NewPopulated`, ccTypeName, `(r, easy)`)
						p.Out()
					}
					p.P(`}`)
				}
			}
			if message.DescriptorProto.HasExtension() {
				p.P(`if !easy && r.Intn(10) != 0 {`)
				p.In()
				p.P(`l := r.Intn(5)`)
				p.P(`for i := 0; i < l; i++ {`)
				p.In()
				if len(message.DescriptorProto.GetExtensionRange()) > 1 {
					p.P(`eIndex := r.Intn(`, strconv.Itoa(len(message.DescriptorProto.GetExtensionRange())), `)`)
					p.P(`fieldNumber := 0`)
					p.P(`switch eIndex {`)
					for i, e := range message.DescriptorProto.GetExtensionRange() {
						p.P(`case `, strconv.Itoa(i), `:`)
						p.In()
						p.P(`fieldNumber = r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
						p.Out()
						if e.GetEnd() > maxFieldNumber {
							maxFieldNumber = e.GetEnd()
						}
					}
					p.P(`}`)
				} else {
					e := message.DescriptorProto.GetExtensionRange()[0]
					p.P(`fieldNumber := r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
					if e.GetEnd() > maxFieldNumber {
						maxFieldNumber = e.GetEnd()
					}
				}
				p.P(`wire := r.Intn(4)`)
				p.P(`if wire == 3 { wire = 5 }`)
				p.P(`data := randField`, p.localName, `(nil, r, fieldNumber, wire)`)
				p.P(protoPkg.Use(), `.SetRawExtension(this, int32(fieldNumber), data)`)
				p.Out()
				p.P(`}`)
				p.Out()
				p.P(`}`)
			}

			if maxFieldNumber < (1 << 10) {
				p.P(`if !easy && r.Intn(10) != 0 {`)
				p.In()
				if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
					p.P(`this.XXX_unrecognized = randUnrecognized`, p.localName, `(r, `, strconv.Itoa(int(maxFieldNumber+1)), `)`)
				}
				p.Out()
				p.P(`}`)
			}
		}
		p.P(`return this`)
		p.Out()
		p.P(`}`)
		p.P(``)

		//Generate NewPopulated functions for oneof fields
		m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
		for _, f := range m.Field {
			oneof := f.OneofIndex != nil
			if !oneof {
				continue
			}
			ccTypeName := p.OneOfTypeName(message, f)
			p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
			p.In()
			p.P(`this := &`, ccTypeName, `{}`)
			vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly(f)
			p.GenerateField(file, message, f)
			p.P(`return this`)
			p.Out()
			p.P(`}`)
		}
	}

	if !p.atleastOne {
		return
	}

	p.P(`type randy`, p.localName, ` interface {`)
	p.In()
	p.P(`Float32() float32`)
	p.P(`Float64() float64`)
	p.P(`Int63() int64`)
	p.P(`Int31() int32`)
	p.P(`Uint32() uint32`)
	p.P(`Intn(n int) int`)
	p.Out()
	p.P(`}`)

	p.P(`func randUTF8Rune`, p.localName, `(r randy`, p.localName, `) rune {`)
	p.In()
	p.P(`ru := r.Intn(62)`)
	p.P(`if ru < 10 {`)
	p.In()
	p.P(`return rune(ru+48)`)
	p.Out()
	p.P(`} else if ru < 36 {`)
	p.In()
	p.P(`return rune(ru+55)`)
	p.Out()
	p.P(`}`)
	p.P(`return rune(ru+61)`)
	p.Out()
	p.P(`}`)

	p.P(`func randString`, p.localName, `(r randy`, p.localName, `) string {`)
	p.In()
	p.P(p.varGen.Next(), ` := r.Intn(100)`)
	p.P(`tmps := make([]rune, `, p.varGen.Current(), `)`)
	p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
	p.In()
	p.P(`tmps[i] = randUTF8Rune`, p.localName, `(r)`)
	p.Out()
	p.P(`}`)
	p.P(`return string(tmps)`)
	p.Out()
	p.P(`}`)

	p.P(`func randUnrecognized`, p.localName, `(r randy`, p.localName, `, maxFieldNumber int) (data []byte) {`)
	p.In()
	p.P(`l := r.Intn(5)`)
	p.P(`for i := 0; i < l; i++ {`)
	p.In()
	p.P(`wire := r.Intn(4)`)
	p.P(`if wire == 3 { wire = 5 }`)
	p.P(`fieldNumber := maxFieldNumber + r.Intn(100)`)
	p.P(`data = randField`, p.localName, `(data, r, fieldNumber, wire)`)
	p.Out()
	p.P(`}`)
	p.P(`return data`)
	p.Out()
	p.P(`}`)

	p.P(`func randField`, p.localName, `(data []byte, r randy`, p.localName, `, fieldNumber int, wire int) []byte {`)
	p.In()
	p.P(`key := uint32(fieldNumber)<<3 | uint32(wire)`)
	p.P(`switch wire {`)
	p.P(`case 0:`)
	p.In()
	p.P(`data = encodeVarintPopulate`, p.localName, `(data, uint64(key))`)
	p.P(p.varGen.Next(), ` := r.Int63()`)
	p.P(`if r.Intn(2) == 0 {`)
	p.In()
	p.P(p.varGen.Current(), ` *= -1`)
	p.Out()
	p.P(`}`)
	p.P(`data = encodeVarintPopulate`, p.localName, `(data, uint64(`, p.varGen.Current(), `))`)
	p.Out()
	p.P(`case 1:`)
	p.In()
	p.P(`data = encodeVarintPopulate`, p.localName, `(data, uint64(key))`)
	p.P(`data = append(data, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
	p.Out()
	p.P(`case 2:`)
	p.In()
	p.P(`data = encodeVarintPopulate`, p.localName, `(data, uint64(key))`)
	p.P(`ll := r.Intn(100)`)
	p.P(`data = encodeVarintPopulate`, p.localName, `(data, uint64(ll))`)
	p.P(`for j := 0; j < ll; j++ {`)
	p.In()
	p.P(`data = append(data, byte(r.Intn(256)))`)
	p.Out()
	p.P(`}`)
	p.Out()
	p.P(`default:`)
	p.In()
	p.P(`data = encodeVarintPopulate`, p.localName, `(data, uint64(key))`)
	p.P(`data = append(data, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
	p.Out()
	p.P(`}`)
	p.P(`return data`)
	p.Out()
	p.P(`}`)

	p.P(`func encodeVarintPopulate`, p.localName, `(data []byte, v uint64) []byte {`)
	p.In()
	p.P(`for v >= 1<<7 {`)
	p.In()
	p.P(`data = append(data, uint8(uint64(v)&0x7f|0x80))`)
	p.P(`v >>= 7`)
	p.Out()
	p.P(`}`)
	p.P(`data = append(data, uint8(v))`)
	p.P(`return data`)
	p.Out()
	p.P(`}`)

}
Ejemplo n.º 7
0
func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	goTyp, _ := p.GoType(message, field)
	fieldname := p.GetOneOfFieldName(message, field)
	goTypName := generator.GoTypeToName(goTyp)
	if p.IsMap(field) {
		m := p.GoMapType(nil, field)
		keygoTyp, _ := p.GoType(nil, m.KeyField)
		keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
		keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
		keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)

		valuegoTyp, _ := p.GoType(nil, m.ValueField)
		valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
		keytypName := generator.GoTypeToName(keygoTyp)
		keygoAliasTyp = generator.GoTypeToName(keygoAliasTyp)
		valuetypAliasName := generator.GoTypeToName(valuegoAliasTyp)

		nullable, valuegoTyp, valuegoAliasTyp := generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)

		p.P(p.varGen.Next(), ` := r.Intn(10)`)
		p.P(`this.`, fieldname, ` = make(`, m.GoType, `)`)
		p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
		p.In()
		keyval := ""
		if m.KeyField.IsString() {
			keyval = fmt.Sprintf("randString%v(r)", p.localName)
		} else {
			keyval = value(keytypName, m.KeyField.GetType())
		}
		if keygoAliasTyp != keygoTyp {
			keyval = keygoAliasTyp + `(` + keyval + `)`
		}
		if m.ValueField.IsMessage() || p.IsGroup(field) ||
			(m.ValueField.IsBytes() && gogoproto.IsCustomType(field)) {
			s := `this.` + fieldname + `[` + keyval + `] = `
			if gogoproto.IsStdTime(field) || gogoproto.IsStdDuration(field) {
				valuegoTyp = valuegoAliasTyp
			}
			funcCall := p.getCustomFuncCall(goTypName)
			if !gogoproto.IsCustomType(field) {
				goTypName = generator.GoTypeToName(valuegoTyp)
				funcCall = p.getFuncCall(goTypName)
			}
			if !nullable {
				funcCall = `*` + funcCall
			}
			if valuegoTyp != valuegoAliasTyp {
				funcCall = `(` + valuegoAliasTyp + `)(` + funcCall + `)`
			}
			s += funcCall
			p.P(s)
		} else if m.ValueField.IsEnum() {
			s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + p.getEnumVal(m.ValueField, valuegoTyp)
			p.P(s)
		} else if m.ValueField.IsBytes() {
			count := p.varGen.Next()
			p.P(count, ` := r.Intn(100)`)
			p.P(p.varGen.Next(), ` := `, keyval)
			p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = make(`, valuegoTyp, `, `, count, `)`)
			p.P(`for i := 0; i < `, count, `; i++ {`)
			p.In()
			p.P(`this.`, fieldname, `[`, p.varGen.Current(), `][i] = byte(r.Intn(256))`)
			p.Out()
			p.P(`}`)
		} else if m.ValueField.IsString() {
			s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + fmt.Sprintf("randString%v(r)", p.localName)
			p.P(s)
		} else {
			p.P(p.varGen.Next(), ` := `, keyval)
			p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = `, value(valuetypAliasName, m.ValueField.GetType()))
			if negative(m.ValueField.GetType()) {
				p.P(`if r.Intn(2) == 0 {`)
				p.In()
				p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] *= -1`)
				p.Out()
				p.P(`}`)
			}
		}
		p.Out()
		p.P(`}`)
	} else if field.IsMessage() || p.IsGroup(field) {
		funcCall := p.getFuncCall(goTypName)
		if field.IsRepeated() {
			p.P(p.varGen.Next(), ` := r.Intn(5)`)
			p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
			p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
			p.In()
			if gogoproto.IsNullable(field) {
				p.P(`this.`, fieldname, `[i] = `, funcCall)
			} else {
				p.P(p.varGen.Next(), `:= `, funcCall)
				p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
			}
			p.Out()
			p.P(`}`)
		} else {
			if gogoproto.IsNullable(field) {
				p.P(`this.`, fieldname, ` = `, funcCall)
			} else {
				p.P(p.varGen.Next(), `:= `, funcCall)
				p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
			}
		}
	} else {
		if field.IsEnum() {
			val := p.getEnumVal(field, goTyp)
			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.`, fieldname, `[i] = `, val)
				p.Out()
				p.P(`}`)
			} else if !gogoproto.IsNullable(field) || proto3 {
				p.P(`this.`, fieldname, ` = `, val)
			} else {
				p.P(p.varGen.Next(), ` := `, val)
				p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
			}
		} else if gogoproto.IsCustomType(field) {
			funcCall := p.getCustomFuncCall(goTypName)
			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.`, fieldname, `[i] = *`, p.varGen.Current())
				p.Out()
				p.P(`}`)
			} else if gogoproto.IsNullable(field) {
				p.P(`this.`, fieldname, ` = `, funcCall)
			} else {
				p.P(p.varGen.Next(), `:= `, funcCall)
				p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
			}
		} else if field.IsBytes() {
			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(), ` := r.Intn(100)`)
				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.`, fieldname, `[i] = byte(r.Intn(256))`)
				p.Out()
				p.P(`}`)
			}
		} 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.`, fieldname, `[i] = `, val)
				p.Out()
				p.P(`}`)
			} else if !gogoproto.IsNullable(field) || proto3 {
				p.P(`this.`, fieldname, ` = `, val)
			} else {
				p.P(p.varGen.Next(), `:= `, val)
				p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
			}
		} else {
			typName := generator.GoTypeToName(goTyp)
			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.`, fieldname, `[i] = `, value(typName, field.GetType()))
				if negative(field.GetType()) {
					p.P(`if r.Intn(2) == 0 {`)
					p.In()
					p.P(`this.`, fieldname, `[i] *= -1`)
					p.Out()
					p.P(`}`)
				}
				p.Out()
				p.P(`}`)
			} else if !gogoproto.IsNullable(field) || proto3 {
				p.P(`this.`, fieldname, ` = `, value(typName, field.GetType()))
				if negative(field.GetType()) {
					p.P(`if r.Intn(2) == 0 {`)
					p.In()
					p.P(`this.`, fieldname, ` *= -1`)
					p.Out()
					p.P(`}`)
				}
			} else {
				p.P(p.varGen.Next(), ` := `, value(typName, field.GetType()))
				if negative(field.GetType()) {
					p.P(`if r.Intn(2) == 0 {`)
					p.In()
					p.P(p.varGen.Current(), ` *= -1`)
					p.Out()
					p.P(`}`)
				}
				p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
			}
		}
	}
}
Ejemplo n.º 8
0
func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, sizeName string) {
	fieldname := p.GetOneOfFieldName(message, field)
	nullable := gogoproto.IsNullable(field)
	repeated := field.IsRepeated()
	doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
	if repeated {
		p.P(`if len(m.`, fieldname, `) > 0 {`)
		p.In()
	} else if doNilCheck {
		p.P(`if m.`, fieldname, ` != nil {`)
		p.In()
	}
	packed := field.IsPacked() || (proto3 && field.IsRepeated() && generator.IsScalar(field))
	_, wire := p.GoType(message, field)
	wireType := wireToType(wire)
	fieldNumber := field.GetNumber()
	if packed {
		wireType = proto.WireBytes
	}
	key := keySize(fieldNumber, wireType)
	switch *field.Type {
	case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
		descriptor.FieldDescriptorProto_TYPE_FIXED64,
		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
		if packed {
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*8))`, `+len(m.`, fieldname, `)*8`)
		} else if repeated {
			p.P(`n+=`, strconv.Itoa(key+8), `*len(m.`, fieldname, `)`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key+8))
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`n+=`, strconv.Itoa(key+8))
		} else {
			p.P(`n+=`, strconv.Itoa(key+8))
		}
	case descriptor.FieldDescriptorProto_TYPE_FLOAT,
		descriptor.FieldDescriptorProto_TYPE_FIXED32,
		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
		if packed {
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*4))`, `+len(m.`, fieldname, `)*4`)
		} else if repeated {
			p.P(`n+=`, strconv.Itoa(key+4), `*len(m.`, fieldname, `)`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key+4))
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`n+=`, strconv.Itoa(key+4))
		} else {
			p.P(`n+=`, strconv.Itoa(key+4))
		}
	case descriptor.FieldDescriptorProto_TYPE_INT64,
		descriptor.FieldDescriptorProto_TYPE_UINT64,
		descriptor.FieldDescriptorProto_TYPE_UINT32,
		descriptor.FieldDescriptorProto_TYPE_ENUM,
		descriptor.FieldDescriptorProto_TYPE_INT32:
		if packed {
			p.P(`l = 0`)
			p.P(`for _, e := range m.`, fieldname, ` {`)
			p.In()
			p.P(`l+=sov`, p.localName, `(uint64(e))`)
			p.Out()
			p.P(`}`)
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
		} else if repeated {
			p.P(`for _, e := range m.`, fieldname, ` {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(e))`)
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(*m.`, fieldname, `))`)
		} else {
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_BOOL:
		if packed {
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)))`, `+len(m.`, fieldname, `)*1`)
		} else if repeated {
			p.P(`n+=`, strconv.Itoa(key+1), `*len(m.`, fieldname, `)`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key+1))
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`n+=`, strconv.Itoa(key+1))
		} else {
			p.P(`n+=`, strconv.Itoa(key+1))
		}
	case descriptor.FieldDescriptorProto_TYPE_STRING:
		if repeated {
			p.P(`for _, s := range m.`, fieldname, ` { `)
			p.In()
			p.P(`l = len(s)`)
			p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`l=len(m.`, fieldname, `)`)
			p.P(`if l > 0 {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`l=len(*m.`, fieldname, `)`)
			p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
		} else {
			p.P(`l=len(m.`, fieldname, `)`)
			p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_GROUP:
		panic(fmt.Errorf("size does not support group %v", fieldname))
	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
		if p.IsMap(field) {
			m := p.GoMapType(nil, field)
			_, keywire := p.GoType(nil, m.KeyAliasField)
			valuegoTyp, _ := p.GoType(nil, m.ValueField)
			valuegoAliasTyp, valuewire := p.GoType(nil, m.ValueAliasField)
			_, fieldwire := p.GoType(nil, field)

			nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)

			fieldKeySize := keySize(field.GetNumber(), wireToType(fieldwire))
			keyKeySize := keySize(1, wireToType(keywire))
			valueKeySize := keySize(2, wireToType(valuewire))
			p.P(`for k, v := range m.`, fieldname, ` { `)
			p.In()
			p.P(`_ = k`)
			p.P(`_ = v`)
			sum := []string{strconv.Itoa(keyKeySize)}
			switch m.KeyField.GetType() {
			case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
				descriptor.FieldDescriptorProto_TYPE_FIXED64,
				descriptor.FieldDescriptorProto_TYPE_SFIXED64:
				sum = append(sum, `8`)
			case descriptor.FieldDescriptorProto_TYPE_FLOAT,
				descriptor.FieldDescriptorProto_TYPE_FIXED32,
				descriptor.FieldDescriptorProto_TYPE_SFIXED32:
				sum = append(sum, `4`)
			case descriptor.FieldDescriptorProto_TYPE_INT64,
				descriptor.FieldDescriptorProto_TYPE_UINT64,
				descriptor.FieldDescriptorProto_TYPE_UINT32,
				descriptor.FieldDescriptorProto_TYPE_ENUM,
				descriptor.FieldDescriptorProto_TYPE_INT32:
				sum = append(sum, `sov`+p.localName+`(uint64(k))`)
			case descriptor.FieldDescriptorProto_TYPE_BOOL:
				sum = append(sum, `1`)
			case descriptor.FieldDescriptorProto_TYPE_STRING,
				descriptor.FieldDescriptorProto_TYPE_BYTES:
				sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
			case descriptor.FieldDescriptorProto_TYPE_SINT32,
				descriptor.FieldDescriptorProto_TYPE_SINT64:
				sum = append(sum, `soz`+p.localName+`(uint64(k))`)
			}
			switch m.ValueField.GetType() {
			case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
				descriptor.FieldDescriptorProto_TYPE_FIXED64,
				descriptor.FieldDescriptorProto_TYPE_SFIXED64:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, strconv.Itoa(8))
			case descriptor.FieldDescriptorProto_TYPE_FLOAT,
				descriptor.FieldDescriptorProto_TYPE_FIXED32,
				descriptor.FieldDescriptorProto_TYPE_SFIXED32:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, strconv.Itoa(4))
			case descriptor.FieldDescriptorProto_TYPE_INT64,
				descriptor.FieldDescriptorProto_TYPE_UINT64,
				descriptor.FieldDescriptorProto_TYPE_UINT32,
				descriptor.FieldDescriptorProto_TYPE_ENUM,
				descriptor.FieldDescriptorProto_TYPE_INT32:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `sov`+p.localName+`(uint64(v))`)
			case descriptor.FieldDescriptorProto_TYPE_BOOL:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `1`)
			case descriptor.FieldDescriptorProto_TYPE_STRING:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
			case descriptor.FieldDescriptorProto_TYPE_BYTES:
				if gogoproto.IsCustomType(field) {
					p.P(`l = 0`)
					if nullable {
						p.P(`if v != nil {`)
						p.In()
					}
					p.P(`l = v.`, sizeName, `()`)
					p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
					if nullable {
						p.Out()
						p.P(`}`)
					}
					sum = append(sum, `l`)
				} else {
					p.P(`l = 0`)
					if proto3 {
						p.P(`if len(v) > 0 {`)
					} else {
						p.P(`if v != nil {`)
					}
					p.In()
					p.P(`l = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
					p.Out()
					p.P(`}`)
					sum = append(sum, `l`)
				}
			case descriptor.FieldDescriptorProto_TYPE_SINT32,
				descriptor.FieldDescriptorProto_TYPE_SINT64:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `soz`+p.localName+`(uint64(v))`)
			case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
				stdSizeCall, stdOk := p.std(field, "v")
				if nullable {
					p.P(`l = 0`)
					p.P(`if v != nil {`)
					p.In()
					if stdOk {
						p.P(`l = `, stdSizeCall)
					} else if valuegoTyp != valuegoAliasTyp {
						p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
					} else {
						p.P(`l = v.`, sizeName, `()`)
					}
					p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
					p.Out()
					p.P(`}`)
					sum = append(sum, `l`)
				} else {
					if stdOk {
						p.P(`l = `, stdSizeCall)
					} else if valuegoTyp != valuegoAliasTyp {
						p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
					} else {
						p.P(`l = v.`, sizeName, `()`)
					}
					sum = append(sum, strconv.Itoa(valueKeySize))
					sum = append(sum, `l+sov`+p.localName+`(uint64(l))`)
				}
			}
			p.P(`mapEntrySize := `, strings.Join(sum, "+"))
			p.P(`n+=mapEntrySize+`, fieldKeySize, `+sov`, p.localName, `(uint64(mapEntrySize))`)
			p.Out()
			p.P(`}`)
		} else if repeated {
			p.P(`for _, e := range m.`, fieldname, ` { `)
			p.In()
			stdSizeCall, stdOk := p.std(field, "e")
			if stdOk {
				p.P(`l=`, stdSizeCall)
			} else {
				p.P(`l=e.`, sizeName, `()`)
			}
			p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
			p.Out()
			p.P(`}`)
		} else {
			stdSizeCall, stdOk := p.std(field, "m."+fieldname)
			if stdOk {
				p.P(`l=`, stdSizeCall)
			} else {
				p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
			}
			p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_BYTES:
		if !gogoproto.IsCustomType(field) {
			if repeated {
				p.P(`for _, b := range m.`, fieldname, ` { `)
				p.In()
				p.P(`l = len(b)`)
				p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`l=len(m.`, fieldname, `)`)
				p.P(`if l > 0 {`)
				p.In()
				p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
				p.Out()
				p.P(`}`)
			} else {
				p.P(`l=len(m.`, fieldname, `)`)
				p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
			}
		} else {
			if repeated {
				p.P(`for _, e := range m.`, fieldname, ` { `)
				p.In()
				p.P(`l=e.`, sizeName, `()`)
				p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
				p.Out()
				p.P(`}`)
			} else {
				p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
				p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT32,
		descriptor.FieldDescriptorProto_TYPE_SINT64:
		if packed {
			p.P(`l = 0`)
			p.P(`for _, e := range m.`, fieldname, ` {`)
			p.In()
			p.P(`l+=soz`, p.localName, `(uint64(e))`)
			p.Out()
			p.P(`}`)
			p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
		} else if repeated {
			p.P(`for _, e := range m.`, fieldname, ` {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(e))`)
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(*m.`, fieldname, `))`)
		} else {
			p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
		}
	default:
		panic("not implemented")
	}
	if repeated || doNilCheck {
		p.Out()
		p.P(`}`)
	}
}
Ejemplo n.º 9
0
func (p *gostring) Generate(file *generator.FileDescriptor) {
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	p.PluginImports = generator.NewPluginImports(p.Generator)
	p.atleastOne = false

	p.localName = generator.FileName(file)

	fmtPkg := p.NewImport("fmt")
	stringsPkg := p.NewImport("strings")
	protoPkg := p.NewImport("github.com/maditya/protobuf/proto")
	if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
		protoPkg = p.NewImport("github.com/golang/protobuf/proto")
	}
	sortPkg := p.NewImport("sort")
	strconvPkg := p.NewImport("strconv")
	reflectPkg := p.NewImport("reflect")
	sortKeysPkg := p.NewImport("github.com/maditya/protobuf/sortkeys")

	for _, message := range file.Messages() {
		if !p.overwrite && !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
			continue
		}
		if message.DescriptorProto.GetOptions().GetMapEntry() {
			continue
		}
		p.atleastOne = true
		packageName := file.PackageName()

		ccTypeName := generator.CamelCaseSlice(message.TypeName())
		p.P(`func (this *`, ccTypeName, `) GoString() string {`)
		p.In()
		p.P(`if this == nil {`)
		p.In()
		p.P(`return "nil"`)
		p.Out()
		p.P(`}`)

		p.P(`s := make([]string, 0, `, strconv.Itoa(len(message.Field)+4), `)`)
		p.P(`s = append(s, "&`, packageName, ".", ccTypeName, `{")`)

		oneofs := make(map[string]struct{})
		for _, field := range message.Field {
			nullable := gogoproto.IsNullable(field)
			repeated := field.IsRepeated()
			fieldname := p.GetFieldName(message, field)
			oneof := field.OneofIndex != nil
			if oneof {
				if _, ok := oneofs[fieldname]; ok {
					continue
				} else {
					oneofs[fieldname] = struct{}{}
				}
				p.P(`if this.`, fieldname, ` != nil {`)
				p.In()
				p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
				p.Out()
				p.P(`}`)
			} else if p.IsMap(field) {
				m := p.GoMapType(nil, field)
				mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
				keysName := `keysFor` + fieldname
				keygoTyp, _ := p.GoType(nil, keyField)
				keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
				keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
				keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
				keyCapTyp := generator.CamelCase(keygoTyp)
				p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
				p.P(`for k, _ := range this.`, fieldname, ` {`)
				p.In()
				if keygoAliasTyp == keygoTyp {
					p.P(keysName, ` = append(`, keysName, `, k)`)
				} else {
					p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
				}
				p.Out()
				p.P(`}`)
				p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
				mapName := `mapStringFor` + fieldname
				p.P(mapName, ` := "`, mapgoTyp, `{"`)
				p.P(`for _, k := range `, keysName, ` {`)
				p.In()
				if keygoAliasTyp == keygoTyp {
					p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[k])`)
				} else {
					p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
				}
				p.Out()
				p.P(`}`)
				p.P(mapName, ` += "}"`)
				p.P(`if this.`, fieldname, ` != nil {`)
				p.In()
				p.P(`s = append(s, "`, fieldname, `: " + `, mapName, `+ ",\n")`)
				p.Out()
				p.P(`}`)
			} else if field.IsMessage() || p.IsGroup(field) {
				if nullable || repeated {
					p.P(`if this.`, fieldname, ` != nil {`)
					p.In()
				}
				if nullable || repeated {
					p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
				} else {
					p.P(`s = append(s, "`, fieldname, `: " + `, stringsPkg.Use(), `.Replace(this.`, fieldname, `.GoString()`, ",`&`,``,1)", ` + ",\n")`)
				}
				if nullable || repeated {
					p.Out()
					p.P(`}`)
				}
			} else {
				if !proto3 && (nullable || repeated) {
					p.P(`if this.`, fieldname, ` != nil {`)
					p.In()
				}
				if field.IsEnum() {
					if nullable && !repeated && !proto3 {
						goTyp, _ := p.GoType(message, field)
						p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, packageName, ".", generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
					} else {
						p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
					}
				} else {
					if nullable && !repeated && !proto3 {
						goTyp, _ := p.GoType(message, field)
						p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
					} else {
						p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
					}
				}
				if !proto3 && (nullable || repeated) {
					p.Out()
					p.P(`}`)
				}
			}
		}
		if message.DescriptorProto.HasExtension() {
			if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
				p.P(`s = append(s, "XXX_InternalExtensions: " + extensionToGoString`, p.localName, `(this) + ",\n")`)
			} else {
				p.P(`if this.XXX_extensions != nil {`)
				p.In()
				p.P(`s = append(s, "XXX_extensions: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_extensions) + ",\n")`)
				p.Out()
				p.P(`}`)
			}
		}
		if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
			p.P(`if this.XXX_unrecognized != nil {`)
			p.In()
			p.P(`s = append(s, "XXX_unrecognized:" + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_unrecognized) + ",\n")`)
			p.Out()
			p.P(`}`)
		}

		p.P(`s = append(s, "}")`)
		//outStr += strings.Join([]string{" + `}`", `}`, `,", "`, ")"}, "")
		p.P(`return `, stringsPkg.Use(), `.Join(s, "")`)
		p.Out()
		p.P(`}`)

		//Generate GoString methods for oneof fields
		for _, field := range message.Field {
			oneof := field.OneofIndex != nil
			if !oneof {
				continue
			}
			ccTypeName := p.OneOfTypeName(message, field)
			p.P(`func (this *`, ccTypeName, `) GoString() string {`)
			p.In()
			p.P(`if this == nil {`)
			p.In()
			p.P(`return "nil"`)
			p.Out()
			p.P(`}`)
			outFlds := []string{}
			fieldname := p.GetOneOfFieldName(message, field)
			if field.IsMessage() || p.IsGroup(field) {
				tmp := strings.Join([]string{"`", fieldname, ":` + "}, "")
				tmp += strings.Join([]string{fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `)`}, "")
				outFlds = append(outFlds, tmp)
			} else {
				tmp := strings.Join([]string{"`", fieldname, ":` + "}, "")
				tmp += strings.Join([]string{fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, ")"}, "")
				outFlds = append(outFlds, tmp)
			}
			outStr := strings.Join([]string{"s := ", stringsPkg.Use(), ".Join([]string{`&", packageName, ".", ccTypeName, "{` + \n"}, "")
			outStr += strings.Join(outFlds, ",\n")
			outStr += strings.Join([]string{" + `}`", `}`, `,", "`, ")"}, "")
			p.P(outStr)
			p.P(`return s`)
			p.Out()
			p.P(`}`)
		}
	}

	if !p.atleastOne {
		return
	}

	p.P(`func valueToGoString`, p.localName, `(v interface{}, typ string) string {`)
	p.In()
	p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
	p.P(`if rv.IsNil() {`)
	p.In()
	p.P(`return "nil"`)
	p.Out()
	p.P(`}`)
	p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
	p.P(`return `, fmtPkg.Use(), `.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)`)
	p.Out()
	p.P(`}`)

	p.P(`func extensionToGoString`, p.localName, `(m `, protoPkg.Use(), `.Message) string {`)
	p.In()
	p.P(`e := `, protoPkg.Use(), `.GetUnsafeExtensionsMap(m)`)
	p.P(`if e == nil { return "nil" }`)
	p.P(`s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"`)
	p.P(`keys := make([]int, 0, len(e))`)
	p.P(`for k := range e {`)
	p.In()
	p.P(`keys = append(keys, int(k))`)
	p.Out()
	p.P(`}`)
	p.P(sortPkg.Use(), `.Ints(keys)`)
	p.P(`ss := []string{}`)
	p.P(`for _, k := range keys {`)
	p.In()
	p.P(`ss = append(ss, `, strconvPkg.Use(), `.Itoa(k) + ": " + e[int32(k)].GoString())`)
	p.Out()
	p.P(`}`)
	p.P(`s+=`, stringsPkg.Use(), `.Join(ss, ",") + "})"`)
	p.P(`return s`)
	p.Out()
	p.P(`}`)

}
Ejemplo n.º 10
0
func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
	fieldname := p.GetOneOfFieldName(message, field)
	nullable := gogoproto.IsNullable(field)
	repeated := field.IsRepeated()
	required := field.IsRequired()

	protoSizer := gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto)
	doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
	if required && nullable {
		p.P(`if m.`, fieldname, `== nil {`)
		p.In()
		if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
			p.P(`return 0, new(`, p.protoPkg.Use(), `.RequiredNotSetError)`)
		} else {
			p.P(`return 0, `, p.protoPkg.Use(), `.NewRequiredNotSetError("`, field.GetName(), `")`)
		}
		p.Out()
		p.P(`} else {`)
	} else if repeated {
		p.P(`if len(m.`, fieldname, `) > 0 {`)
		p.In()
	} else if doNilCheck {
		p.P(`if m.`, fieldname, ` != nil {`)
		p.In()
	}
	packed := field.IsPacked() || (proto3 && field.IsRepeated() && generator.IsScalar(field))
	wireType := field.WireType()
	fieldNumber := field.GetNumber()
	if packed {
		wireType = proto.WireBytes
	}
	switch *field.Type {
	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
		if !p.unsafe || gogoproto.IsCastType(field) {
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 8`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
				p.encodeFixed64("f" + numGen.Current())
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
				p.encodeFixed64("f" + numGen.Current())
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(*m.`+fieldname, `))`)
			}
		} else {
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 8`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.unsafeFixed64("num", "float64")
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64("num", "float64")
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64(`m.`+fieldname, "float64")
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64(`m.`+fieldname, "float64")
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64(`*m.`+fieldname, `float64`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
		if !p.unsafe || gogoproto.IsCastType(field) {
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 4`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
				p.encodeFixed32("f" + numGen.Current())
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
				p.encodeFixed32("f" + numGen.Current())
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(*m.`+fieldname, `))`)
			}
		} else {
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 4`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.unsafeFixed32("num", "float32")
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32("num", "float32")
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32(`m.`+fieldname, `float32`)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32(`m.`+fieldname, `float32`)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32(`*m.`+fieldname, "float32")
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_INT64,
		descriptor.FieldDescriptorProto_TYPE_UINT64,
		descriptor.FieldDescriptorProto_TYPE_INT32,
		descriptor.FieldDescriptorProto_TYPE_UINT32,
		descriptor.FieldDescriptorProto_TYPE_ENUM:
		if packed {
			jvar := "j" + numGen.Next()
			p.P(`data`, numGen.Next(), ` := make([]byte, len(m.`, fieldname, `)*10)`)
			p.P(`var `, jvar, ` int`)
			if *field.Type == descriptor.FieldDescriptorProto_TYPE_INT64 ||
				*field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
				p.P(`for _, num1 := range m.`, fieldname, ` {`)
				p.In()
				p.P(`num := uint64(num1)`)
			} else {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
			}
			p.P(`for num >= 1<<7 {`)
			p.In()
			p.P(`data`, numGen.Current(), `[`, jvar, `] = uint8(uint64(num)&0x7f|0x80)`)
			p.P(`num >>= 7`)
			p.P(jvar, `++`)
			p.Out()
			p.P(`}`)
			p.P(`data`, numGen.Current(), `[`, jvar, `] = uint8(num)`)
			p.P(jvar, `++`)
			p.Out()
			p.P(`}`)
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(jvar)
			p.P(`i += copy(data[i:], data`, numGen.Current(), `[:`, jvar, `])`)
		} else if repeated {
			p.P(`for _, num := range m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.callVarint("num")
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`m.`, fieldname)
			p.Out()
			p.P(`}`)
		} else if !nullable {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`m.`, fieldname)
		} else {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`*m.`, fieldname)
		}
	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
		if !p.unsafe {
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 8`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeFixed64("num")
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.encodeFixed64("num")
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.callFixed64("m." + fieldname)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed64("m." + fieldname)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed64("*m." + fieldname)
			}
		} else {
			typeName := "int64"
			if *field.Type == descriptor.FieldDescriptorProto_TYPE_FIXED64 {
				typeName = "uint64"
			}
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 8`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.unsafeFixed64("num", typeName)
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64("num", typeName)
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64("m."+fieldname, typeName)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64("m."+fieldname, typeName)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed64("*m."+fieldname, typeName)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
		if !p.unsafe {
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 4`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeFixed32("num")
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.encodeFixed32("num")
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.callFixed32("m." + fieldname)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed32("m." + fieldname)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.callFixed32("*m." + fieldname)
			}
		} else {
			typeName := "int32"
			if *field.Type == descriptor.FieldDescriptorProto_TYPE_FIXED32 {
				typeName = "uint32"
			}
			if packed {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `) * 4`)
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.unsafeFixed32("num", typeName)
				p.Out()
				p.P(`}`)
			} else if repeated {
				p.P(`for _, num := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32("num", typeName)
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if m.`, fieldname, ` != 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32("m."+fieldname, typeName)
				p.Out()
				p.P(`}`)
			} else if !nullable {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32("m."+fieldname, typeName)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.unsafeFixed32("*m."+fieldname, typeName)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_BOOL:
		if packed {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`len(m.`, fieldname, `)`)
			p.P(`for _, b := range m.`, fieldname, ` {`)
			p.In()
			p.P(`if b {`)
			p.In()
			p.P(`data[i] = 1`)
			p.Out()
			p.P(`} else {`)
			p.In()
			p.P(`data[i] = 0`)
			p.Out()
			p.P(`}`)
			p.P(`i++`)
			p.Out()
			p.P(`}`)
		} else if repeated {
			p.P(`for _, b := range m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.P(`if b {`)
			p.In()
			p.P(`data[i] = 1`)
			p.Out()
			p.P(`} else {`)
			p.In()
			p.P(`data[i] = 0`)
			p.Out()
			p.P(`}`)
			p.P(`i++`)
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.P(`if m.`, fieldname, ` {`)
			p.In()
			p.P(`data[i] = 1`)
			p.Out()
			p.P(`} else {`)
			p.In()
			p.P(`data[i] = 0`)
			p.Out()
			p.P(`}`)
			p.P(`i++`)
			p.Out()
			p.P(`}`)
		} else if !nullable {
			p.encodeKey(fieldNumber, wireType)
			p.P(`if m.`, fieldname, ` {`)
			p.In()
			p.P(`data[i] = 1`)
			p.Out()
			p.P(`} else {`)
			p.In()
			p.P(`data[i] = 0`)
			p.Out()
			p.P(`}`)
			p.P(`i++`)
		} else {
			p.encodeKey(fieldNumber, wireType)
			p.P(`if *m.`, fieldname, ` {`)
			p.In()
			p.P(`data[i] = 1`)
			p.Out()
			p.P(`} else {`)
			p.In()
			p.P(`data[i] = 0`)
			p.Out()
			p.P(`}`)
			p.P(`i++`)
		}
	case descriptor.FieldDescriptorProto_TYPE_STRING:
		if repeated {
			p.P(`for _, s := range m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.P(`l = len(s)`)
			p.encodeVarint("l")
			p.P(`i+=copy(data[i:], s)`)
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if len(m.`, fieldname, `) > 0 {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`len(m.`, fieldname, `)`)
			p.P(`i+=copy(data[i:], m.`, fieldname, `)`)
			p.Out()
			p.P(`}`)
		} else if !nullable {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`len(m.`, fieldname, `)`)
			p.P(`i+=copy(data[i:], m.`, fieldname, `)`)
		} else {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`len(*m.`, fieldname, `)`)
			p.P(`i+=copy(data[i:], *m.`, fieldname, `)`)
		}
	case descriptor.FieldDescriptorProto_TYPE_GROUP:
		panic(fmt.Errorf("marshaler does not support group %v", fieldname))
	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
		if p.IsMap(field) {
			m := p.GoMapType(nil, field)
			keygoTyp, keywire := p.GoType(nil, m.KeyField)
			keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
			// keys may not be pointers
			keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
			keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
			keyCapTyp := generator.CamelCase(keygoTyp)
			valuegoTyp, valuewire := p.GoType(nil, m.ValueField)
			valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
			nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
			keyKeySize := keySize(1, wireToType(keywire))
			valueKeySize := keySize(2, wireToType(valuewire))
			if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
				keysName := `keysFor` + fieldname
				p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(m.`, fieldname, `))`)
				p.P(`for k, _ := range m.`, fieldname, ` {`)
				p.In()
				p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
				p.Out()
				p.P(`}`)
				p.P(p.sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
				p.P(`for _, k := range `, keysName, ` {`)
			} else {
				p.P(`for k, _ := range m.`, fieldname, ` {`)
			}
			p.In()
			p.encodeKey(fieldNumber, wireType)
			sum := []string{strconv.Itoa(keyKeySize)}
			switch m.KeyField.GetType() {
			case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
				descriptor.FieldDescriptorProto_TYPE_FIXED64,
				descriptor.FieldDescriptorProto_TYPE_SFIXED64:
				sum = append(sum, `8`)
			case descriptor.FieldDescriptorProto_TYPE_FLOAT,
				descriptor.FieldDescriptorProto_TYPE_FIXED32,
				descriptor.FieldDescriptorProto_TYPE_SFIXED32:
				sum = append(sum, `4`)
			case descriptor.FieldDescriptorProto_TYPE_INT64,
				descriptor.FieldDescriptorProto_TYPE_UINT64,
				descriptor.FieldDescriptorProto_TYPE_UINT32,
				descriptor.FieldDescriptorProto_TYPE_ENUM,
				descriptor.FieldDescriptorProto_TYPE_INT32:
				sum = append(sum, `sov`+p.localName+`(uint64(k))`)
			case descriptor.FieldDescriptorProto_TYPE_BOOL:
				sum = append(sum, `1`)
			case descriptor.FieldDescriptorProto_TYPE_STRING,
				descriptor.FieldDescriptorProto_TYPE_BYTES:
				sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
			case descriptor.FieldDescriptorProto_TYPE_SINT32,
				descriptor.FieldDescriptorProto_TYPE_SINT64:
				sum = append(sum, `soz`+p.localName+`(uint64(k))`)
			}
			if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
				p.P(`v := m.`, fieldname, `[`, keygoAliasTyp, `(k)]`)
			} else {
				p.P(`v := m.`, fieldname, `[k]`)
			}
			accessor := `v`
			switch m.ValueField.GetType() {
			case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
				descriptor.FieldDescriptorProto_TYPE_FIXED64,
				descriptor.FieldDescriptorProto_TYPE_SFIXED64:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, strconv.Itoa(8))
			case descriptor.FieldDescriptorProto_TYPE_FLOAT,
				descriptor.FieldDescriptorProto_TYPE_FIXED32,
				descriptor.FieldDescriptorProto_TYPE_SFIXED32:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, strconv.Itoa(4))
			case descriptor.FieldDescriptorProto_TYPE_INT64,
				descriptor.FieldDescriptorProto_TYPE_UINT64,
				descriptor.FieldDescriptorProto_TYPE_UINT32,
				descriptor.FieldDescriptorProto_TYPE_ENUM,
				descriptor.FieldDescriptorProto_TYPE_INT32:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `sov`+p.localName+`(uint64(v))`)
			case descriptor.FieldDescriptorProto_TYPE_BOOL:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `1`)
			case descriptor.FieldDescriptorProto_TYPE_STRING:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
			case descriptor.FieldDescriptorProto_TYPE_BYTES:
				if gogoproto.IsCustomType(field) {
					p.P(`cSize := 0`)
					if gogoproto.IsNullable(field) {
						p.P(`if `, accessor, ` != nil {`)
						p.In()
					}
					p.P(`cSize = `, accessor, `.Size()`)
					p.P(`cSize += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(cSize))`)
					if gogoproto.IsNullable(field) {
						p.Out()
						p.P(`}`)
					}
					sum = append(sum, `cSize`)
				} else {
					p.P(`byteSize := 0`)
					if proto3 {
						p.P(`if len(v) > 0 {`)
					} else {
						p.P(`if v != nil {`)
					}
					p.In()
					p.P(`byteSize = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
					p.Out()
					p.P(`}`)
					sum = append(sum, `byteSize`)
				}
			case descriptor.FieldDescriptorProto_TYPE_SINT32,
				descriptor.FieldDescriptorProto_TYPE_SINT64:
				sum = append(sum, strconv.Itoa(valueKeySize))
				sum = append(sum, `soz`+p.localName+`(uint64(v))`)
			case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
				if valuegoTyp != valuegoAliasTyp &&
					!gogoproto.IsStdTime(field) &&
					!gogoproto.IsStdDuration(field) {
					if nullable {
						// cast back to the type that has the generated methods on it
						accessor = `((` + valuegoTyp + `)(` + accessor + `))`
					} else {
						accessor = `((*` + valuegoTyp + `)(&` + accessor + `))`
					}
				} else if !nullable {
					accessor = `(&v)`
				}
				p.P(`msgSize := 0`)
				p.P(`if `, accessor, ` != nil {`)
				p.In()
				if gogoproto.IsStdTime(field) {
					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdTime(*`, accessor, `)`)
				} else if gogoproto.IsStdDuration(field) {
					p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdDuration(*`, accessor, `)`)
				} else if protoSizer {
					p.P(`msgSize = `, accessor, `.ProtoSize()`)
				} else {
					p.P(`msgSize = `, accessor, `.Size()`)
				}
				p.P(`msgSize += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(msgSize))`)
				p.Out()
				p.P(`}`)
				sum = append(sum, `msgSize`)
			}
			p.P(`mapSize := `, strings.Join(sum, " + "))
			p.callVarint("mapSize")
			p.encodeKey(1, wireToType(keywire))
			p.mapField(numGen, field, m.KeyField, "k", protoSizer)
			nullableMsg := nullable && (m.ValueField.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
				gogoproto.IsCustomType(field) && m.ValueField.IsBytes())
			plainBytes := m.ValueField.IsBytes() && !gogoproto.IsCustomType(field)
			if nullableMsg {
				p.P(`if `, accessor, ` != nil { `)
				p.In()
			} else if plainBytes {
				if proto3 {
					p.P(`if len(`, accessor, `) > 0 {`)
				} else {
					p.P(`if `, accessor, ` != nil {`)
				}
				p.In()
			}
			p.encodeKey(2, wireToType(valuewire))
			p.mapField(numGen, field, m.ValueField, accessor, protoSizer)
			if nullableMsg || plainBytes {
				p.Out()
				p.P(`}`)
			}
			p.Out()
			p.P(`}`)
		} else if repeated {
			p.P(`for _, msg := range m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			varName := "msg"
			if gogoproto.IsStdTime(field) {
				if gogoproto.IsNullable(field) {
					varName = "*" + varName
				}
				p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(`, varName, `)`)
				p.P(`n, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(`, varName, `, data[i:])`)
			} else if gogoproto.IsStdDuration(field) {
				if gogoproto.IsNullable(field) {
					varName = "*" + varName
				}
				p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(`, varName, `)`)
				p.P(`n, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(`, varName, `, data[i:])`)
			} else if protoSizer {
				p.callVarint(varName, ".ProtoSize()")
				p.P(`n, err := `, varName, `.MarshalTo(data[i:])`)
			} else {
				p.callVarint(varName, ".Size()")
				p.P(`n, err := `, varName, `.MarshalTo(data[i:])`)
			}
			p.P(`if err != nil {`)
			p.In()
			p.P(`return 0, err`)
			p.Out()
			p.P(`}`)
			p.P(`i+=n`)
			p.Out()
			p.P(`}`)
		} else {
			p.encodeKey(fieldNumber, wireType)
			varName := `m.` + fieldname
			if gogoproto.IsStdTime(field) {
				if gogoproto.IsNullable(field) {
					varName = "*" + varName
				}
				p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(`, varName, `)`)
				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(`, varName, `, data[i:])`)
			} else if gogoproto.IsStdDuration(field) {
				if gogoproto.IsNullable(field) {
					varName = "*" + varName
				}
				p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(`, varName, `)`)
				p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(`, varName, `, data[i:])`)
			} else if protoSizer {
				p.callVarint(varName, `.ProtoSize()`)
				p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(data[i:])`)
			} else {
				p.callVarint(varName, `.Size()`)
				p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(data[i:])`)
			}
			p.P(`if err != nil {`)
			p.In()
			p.P(`return 0, err`)
			p.Out()
			p.P(`}`)
			p.P(`i+=n`, numGen.Current())
		}
	case descriptor.FieldDescriptorProto_TYPE_BYTES:
		if !gogoproto.IsCustomType(field) {
			if repeated {
				p.P(`for _, b := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.callVarint("len(b)")
				p.P(`i+=copy(data[i:], b)`)
				p.Out()
				p.P(`}`)
			} else if proto3 {
				p.P(`if len(m.`, fieldname, `) > 0 {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `)`)
				p.P(`i+=copy(data[i:], m.`, fieldname, `)`)
				p.Out()
				p.P(`}`)
			} else {
				p.encodeKey(fieldNumber, wireType)
				p.callVarint(`len(m.`, fieldname, `)`)
				p.P(`i+=copy(data[i:], m.`, fieldname, `)`)
			}
		} else {
			if repeated {
				p.P(`for _, msg := range m.`, fieldname, ` {`)
				p.In()
				p.encodeKey(fieldNumber, wireType)
				if protoSizer {
					p.callVarint(`msg.ProtoSize()`)
				} else {
					p.callVarint(`msg.Size()`)
				}
				p.P(`n, err := msg.MarshalTo(data[i:])`)
				p.P(`if err != nil {`)
				p.In()
				p.P(`return 0, err`)
				p.Out()
				p.P(`}`)
				p.P(`i+=n`)
				p.Out()
				p.P(`}`)
			} else {
				p.encodeKey(fieldNumber, wireType)
				if protoSizer {
					p.callVarint(`m.`, fieldname, `.ProtoSize()`)
				} else {
					p.callVarint(`m.`, fieldname, `.Size()`)
				}
				p.P(`n`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(data[i:])`)
				p.P(`if err != nil {`)
				p.In()
				p.P(`return 0, err`)
				p.Out()
				p.P(`}`)
				p.P(`i+=n`, numGen.Current())
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT32:
		if packed {
			datavar := "data" + numGen.Next()
			jvar := "j" + numGen.Next()
			p.P(datavar, ` := make([]byte, len(m.`, fieldname, ")*5)")
			p.P(`var `, jvar, ` int`)
			p.P(`for _, num := range m.`, fieldname, ` {`)
			p.In()
			xvar := "x" + numGen.Next()
			p.P(xvar, ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
			p.P(`for `, xvar, ` >= 1<<7 {`)
			p.In()
			p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
			p.P(jvar, `++`)
			p.P(xvar, ` >>= 7`)
			p.Out()
			p.P(`}`)
			p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
			p.P(jvar, `++`)
			p.Out()
			p.P(`}`)
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(jvar)
			p.P(`i+=copy(data[i:], `, datavar, `[:`, jvar, `])`)
		} else if repeated {
			p.P(`for _, num := range m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.P(`x`, numGen.Next(), ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
			p.encodeVarint("x" + numGen.Current())
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
			p.Out()
			p.P(`}`)
		} else if !nullable {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
		} else {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`(uint32(*m.`, fieldname, `) << 1) ^ uint32((*m.`, fieldname, ` >> 31))`)
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT64:
		if packed {
			jvar := "j" + numGen.Next()
			xvar := "x" + numGen.Next()
			datavar := "data" + numGen.Next()
			p.P(`var `, jvar, ` int`)
			p.P(datavar, ` := make([]byte, len(m.`, fieldname, `)*10)`)
			p.P(`for _, num := range m.`, fieldname, ` {`)
			p.In()
			p.P(xvar, ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
			p.P(`for `, xvar, ` >= 1<<7 {`)
			p.In()
			p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
			p.P(jvar, `++`)
			p.P(xvar, ` >>= 7`)
			p.Out()
			p.P(`}`)
			p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
			p.P(jvar, `++`)
			p.Out()
			p.P(`}`)
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(jvar)
			p.P(`i+=copy(data[i:], `, datavar, `[:`, jvar, `])`)
		} else if repeated {
			p.P(`for _, num := range m.`, fieldname, ` {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.P(`x`, numGen.Next(), ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
			p.encodeVarint("x" + numGen.Current())
			p.Out()
			p.P(`}`)
		} else if proto3 {
			p.P(`if m.`, fieldname, ` != 0 {`)
			p.In()
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
			p.Out()
			p.P(`}`)
		} else if !nullable {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
		} else {
			p.encodeKey(fieldNumber, wireType)
			p.callVarint(`(uint64(*m.`, fieldname, `) << 1) ^ uint64((*m.`, fieldname, ` >> 63))`)
		}
	default:
		panic("not implemented")
	}
	if (required && nullable) || repeated || doNilCheck {
		p.Out()
		p.P(`}`)
	}
}
Ejemplo n.º 11
0
func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	fieldname := p.GetOneOfFieldName(message, field)
	repeated := field.IsRepeated()
	ctype := gogoproto.IsCustomType(field)
	nullable := gogoproto.IsNullable(field)
	// oneof := field.OneofIndex != nil
	if !repeated {
		if ctype {
			if nullable {
				p.P(`if that1.`, fieldname, ` == nil {`)
				p.In()
				p.P(`if this.`, fieldname, ` != nil {`)
				p.In()
				p.P(`return 1`)
				p.Out()
				p.P(`}`)
				p.Out()
				p.P(`} else if this.`, fieldname, ` == nil {`)
				p.In()
				p.P(`return -1`)
				p.Out()
				p.P(`} else if c := this.`, fieldname, `.Compare(*that1.`, fieldname, `); c != 0 {`)
			} else {
				p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
			}
			p.In()
			p.P(`return c`)
			p.Out()
			p.P(`}`)
		} else {
			if field.IsMessage() || p.IsGroup(field) {
				if nullable {
					p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
				} else {
					p.P(`if c := this.`, fieldname, `.Compare(&that1.`, fieldname, `); c != 0 {`)
				}
				p.In()
				p.P(`return c`)
				p.Out()
				p.P(`}`)
			} else if field.IsBytes() {
				p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
				p.In()
				p.P(`return c`)
				p.Out()
				p.P(`}`)
			} else if field.IsString() {
				if nullable && !proto3 {
					p.generateNullableField(fieldname)
				} else {
					p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
					p.In()
					p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
					p.P(`return 1`)
					p.Out()
					p.P(`}`)
				}
			} else if field.IsBool() {
				if nullable && !proto3 {
					p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
					p.In()
					p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
					p.In()
					p.P(`if !*this.`, fieldname, ` {`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
					p.P(`return 1`)
					p.Out()
					p.P(`}`)
					p.Out()
					p.P(`} else if this.`, fieldname, ` != nil {`)
					p.In()
					p.P(`return 1`)
					p.Out()
					p.P(`} else if that1.`, fieldname, ` != nil {`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
				} else {
					p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
					p.In()
					p.P(`if !this.`, fieldname, ` {`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
					p.P(`return 1`)
					p.Out()
					p.P(`}`)
				}
			} else {
				if nullable && !proto3 {
					p.generateNullableField(fieldname)
				} else {
					p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
					p.In()
					p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
					p.P(`return 1`)
					p.Out()
					p.P(`}`)
				}
			}
		}
	} else {
		p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
		p.In()
		p.P(`if len(this.`, fieldname, `) < len(that1.`, fieldname, `) {`)
		p.In()
		p.P(`return -1`)
		p.Out()
		p.P(`}`)
		p.P(`return 1`)
		p.Out()
		p.P(`}`)
		p.P(`for i := range this.`, fieldname, ` {`)
		p.In()
		if ctype {
			p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
			p.In()
			p.P(`return c`)
			p.Out()
			p.P(`}`)
		} else {
			if p.IsMap(field) {
				m := p.GoMapType(nil, field)
				valuegoTyp, _ := p.GoType(nil, m.ValueField)
				valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
				nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)

				mapValue := m.ValueAliasField
				if mapValue.IsMessage() || p.IsGroup(mapValue) {
					if nullable && valuegoTyp == valuegoAliasTyp {
						p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
					} else {
						// Compare() has a pointer receiver, but map value is a value type
						a := `this.` + fieldname + `[i]`
						b := `that1.` + fieldname + `[i]`
						if valuegoTyp != valuegoAliasTyp {
							// cast back to the type that has the generated methods on it
							a = `(` + valuegoTyp + `)(` + a + `)`
							b = `(` + valuegoTyp + `)(` + b + `)`
						}
						p.P(`a := `, a)
						p.P(`b := `, b)
						if nullable {
							p.P(`if c := a.Compare(b); c != 0 {`)
						} else {
							p.P(`if c := (&a).Compare(&b); c != 0 {`)
						}
					}
					p.In()
					p.P(`return c`)
					p.Out()
					p.P(`}`)
				} else if mapValue.IsBytes() {
					p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
					p.In()
					p.P(`return c`)
					p.Out()
					p.P(`}`)
				} else if mapValue.IsString() {
					p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
					p.In()
					p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
					p.P(`return 1`)
					p.Out()
					p.P(`}`)
				} else {
					p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
					p.In()
					p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
					p.In()
					p.P(`return -1`)
					p.Out()
					p.P(`}`)
					p.P(`return 1`)
					p.Out()
					p.P(`}`)
				}
			} else if field.IsMessage() || p.IsGroup(field) {
				if nullable {
					p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
					p.In()
					p.P(`return c`)
					p.Out()
					p.P(`}`)
				} else {
					p.P(`if c := this.`, fieldname, `[i].Compare(&that1.`, fieldname, `[i]); c != 0 {`)
					p.In()
					p.P(`return c`)
					p.Out()
					p.P(`}`)
				}
			} else if field.IsBytes() {
				p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
				p.In()
				p.P(`return c`)
				p.Out()
				p.P(`}`)
			} else if field.IsString() {
				p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
				p.In()
				p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
				p.In()
				p.P(`return -1`)
				p.Out()
				p.P(`}`)
				p.P(`return 1`)
				p.Out()
				p.P(`}`)
			} else if field.IsBool() {
				p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
				p.In()
				p.P(`if !this.`, fieldname, `[i] {`)
				p.In()
				p.P(`return -1`)
				p.Out()
				p.P(`}`)
				p.P(`return 1`)
				p.Out()
				p.P(`}`)
			} else {
				p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
				p.In()
				p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
				p.In()
				p.P(`return -1`)
				p.Out()
				p.P(`}`)
				p.P(`return 1`)
				p.Out()
				p.P(`}`)
			}
		}
		p.Out()
		p.P(`}`)
	}
}
Ejemplo n.º 12
0
func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, verbose bool) {
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	fieldname := p.GetOneOfFieldName(message, field)
	repeated := field.IsRepeated()
	ctype := gogoproto.IsCustomType(field)
	nullable := gogoproto.IsNullable(field)
	isDuration := gogoproto.IsStdDuration(field)
	isTimestamp := gogoproto.IsStdTime(field)
	// oneof := field.OneofIndex != nil
	if !repeated {
		if ctype || isTimestamp {
			if nullable {
				p.P(`if that1.`, fieldname, ` == nil {`)
				p.In()
				p.P(`if this.`, fieldname, ` != nil {`)
				p.In()
				if verbose {
					p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
				} else {
					p.P(`return false`)
				}
				p.Out()
				p.P(`}`)
				p.Out()
				p.P(`} else if !this.`, fieldname, `.Equal(*that1.`, fieldname, `) {`)
			} else {
				p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
			}
			p.In()
			if verbose {
				p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
			} else {
				p.P(`return false`)
			}
			p.Out()
			p.P(`}`)
		} else if isDuration {
			if nullable {
				p.generateNullableField(fieldname, verbose)
			} else {
				p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
			}
			p.In()
			if verbose {
				p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
			} else {
				p.P(`return false`)
			}
			p.Out()
			p.P(`}`)
		} else {
			if field.IsMessage() || p.IsGroup(field) {
				if nullable {
					p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
				} else {
					p.P(`if !this.`, fieldname, `.Equal(&that1.`, fieldname, `) {`)
				}
			} else if field.IsBytes() {
				p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
			} else if field.IsString() {
				if nullable && !proto3 {
					p.generateNullableField(fieldname, verbose)
				} else {
					p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
				}
			} else {
				if nullable && !proto3 {
					p.generateNullableField(fieldname, verbose)
				} else {
					p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
				}
			}
			p.In()
			if verbose {
				p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
			} else {
				p.P(`return false`)
			}
			p.Out()
			p.P(`}`)
		}
	} else {
		p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
		p.In()
		if verbose {
			p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", len(this.`, fieldname, `), len(that1.`, fieldname, `))`)
		} else {
			p.P(`return false`)
		}
		p.Out()
		p.P(`}`)
		p.P(`for i := range this.`, fieldname, ` {`)
		p.In()
		if ctype && !p.IsMap(field) {
			p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
		} else if isTimestamp {
			if nullable {
				p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) {`)
			} else {
				p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
			}
		} else if isDuration {
			if nullable {
				p.P(`if dthis, dthat := this.`, fieldname, `[i], that1.`, fieldname, `[i]; (dthis != nil && dthat != nil && *dthis != *dthat) || (dthis != nil && dthat == nil) || (dthis == nil && dthat != nil)  {`)
			} else {
				p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
			}
		} else {
			if p.IsMap(field) {
				m := p.GoMapType(nil, field)
				valuegoTyp, _ := p.GoType(nil, m.ValueField)
				valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
				nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)

				mapValue := m.ValueAliasField
				if mapValue.IsMessage() || p.IsGroup(mapValue) {
					if nullable && valuegoTyp == valuegoAliasTyp {
						p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
					} else {
						// Equal() has a pointer receiver, but map value is a value type
						a := `this.` + fieldname + `[i]`
						b := `that1.` + fieldname + `[i]`
						if valuegoTyp != valuegoAliasTyp {
							// cast back to the type that has the generated methods on it
							a = `(` + valuegoTyp + `)(` + a + `)`
							b = `(` + valuegoTyp + `)(` + b + `)`
						}
						p.P(`a := `, a)
						p.P(`b := `, b)
						if nullable {
							p.P(`if !a.Equal(b) {`)
						} else {
							p.P(`if !(&a).Equal(&b) {`)
						}
					}
				} else if mapValue.IsBytes() {
					if ctype {
						if nullable {
							p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) { //nullable`)
						} else {
							p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) { //not nullable`)
						}
					} else {
						p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
					}
				} else if mapValue.IsString() {
					p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
				} else {
					p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
				}
			} else if field.IsMessage() || p.IsGroup(field) {
				if nullable {
					p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
				} else {
					p.P(`if !this.`, fieldname, `[i].Equal(&that1.`, fieldname, `[i]) {`)
				}
			} else if field.IsBytes() {
				p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
			} else if field.IsString() {
				p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
			} else {
				p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
			}
		}
		p.In()
		if verbose {
			p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", i, this.`, fieldname, `[i], i, that1.`, fieldname, `[i])`)
		} else {
			p.P(`return false`)
		}
		p.Out()
		p.P(`}`)
		p.Out()
		p.P(`}`)
	}
}
Ejemplo n.º 13
0
func (p *unmarshal) field(file *generator.FileDescriptor, msg *generator.Descriptor, field *descriptor.FieldDescriptorProto, fieldname string, proto3 bool) {
	repeated := field.IsRepeated()
	nullable := gogoproto.IsNullable(field)
	typ := p.noStarOrSliceType(msg, field)
	oneof := field.OneofIndex != nil
	switch *field.Type {
	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
		if !p.unsafe || gogoproto.IsCastType(field) {
			p.P(`var v uint64`)
			p.decodeFixed64("v", "uint64")
			if oneof {
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))}`)
			} else if repeated {
				p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))`)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v2)`)
			} else if proto3 || !nullable {
				p.P(`m.`, fieldname, ` = `, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))`)
			} else {
				p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float64frombits(v))`)
				p.P(`m.`, fieldname, ` = &v2`)
			}
		} else {
			if oneof {
				p.P(`var v float64`)
				p.unsafeFixed64("v", "float64")
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v float64`)
				p.unsafeFixed64("v", "float64")
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.unsafeFixed64(`m.`+fieldname, "float64")
			} else {
				p.P(`var v float64`)
				p.unsafeFixed64("v", "float64")
				p.P(`m.`, fieldname, ` = &v`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
		if !p.unsafe || gogoproto.IsCastType(field) {
			p.P(`var v uint32`)
			p.decodeFixed32("v", "uint32")
			if oneof {
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))}`)
			} else if repeated {
				p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))`)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v2)`)
			} else if proto3 || !nullable {
				p.P(`m.`, fieldname, ` = `, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))`)
			} else {
				p.P(`v2 := `, typ, "(", p.mathPkg.Use(), `.Float32frombits(v))`)
				p.P(`m.`, fieldname, ` = &v2`)
			}
		} else {
			if oneof {
				p.P(`var v float32`)
				p.unsafeFixed32("v", "float32")
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v float32`)
				p.unsafeFixed32("v", "float32")
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.unsafeFixed32("m."+fieldname, "float32")
			} else {
				p.P(`var v float32`)
				p.unsafeFixed32("v", "float32")
				p.P(`m.`, fieldname, ` = &v`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_INT64:
		if oneof {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if repeated {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = 0`)
			p.decodeVarint("m."+fieldname, typ)
		} else {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &v`)
		}
	case descriptor.FieldDescriptorProto_TYPE_UINT64:
		if oneof {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if repeated {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = 0`)
			p.decodeVarint("m."+fieldname, typ)
		} else {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &v`)
		}
	case descriptor.FieldDescriptorProto_TYPE_INT32:
		if oneof {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if repeated {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = 0`)
			p.decodeVarint("m."+fieldname, typ)
		} else {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &v`)
		}
	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
		if !p.unsafe || gogoproto.IsCastType(field) {
			if oneof {
				p.P(`var v `, typ)
				p.decodeFixed64("v", typ)
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v `, typ)
				p.decodeFixed64("v", typ)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.P(`m.`, fieldname, ` = 0`)
				p.decodeFixed64("m."+fieldname, typ)
			} else {
				p.P(`var v `, typ)
				p.decodeFixed64("v", typ)
				p.P(`m.`, fieldname, ` = &v`)
			}
		} else {
			if oneof {
				p.P(`var v uint64`)
				p.unsafeFixed64("v", "uint64")
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v uint64`)
				p.unsafeFixed64("v", "uint64")
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.unsafeFixed64("m."+fieldname, "uint64")
			} else {
				p.P(`var v uint64`)
				p.unsafeFixed64("v", "uint64")
				p.P(`m.`, fieldname, ` = &v`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
		if !p.unsafe || gogoproto.IsCastType(field) {
			if oneof {
				p.P(`var v `, typ)
				p.decodeFixed32("v", typ)
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v `, typ)
				p.decodeFixed32("v", typ)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.P(`m.`, fieldname, ` = 0`)
				p.decodeFixed32("m."+fieldname, typ)
			} else {
				p.P(`var v `, typ)
				p.decodeFixed32("v", typ)
				p.P(`m.`, fieldname, ` = &v`)
			}
		} else {
			if oneof {
				p.P(`var v uint32`)
				p.unsafeFixed32("v", "uint32")
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v uint32`)
				p.unsafeFixed32("v", "uint32")
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.unsafeFixed32("m."+fieldname, "uint32")
			} else {
				p.P(`var v uint32`)
				p.unsafeFixed32("v", "uint32")
				p.P(`m.`, fieldname, ` = &v`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_BOOL:
		p.P(`var v int`)
		p.decodeVarint("v", "int")
		if oneof {
			p.P(`b := `, typ, `(v != 0)`)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{b}`)
		} else if repeated {
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, typ, `(v != 0))`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = `, typ, `(v != 0)`)
		} else {
			p.P(`b := `, typ, `(v != 0)`)
			p.P(`m.`, fieldname, ` = &b`)
		}
	case descriptor.FieldDescriptorProto_TYPE_STRING:
		p.P(`var stringLen uint64`)
		p.decodeVarint("stringLen", "uint64")
		p.P(`intStringLen := int(stringLen)`)
		p.P(`if intStringLen < 0 {`)
		p.In()
		p.P(`return ErrInvalidLength` + p.localName)
		p.Out()
		p.P(`}`)
		p.P(`postIndex := iNdEx + intStringLen`)
		p.P(`if postIndex > l {`)
		p.In()
		p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
		p.Out()
		p.P(`}`)
		if oneof {
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, `(data[iNdEx:postIndex])}`)
		} else if repeated {
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, typ, `(data[iNdEx:postIndex]))`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = `, typ, `(data[iNdEx:postIndex])`)
		} else {
			p.P(`s := `, typ, `(data[iNdEx:postIndex])`)
			p.P(`m.`, fieldname, ` = &s`)
		}
		p.P(`iNdEx = postIndex`)
	case descriptor.FieldDescriptorProto_TYPE_GROUP:
		panic(fmt.Errorf("unmarshaler does not support group %v", fieldname))
	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
		desc := p.ObjectNamed(field.GetTypeName())
		msgname := p.TypeName(desc)
		p.P(`var msglen int`)
		p.decodeVarint("msglen", "int")
		p.P(`if msglen < 0 {`)
		p.In()
		p.P(`return ErrInvalidLength` + p.localName)
		p.Out()
		p.P(`}`)
		p.P(`postIndex := iNdEx + msglen`)
		p.P(`if postIndex > l {`)
		p.In()
		p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
		p.Out()
		p.P(`}`)
		if oneof {
			buf := `data[iNdEx:postIndex]`
			if gogoproto.IsStdTime(field) {
				if nullable {
					p.P(`v := new(time.Time)`)
					p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(v, `, buf, `); err != nil {`)
				} else {
					p.P(`v := time.Time{}`)
					p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(&v, `, buf, `); err != nil {`)
				}
			} else if gogoproto.IsStdDuration(field) {
				if nullable {
					p.P(`v := new(time.Duration)`)
					p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(v, `, buf, `); err != nil {`)
				} else {
					p.P(`v := time.Duration(0)`)
					p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(&v, `, buf, `); err != nil {`)
				}
			} else {
				p.P(`v := &`, msgname, `{}`)
				p.P(`if err := v.Unmarshal(`, buf, `); err != nil {`)
			}
			p.In()
			p.P(`return err`)
			p.Out()
			p.P(`}`)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if p.IsMap(field) {
			m := p.GoMapType(nil, field)

			keygoTyp, _ := p.GoType(nil, m.KeyField)
			keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
			// keys may not be pointers
			keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
			keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)

			valuegoTyp, _ := p.GoType(nil, m.ValueField)
			valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)

			// if the map type is an alias and key or values are aliases (type Foo map[Bar]Baz),
			// we need to explicitly record their use here.
			p.RecordTypeUse(m.KeyAliasField.GetTypeName())
			p.RecordTypeUse(m.ValueAliasField.GetTypeName())

			nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
			if gogoproto.IsStdTime(field) || gogoproto.IsStdDuration(field) {
				valuegoTyp = valuegoAliasTyp
			}

			p.P(`var keykey uint64`)
			p.decodeVarint("keykey", "uint64")
			p.mapField("mapkey", false, m.KeyAliasField)
			p.P(`if m.`, fieldname, ` == nil {`)
			p.In()
			p.P(`m.`, fieldname, ` = make(`, m.GoType, `)`)
			p.Out()
			p.P(`}`)
			s := `m.` + fieldname
			if keygoTyp == keygoAliasTyp {
				s += `[mapkey]`
			} else {
				s += `[` + keygoAliasTyp + `(mapkey)]`
			}
			v := `mapvalue`
			if (m.ValueField.IsMessage() || gogoproto.IsCustomType(field)) && !nullable {
				v = `*` + v
			}
			if valuegoTyp != valuegoAliasTyp {
				v = `((` + valuegoAliasTyp + `)(` + v + `))`
			}
			p.P(`if iNdEx < postIndex {`)
			p.In()
			p.P(`var valuekey uint64`)
			p.decodeVarint("valuekey", "uint64")
			p.mapField("mapvalue", gogoproto.IsCustomType(field), m.ValueAliasField)
			p.P(s, ` = `, v)
			p.Out()
			p.P(`} else {`)
			p.In()
			if gogoproto.IsStdTime(field) {
				p.P(`var mapvalue = new(time.Time)`)
				if nullable {
					p.P(s, ` = mapvalue`)
				} else {
					p.P(s, ` = *mapvalue`)
				}
			} else if gogoproto.IsStdDuration(field) {
				p.P(`var mapvalue = new(time.Duration)`)
				if nullable {
					p.P(s, ` = mapvalue`)
				} else {
					p.P(s, ` = *mapvalue`)
				}
			} else {
				p.P(`var mapvalue `, valuegoAliasTyp)
				p.P(s, ` = mapvalue`)
			}
			p.Out()
			p.P(`}`)
		} else if repeated {
			if gogoproto.IsStdTime(field) {
				if nullable {
					p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(time.Time))`)
				} else {
					p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, time.Time{})`)
				}
			} else if gogoproto.IsStdDuration(field) {
				if nullable {
					p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, new(time.Duration))`)
				} else {
					p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, time.Duration(0))`)
				}
			} else if nullable {
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, &`, msgname, `{})`)
			} else {
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, msgname, `{})`)
			}
			varName := `m.` + fieldname + `[len(m.` + fieldname + `)-1]`
			buf := `data[iNdEx:postIndex]`
			if gogoproto.IsStdTime(field) {
				if nullable {
					p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(`, varName, `,`, buf, `); err != nil {`)
				} else {
					p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
				}
			} else if gogoproto.IsStdDuration(field) {
				if nullable {
					p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(`, varName, `,`, buf, `); err != nil {`)
				} else {
					p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(&(`, varName, `),`, buf, `); err != nil {`)
				}
			} else {
				p.P(`if err := `, varName, `.Unmarshal(`, buf, `); err != nil {`)
			}
			p.In()
			p.P(`return err`)
			p.Out()
			p.P(`}`)
		} else if nullable {
			p.P(`if m.`, fieldname, ` == nil {`)
			p.In()
			if gogoproto.IsStdTime(field) {
				p.P(`m.`, fieldname, ` = new(time.Time)`)
			} else if gogoproto.IsStdDuration(field) {
				p.P(`m.`, fieldname, ` = new(time.Duration)`)
			} else {
				p.P(`m.`, fieldname, ` = &`, msgname, `{}`)
			}
			p.Out()
			p.P(`}`)
			if gogoproto.IsStdTime(field) {
				p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(m.`, fieldname, `, data[iNdEx:postIndex]); err != nil {`)
			} else if gogoproto.IsStdDuration(field) {
				p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(m.`, fieldname, `, data[iNdEx:postIndex]); err != nil {`)
			} else {
				p.P(`if err := m.`, fieldname, `.Unmarshal(data[iNdEx:postIndex]); err != nil {`)
			}
			p.In()
			p.P(`return err`)
			p.Out()
			p.P(`}`)
		} else {
			if gogoproto.IsStdTime(field) {
				p.P(`if err := `, p.typesPkg.Use(), `.StdTimeUnmarshal(&m.`, fieldname, `, data[iNdEx:postIndex]); err != nil {`)
			} else if gogoproto.IsStdDuration(field) {
				p.P(`if err := `, p.typesPkg.Use(), `.StdDurationUnmarshal(&m.`, fieldname, `, data[iNdEx:postIndex]); err != nil {`)
			} else {
				p.P(`if err := m.`, fieldname, `.Unmarshal(data[iNdEx:postIndex]); err != nil {`)
			}
			p.In()
			p.P(`return err`)
			p.Out()
			p.P(`}`)
		}
		p.P(`iNdEx = postIndex`)
	case descriptor.FieldDescriptorProto_TYPE_BYTES:
		p.P(`var byteLen int`)
		p.decodeVarint("byteLen", "int")
		p.P(`if byteLen < 0 {`)
		p.In()
		p.P(`return ErrInvalidLength` + p.localName)
		p.Out()
		p.P(`}`)
		p.P(`postIndex := iNdEx + byteLen`)
		p.P(`if postIndex > l {`)
		p.In()
		p.P(`return `, p.ioPkg.Use(), `.ErrUnexpectedEOF`)
		p.Out()
		p.P(`}`)
		if !gogoproto.IsCustomType(field) {
			if oneof {
				p.P(`v := make([]byte, postIndex-iNdEx)`)
				p.P(`copy(v, data[iNdEx:postIndex])`)
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, make([]byte, postIndex-iNdEx))`)
				p.P(`copy(m.`, fieldname, `[len(m.`, fieldname, `)-1], data[iNdEx:postIndex])`)
			} else {
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `[:0] , data[iNdEx:postIndex]...)`)
				p.P(`if m.`, fieldname, ` == nil {`)
				p.In()
				p.P(`m.`, fieldname, ` = []byte{}`)
				p.Out()
				p.P(`}`)
			}
		} else {
			_, ctyp, err := generator.GetCustomType(field)
			if err != nil {
				panic(err)
			}
			if oneof {
				p.P(`var vv `, ctyp)
				p.P(`v := &vv`)
				p.P(`if err := v.Unmarshal(data[iNdEx:postIndex]); err != nil {`)
				p.In()
				p.P(`return err`)
				p.Out()
				p.P(`}`)
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{*v}`)
			} else if repeated {
				p.P(`var v `, ctyp)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
				p.P(`if err := m.`, fieldname, `[len(m.`, fieldname, `)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {`)
				p.In()
				p.P(`return err`)
				p.Out()
				p.P(`}`)
			} else if nullable {
				p.P(`var v `, ctyp)
				p.P(`m.`, fieldname, ` = &v`)
				p.P(`if err := m.`, fieldname, `.Unmarshal(data[iNdEx:postIndex]); err != nil {`)
				p.In()
				p.P(`return err`)
				p.Out()
				p.P(`}`)
			} else {
				p.P(`if err := m.`, fieldname, `.Unmarshal(data[iNdEx:postIndex]); err != nil {`)
				p.In()
				p.P(`return err`)
				p.Out()
				p.P(`}`)
			}
		}
		p.P(`iNdEx = postIndex`)
	case descriptor.FieldDescriptorProto_TYPE_UINT32:
		if oneof {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if repeated {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = 0`)
			p.decodeVarint("m."+fieldname, typ)
		} else {
			p.P(`var v `, typ)
			p.decodeVarint("v", typ)
			p.P(`m.`, fieldname, ` = &v`)
		}
	case descriptor.FieldDescriptorProto_TYPE_ENUM:
		typName := p.TypeName(p.ObjectNamed(field.GetTypeName()))
		if oneof {
			p.P(`var v `, typName)
			p.decodeVarint("v", typName)
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if repeated {
			p.P(`var v `, typName)
			p.decodeVarint("v", typName)
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = 0`)
			p.decodeVarint("m."+fieldname, typName)
		} else {
			p.P(`var v `, typName)
			p.decodeVarint("v", typName)
			p.P(`m.`, fieldname, ` = &v`)
		}
	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
		if !p.unsafe || gogoproto.IsCastType(field) {
			if oneof {
				p.P(`var v `, typ)
				p.decodeFixed32("v", typ)
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v `, typ)
				p.decodeFixed32("v", typ)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.P(`m.`, fieldname, ` = 0`)
				p.decodeFixed32("m."+fieldname, typ)
			} else {
				p.P(`var v `, typ)
				p.decodeFixed32("v", typ)
				p.P(`m.`, fieldname, ` = &v`)
			}
		} else {
			if oneof {
				p.P(`var v int32`)
				p.unsafeFixed32("v", "int32")
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v int32`)
				p.unsafeFixed32("v", "int32")
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.unsafeFixed32("m."+fieldname, "int32")
			} else {
				p.P(`var v int32`)
				p.unsafeFixed32("v", "int32")
				p.P(`m.`, fieldname, ` = &v`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
		if !p.unsafe || gogoproto.IsCastType(field) {
			if oneof {
				p.P(`var v `, typ)
				p.decodeFixed64("v", typ)
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v `, typ)
				p.decodeFixed64("v", typ)
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.P(`m.`, fieldname, ` = 0`)
				p.decodeFixed64("m."+fieldname, typ)
			} else {
				p.P(`var v `, typ)
				p.decodeFixed64("v", typ)
				p.P(`m.`, fieldname, ` = &v`)
			}
		} else {
			if oneof {
				p.P(`var v int64`)
				p.unsafeFixed64("v", "int64")
				p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
			} else if repeated {
				p.P(`var v int64`)
				p.unsafeFixed64("v", "int64")
				p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
			} else if proto3 || !nullable {
				p.unsafeFixed64("m."+fieldname, "int64")
			} else {
				p.P(`var v int64`)
				p.unsafeFixed64("v", "int64")
				p.P(`m.`, fieldname, ` = &v`)
			}
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT32:
		p.P(`var v `, typ)
		p.decodeVarint("v", typ)
		p.P(`v = `, typ, `((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))`)
		if oneof {
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{v}`)
		} else if repeated {
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, v)`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = v`)
		} else {
			p.P(`m.`, fieldname, ` = &v`)
		}
	case descriptor.FieldDescriptorProto_TYPE_SINT64:
		p.P(`var v uint64`)
		p.decodeVarint("v", "uint64")
		p.P(`v = (v >> 1) ^ uint64((int64(v&1)<<63)>>63)`)
		if oneof {
			p.P(`m.`, fieldname, ` = &`, p.OneOfTypeName(msg, field), `{`, typ, `(v)}`)
		} else if repeated {
			p.P(`m.`, fieldname, ` = append(m.`, fieldname, `, `, typ, `(v))`)
		} else if proto3 || !nullable {
			p.P(`m.`, fieldname, ` = `, typ, `(v)`)
		} else {
			p.P(`v2 := `, typ, `(v)`)
			p.P(`m.`, fieldname, ` = &v2`)
		}
	default:
		panic("not implemented")
	}
}
Ejemplo n.º 14
0
func (p *stringer) Generate(file *generator.FileDescriptor) {
	proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
	p.PluginImports = generator.NewPluginImports(p.Generator)
	p.atleastOne = false

	p.localName = generator.FileName(file)

	fmtPkg := p.NewImport("fmt")
	stringsPkg := p.NewImport("strings")
	reflectPkg := p.NewImport("reflect")
	sortKeysPkg := p.NewImport("github.com/maditya/protobuf/sortkeys")
	protoPkg := p.NewImport("github.com/maditya/protobuf/proto")
	for _, message := range file.Messages() {
		if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
			continue
		}
		if gogoproto.EnabledGoStringer(file.FileDescriptorProto, message.DescriptorProto) {
			panic("old string method needs to be disabled, please use gogoproto.goproto_stringer or gogoproto.goproto_stringer_all and set it to false")
		}
		if message.DescriptorProto.GetOptions().GetMapEntry() {
			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(`}`)
		for _, field := range message.Field {
			if !p.IsMap(field) {
				continue
			}
			fieldname := p.GetFieldName(message, field)

			m := p.GoMapType(nil, field)
			mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
			keysName := `keysFor` + fieldname
			keygoTyp, _ := p.GoType(nil, keyField)
			keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
			keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
			keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
			keyCapTyp := generator.CamelCase(keygoTyp)
			p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
			p.P(`for k, _ := range this.`, fieldname, ` {`)
			p.In()
			if keygoAliasTyp == keygoTyp {
				p.P(keysName, ` = append(`, keysName, `, k)`)
			} else {
				p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
			}
			p.Out()
			p.P(`}`)
			p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
			mapName := `mapStringFor` + fieldname
			p.P(mapName, ` := "`, mapgoTyp, `{"`)
			p.P(`for _, k := range `, keysName, ` {`)
			p.In()
			if keygoAliasTyp == keygoTyp {
				p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[k])`)
			} else {
				p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
			}
			p.Out()
			p.P(`}`)
			p.P(mapName, ` += "}"`)
		}
		p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
		oneofs := make(map[string]struct{})
		for _, field := range message.Field {
			nullable := gogoproto.IsNullable(field)
			repeated := field.IsRepeated()
			fieldname := p.GetFieldName(message, field)
			oneof := field.OneofIndex != nil
			if oneof {
				if _, ok := oneofs[fieldname]; ok {
					continue
				} else {
					oneofs[fieldname] = struct{}{}
				}
				p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
			} else if p.IsMap(field) {
				mapName := `mapStringFor` + fieldname
				p.P("`", fieldname, ":`", ` + `, mapName, " + `,", "`,")
			} else 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 nullable {
					p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
				} else if repeated {
					p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,")
				} else {
					p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(this.`, fieldname, `.String(), "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,")
				}
			} else {
				if nullable && !repeated && !proto3 {
					p.P("`", fieldname, ":`", ` + valueToString`, p.localName, `(this.`, fieldname, ") + `,", "`,")
				} else {
					p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
				}
			}
		}
		if message.DescriptorProto.HasExtension() {
			if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
				p.P("`XXX_InternalExtensions:` + ", protoPkg.Use(), ".StringFromInternalExtension(this) + `,`,")
			} else {
				p.P("`XXX_extensions:` + ", protoPkg.Use(), ".StringFromExtensionsBytes(this.XXX_extensions) + `,`,")
			}
		}
		if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
			p.P("`XXX_unrecognized:` + ", fmtPkg.Use(), `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,")
		}
		p.P("`}`,")
		p.P(`}`, `,""`, ")")
		p.P(`return s`)
		p.Out()
		p.P(`}`)

		//Generate String methods for oneof fields
		for _, field := range message.Field {
			oneof := field.OneofIndex != nil
			if !oneof {
				continue
			}
			ccTypeName := p.OneOfTypeName(message, field)
			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, "{`,")
			fieldname := p.GetOneOfFieldName(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]
				p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
			} else {
				p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
			}
			p.P("`}`,")
			p.P(`}`, `,""`, ")")
			p.P(`return s`)
			p.Out()
			p.P(`}`)
		}
	}

	if !p.atleastOne {
		return
	}

	p.P(`func valueToString`, p.localName, `(v interface{}) string {`)
	p.In()
	p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
	p.P(`if rv.IsNil() {`)
	p.In()
	p.P(`return "nil"`)
	p.Out()
	p.P(`}`)
	p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
	p.P(`return `, fmtPkg.Use(), `.Sprintf("*%v", pv)`)
	p.Out()
	p.P(`}`)

}