github.com/cosmos/cosmos-proto@v1.0.0-beta.3/features/fastreflection/set.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 setGen struct { 10 *generator.GeneratedFile 11 typeName string 12 message *protogen.Message 13 } 14 15 func (g *setGen) generate() { 16 g.genComment() 17 g.P("func (x *", g.typeName, ") Set(fd ", protoreflectPkg.Ident("FieldDescriptor"), ", value ", 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.genDefaultCase() 25 g.P("}") 26 g.P("}") 27 g.P() 28 } 29 30 func (g *setGen) genComment() { 31 g.P("// Set stores the value for a field.") 32 g.P("//") 33 g.P("// For a field belonging to a oneof, it implicitly clears any other field") 34 g.P("// that may be currently set within the same oneof.") 35 g.P("// For extension fields, it implicitly stores the provided ExtensionType.") 36 g.P("// When setting a composite type, it is unspecified whether the stored value") 37 g.P("// aliases the source's memory in any way. If the composite value is an") 38 g.P("// empty, read-only value, then it panics.") 39 g.P("//") 40 g.P("// Set is a mutating operation and unsafe for concurrent use.") 41 } 42 43 func (g *setGen) genField(field *protogen.Field) { 44 if field.Oneof != nil { 45 g.genOneof(field) 46 return 47 } 48 49 switch { 50 case field.Desc.IsMap(): 51 g.genMap(field) 52 return 53 case field.Desc.IsList(): 54 g.genList(field) 55 return 56 } 57 58 fieldRef := "x." + field.GoName 59 60 switch field.Desc.Kind() { 61 case protoreflect.BoolKind: 62 g.P(fieldRef, " = value.Bool()") 63 case protoreflect.EnumKind: 64 g.P(fieldRef, " = (", g.QualifiedGoIdent(field.Enum.GoIdent), ")(value.Enum())") 65 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 66 g.P(fieldRef, " = int32(value.Int())") 67 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 68 g.P(fieldRef, " = uint32(value.Uint())") 69 case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 70 g.P(fieldRef, " = value.Int()") 71 case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 72 g.P(fieldRef, " = value.Uint()") 73 case protoreflect.FloatKind: 74 g.P(fieldRef, " = float32(value.Float())") 75 case protoreflect.DoubleKind: 76 g.P(fieldRef, " = value.Float()") 77 case protoreflect.StringKind: 78 g.P(fieldRef, " = value.Interface().(string)") 79 case protoreflect.BytesKind: 80 g.P(fieldRef, " = value.Bytes()") 81 case protoreflect.MessageKind, protoreflect.GroupKind: 82 g.P(fieldRef, " = value.Message().Interface().(*", g.QualifiedGoIdent(field.Message.GoIdent), ")") 83 } 84 85 } 86 87 // genDefaultCase generates the default case for field descriptor 88 func (g *setGen) genDefaultCase() { 89 g.P("if fd.IsExtension() {") 90 g.P("panic(", fmtPkg.Ident("Errorf"), "(\"proto3 declared messages do not support extensions: ", g.message.Desc.FullName(), "\"))") 91 g.P("}") 92 g.P("panic(fmt.Errorf(\"message ", g.message.Desc.FullName(), " does not contain field %s\", fd.FullName()))") 93 } 94 95 func (g *setGen) genOneof(field *protogen.Field) { 96 g.genOneofValueUnwrapper(field) 97 g.P("x.", field.Oneof.GoName, " = &", g.QualifiedGoIdent(field.GoIdent), "{", field.GoName, ": cv", "}") 98 } 99 100 // genMap generates the implementation of set for map types. 101 // for implementation details look at genList 102 func (g *setGen) genMap(field *protogen.Field) { 103 g.P("mv := value.Map()") 104 g.P("cmv := mv.(*", mapTypeName(field), ")") 105 g.P("x.", field.GoName, " = *cmv.m") 106 } 107 108 // genList generates the implementation of set for list types. 109 // NOTE: in the original protoreflect implementation, using a List implementation 110 // which does not match the expected impl.listReflect type panics. 111 // To respect this behaviour, we use the fastpath list casting to our 112 // list implementation. This is to respect mutability guarantees. 113 // After we set a list the value can still be mutated. 114 func (g *setGen) genList(field *protogen.Field) { 115 g.P("lv := value.List()") 116 g.P("clv := lv.(*", listTypeName(field), ")") 117 g.P("x.", field.GoName, " = *clv.list") 118 } 119 120 func (g *setGen) genOneofValueUnwrapper(field *protogen.Field) { 121 fieldRef := "cv := " 122 switch field.Desc.Kind() { 123 case protoreflect.BoolKind: 124 g.P(fieldRef, " value.Bool()") 125 case protoreflect.EnumKind: 126 g.P(fieldRef, " (", g.QualifiedGoIdent(field.Enum.GoIdent), ")(value.Enum())") 127 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 128 g.P(fieldRef, " int32(value.Int())") 129 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 130 g.P(fieldRef, " uint32(value.Uint())") 131 case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 132 g.P(fieldRef, " value.Int()") 133 case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 134 g.P(fieldRef, " value.Uint()") 135 case protoreflect.FloatKind: 136 g.P(fieldRef, " float32(value.Float())") 137 case protoreflect.DoubleKind: 138 g.P(fieldRef, " value.Float()") 139 case protoreflect.StringKind: 140 g.P(fieldRef, " value.Interface().(string)") 141 case protoreflect.BytesKind: 142 g.P(fieldRef, " value.Bytes()") 143 case protoreflect.MessageKind, protoreflect.GroupKind: 144 g.P(fieldRef, " value.Message().Interface().(*", g.QualifiedGoIdent(field.Message.GoIdent), ")") 145 } 146 }