blob: f5c87c0e74bd33e59378edaa26b334a9381e0a93 [file] [log] [blame]
Adam Cozzette501ecec2023-09-26 14:36:20 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
Adam Cozzette501ecec2023-09-26 14:36:20 -07003//
Hong Shinb837d172023-11-07 13:24:59 -08004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
Adam Cozzette501ecec2023-09-26 14:36:20 -07007
Adam Cozzette12c7bb02023-09-28 12:54:11 -07008#include "upb_generator/code_generator_request.h"
Adam Cozzette501ecec2023-09-26 14:36:20 -07009
10#include <inttypes.h>
11
12#include "google/protobuf/compiler/plugin.upb.h"
13#include "upb/mini_descriptor/decode.h"
14#include "upb/reflection/def.h"
15
16// Must be last.
17#include "upb/port/def.inc"
18
19/******************************************************************************/
20
21// Kitchen sink storage for all of our state as we build the mini descriptors.
22
23typedef struct {
24 upb_Arena* arena;
25 upb_Status* status;
26 upb_DefPool* symtab;
27
Adam Cozzette12c7bb02023-09-28 12:54:11 -070028 upb_CodeGeneratorRequest* out;
Adam Cozzette501ecec2023-09-26 14:36:20 -070029
30 jmp_buf jmp;
31} upbc_State;
32
33static void upbc_State_Fini(upbc_State* s) {
34 if (s->symtab) upb_DefPool_Free(s->symtab);
35}
36
37UPB_NORETURN static void upbc_Error(upbc_State* s, const char* fn,
38 const char* msg) {
39 upb_Status_SetErrorFormat(s->status, "%s(): %s", fn, msg);
40 upbc_State_Fini(s);
41 UPB_LONGJMP(s->jmp, -1);
42}
43
44static void upbc_State_Init(upbc_State* s) {
45 s->symtab = upb_DefPool_New();
46 if (!s->symtab) upbc_Error(s, __func__, "could not allocate def pool");
47
Adam Cozzette12c7bb02023-09-28 12:54:11 -070048 s->out = upb_CodeGeneratorRequest_new(s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -070049 if (!s->out) upbc_Error(s, __func__, "could not allocate request");
50}
51
52static upb_StringView upbc_State_StrDup(upbc_State* s, const char* str) {
53 upb_StringView from = upb_StringView_FromString(str);
54 char* to = upb_Arena_Malloc(s->arena, from.size);
55 if (!to) upbc_Error(s, __func__, "Out of memory");
56 memcpy(to, from.data, from.size);
57 return upb_StringView_FromDataAndSize(to, from.size);
58}
59
60static void upbc_State_AddMiniDescriptor(upbc_State* s, const char* name,
61 upb_StringView encoding) {
62 const upb_StringView key = upb_StringView_FromString(name);
Adam Cozzette12c7bb02023-09-28 12:54:11 -070063 upb_CodeGeneratorRequest_UpbInfo* info =
64 upb_CodeGeneratorRequest_UpbInfo_new(s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -070065 if (!info) upbc_Error(s, __func__, "Out of memory");
Adam Cozzette12c7bb02023-09-28 12:54:11 -070066 upb_CodeGeneratorRequest_UpbInfo_set_mini_descriptor(info, encoding);
67 bool ok = upb_CodeGeneratorRequest_upb_info_set(s->out, key, info, s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -070068 if (!ok) upbc_Error(s, __func__, "could not set mini descriptor in map");
69}
70
71/******************************************************************************/
72
73// Forward declaration.
74static void upbc_Scrape_Message(upbc_State*, const upb_MessageDef*);
75
76static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* e) {
77 upb_StringView desc;
78 bool ok = upb_EnumDef_MiniDescriptorEncode(e, s->arena, &desc);
79 if (!ok) upbc_Error(s, __func__, "could not encode enum");
80
81 upbc_State_AddMiniDescriptor(s, upb_EnumDef_FullName(e), desc);
82}
83
84static void upbc_Scrape_Extension(upbc_State* s, const upb_FieldDef* f) {
85 upb_StringView desc;
86 bool ok = upb_FieldDef_MiniDescriptorEncode(f, s->arena, &desc);
87 if (!ok) upbc_Error(s, __func__, "could not encode extension");
88
89 upbc_State_AddMiniDescriptor(s, upb_FieldDef_FullName(f), desc);
90}
91
92static void upbc_Scrape_FileEnums(upbc_State* s, const upb_FileDef* f) {
93 const size_t len = upb_FileDef_TopLevelEnumCount(f);
94
95 for (size_t i = 0; i < len; i++) {
96 upbc_Scrape_Enum(s, upb_FileDef_TopLevelEnum(f, i));
97 }
98}
99
100static void upbc_Scrape_FileExtensions(upbc_State* s, const upb_FileDef* f) {
101 const size_t len = upb_FileDef_TopLevelExtensionCount(f);
102
103 for (size_t i = 0; i < len; i++) {
104 upbc_Scrape_Extension(s, upb_FileDef_TopLevelExtension(f, i));
105 }
106}
107
108static void upbc_Scrape_FileMessages(upbc_State* s, const upb_FileDef* f) {
109 const size_t len = upb_FileDef_TopLevelMessageCount(f);
110
111 for (size_t i = 0; i < len; i++) {
112 upbc_Scrape_Message(s, upb_FileDef_TopLevelMessage(f, i));
113 }
114}
115
116static void upbc_Scrape_File(upbc_State* s, const upb_FileDef* f) {
117 upbc_Scrape_FileEnums(s, f);
118 upbc_Scrape_FileExtensions(s, f);
119 upbc_Scrape_FileMessages(s, f);
120}
121
122static void upbc_Scrape_Files(upbc_State* s) {
123 const google_protobuf_compiler_CodeGeneratorRequest* request =
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700124 upb_CodeGeneratorRequest_request(s->out);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700125
126 size_t len = 0;
127 const google_protobuf_FileDescriptorProto* const* files =
128 google_protobuf_compiler_CodeGeneratorRequest_proto_file(request, &len);
129
130 for (size_t i = 0; i < len; i++) {
131 const upb_FileDef* f = upb_DefPool_AddFile(s->symtab, files[i], s->status);
132 if (!f) upbc_Error(s, __func__, "could not add file to def pool");
133
134 upbc_Scrape_File(s, f);
135 }
136}
137
138static void upbc_Scrape_NestedEnums(upbc_State* s, const upb_MessageDef* m) {
139 const size_t len = upb_MessageDef_NestedEnumCount(m);
140
141 for (size_t i = 0; i < len; i++) {
142 upbc_Scrape_Enum(s, upb_MessageDef_NestedEnum(m, i));
143 }
144}
145
146static void upbc_Scrape_NestedExtensions(upbc_State* s,
147 const upb_MessageDef* m) {
148 const size_t len = upb_MessageDef_NestedExtensionCount(m);
149
150 for (size_t i = 0; i < len; i++) {
151 upbc_Scrape_Extension(s, upb_MessageDef_NestedExtension(m, i));
152 }
153}
154
155static void upbc_Scrape_NestedMessages(upbc_State* s, const upb_MessageDef* m) {
156 const size_t len = upb_MessageDef_NestedMessageCount(m);
157
158 for (size_t i = 0; i < len; i++) {
159 upbc_Scrape_Message(s, upb_MessageDef_NestedMessage(m, i));
160 }
161}
162
163static void upbc_Scrape_MessageSubs(upbc_State* s,
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700164 upb_CodeGeneratorRequest_UpbInfo* info,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700165 const upb_MessageDef* m) {
166 const upb_MiniTableField** fields =
167 malloc(upb_MessageDef_FieldCount(m) * sizeof(*fields));
168 const upb_MiniTable* mt = upb_MessageDef_MiniTable(m);
169 uint32_t counts = upb_MiniTable_GetSubList(mt, fields);
170 uint32_t msg_count = counts >> 16;
171 uint32_t enum_count = counts & 0xffff;
172
173 for (uint32_t i = 0; i < msg_count; i++) {
174 const upb_FieldDef* f =
175 upb_MessageDef_FindFieldByNumber(m, fields[i]->number);
176 if (!f) upbc_Error(s, __func__, "Missing f");
177 const upb_MessageDef* sub = upb_FieldDef_MessageSubDef(f);
178 if (!sub) upbc_Error(s, __func__, "Missing sub");
179 upb_StringView name = upbc_State_StrDup(s, upb_MessageDef_FullName(sub));
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700180 upb_CodeGeneratorRequest_UpbInfo_add_sub_message(info, name, s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700181 }
182
183 for (uint32_t i = 0; i < enum_count; i++) {
184 const upb_FieldDef* f =
185 upb_MessageDef_FindFieldByNumber(m, fields[msg_count + i]->number);
186 if (!f) upbc_Error(s, __func__, "Missing f (2)");
187 const upb_EnumDef* sub = upb_FieldDef_EnumSubDef(f);
188 if (!sub) upbc_Error(s, __func__, "Missing sub (2)");
189 upb_StringView name = upbc_State_StrDup(s, upb_EnumDef_FullName(sub));
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700190 upb_CodeGeneratorRequest_UpbInfo_add_sub_enum(info, name, s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700191 }
192
193 free(fields);
194}
195
196static void upbc_Scrape_Message(upbc_State* s, const upb_MessageDef* m) {
197 upb_StringView desc;
198 bool ok = upb_MessageDef_MiniDescriptorEncode(m, s->arena, &desc);
199 if (!ok) upbc_Error(s, __func__, "could not encode message");
200
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700201 upb_CodeGeneratorRequest_UpbInfo* info =
202 upb_CodeGeneratorRequest_UpbInfo_new(s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700203 if (!info) upbc_Error(s, __func__, "Out of memory");
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700204 upb_CodeGeneratorRequest_UpbInfo_set_mini_descriptor(info, desc);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700205
206 upbc_Scrape_MessageSubs(s, info, m);
207
208 const upb_StringView key = upbc_State_StrDup(s, upb_MessageDef_FullName(m));
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700209 ok = upb_CodeGeneratorRequest_upb_info_set(s->out, key, info, s->arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700210 if (!ok) upbc_Error(s, __func__, "could not set mini descriptor in map");
211
212 upbc_Scrape_NestedEnums(s, m);
213 upbc_Scrape_NestedExtensions(s, m);
214 upbc_Scrape_NestedMessages(s, m);
215}
216
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700217static upb_CodeGeneratorRequest* upbc_State_MakeCodeGeneratorRequest(
Adam Cozzette501ecec2023-09-26 14:36:20 -0700218 upbc_State* const s, google_protobuf_compiler_CodeGeneratorRequest* const request) {
219 if (UPB_SETJMP(s->jmp)) return NULL;
220 upbc_State_Init(s);
221
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700222 upb_CodeGeneratorRequest_set_request(s->out, request);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700223 upbc_Scrape_Files(s);
224 upbc_State_Fini(s);
225 return s->out;
226}
227
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700228upb_CodeGeneratorRequest* upbc_MakeCodeGeneratorRequest(
Adam Cozzette501ecec2023-09-26 14:36:20 -0700229 google_protobuf_compiler_CodeGeneratorRequest* request, upb_Arena* arena,
230 upb_Status* status) {
231 upbc_State s = {
232 .arena = arena,
233 .status = status,
234 .symtab = NULL,
235 .out = NULL,
236 };
237
238 return upbc_State_MakeCodeGeneratorRequest(&s, request);
239}