1package builder 2 3import ( 4 "fmt" 5 6 dpb "github.com/golang/protobuf/protoc-gen-go/descriptor" 7 8 "github.com/jhump/protoreflect/desc" 9) 10 11// FieldType represents the type of a field or extension. It can represent a 12// message or enum type or any of the scalar types supported by protobufs. 13// 14// Message and enum types can reference a message or enum builder. A type that 15// refers to a built message or enum descriptor is called an "imported" type. 16// 17// There are numerous factory methods for creating FieldType instances. 18type FieldType struct { 19 fieldType dpb.FieldDescriptorProto_Type 20 foreignMsgType *desc.MessageDescriptor 21 localMsgType *MessageBuilder 22 foreignEnumType *desc.EnumDescriptor 23 localEnumType *EnumBuilder 24} 25 26// GetType returns the enum value indicating the type of the field. If the type 27// is a message (or group) or enum type, GetTypeName provides the name of the 28// referenced type. 29func (ft *FieldType) GetType() dpb.FieldDescriptorProto_Type { 30 return ft.fieldType 31} 32 33// GetTypeName returns the fully-qualified name of the referenced message or 34// enum type. It returns an empty string if this type does not represent a 35// message or enum type. 36func (ft *FieldType) GetTypeName() string { 37 if ft.foreignMsgType != nil { 38 return ft.foreignMsgType.GetFullyQualifiedName() 39 } else if ft.foreignEnumType != nil { 40 return ft.foreignEnumType.GetFullyQualifiedName() 41 } else if ft.localMsgType != nil { 42 return GetFullyQualifiedName(ft.localMsgType) 43 } else if ft.localEnumType != nil { 44 return GetFullyQualifiedName(ft.localEnumType) 45 } else { 46 return "" 47 } 48} 49 50var scalarTypes = map[dpb.FieldDescriptorProto_Type]*FieldType{ 51 dpb.FieldDescriptorProto_TYPE_BOOL: {fieldType: dpb.FieldDescriptorProto_TYPE_BOOL}, 52 dpb.FieldDescriptorProto_TYPE_INT32: {fieldType: dpb.FieldDescriptorProto_TYPE_INT32}, 53 dpb.FieldDescriptorProto_TYPE_INT64: {fieldType: dpb.FieldDescriptorProto_TYPE_INT64}, 54 dpb.FieldDescriptorProto_TYPE_SINT32: {fieldType: dpb.FieldDescriptorProto_TYPE_SINT32}, 55 dpb.FieldDescriptorProto_TYPE_SINT64: {fieldType: dpb.FieldDescriptorProto_TYPE_SINT64}, 56 dpb.FieldDescriptorProto_TYPE_UINT32: {fieldType: dpb.FieldDescriptorProto_TYPE_UINT32}, 57 dpb.FieldDescriptorProto_TYPE_UINT64: {fieldType: dpb.FieldDescriptorProto_TYPE_UINT64}, 58 dpb.FieldDescriptorProto_TYPE_FIXED32: {fieldType: dpb.FieldDescriptorProto_TYPE_FIXED32}, 59 dpb.FieldDescriptorProto_TYPE_FIXED64: {fieldType: dpb.FieldDescriptorProto_TYPE_FIXED64}, 60 dpb.FieldDescriptorProto_TYPE_SFIXED32: {fieldType: dpb.FieldDescriptorProto_TYPE_SFIXED32}, 61 dpb.FieldDescriptorProto_TYPE_SFIXED64: {fieldType: dpb.FieldDescriptorProto_TYPE_SFIXED64}, 62 dpb.FieldDescriptorProto_TYPE_FLOAT: {fieldType: dpb.FieldDescriptorProto_TYPE_FLOAT}, 63 dpb.FieldDescriptorProto_TYPE_DOUBLE: {fieldType: dpb.FieldDescriptorProto_TYPE_DOUBLE}, 64 dpb.FieldDescriptorProto_TYPE_STRING: {fieldType: dpb.FieldDescriptorProto_TYPE_STRING}, 65 dpb.FieldDescriptorProto_TYPE_BYTES: {fieldType: dpb.FieldDescriptorProto_TYPE_BYTES}, 66} 67 68// FieldTypeScalar returns a FieldType for the given scalar type. If the given 69// type is not scalar (e.g. it is a message, group, or enum) than this function 70// will panic. 71func FieldTypeScalar(t dpb.FieldDescriptorProto_Type) *FieldType { 72 if ft, ok := scalarTypes[t]; ok { 73 return ft 74 } 75 panic(fmt.Sprintf("field %v is not scalar", t)) 76} 77 78// FieldTypeInt32 returns a FieldType for the int32 scalar type. 79func FieldTypeInt32() *FieldType { 80 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_INT32) 81} 82 83// FieldTypeUInt32 returns a FieldType for the uint32 scalar type. 84func FieldTypeUInt32() *FieldType { 85 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_UINT32) 86} 87 88// FieldTypeSInt32 returns a FieldType for the sint32 scalar type. 89func FieldTypeSInt32() *FieldType { 90 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_SINT32) 91} 92 93// FieldTypeFixed32 returns a FieldType for the fixed32 scalar type. 94func FieldTypeFixed32() *FieldType { 95 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_FIXED32) 96} 97 98// FieldTypeSFixed32 returns a FieldType for the sfixed32 scalar type. 99func FieldTypeSFixed32() *FieldType { 100 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_SFIXED32) 101} 102 103// FieldTypeInt64 returns a FieldType for the int64 scalar type. 104func FieldTypeInt64() *FieldType { 105 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_INT64) 106} 107 108// FieldTypeUInt64 returns a FieldType for the uint64 scalar type. 109func FieldTypeUInt64() *FieldType { 110 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_UINT64) 111} 112 113// FieldTypeSInt64 returns a FieldType for the sint64 scalar type. 114func FieldTypeSInt64() *FieldType { 115 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_SINT64) 116} 117 118// FieldTypeFixed64 returns a FieldType for the fixed64 scalar type. 119func FieldTypeFixed64() *FieldType { 120 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_FIXED64) 121} 122 123// FieldTypeSFixed64 returns a FieldType for the sfixed64 scalar type. 124func FieldTypeSFixed64() *FieldType { 125 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_SFIXED64) 126} 127 128// FieldTypeFloat returns a FieldType for the float scalar type. 129func FieldTypeFloat() *FieldType { 130 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_FLOAT) 131} 132 133// FieldTypeDouble returns a FieldType for the double scalar type. 134func FieldTypeDouble() *FieldType { 135 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_DOUBLE) 136} 137 138// FieldTypeBool returns a FieldType for the bool scalar type. 139func FieldTypeBool() *FieldType { 140 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_BOOL) 141} 142 143// FieldTypeString returns a FieldType for the string scalar type. 144func FieldTypeString() *FieldType { 145 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_STRING) 146} 147 148// FieldTypeBytes returns a FieldType for the bytes scalar type. 149func FieldTypeBytes() *FieldType { 150 return FieldTypeScalar(dpb.FieldDescriptorProto_TYPE_BYTES) 151} 152 153// FieldTypeMessage returns a FieldType for the given message type. 154func FieldTypeMessage(mb *MessageBuilder) *FieldType { 155 return &FieldType{ 156 fieldType: dpb.FieldDescriptorProto_TYPE_MESSAGE, 157 localMsgType: mb, 158 } 159} 160 161// FieldTypeImportedMessage returns a FieldType that references the given 162// message descriptor. 163func FieldTypeImportedMessage(md *desc.MessageDescriptor) *FieldType { 164 return &FieldType{ 165 fieldType: dpb.FieldDescriptorProto_TYPE_MESSAGE, 166 foreignMsgType: md, 167 } 168} 169 170// FieldTypeEnum returns a FieldType for the given enum type. 171func FieldTypeEnum(eb *EnumBuilder) *FieldType { 172 return &FieldType{ 173 fieldType: dpb.FieldDescriptorProto_TYPE_ENUM, 174 localEnumType: eb, 175 } 176} 177 178// FieldTypeImportedEnum returns a FieldType that references the given enum 179// descriptor. 180func FieldTypeImportedEnum(ed *desc.EnumDescriptor) *FieldType { 181 return &FieldType{ 182 fieldType: dpb.FieldDescriptorProto_TYPE_ENUM, 183 foreignEnumType: ed, 184 } 185} 186 187func fieldTypeFromDescriptor(fld *desc.FieldDescriptor) *FieldType { 188 switch fld.GetType() { 189 case dpb.FieldDescriptorProto_TYPE_GROUP: 190 return &FieldType{fieldType: dpb.FieldDescriptorProto_TYPE_GROUP, foreignMsgType: fld.GetMessageType()} 191 case dpb.FieldDescriptorProto_TYPE_MESSAGE: 192 return FieldTypeImportedMessage(fld.GetMessageType()) 193 case dpb.FieldDescriptorProto_TYPE_ENUM: 194 return FieldTypeImportedEnum(fld.GetEnumType()) 195 default: 196 return FieldTypeScalar(fld.GetType()) 197 } 198} 199 200// RpcType represents the type of an RPC request or response. The only allowed 201// types are messages, but can be streams or unary messages. 202// 203// Message types can reference a message builder. A type that refers to a built 204// message descriptor is called an "imported" type. 205// 206// To create an RpcType, see RpcTypeMessage and RpcTypeImportedMessage. 207type RpcType struct { 208 IsStream bool 209 210 foreignType *desc.MessageDescriptor 211 localType *MessageBuilder 212} 213 214// RpcTypeMessage creates an RpcType that refers to the given message builder. 215func RpcTypeMessage(mb *MessageBuilder, stream bool) *RpcType { 216 return &RpcType{ 217 IsStream: stream, 218 localType: mb, 219 } 220} 221 222// RpcTypeImportedMessage creates an RpcType that refers to the given message 223// descriptor. 224func RpcTypeImportedMessage(md *desc.MessageDescriptor, stream bool) *RpcType { 225 return &RpcType{ 226 IsStream: stream, 227 foreignType: md, 228 } 229} 230 231// GetTypeName returns the fully qualified name of the message type to which 232// this RpcType refers. 233func (rt *RpcType) GetTypeName() string { 234 if rt.foreignType != nil { 235 return rt.foreignType.GetFullyQualifiedName() 236 } else { 237 return GetFullyQualifiedName(rt.localType) 238 } 239} 240