github.com/cosmos/cosmos-proto@v1.0.0-beta.3/features/fastreflection/new_field.go (about) 1 package fastreflection 2 3 import ( 4 "github.com/cosmos/cosmos-proto/generator" 5 "google.golang.org/protobuf/compiler/protogen" 6 "google.golang.org/protobuf/reflect/protoreflect" 7 ) 8 9 type newFieldGen struct { 10 *generator.GeneratedFile 11 typeName string 12 message *protogen.Message 13 } 14 15 func (g *newFieldGen) generate() { 16 g.genComment() 17 g.P("func (x *", g.typeName, ") NewField(fd ", protoreflectPkg.Ident("FieldDescriptor"), ") ", protoreflectPkg.Ident("Value"), " {") 18 g.P("switch fd.FullName() {") 19 for _, field := range g.message.Fields { 20 g.P("case \"", field.Desc.FullName(), "\":") 21 g.genField(field) 22 } 23 g.P("default: ") 24 g.P("if fd.IsExtension() {") 25 g.P("panic(", fmtPkg.Ident("Errorf"), "(\"proto3 declared messages do not support extensions: ", g.message.Desc.FullName(), "\"))") 26 g.P("}") 27 g.P("panic(fmt.Errorf(\"message ", g.message.Desc.FullName(), " does not contain field %s\", fd.FullName()))") 28 g.P("}") 29 g.P("}") 30 } 31 32 func (g *newFieldGen) genComment() { 33 g.P("// NewField returns a new value that is assignable to the field") 34 g.P("// for the given descriptor. For scalars, this returns the default value.") 35 g.P("// For lists, maps, and messages, this returns a new, empty, mutable value.") 36 } 37 38 func (g *newFieldGen) genField(field *protogen.Field) { 39 switch { 40 case field.Desc.IsMap(), field.Desc.IsList(), field.Desc.Kind() == protoreflect.MessageKind: 41 g.genMutable(field) 42 default: 43 g.P("return ", kindToValueConstructor(field.Desc.Kind()), "(", zeroValueForField(g.GeneratedFile, field), ")") 44 } 45 } 46 47 func (g *newFieldGen) genMutable(field *protogen.Field) { 48 switch { 49 case field.Oneof != nil: 50 g.genOneof(field) 51 case field.Desc.IsMap(): 52 g.P("m := make(map[", getGoType(g.GeneratedFile, field.Message.Fields[0]), "]", getGoType(g.GeneratedFile, field.Message.Fields[1]), ")") 53 g.P("return ", protoreflectPkg.Ident("ValueOfMap"), "(&", mapTypeName(field), "{m: &m})") 54 case field.Desc.IsList(): 55 g.P("list := []", getGoType(g.GeneratedFile, field), "{}") 56 g.P("return ", protoreflectPkg.Ident("ValueOfList"), "(&", listTypeName(field), "{list: &list})") 57 case field.Desc.Kind() == protoreflect.MessageKind: 58 g.P("m := new(", g.QualifiedGoIdent(field.Message.GoIdent), ")") 59 g.P("return ", protoreflectPkg.Ident("ValueOfMessage"), "(m.ProtoReflect())") 60 default: 61 panic("unreachable") 62 } 63 } 64 65 func (g *newFieldGen) genOneof(field *protogen.Field) { 66 if field.Desc.Kind() != protoreflect.MessageKind { 67 panic("newfield oneof fastGenerator should be applied only to mutable message types") 68 } 69 g.P("value := &", g.QualifiedGoIdent(field.Message.GoIdent), "{}") 70 g.P("return ", protoreflectPkg.Ident("ValueOfMessage"), "(value.ProtoReflect())") 71 }