123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795 |
- // Protocol Buffers for Go with Gadgets
- //
- // Copyright (c) 2013, The GoGo Authors. All rights reserved.
- // http://github.com/gogo/protobuf
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- /*
- The populate plugin generates a NewPopulated function.
- This function returns a newly populated structure.
- It is enabled by the following extensions:
- - populate
- - populate_all
- Let us look at:
- github.com/gogo/protobuf/test/example/example.proto
- Btw all the output can be seen at:
- github.com/gogo/protobuf/test/example/*
- The following message:
- option (gogoproto.populate_all) = true;
- message B {
- optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
- repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
- }
- given to the populate plugin, will generate code the following code:
- func NewPopulatedB(r randyExample, easy bool) *B {
- this := &B{}
- v2 := NewPopulatedA(r, easy)
- this.A = *v2
- if r.Intn(10) != 0 {
- v3 := r.Intn(10)
- this.G = make([]github_com_gogo_protobuf_test_custom.Uint128, v3)
- for i := 0; i < v3; i++ {
- v4 := github_com_gogo_protobuf_test_custom.NewPopulatedUint128(r)
- this.G[i] = *v4
- }
- }
- if !easy && r.Intn(10) != 0 {
- this.XXX_unrecognized = randUnrecognizedExample(r, 3)
- }
- return this
- }
- The idea that is useful for testing.
- Most of the other plugins' generated test code uses it.
- You will still be able to use the generated test code of other packages
- if you turn off the popluate plugin and write your own custom NewPopulated function.
- If the easy flag is not set the XXX_unrecognized and XXX_extensions fields are also populated.
- These have caused problems with JSON marshalling and unmarshalling tests.
- */
- package populate
- import (
- "fmt"
- "math"
- "strconv"
- "strings"
- "github.com/gogo/protobuf/gogoproto"
- "github.com/gogo/protobuf/proto"
- descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
- "github.com/gogo/protobuf/protoc-gen-gogo/generator"
- "github.com/gogo/protobuf/vanity"
- )
- type VarGen interface {
- Next() string
- Current() string
- }
- type varGen struct {
- index int64
- }
- func NewVarGen() VarGen {
- return &varGen{0}
- }
- func (this *varGen) Next() string {
- this.index++
- return fmt.Sprintf("v%d", this.index)
- }
- func (this *varGen) Current() string {
- return fmt.Sprintf("v%d", this.index)
- }
- type plugin struct {
- *generator.Generator
- generator.PluginImports
- varGen VarGen
- atleastOne bool
- localName string
- typesPkg generator.Single
- }
- func NewPlugin() *plugin {
- return &plugin{}
- }
- func (p *plugin) Name() string {
- return "populate"
- }
- func (p *plugin) Init(g *generator.Generator) {
- p.Generator = g
- }
- func value(typeName string, fieldType descriptor.FieldDescriptorProto_Type) string {
- switch fieldType {
- case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
- return typeName + "(r.Float64())"
- case descriptor.FieldDescriptorProto_TYPE_FLOAT:
- return typeName + "(r.Float32())"
- case descriptor.FieldDescriptorProto_TYPE_INT64,
- descriptor.FieldDescriptorProto_TYPE_SFIXED64,
- descriptor.FieldDescriptorProto_TYPE_SINT64:
- return typeName + "(r.Int63())"
- case descriptor.FieldDescriptorProto_TYPE_UINT64,
- descriptor.FieldDescriptorProto_TYPE_FIXED64:
- return typeName + "(uint64(r.Uint32()))"
- case descriptor.FieldDescriptorProto_TYPE_INT32,
- descriptor.FieldDescriptorProto_TYPE_SINT32,
- descriptor.FieldDescriptorProto_TYPE_SFIXED32,
- descriptor.FieldDescriptorProto_TYPE_ENUM:
- return typeName + "(r.Int31())"
- case descriptor.FieldDescriptorProto_TYPE_UINT32,
- descriptor.FieldDescriptorProto_TYPE_FIXED32:
- return typeName + "(r.Uint32())"
- case descriptor.FieldDescriptorProto_TYPE_BOOL:
- return typeName + `(bool(r.Intn(2) == 0))`
- case descriptor.FieldDescriptorProto_TYPE_STRING,
- descriptor.FieldDescriptorProto_TYPE_GROUP,
- descriptor.FieldDescriptorProto_TYPE_MESSAGE,
- descriptor.FieldDescriptorProto_TYPE_BYTES:
- }
- panic(fmt.Errorf("unexpected type %v", typeName))
- }
- func negative(fieldType descriptor.FieldDescriptorProto_Type) bool {
- switch fieldType {
- case descriptor.FieldDescriptorProto_TYPE_UINT64,
- descriptor.FieldDescriptorProto_TYPE_FIXED64,
- descriptor.FieldDescriptorProto_TYPE_UINT32,
- descriptor.FieldDescriptorProto_TYPE_FIXED32,
- descriptor.FieldDescriptorProto_TYPE_BOOL:
- return false
- }
- return true
- }
- func (p *plugin) getFuncName(goTypName string) string {
- funcName := "NewPopulated" + goTypName
- goTypNames := strings.Split(goTypName, ".")
- if len(goTypNames) == 2 {
- funcName = goTypNames[0] + ".NewPopulated" + goTypNames[1]
- } else if len(goTypNames) != 1 {
- panic(fmt.Errorf("unreachable: too many dots in %v", goTypName))
- }
- switch funcName {
- case "time.NewPopulatedTime":
- funcName = p.typesPkg.Use() + ".NewPopulatedStdTime"
- case "time.NewPopulatedDuration":
- funcName = p.typesPkg.Use() + ".NewPopulatedStdDuration"
- }
- return funcName
- }
- func (p *plugin) getFuncCall(goTypName string) string {
- funcName := p.getFuncName(goTypName)
- funcCall := funcName + "(r, easy)"
- return funcCall
- }
- func (p *plugin) getCustomFuncCall(goTypName string) string {
- funcName := p.getFuncName(goTypName)
- funcCall := funcName + "(r)"
- return funcCall
- }
- func (p *plugin) getEnumVal(field *descriptor.FieldDescriptorProto, goTyp string) string {
- enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
- l := len(enum.Value)
- values := make([]string, l)
- for i := range enum.Value {
- values[i] = strconv.Itoa(int(*enum.Value[i].Number))
- }
- arr := "[]int32{" + strings.Join(values, ",") + "}"
- val := strings.Join([]string{generator.GoTypeToName(goTyp), `(`, arr, `[r.Intn(`, fmt.Sprintf("%d", l), `)])`}, "")
- return val
- }
- 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 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.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 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() {
- typName := generator.GoTypeToName(goTyp)
- val := fmt.Sprintf("%s(randString%v(r))", typName, 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())
- }
- }
- }
- }
- func (p *plugin) hasLoop(pkg string, field *descriptor.FieldDescriptorProto, visited []*generator.Descriptor, excludes []*generator.Descriptor) *generator.Descriptor {
- if field.IsMessage() || p.IsGroup(field) || p.IsMap(field) {
- var fieldMessage *generator.Descriptor
- if p.IsMap(field) {
- m := p.GoMapType(nil, field)
- if !m.ValueField.IsMessage() {
- return nil
- }
- fieldMessage = p.ObjectNamed(m.ValueField.GetTypeName()).(*generator.Descriptor)
- } else {
- fieldMessage = p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
- }
- fieldTypeName := generator.CamelCaseSlice(fieldMessage.TypeName())
- for _, message := range visited {
- messageTypeName := generator.CamelCaseSlice(message.TypeName())
- if fieldTypeName == messageTypeName {
- for _, e := range excludes {
- if fieldTypeName == generator.CamelCaseSlice(e.TypeName()) {
- return nil
- }
- }
- return fieldMessage
- }
- }
- for _, f := range fieldMessage.Field {
- if strings.HasPrefix(f.GetTypeName(), "."+pkg) {
- visited = append(visited, fieldMessage)
- loopTo := p.hasLoop(pkg, f, visited, excludes)
- if loopTo != nil {
- return loopTo
- }
- }
- }
- }
- return nil
- }
- func (p *plugin) loops(pkg string, field *descriptor.FieldDescriptorProto, message *generator.Descriptor) int {
- //fmt.Fprintf(os.Stderr, "loops %v %v\n", field.GetTypeName(), generator.CamelCaseSlice(message.TypeName()))
- excludes := []*generator.Descriptor{}
- loops := 0
- for {
- visited := []*generator.Descriptor{}
- loopTo := p.hasLoop(pkg, field, visited, excludes)
- if loopTo == nil {
- break
- }
- //fmt.Fprintf(os.Stderr, "loopTo %v\n", generator.CamelCaseSlice(loopTo.TypeName()))
- excludes = append(excludes, loopTo)
- loops++
- }
- return loops
- }
- 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/gogo/protobuf/types")
- p.localName = generator.FileName(file)
- protoPkg := p.NewImport("github.com/gogo/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(file.GetPackage(), 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().FileDescriptorProto, 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.TurnOffNullableForNativeTypes(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(`}`)
- }
- func init() {
- generator.RegisterPlugin(NewPlugin())
- }
|