github.com/cosmos/cosmos-proto@v1.0.0-beta.3/features/fastreflection/range.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 rangeGen struct { 10 *generator.GeneratedFile 11 typeName string 12 message *protogen.Message 13 14 processedOneofs map[string]struct{} 15 } 16 17 func (g *rangeGen) generate() { 18 g.processedOneofs = map[string]struct{}{} 19 20 g.genComment() 21 g.P("func (x *", g.typeName, ") Range(f func(", protoreflectPkg.Ident("FieldDescriptor"), ", ", protoreflectPkg.Ident("Value"), ") bool) {") 22 for _, field := range g.message.Fields { 23 g.genField(field) 24 } 25 g.P("}") 26 } 27 28 func (g *rangeGen) genComment() { 29 g.P("// Range iterates over every populated field in an undefined order,") 30 g.P("// calling f for each field descriptor and value encountered.") 31 g.P("// Range returns immediately if f returns false.") 32 g.P("// While iterating, mutating operations may only be performed") 33 g.P("// on the current field descriptor.") 34 } 35 36 func (g *rangeGen) genField(field *protogen.Field) { 37 if field.Oneof != nil { 38 g.genOneof(field) 39 return 40 } 41 42 switch { 43 case field.Desc.IsMap(): 44 g.P("if len(x.", field.GoName, ") != 0 {") 45 g.P("value := ", protoreflectPkg.Ident("ValueOfMap"), "(&", mapTypeName(field), "{m: &x.", field.GoName, "})") 46 g.P("if !f(", fieldDescriptorName(field), ", value) {") 47 g.P("return") 48 g.P("}") 49 g.P("}") 50 case field.Desc.IsList(): 51 g.P("if len(x.", field.GoName, ") != 0 {") 52 g.P("value := ", protoreflectPkg.Ident("ValueOfList"), "(&", listTypeName(field), "{list: &x.", field.GoName, "})") 53 g.P("if !f(", fieldDescriptorName(field), ", value) {") 54 g.P("return") 55 g.P("}") 56 g.P("}") 57 case field.Desc.Kind() == protoreflect.MessageKind: 58 g.P("if x.", field.GoName, " != nil {") 59 g.P("value := ", protoreflectPkg.Ident("ValueOfMessage"), "(x.", field.GoName, ".ProtoReflect())") 60 g.P("if !f(", fieldDescriptorName(field), ", value) {") 61 g.P("return") 62 g.P("}") 63 g.P("}") 64 case field.Desc.Kind() == protoreflect.BytesKind: 65 g.P("if len(x.", field.GoName, ") != 0 {") 66 g.P("value := ", protoreflectPkg.Ident("ValueOfBytes"), "(x.", field.GoName, ")") 67 g.P("if !f(", fieldDescriptorName(field), ", value) {") 68 g.P("return") 69 g.P("}") 70 g.P("}") 71 case field.Desc.Kind() == protoreflect.DoubleKind: 72 g.P("if x.", field.GoName, " != ", zeroValueForField(g.GeneratedFile, field), " || ", mathPkg.Ident("Signbit"), "(x.", field.GoName, ")", "{") 73 g.P("value := ", kindToValueConstructor(field.Desc.Kind()), "(x.", field.GoName, ")") 74 g.P("if !f(", fieldDescriptorName(field), ", value) {") 75 g.P("return") 76 g.P("}") 77 g.P("}") 78 case field.Desc.Kind() == protoreflect.FloatKind: 79 g.P("if x.", field.GoName, " != ", zeroValueForField(g.GeneratedFile, field), " || ", mathPkg.Ident("Signbit"), "(float64(x.", field.GoName, "))", "{") 80 g.P("value := ", kindToValueConstructor(field.Desc.Kind()), "(x.", field.GoName, ")") 81 g.P("if !f(", fieldDescriptorName(field), ", value) {") 82 g.P("return") 83 g.P("}") 84 g.P("}") 85 default: 86 g.P("if x.", field.GoName, " != ", zeroValueForField(g.GeneratedFile, field), "{") 87 switch { 88 case field.Desc.Kind() == protoreflect.EnumKind: 89 g.P("value := ", kindToValueConstructor(field.Desc.Kind()), "((", protoreflectPkg.Ident("EnumNumber"), ")(x.", field.GoName, ")) ") 90 default: 91 g.P("value := ", kindToValueConstructor(field.Desc.Kind()), "(x.", field.GoName, ")") 92 } 93 g.P("if !f(", fieldDescriptorName(field), ", value) {") 94 g.P("return") 95 g.P("}") 96 g.P("}") 97 } 98 } 99 100 func (g *rangeGen) genOneof(field *protogen.Field) { 101 // we check if it was processed or not 102 if _, ok := g.processedOneofs[field.Oneof.GoIdent.String()]; ok { 103 return 104 } 105 // we process it only if its != nil 106 g.P("if x.", field.Oneof.GoName, " != nil {") 107 g.P("switch o := x.", field.Oneof.GoName, ".(type) {") 108 for _, oneofField := range field.Oneof.Fields { 109 g.P("case *", g.QualifiedGoIdent(oneofField.GoIdent), ":") 110 g.P("v := ", "o.", oneofField.GoName) 111 switch oneofField.Desc.Kind() { 112 case protoreflect.MessageKind: 113 g.P("value := ", kindToValueConstructor(oneofField.Desc.Kind()), "(v.ProtoReflect())") 114 case protoreflect.EnumKind: 115 g.P("value :=", kindToValueConstructor(oneofField.Desc.Kind()), "((", protoreflectPkg.Ident("EnumNumber"), ")(v))") 116 default: 117 g.P("value := ", kindToValueConstructor(oneofField.Desc.Kind()), "(v)") 118 119 } 120 g.P("if !f(", fieldDescriptorName(oneofField), ", value) {") 121 g.P("return") 122 g.P("}") 123 124 } 125 g.P("}") 126 g.P("}") 127 // add this as processed oneof 128 g.processedOneofs[field.Oneof.GoIdent.String()] = struct{}{} 129 }