1package pgsgo 2 3import ( 4 "fmt" 5 "strings" 6 7 pgs "github.com/lyft/protoc-gen-star" 8) 9 10func (c context) Type(f pgs.Field) TypeName { 11 ft := f.Type() 12 13 var t TypeName 14 switch { 15 case ft.IsMap(): 16 key := scalarType(ft.Key().ProtoType()) 17 return TypeName(fmt.Sprintf("map[%s]%s", key, c.elType(ft))) 18 case ft.IsRepeated(): 19 return TypeName(fmt.Sprintf("[]%s", c.elType(ft))) 20 case ft.IsEmbed(): 21 return c.importableTypeName(f, ft.Embed()).Pointer() 22 case ft.IsEnum(): 23 t = c.importableTypeName(f, ft.Enum()) 24 default: 25 t = scalarType(ft.ProtoType()) 26 } 27 28 if f.Syntax() == pgs.Proto2 { 29 return t.Pointer() 30 } 31 32 return t 33} 34 35func (c context) importableTypeName(f pgs.Field, e pgs.Entity) TypeName { 36 t := TypeName(c.Name(e)) 37 38 if c.ImportPath(e) == c.ImportPath(f) { 39 return t 40 } 41 42 return TypeName(fmt.Sprintf("%s.%s", c.PackageName(e), t)) 43} 44 45func (c context) elType(ft pgs.FieldType) TypeName { 46 el := ft.Element() 47 switch { 48 case el.IsEnum(): 49 return c.importableTypeName(ft.Field(), el.Enum()) 50 case el.IsEmbed(): 51 return c.importableTypeName(ft.Field(), el.Embed()).Pointer() 52 default: 53 return scalarType(el.ProtoType()) 54 } 55} 56 57func scalarType(t pgs.ProtoType) TypeName { 58 switch t { 59 case pgs.DoubleT: 60 return "float64" 61 case pgs.FloatT: 62 return "float32" 63 case pgs.Int64T, pgs.SFixed64, pgs.SInt64: 64 return "int64" 65 case pgs.UInt64T, pgs.Fixed64T: 66 return "uint64" 67 case pgs.Int32T, pgs.SFixed32, pgs.SInt32: 68 return "int32" 69 case pgs.UInt32T, pgs.Fixed32T: 70 return "uint32" 71 case pgs.BoolT: 72 return "bool" 73 case pgs.StringT: 74 return "string" 75 case pgs.BytesT: 76 return "[]byte" 77 default: 78 panic("unreachable: invalid scalar type") 79 } 80} 81 82// A TypeName describes the name of a type (type on a field, or method signature) 83type TypeName string 84 85// String satisfies the strings.Stringer interface. 86func (n TypeName) String() string { return string(n) } 87 88// Element returns the TypeName of the element of n. For types other than 89// slices and maps, this just returns n. 90func (n TypeName) Element() TypeName { 91 parts := strings.SplitN(string(n), "]", 2) 92 return TypeName(parts[len(parts)-1]) 93} 94 95// Key returns the TypeName of the key of n. For slices, the return TypeName is 96// always "int", and for non slice/map types an empty TypeName is returned. 97func (n TypeName) Key() TypeName { 98 parts := strings.SplitN(string(n), "]", 2) 99 if len(parts) == 1 { 100 return TypeName("") 101 } 102 103 parts = strings.SplitN(parts[0], "[", 2) 104 if len(parts) != 2 { 105 return TypeName("") 106 } else if parts[1] == "" { 107 return TypeName("int") 108 } 109 110 return TypeName(parts[1]) 111} 112 113// Pointer converts TypeName n to it's pointer type. If n is already a pointer, 114// slice, or map, it is returned unmodified. 115func (n TypeName) Pointer() TypeName { 116 ns := string(n) 117 if strings.HasPrefix(ns, "*") || 118 strings.HasPrefix(ns, "[") || 119 strings.HasPrefix(ns, "map[") { 120 return n 121 } 122 123 return TypeName("*" + ns) 124} 125 126// Value converts TypeName n to it's value type. If n is already a value type, 127// slice, or map it is returned unmodified. 128func (n TypeName) Value() TypeName { 129 return TypeName(strings.TrimPrefix(string(n), "*")) 130} 131