corntext.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "reflect"
  6. "strings"
  7. "sort"
  8. "github.com/golang/protobuf/protoc-gen-go/descriptor"
  9. plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
  10. )
  11. type GeneratableType interface {
  12. IdentifierName() string
  13. CppType() string
  14. WriteDeclarations(gen *CppGenerator)
  15. WriteReflection(gen *CppGenerator)
  16. }
  17. type GenericType interface {
  18. GeneratableType
  19. GetInnerType() GeneratableType
  20. }
  21. type ForwardDeclarable interface {
  22. ForwardDeclaration() string
  23. }
  24. type DelcarationOrderable interface {
  25. DeclarationOrder() int
  26. }
  27. type Corntext struct {
  28. CG *CppGenerator
  29. Request *plugin.CodeGeneratorRequest // The input.
  30. Response *plugin.CodeGeneratorResponse // The output.
  31. AllTypes []GeneratableType
  32. PrimitiveTypes map[string]GeneratableType
  33. // types required for reflection
  34. TypeIDEnum GeneratableType
  35. ReflectType GeneratableType
  36. ReflectField GeneratableType
  37. ReflectEnumValue GeneratableType
  38. TypeKindEnum GeneratableType
  39. vectorOfReflectFields GeneratableType
  40. vectorOfReflectEnumValues GeneratableType
  41. }
  42. func NewCorntext() *Corntext {
  43. i64 := &PrimitiveType{identifierName: "Int64", cppType: "int64_t"}
  44. return &Corntext{
  45. Request: new(plugin.CodeGeneratorRequest),
  46. Response: new(plugin.CodeGeneratorResponse),
  47. CG: NewCppGenerator("protobuf.h"),
  48. AllTypes: []GeneratableType{},
  49. PrimitiveTypes: map[string]GeneratableType{
  50. "int": &PrimitiveType{identifierName: "Int", cppType: "int"},
  51. // "unsigned int": &PrimitiveType{identifierName: "UnsignedInt", cppType: "unsigned int"},
  52. "char": &PrimitiveType{identifierName: "Char", cppType: "char"},
  53. "unsigned char": &PrimitiveType{identifierName: "UnsignedChar", cppType: "unsigned char"},
  54. "double": &PrimitiveType{identifierName: "Double", cppType: "double"},
  55. "float": &PrimitiveType{identifierName: "Float", cppType: "float"},
  56. "bool": &PrimitiveType{identifierName: "Bool", cppType: "bool"},
  57. "std::string": &PrimitiveType{identifierName: "String", cppType: "std::string"},
  58. "size_t": &AliasType{Of: i64, cppType: "size_t"},
  59. "int32_t": &PrimitiveType{identifierName: "Int32", cppType: "int32_t"},
  60. "int64_t": i64,
  61. "uint32_t": &PrimitiveType{identifierName: "Uint32", cppType: "uint32_t"},
  62. "uint64_t": &PrimitiveType{identifierName: "Uint64", cppType: "uint64_t"},
  63. "uint8_t": &PrimitiveType{identifierName: "Uint8", cppType: "uint8_t"},
  64. },
  65. }
  66. }
  67. func (c *Corntext) outputTypes() {
  68. c.CG.AddLibraryInclude("utility")
  69. c.CG.AddLibraryInclude("vector")
  70. vht := &VectorHelperTypes{}
  71. oht := &OptionalHelperTypes{}
  72. fmt.Fprintln(c.CG.Body, `
  73. template<class T>
  74. void __reflectConstruct(void *mem) {
  75. new(mem) T;
  76. }
  77. template<class T>
  78. void __reflectDestruct(void *obj) {
  79. ((T*) obj)->~T();
  80. }
  81. `)
  82. vht.GenerateVectorOperationsStruct(c.CG)
  83. oht.GenerateOptionalOperationsStruct(c.CG)
  84. for _, t := range c.AllTypes {
  85. if fwd, ok := t.(ForwardDeclarable); ok {
  86. fmt.Fprintf(c.CG.Body, "%v\n", fwd.ForwardDeclaration())
  87. }
  88. }
  89. c.CG.AddLibraryInclude("type_traits")
  90. typesToDeclare := make([]GeneratableType, len(c.AllTypes))
  91. for i := range c.AllTypes {
  92. typesToDeclare[i] = c.AllTypes[i]
  93. }
  94. sort.SliceStable(typesToDeclare, func(i, j int) bool {
  95. var ival, jval int
  96. if orderable, ok := typesToDeclare[i].(DelcarationOrderable); ok {
  97. ival = orderable.DeclarationOrder()
  98. }
  99. if orderable, ok := typesToDeclare[j].(DelcarationOrderable); ok {
  100. jval = orderable.DeclarationOrder()
  101. }
  102. return ival < jval
  103. })
  104. for _, t := range typesToDeclare {
  105. t.WriteDeclarations(c.CG)
  106. }
  107. primitiveList := make([]GeneratableType, 0, len(c.PrimitiveTypes))
  108. for _, pt := range c.PrimitiveTypes {
  109. primitiveList = append(primitiveList, pt)
  110. }
  111. GenerateAnyTypes(c.CG, primitiveList, c.AllTypes)
  112. vht.GenerateVectorManipulator(c.CG)
  113. oht.GenerateOptionalManipulator(c.CG)
  114. c.CG.OutputArrayVariableExtern(c.ReflectType.CppType(), "reflectTypeInfo", len(c.AllTypes))
  115. dataFile := c.CG.SubFile("ReflectTypeInfo.cpp", false).AddLocalInclude(c.CG.Filename)
  116. dataFile.OutputArrayVariable(c.ReflectType.CppType(), "reflectTypeInfo", len(c.AllTypes), func() {
  117. for _, t := range c.AllTypes {
  118. if _, ok := t.(*AliasType); ok {
  119. continue
  120. }
  121. t.WriteReflection(dataFile)
  122. fmt.Fprintf(dataFile.Body, ",\n")
  123. }
  124. })
  125. GenerateAnyTypesImplementation(c.CG)
  126. c.CG.OutputToDirectory("protos/")
  127. }
  128. func (c *Corntext) buildAllTypes() {
  129. c.generateReflectionTypes()
  130. c.AllTypes = append(c.AllTypes,
  131. c.TypeIDEnum,
  132. c.ReflectField,
  133. c.ReflectEnumValue,
  134. c.ReflectType,
  135. c.TypeKindEnum,
  136. c.vectorOfReflectFields,
  137. c.vectorOfReflectEnumValues,
  138. )
  139. for _, t := range c.PrimitiveTypes {
  140. c.AllTypes = append(c.AllTypes, t)
  141. }
  142. c.generateProtobufTypes()
  143. i := 0
  144. for _, t := range c.AllTypes {
  145. if _, ok := t.(*AliasType); ok {
  146. continue
  147. }
  148. c.TypeIDEnum.(*EnumType).Values = append(c.TypeIDEnum.(*EnumType).Values, EnumValue{Name: t.IdentifierName(), Value: fmt.Sprintf("%v", i)})
  149. i++
  150. }
  151. }
  152. func (c *Corntext) generateProtobufTypes() {
  153. var pbType2reflection = map[descriptor.FieldDescriptorProto_Type]GeneratableType{
  154. descriptor.FieldDescriptorProto_TYPE_INT32: c.PrimitiveTypes["int32_t"],
  155. descriptor.FieldDescriptorProto_TYPE_SINT32: c.PrimitiveTypes["int32_t"],
  156. descriptor.FieldDescriptorProto_TYPE_SINT64: c.PrimitiveTypes["int64_t"],
  157. descriptor.FieldDescriptorProto_TYPE_INT64: c.PrimitiveTypes["int64_t"],
  158. descriptor.FieldDescriptorProto_TYPE_UINT32: c.PrimitiveTypes["uint32_t"],
  159. descriptor.FieldDescriptorProto_TYPE_UINT64: c.PrimitiveTypes["uint64_t"],
  160. descriptor.FieldDescriptorProto_TYPE_BOOL: c.PrimitiveTypes["bool"],
  161. descriptor.FieldDescriptorProto_TYPE_BYTES: c.genericOf(NewVectorType, c.PrimitiveTypes["uint8_t"]),
  162. descriptor.FieldDescriptorProto_TYPE_STRING: c.PrimitiveTypes["std::string"],
  163. }
  164. for _, f := range c.Request.ProtoFile {
  165. log.Printf("Doing file %v", *f.Name)
  166. typeMappings := map[string]GeneratableType{}
  167. for _, e := range f.EnumType {
  168. values := make([]EnumValue, 0, len(e.Value))
  169. for _, v := range e.Value {
  170. values = append(values, EnumValue{
  171. Name: *v.Name,
  172. Value: fmt.Sprint(*v.Number),
  173. })
  174. }
  175. log.Printf("name: %v", *f.Name)
  176. et := &EnumType{
  177. Name: *e.Name,
  178. Values: values,
  179. ProtoName: StripExtenstion(*f.Name),
  180. }
  181. typeMappings[*e.Name] = et
  182. c.AllTypes = append(c.AllTypes, et)
  183. }
  184. for _, m := range f.MessageType {
  185. ct := &ClassType{
  186. Name: *m.Name,
  187. ProtoName: StripExtenstion(*f.Name),
  188. }
  189. typeMappings[*m.Name] = ct
  190. c.AllTypes = append(c.AllTypes, ct)
  191. }
  192. for _, m := range f.MessageType {
  193. fields := []ClassField{}
  194. for _, f := range m.Field {
  195. isMessage := *f.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE
  196. isEnum := *f.Type == descriptor.FieldDescriptorProto_TYPE_ENUM
  197. var fieldType GeneratableType
  198. if isMessage || isEnum {
  199. fqn := strings.Split(*f.TypeName, ".")
  200. className := fqn[1]
  201. fieldType = typeMappings[className]
  202. } else {
  203. primitiveType, ok := pbType2reflection[*f.Type]
  204. if !ok {
  205. log.Fatal("unsupported proto type", (*f.Type).String())
  206. }
  207. fieldType = primitiveType
  208. // log.Printf("%#v == %v", primitiveType, *f.Type)
  209. }
  210. if f.Label != nil && *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
  211. fieldType = c.genericOf(NewVectorType, fieldType)
  212. } else if f.Label != nil && *f.Label != descriptor.FieldDescriptorProto_LABEL_REQUIRED {
  213. fieldType = c.genericOf(NewOptionalType, fieldType)
  214. }
  215. fields = append(fields, ClassField{
  216. Name: *f.Name,
  217. Type: fieldType,
  218. ProtobufTag: uint32(*f.Number),
  219. })
  220. }
  221. ct := typeMappings[*m.Name].(*ClassType)
  222. ct.Fields = fields
  223. }
  224. }
  225. }
  226. func (c *Corntext) genericOf(constructor func(inner GeneratableType) GenericType, inner GeneratableType) (ret GeneratableType) {
  227. sample := constructor(nil)
  228. for _, t := range c.AllTypes {
  229. if v, ok := t.(GenericType); ok {
  230. if reflect.TypeOf(sample).String() == reflect.TypeOf(v).String() && v.GetInnerType() == inner {
  231. ret = v
  232. }
  233. }
  234. }
  235. if ret == nil {
  236. ret = constructor(inner)
  237. c.AllTypes = append(c.AllTypes, ret)
  238. }
  239. return
  240. }
  241. func (c *Corntext) generateReflectionTypes() {
  242. c.TypeIDEnum = &EnumType{
  243. Name: "ReflectTypeID",
  244. ProtoName: "ReflectionInternal",
  245. Values: []EnumValue{},
  246. }
  247. c.TypeKindEnum = &EnumType{
  248. Name: "ReflectTypeKind",
  249. ProtoName: "ReflectionInternal",
  250. Values: []EnumValue{
  251. {Name: "Primitive", Value: "0"},
  252. {Name: "Enum", Value: "1"},
  253. {Name: "Class", Value: "2"},
  254. {Name: "Vector", Value: "3"},
  255. {Name: "Optional", Value: "4"},
  256. },
  257. }
  258. c.ReflectField = &ClassType{
  259. Name: "ReflectField",
  260. ProtoName: "ReflectionInternal",
  261. Fields: []ClassField{
  262. {"typeID", 0, c.TypeIDEnum},
  263. {"name", 0, c.PrimitiveTypes["std::string"]},
  264. {"offset", 0, c.PrimitiveTypes["size_t"]},
  265. {"protobufTag", 0, c.PrimitiveTypes["uint32_t"]},
  266. },
  267. AdditionalLibraryIncludes: []string{
  268. "string",
  269. },
  270. AdditionalCode: `
  271. ReflectField() {};
  272. ReflectField(ReflectTypeID typeID, std::string name, size_t offset, uint32_t protobufTag) {
  273. this->typeID = typeID;
  274. this->name = name;
  275. this->offset = offset;
  276. this->protobufTag = protobufTag;
  277. }
  278. `,
  279. }
  280. c.ReflectEnumValue = &ClassType{
  281. Name: "ReflectEnumValue",
  282. ProtoName: "ReflectionInternal",
  283. Fields: []ClassField{
  284. {"name", 0, c.PrimitiveTypes["std::string"]},
  285. {"value", 0, c.PrimitiveTypes["int"]},
  286. },
  287. AdditionalLibraryIncludes: []string{
  288. "string",
  289. },
  290. AdditionalCode: `
  291. ReflectEnumValue(){};
  292. ReflectEnumValue( std::string name, int value) {
  293. this->name = name;
  294. this->value = value;
  295. }
  296. `,
  297. }
  298. c.vectorOfReflectFields = &VectorType{
  299. InnerType: c.ReflectField,
  300. }
  301. c.vectorOfReflectEnumValues = &VectorType{
  302. InnerType: c.ReflectEnumValue,
  303. }
  304. c.ReflectType = &ClassType{
  305. Name: "ReflectType",
  306. ProtoName: "ReflectionInternal",
  307. Fields: []ClassField{
  308. {"typeID", 0, c.TypeIDEnum},
  309. {"name", 0, c.PrimitiveTypes["std::string"]},
  310. {"kind", 0, c.TypeKindEnum},
  311. {"size", 0, c.PrimitiveTypes["size_t"]},
  312. {"innerType", 0, c.TypeIDEnum},
  313. {"fields", 0, c.vectorOfReflectFields},
  314. {"enumValues", 0, c.vectorOfReflectEnumValues},
  315. },
  316. AdditionalLibraryIncludes: []string{
  317. "string",
  318. "vector",
  319. },
  320. AdditionalCode: `
  321. void (*_Construct)(void *mem);
  322. void (*_Destruct)(void *obj);
  323. VectorOperations vectorOps;
  324. OptionalOperations optionalOps;
  325. static ReflectType ofPrimitive(ReflectTypeID id, std::string name, size_t size) {
  326. ReflectType t;
  327. t.kind = ReflectTypeKind::Primitive;
  328. t.typeID = id;
  329. t.name = name;
  330. t.size = size;
  331. return t;
  332. }
  333. static ReflectType ofEnum(ReflectTypeID id, std::string name, std::vector<ReflectEnumValue> enumValues, size_t size) {
  334. ReflectType t;
  335. t.kind = ReflectTypeKind::Enum;
  336. t.typeID = id;
  337. t.name = name;
  338. t.size = size;
  339. t.enumValues = enumValues;
  340. return t;
  341. }
  342. static ReflectType ofVector(ReflectTypeID id, ReflectTypeID innerType, size_t size,
  343. VectorOperations vectorOps,
  344. void (*_Construct)(void *mem), void (*_Destruct)(void *obj)) {
  345. ReflectType t;
  346. t.kind = ReflectTypeKind::Vector;
  347. t.typeID = id;
  348. t.innerType = innerType;
  349. t.size = size;
  350. t._Construct = _Construct;
  351. t._Destruct = _Destruct;
  352. t.vectorOps = vectorOps;
  353. return t;
  354. }
  355. static ReflectType ofOptional(ReflectTypeID id, ReflectTypeID innerType, size_t size,
  356. OptionalOperations optionalOps,
  357. void (*_Construct)(void *mem), void (*_Destruct)(void *obj)) {
  358. ReflectType t;
  359. t.kind = ReflectTypeKind::Optional;
  360. t.typeID = id;
  361. t.innerType = innerType;
  362. t.size = size;
  363. t._Construct = _Construct;
  364. t._Destruct = _Destruct;
  365. t.optionalOps = optionalOps;
  366. return t;
  367. }
  368. static ReflectType ofClass(ReflectTypeID id, std::string name, std::vector<ReflectField> fields, size_t size, void (*_Construct)(void *mem), void (*_Destruct)(void *obj)) {
  369. ReflectType t;
  370. t.kind = ReflectTypeKind::Class;
  371. t.name = name;
  372. t.typeID = id;
  373. t.size = size;
  374. t.fields = std::move(fields);
  375. t._Construct = _Construct;
  376. t._Destruct = _Destruct;
  377. return t;
  378. }
  379. `,
  380. }
  381. }