1
2 #include <float.h>
3 #include <math.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "lauxlib.h"
7 #include "upb/bindings/lua/upb.h"
8 #include "upb/def.h"
9
10 #define LUPB_ENUMDEF "lupb.enumdef"
11 #define LUPB_FIELDDEF "lupb.fielddef"
12 #define LUPB_FILEDEF "lupb.filedef"
13 #define LUPB_MSGDEF "lupb.msgdef"
14 #define LUPB_ONEOFDEF "lupb.oneof"
15 #define LUPB_SYMTAB "lupb.symtab"
16 #define LUPB_OBJCACHE "lupb.objcache"
17
18 static void lupb_symtab_pushwrapper(lua_State *L, int narg, const void *def,
19 const char *type);
20
21 /* lupb_wrapper ***************************************************************/
22
23 /* Wrappers around upb def objects. The userval contains a reference to the
24 * symtab. */
25
26 #define LUPB_SYMTAB_INDEX 1
27
28 typedef struct {
29 const void* def; /* upb_msgdef, upb_enumdef, upb_oneofdef, etc. */
30 } lupb_wrapper;
31
lupb_wrapper_check(lua_State * L,int narg,const char * type)32 static const void *lupb_wrapper_check(lua_State *L, int narg,
33 const char *type) {
34 lupb_wrapper *w = luaL_checkudata(L, narg, type);
35 return w->def;
36 }
37
lupb_wrapper_pushsymtab(lua_State * L,int narg)38 static void lupb_wrapper_pushsymtab(lua_State *L, int narg) {
39 lua_getiuservalue(L, narg, LUPB_SYMTAB_INDEX);
40 }
41
42 /* lupb_wrapper_pushwrapper()
43 *
44 * For a given def wrapper at index |narg|, pushes a wrapper for the given |def|
45 * and the given |type|. The new wrapper will be part of the same symtab. */
lupb_wrapper_pushwrapper(lua_State * L,int narg,const void * def,const char * type)46 static void lupb_wrapper_pushwrapper(lua_State *L, int narg, const void *def,
47 const char *type) {
48 lupb_wrapper_pushsymtab(L, narg);
49 lupb_symtab_pushwrapper(L, -1, def, type);
50 lua_replace(L, -2); /* Remove symtab from stack. */
51 }
52
53 /* lupb_msgdef_pushsubmsgdef()
54 *
55 * Pops the msgdef wrapper at the top of the stack and replaces it with a msgdef
56 * wrapper for field |f| of this msgdef (submsg may not be direct, for example it
57 * may be the submessage of the map value).
58 */
lupb_msgdef_pushsubmsgdef(lua_State * L,const upb_fielddef * f)59 void lupb_msgdef_pushsubmsgdef(lua_State *L, const upb_fielddef *f) {
60 const upb_msgdef *m = upb_fielddef_msgsubdef(f);
61 assert(m);
62 lupb_wrapper_pushwrapper(L, -1, m, LUPB_MSGDEF);
63 lua_replace(L, -2); /* Replace msgdef with submsgdef. */
64 }
65
66 /* lupb_fielddef **************************************************************/
67
lupb_fielddef_check(lua_State * L,int narg)68 const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) {
69 return lupb_wrapper_check(L, narg, LUPB_FIELDDEF);
70 }
71
lupb_fielddef_containingoneof(lua_State * L)72 static int lupb_fielddef_containingoneof(lua_State *L) {
73 const upb_fielddef *f = lupb_fielddef_check(L, 1);
74 const upb_oneofdef *o = upb_fielddef_containingoneof(f);
75 lupb_wrapper_pushwrapper(L, 1, o, LUPB_ONEOFDEF);
76 return 1;
77 }
78
lupb_fielddef_containingtype(lua_State * L)79 static int lupb_fielddef_containingtype(lua_State *L) {
80 const upb_fielddef *f = lupb_fielddef_check(L, 1);
81 const upb_msgdef *m = upb_fielddef_containingtype(f);
82 lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF);
83 return 1;
84 }
85
lupb_fielddef_default(lua_State * L)86 static int lupb_fielddef_default(lua_State *L) {
87 const upb_fielddef *f = lupb_fielddef_check(L, 1);
88 switch (upb_fielddef_type(f)) {
89 case UPB_TYPE_INT32:
90 case UPB_TYPE_ENUM:
91 lupb_pushint32(L, upb_fielddef_defaultint32(f)); break;
92 case UPB_TYPE_INT64:
93 lupb_pushint64(L, upb_fielddef_defaultint64(f)); break;
94 case UPB_TYPE_UINT32:
95 lupb_pushuint32(L, upb_fielddef_defaultuint32(f)); break;
96 case UPB_TYPE_UINT64:
97 lupb_pushuint64(L, upb_fielddef_defaultuint64(f)); break;
98 case UPB_TYPE_DOUBLE:
99 lua_pushnumber(L, upb_fielddef_defaultdouble(f)); break;
100 case UPB_TYPE_FLOAT:
101 lua_pushnumber(L, upb_fielddef_defaultfloat(f)); break;
102 case UPB_TYPE_BOOL:
103 lua_pushboolean(L, upb_fielddef_defaultbool(f)); break;
104 case UPB_TYPE_STRING:
105 case UPB_TYPE_BYTES: {
106 size_t len;
107 const char *data = upb_fielddef_defaultstr(f, &len);
108 lua_pushlstring(L, data, len);
109 break;
110 }
111 case UPB_TYPE_MESSAGE:
112 return luaL_error(L, "Message fields do not have explicit defaults.");
113 }
114 return 1;
115 }
116
lupb_fielddef_descriptortype(lua_State * L)117 static int lupb_fielddef_descriptortype(lua_State *L) {
118 const upb_fielddef *f = lupb_fielddef_check(L, 1);
119 lua_pushnumber(L, upb_fielddef_descriptortype(f));
120 return 1;
121 }
122
lupb_fielddef_hassubdef(lua_State * L)123 static int lupb_fielddef_hassubdef(lua_State *L) {
124 const upb_fielddef *f = lupb_fielddef_check(L, 1);
125 lua_pushboolean(L, upb_fielddef_hassubdef(f));
126 return 1;
127 }
128
lupb_fielddef_index(lua_State * L)129 static int lupb_fielddef_index(lua_State *L) {
130 const upb_fielddef *f = lupb_fielddef_check(L, 1);
131 lua_pushinteger(L, upb_fielddef_index(f));
132 return 1;
133 }
134
lupb_fielddef_isextension(lua_State * L)135 static int lupb_fielddef_isextension(lua_State *L) {
136 const upb_fielddef *f = lupb_fielddef_check(L, 1);
137 lua_pushboolean(L, upb_fielddef_isextension(f));
138 return 1;
139 }
140
lupb_fielddef_label(lua_State * L)141 static int lupb_fielddef_label(lua_State *L) {
142 const upb_fielddef *f = lupb_fielddef_check(L, 1);
143 lua_pushinteger(L, upb_fielddef_label(f));
144 return 1;
145 }
146
lupb_fielddef_lazy(lua_State * L)147 static int lupb_fielddef_lazy(lua_State *L) {
148 const upb_fielddef *f = lupb_fielddef_check(L, 1);
149 lua_pushboolean(L, upb_fielddef_lazy(f));
150 return 1;
151 }
152
lupb_fielddef_name(lua_State * L)153 static int lupb_fielddef_name(lua_State *L) {
154 const upb_fielddef *f = lupb_fielddef_check(L, 1);
155 lua_pushstring(L, upb_fielddef_name(f));
156 return 1;
157 }
158
lupb_fielddef_number(lua_State * L)159 static int lupb_fielddef_number(lua_State *L) {
160 const upb_fielddef *f = lupb_fielddef_check(L, 1);
161 int32_t num = upb_fielddef_number(f);
162 if (num) {
163 lua_pushinteger(L, num);
164 } else {
165 lua_pushnil(L);
166 }
167 return 1;
168 }
169
lupb_fielddef_packed(lua_State * L)170 static int lupb_fielddef_packed(lua_State *L) {
171 const upb_fielddef *f = lupb_fielddef_check(L, 1);
172 lua_pushboolean(L, upb_fielddef_packed(f));
173 return 1;
174 }
175
lupb_fielddef_msgsubdef(lua_State * L)176 static int lupb_fielddef_msgsubdef(lua_State *L) {
177 const upb_fielddef *f = lupb_fielddef_check(L, 1);
178 const upb_msgdef *m = upb_fielddef_msgsubdef(f);
179 lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF);
180 return 1;
181 }
182
lupb_fielddef_enumsubdef(lua_State * L)183 static int lupb_fielddef_enumsubdef(lua_State *L) {
184 const upb_fielddef *f = lupb_fielddef_check(L, 1);
185 const upb_enumdef *e = upb_fielddef_enumsubdef(f);
186 lupb_wrapper_pushwrapper(L, 1, e, LUPB_ENUMDEF);
187 return 1;
188 }
189
lupb_fielddef_type(lua_State * L)190 static int lupb_fielddef_type(lua_State *L) {
191 const upb_fielddef *f = lupb_fielddef_check(L, 1);
192 lua_pushinteger(L, upb_fielddef_type(f));
193 return 1;
194 }
195
196 static const struct luaL_Reg lupb_fielddef_m[] = {
197 {"containing_oneof", lupb_fielddef_containingoneof},
198 {"containing_type", lupb_fielddef_containingtype},
199 {"default", lupb_fielddef_default},
200 {"descriptor_type", lupb_fielddef_descriptortype},
201 {"has_subdef", lupb_fielddef_hassubdef},
202 {"index", lupb_fielddef_index},
203 {"is_extension", lupb_fielddef_isextension},
204 {"label", lupb_fielddef_label},
205 {"lazy", lupb_fielddef_lazy},
206 {"name", lupb_fielddef_name},
207 {"number", lupb_fielddef_number},
208 {"packed", lupb_fielddef_packed},
209 {"msgsubdef", lupb_fielddef_msgsubdef},
210 {"enumsubdef", lupb_fielddef_enumsubdef},
211 {"type", lupb_fielddef_type},
212 {NULL, NULL}
213 };
214
215 /* lupb_oneofdef **************************************************************/
216
lupb_oneofdef_check(lua_State * L,int narg)217 const upb_oneofdef *lupb_oneofdef_check(lua_State *L, int narg) {
218 return lupb_wrapper_check(L, narg, LUPB_ONEOFDEF);
219 }
220
lupb_oneofdef_containingtype(lua_State * L)221 static int lupb_oneofdef_containingtype(lua_State *L) {
222 const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
223 const upb_msgdef *m = upb_oneofdef_containingtype(o);
224 lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF);
225 return 1;
226 }
227
lupb_oneofdef_field(lua_State * L)228 static int lupb_oneofdef_field(lua_State *L) {
229 const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
230 int32_t idx = lupb_checkint32(L, 2);
231 int count = upb_oneofdef_fieldcount(o);
232
233 if (idx < 0 || idx >= count) {
234 const char *msg = lua_pushfstring(L, "index %d exceeds field count %d",
235 idx, count);
236 return luaL_argerror(L, 2, msg);
237 }
238
239 lupb_wrapper_pushwrapper(L, 1, upb_oneofdef_field(o, idx), LUPB_FIELDDEF);
240 return 1;
241 }
242
lupb_oneofiter_next(lua_State * L)243 static int lupb_oneofiter_next(lua_State *L) {
244 const upb_oneofdef *o = lupb_oneofdef_check(L, lua_upvalueindex(1));
245 int *index = lua_touserdata(L, lua_upvalueindex(2));
246 const upb_fielddef *f;
247 if (*index == upb_oneofdef_fieldcount(o)) return 0;
248 f = upb_oneofdef_field(o, (*index)++);
249 lupb_wrapper_pushwrapper(L, lua_upvalueindex(1), f, LUPB_FIELDDEF);
250 return 1;
251 }
252
lupb_oneofdef_fields(lua_State * L)253 static int lupb_oneofdef_fields(lua_State *L) {
254 int *index = lua_newuserdata(L, sizeof(int));
255 lupb_oneofdef_check(L, 1);
256 *index = 0;
257
258 /* Closure upvalues are: oneofdef, index. */
259 lua_pushcclosure(L, &lupb_oneofiter_next, 2);
260 return 1;
261 }
262
lupb_oneofdef_len(lua_State * L)263 static int lupb_oneofdef_len(lua_State *L) {
264 const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
265 lua_pushinteger(L, upb_oneofdef_fieldcount(o));
266 return 1;
267 }
268
269 /* lupb_oneofdef_lookupfield()
270 *
271 * Handles:
272 * oneof.lookup_field(field_number)
273 * oneof.lookup_field(field_name)
274 */
lupb_oneofdef_lookupfield(lua_State * L)275 static int lupb_oneofdef_lookupfield(lua_State *L) {
276 const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
277 const upb_fielddef *f;
278
279 switch (lua_type(L, 2)) {
280 case LUA_TNUMBER:
281 f = upb_oneofdef_itof(o, lua_tointeger(L, 2));
282 break;
283 case LUA_TSTRING:
284 f = upb_oneofdef_ntofz(o, lua_tostring(L, 2));
285 break;
286 default: {
287 const char *msg = lua_pushfstring(L, "number or string expected, got %s",
288 luaL_typename(L, 2));
289 return luaL_argerror(L, 2, msg);
290 }
291 }
292
293 lupb_wrapper_pushwrapper(L, 1, f, LUPB_FIELDDEF);
294 return 1;
295 }
296
lupb_oneofdef_name(lua_State * L)297 static int lupb_oneofdef_name(lua_State *L) {
298 const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
299 lua_pushstring(L, upb_oneofdef_name(o));
300 return 1;
301 }
302
303 static const struct luaL_Reg lupb_oneofdef_m[] = {
304 {"containing_type", lupb_oneofdef_containingtype},
305 {"field", lupb_oneofdef_field},
306 {"fields", lupb_oneofdef_fields},
307 {"lookup_field", lupb_oneofdef_lookupfield},
308 {"name", lupb_oneofdef_name},
309 {NULL, NULL}
310 };
311
312 static const struct luaL_Reg lupb_oneofdef_mm[] = {
313 {"__len", lupb_oneofdef_len},
314 {NULL, NULL}
315 };
316
317
318 /* lupb_msgdef ****************************************************************/
319
320 typedef struct {
321 const upb_msgdef *md;
322 } lupb_msgdef;
323
lupb_msgdef_check(lua_State * L,int narg)324 const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) {
325 return lupb_wrapper_check(L, narg, LUPB_MSGDEF);
326 }
327
lupb_msgdef_fieldcount(lua_State * L)328 static int lupb_msgdef_fieldcount(lua_State *L) {
329 const upb_msgdef *m = lupb_msgdef_check(L, 1);
330 lua_pushinteger(L, upb_msgdef_fieldcount(m));
331 return 1;
332 }
333
lupb_msgdef_oneofcount(lua_State * L)334 static int lupb_msgdef_oneofcount(lua_State *L) {
335 const upb_msgdef *m = lupb_msgdef_check(L, 1);
336 lua_pushinteger(L, upb_msgdef_oneofcount(m));
337 return 1;
338 }
339
lupb_msgdef_pushnested(lua_State * L,int msgdef,int name)340 static bool lupb_msgdef_pushnested(lua_State *L, int msgdef, int name) {
341 const upb_msgdef *m = lupb_msgdef_check(L, msgdef);
342 lupb_wrapper_pushsymtab(L, msgdef);
343 upb_symtab *symtab = lupb_symtab_check(L, -1);
344 lua_pop(L, 1);
345
346 /* Construct full package.Message.SubMessage name. */
347 lua_pushstring(L, upb_msgdef_fullname(m));
348 lua_pushstring(L, ".");
349 lua_pushvalue(L, name);
350 lua_concat(L, 3);
351 const char *nested_name = lua_tostring(L, -1);
352
353 /* Try lookup. */
354 const upb_msgdef *nested = upb_symtab_lookupmsg(symtab, nested_name);
355 if (!nested) return false;
356 lupb_wrapper_pushwrapper(L, msgdef, nested, LUPB_MSGDEF);
357 return true;
358 }
359
360 /* lupb_msgdef_field()
361 *
362 * Handles:
363 * msg.field(field_number) -> fielddef
364 * msg.field(field_name) -> fielddef
365 */
lupb_msgdef_field(lua_State * L)366 static int lupb_msgdef_field(lua_State *L) {
367 const upb_msgdef *m = lupb_msgdef_check(L, 1);
368 const upb_fielddef *f;
369
370 switch (lua_type(L, 2)) {
371 case LUA_TNUMBER:
372 f = upb_msgdef_itof(m, lua_tointeger(L, 2));
373 break;
374 case LUA_TSTRING:
375 f = upb_msgdef_ntofz(m, lua_tostring(L, 2));
376 break;
377 default: {
378 const char *msg = lua_pushfstring(L, "number or string expected, got %s",
379 luaL_typename(L, 2));
380 return luaL_argerror(L, 2, msg);
381 }
382 }
383
384 lupb_wrapper_pushwrapper(L, 1, f, LUPB_FIELDDEF);
385 return 1;
386 }
387
388 /* lupb_msgdef_lookupname()
389 *
390 * Handles:
391 * msg.lookup_name(name) -> fielddef or oneofdef
392 */
lupb_msgdef_lookupname(lua_State * L)393 static int lupb_msgdef_lookupname(lua_State *L) {
394 const upb_msgdef *m = lupb_msgdef_check(L, 1);
395 const upb_fielddef *f;
396 const upb_oneofdef *o;
397
398 if (!upb_msgdef_lookupnamez(m, lua_tostring(L, 2), &f, &o)) {
399 lua_pushnil(L);
400 } else if (o) {
401 lupb_wrapper_pushwrapper(L, 1, o, LUPB_ONEOFDEF);
402 } else {
403 lupb_wrapper_pushwrapper(L, 1, f, LUPB_FIELDDEF);
404 }
405
406 return 1;
407 }
408
409 /* lupb_msgdef_name()
410 *
411 * Handles:
412 * msg.name() -> string
413 */
lupb_msgdef_name(lua_State * L)414 static int lupb_msgdef_name(lua_State *L) {
415 const upb_msgdef *m = lupb_msgdef_check(L, 1);
416 lua_pushstring(L, upb_msgdef_name(m));
417 return 1;
418 }
419
lupb_msgfielditer_next(lua_State * L)420 static int lupb_msgfielditer_next(lua_State *L) {
421 const upb_msgdef *m = lupb_msgdef_check(L, lua_upvalueindex(1));
422 int *index = lua_touserdata(L, lua_upvalueindex(2));
423 const upb_fielddef *f;
424 if (*index == upb_msgdef_fieldcount(m)) return 0;
425 f = upb_msgdef_field(m, (*index)++);
426 lupb_wrapper_pushwrapper(L, lua_upvalueindex(1), f, LUPB_FIELDDEF);
427 return 1;
428 }
429
lupb_msgdef_fields(lua_State * L)430 static int lupb_msgdef_fields(lua_State *L) {
431 int *index = lua_newuserdata(L, sizeof(int));
432 lupb_msgdef_check(L, 1);
433 *index = 0;
434
435 /* Closure upvalues are: msgdef, index. */
436 lua_pushcclosure(L, &lupb_msgfielditer_next, 2);
437 return 1;
438 }
439
lupb_msgdef_file(lua_State * L)440 static int lupb_msgdef_file(lua_State *L) {
441 const upb_msgdef *m = lupb_msgdef_check(L, 1);
442 const upb_filedef *file = upb_msgdef_file(m);
443 lupb_wrapper_pushwrapper(L, 1, file, LUPB_FILEDEF);
444 return 1;
445 }
446
lupb_msgdef_fullname(lua_State * L)447 static int lupb_msgdef_fullname(lua_State *L) {
448 const upb_msgdef *m = lupb_msgdef_check(L, 1);
449 lua_pushstring(L, upb_msgdef_fullname(m));
450 return 1;
451 }
452
lupb_msgdef_index(lua_State * L)453 static int lupb_msgdef_index(lua_State *L) {
454 if (!lupb_msgdef_pushnested(L, 1, 2)) {
455 luaL_error(L, "No such nested message");
456 }
457 return 1;
458 }
459
lupb_msgoneofiter_next(lua_State * L)460 static int lupb_msgoneofiter_next(lua_State *L) {
461 const upb_msgdef *m = lupb_msgdef_check(L, lua_upvalueindex(1));
462 int *index = lua_touserdata(L, lua_upvalueindex(2));
463 const upb_oneofdef *o;
464 if (*index == upb_msgdef_oneofcount(m)) return 0;
465 o = upb_msgdef_oneof(m, (*index)++);
466 lupb_wrapper_pushwrapper(L, lua_upvalueindex(1), o, LUPB_ONEOFDEF);
467 return 1;
468 }
469
lupb_msgdef_oneofs(lua_State * L)470 static int lupb_msgdef_oneofs(lua_State *L) {
471 int *index = lua_newuserdata(L, sizeof(int));
472 lupb_msgdef_check(L, 1);
473 *index = 0;
474
475 /* Closure upvalues are: msgdef, index. */
476 lua_pushcclosure(L, &lupb_msgoneofiter_next, 2);
477 return 1;
478 }
479
lupb_msgdef_mapentry(lua_State * L)480 static int lupb_msgdef_mapentry(lua_State *L) {
481 const upb_msgdef *m = lupb_msgdef_check(L, 1);
482 lua_pushboolean(L, upb_msgdef_mapentry(m));
483 return 1;
484 }
485
lupb_msgdef_syntax(lua_State * L)486 static int lupb_msgdef_syntax(lua_State *L) {
487 const upb_msgdef *m = lupb_msgdef_check(L, 1);
488 lua_pushinteger(L, upb_msgdef_syntax(m));
489 return 1;
490 }
491
lupb_msgdef_tostring(lua_State * L)492 static int lupb_msgdef_tostring(lua_State *L) {
493 const upb_msgdef *m = lupb_msgdef_check(L, 1);
494 lua_pushfstring(L, "<upb.MessageDef name=%s, field_count=%d>",
495 upb_msgdef_fullname(m), (int)upb_msgdef_numfields(m));
496 return 1;
497 }
498
499 static const struct luaL_Reg lupb_msgdef_mm[] = {
500 {"__call", lupb_msgdef_call},
501 {"__index", lupb_msgdef_index},
502 {"__len", lupb_msgdef_fieldcount},
503 {"__tostring", lupb_msgdef_tostring},
504 {NULL, NULL}
505 };
506
507 static const struct luaL_Reg lupb_msgdef_m[] = {
508 {"field", lupb_msgdef_field},
509 {"fields", lupb_msgdef_fields},
510 {"field_count", lupb_msgdef_fieldcount},
511 {"file", lupb_msgdef_file},
512 {"full_name", lupb_msgdef_fullname},
513 {"lookup_name", lupb_msgdef_lookupname},
514 {"name", lupb_msgdef_name},
515 {"oneof_count", lupb_msgdef_oneofcount},
516 {"oneofs", lupb_msgdef_oneofs},
517 {"syntax", lupb_msgdef_syntax},
518 {"_map_entry", lupb_msgdef_mapentry},
519 {NULL, NULL}
520 };
521
522
523 /* lupb_enumdef ***************************************************************/
524
lupb_enumdef_check(lua_State * L,int narg)525 const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) {
526 return lupb_wrapper_check(L, narg, LUPB_ENUMDEF);
527 }
528
lupb_enumdef_len(lua_State * L)529 static int lupb_enumdef_len(lua_State *L) {
530 const upb_enumdef *e = lupb_enumdef_check(L, 1);
531 lua_pushinteger(L, upb_enumdef_numvals(e));
532 return 1;
533 }
534
lupb_enumdef_file(lua_State * L)535 static int lupb_enumdef_file(lua_State *L) {
536 const upb_enumdef *e = lupb_enumdef_check(L, 1);
537 const upb_filedef *file = upb_enumdef_file(e);
538 lupb_wrapper_pushwrapper(L, 1, file, LUPB_FILEDEF);
539 return 1;
540 }
541
542 /* lupb_enumdef_value()
543 *
544 * Handles:
545 * enum.value(number) -> name
546 * enum.value(name) -> number
547 */
lupb_enumdef_value(lua_State * L)548 static int lupb_enumdef_value(lua_State *L) {
549 const upb_enumdef *e = lupb_enumdef_check(L, 1);
550
551 switch (lua_type(L, 2)) {
552 case LUA_TNUMBER: {
553 int32_t key = lupb_checkint32(L, 2);
554 /* Pushes "nil" for a NULL pointer. */
555 lua_pushstring(L, upb_enumdef_iton(e, key));
556 break;
557 }
558 case LUA_TSTRING: {
559 const char *key = lua_tostring(L, 2);
560 int32_t num;
561 if (upb_enumdef_ntoiz(e, key, &num)) {
562 lua_pushinteger(L, num);
563 } else {
564 lua_pushnil(L);
565 }
566 break;
567 }
568 default: {
569 const char *msg = lua_pushfstring(L, "number or string expected, got %s",
570 luaL_typename(L, 2));
571 return luaL_argerror(L, 2, msg);
572 }
573 }
574
575 return 1;
576 }
577
lupb_enumiter_next(lua_State * L)578 static int lupb_enumiter_next(lua_State *L) {
579 upb_enum_iter *i = lua_touserdata(L, lua_upvalueindex(1));
580 if (upb_enum_done(i)) return 0;
581 lua_pushstring(L, upb_enum_iter_name(i));
582 lua_pushinteger(L, upb_enum_iter_number(i));
583 upb_enum_next(i);
584 return 2;
585 }
586
lupb_enumdef_values(lua_State * L)587 static int lupb_enumdef_values(lua_State *L) {
588 const upb_enumdef *e = lupb_enumdef_check(L, 1);
589 upb_enum_iter *i = lua_newuserdata(L, sizeof(upb_enum_iter));
590 lupb_wrapper_pushsymtab(L, 1);
591 upb_enum_begin(i, e);
592
593 /* Closure upvalues are: iter, symtab. */
594 lua_pushcclosure(L, &lupb_enumiter_next, 2);
595 return 1;
596 }
597
598 static const struct luaL_Reg lupb_enumdef_mm[] = {
599 {"__len", lupb_enumdef_len},
600 {NULL, NULL}
601 };
602
603 static const struct luaL_Reg lupb_enumdef_m[] = {
604 {"file", lupb_enumdef_file},
605 {"value", lupb_enumdef_value},
606 {"values", lupb_enumdef_values},
607 {NULL, NULL}
608 };
609
610
611 /* lupb_filedef ***************************************************************/
612
lupb_filedef_check(lua_State * L,int narg)613 const upb_filedef *lupb_filedef_check(lua_State *L, int narg) {
614 return lupb_wrapper_check(L, narg, LUPB_FILEDEF);
615 }
616
lupb_filedef_dep(lua_State * L)617 static int lupb_filedef_dep(lua_State *L) {
618 const upb_filedef *f = lupb_filedef_check(L, 1);
619 int index = luaL_checkint(L, 2);
620 const upb_filedef *dep = upb_filedef_dep(f, index);
621 lupb_wrapper_pushwrapper(L, 1, dep, LUPB_FILEDEF);
622 return 1;
623 }
624
lupb_filedef_depcount(lua_State * L)625 static int lupb_filedef_depcount(lua_State *L) {
626 const upb_filedef *f = lupb_filedef_check(L, 1);
627 lua_pushnumber(L, upb_filedef_depcount(f));
628 return 1;
629 }
630
lupb_filedef_enum(lua_State * L)631 static int lupb_filedef_enum(lua_State *L) {
632 const upb_filedef *f = lupb_filedef_check(L, 1);
633 int index = luaL_checkint(L, 2);
634 const upb_enumdef *e = upb_filedef_enum(f, index);
635 lupb_wrapper_pushwrapper(L, 1, e, LUPB_ENUMDEF);
636 return 1;
637 }
638
lupb_filedef_enumcount(lua_State * L)639 static int lupb_filedef_enumcount(lua_State *L) {
640 const upb_filedef *f = lupb_filedef_check(L, 1);
641 lua_pushnumber(L, upb_filedef_enumcount(f));
642 return 1;
643 }
644
lupb_filedef_msg(lua_State * L)645 static int lupb_filedef_msg(lua_State *L) {
646 const upb_filedef *f = lupb_filedef_check(L, 1);
647 int index = luaL_checkint(L, 2);
648 const upb_msgdef *m = upb_filedef_msg(f, index);
649 lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF);
650 return 1;
651 }
652
lupb_filedef_msgcount(lua_State * L)653 static int lupb_filedef_msgcount(lua_State *L) {
654 const upb_filedef *f = lupb_filedef_check(L, 1);
655 lua_pushnumber(L, upb_filedef_msgcount(f));
656 return 1;
657 }
658
lupb_filedef_name(lua_State * L)659 static int lupb_filedef_name(lua_State *L) {
660 const upb_filedef *f = lupb_filedef_check(L, 1);
661 lua_pushstring(L, upb_filedef_name(f));
662 return 1;
663 }
664
lupb_filedef_package(lua_State * L)665 static int lupb_filedef_package(lua_State *L) {
666 const upb_filedef *f = lupb_filedef_check(L, 1);
667 lua_pushstring(L, upb_filedef_package(f));
668 return 1;
669 }
670
lupb_filedef_symtab(lua_State * L)671 static int lupb_filedef_symtab(lua_State *L) {
672 const upb_filedef *f = lupb_filedef_check(L, 1);
673 const upb_symtab *symtab = upb_filedef_symtab(f);
674 lupb_wrapper_pushwrapper(L, 1, symtab, LUPB_SYMTAB);
675 return 1;
676 }
677
lupb_filedef_syntax(lua_State * L)678 static int lupb_filedef_syntax(lua_State *L) {
679 const upb_filedef *f = lupb_filedef_check(L, 1);
680 lua_pushnumber(L, upb_filedef_syntax(f));
681 return 1;
682 }
683
684 static const struct luaL_Reg lupb_filedef_m[] = {
685 {"dep", lupb_filedef_dep},
686 {"depcount", lupb_filedef_depcount},
687 {"enum", lupb_filedef_enum},
688 {"enumcount", lupb_filedef_enumcount},
689 {"msg", lupb_filedef_msg},
690 {"msgcount", lupb_filedef_msgcount},
691 {"name", lupb_filedef_name},
692 {"package", lupb_filedef_package},
693 {"symtab", lupb_filedef_symtab},
694 {"syntax", lupb_filedef_syntax},
695 {NULL, NULL}
696 };
697
698
699 /* lupb_symtab ****************************************************************/
700
701 /* The symtab owns all defs. Thus GC-rooting the symtab ensures that all
702 * underlying defs stay alive.
703 *
704 * The symtab's userval is a cache of def* -> object. */
705
706 #define LUPB_CACHE_INDEX 1
707
708 typedef struct {
709 upb_symtab *symtab;
710 } lupb_symtab;
711
lupb_symtab_check(lua_State * L,int narg)712 upb_symtab *lupb_symtab_check(lua_State *L, int narg) {
713 lupb_symtab *lsymtab = luaL_checkudata(L, narg, LUPB_SYMTAB);
714 if (!lsymtab->symtab) {
715 luaL_error(L, "called into dead object");
716 }
717 return lsymtab->symtab;
718 }
719
lupb_symtab_pushwrapper(lua_State * L,int narg,const void * def,const char * type)720 void lupb_symtab_pushwrapper(lua_State *L, int narg, const void *def,
721 const char *type) {
722 narg = lua_absindex(L, narg);
723 assert(luaL_testudata(L, narg, LUPB_SYMTAB));
724
725 if (def == NULL) {
726 lua_pushnil(L);
727 return;
728 }
729
730 lua_getiuservalue(L, narg, LUPB_CACHE_INDEX); /* Get cache. */
731
732 /* Index by "def" pointer. */
733 lua_rawgetp(L, -1, def);
734
735 /* Stack is now: cache, cached value. */
736 if (lua_isnil(L, -1)) {
737 /* Create new wrapper. */
738 lupb_wrapper *w = lupb_newuserdata(L, sizeof(*w), 1, type);
739 w->def = def;
740 lua_replace(L, -2); /* Replace nil */
741
742 /* Set symtab as userval. */
743 lua_pushvalue(L, narg);
744 lua_setiuservalue(L, -2, LUPB_SYMTAB_INDEX);
745
746 /* Add wrapper to the the cache. */
747 lua_pushvalue(L, -1);
748 lua_rawsetp(L, -3, def);
749 }
750
751 lua_replace(L, -2); /* Remove cache, leaving only the wrapper. */
752 }
753
754 /* upb_symtab_new()
755 *
756 * Handles:
757 * upb.SymbolTable() -> <new instance>
758 */
lupb_symtab_new(lua_State * L)759 static int lupb_symtab_new(lua_State *L) {
760 lupb_symtab *lsymtab = lupb_newuserdata(L, sizeof(*lsymtab), 1, LUPB_SYMTAB);
761 lsymtab->symtab = upb_symtab_new();
762
763 /* Create our object cache. */
764 lua_newtable(L);
765
766 /* Cache metatable: specifies that values are weak. */
767 lua_createtable(L, 0, 1);
768 lua_pushstring(L, "v");
769 lua_setfield(L, -2, "__mode");
770 lua_setmetatable(L, -2);
771
772 /* Put the symtab itself in the cache metatable. */
773 lua_pushvalue(L, -2);
774 lua_rawsetp(L, -2, lsymtab->symtab);
775
776 /* Set the cache as our userval. */
777 lua_setiuservalue(L, -2, LUPB_CACHE_INDEX);
778
779 return 1;
780 }
781
lupb_symtab_gc(lua_State * L)782 static int lupb_symtab_gc(lua_State *L) {
783 lupb_symtab *lsymtab = luaL_checkudata(L, 1, LUPB_SYMTAB);
784 upb_symtab_free(lsymtab->symtab);
785 lsymtab->symtab = NULL;
786 return 0;
787 }
788
lupb_symtab_addfile(lua_State * L)789 static int lupb_symtab_addfile(lua_State *L) {
790 size_t len;
791 upb_symtab *s = lupb_symtab_check(L, 1);
792 const char *str = luaL_checklstring(L, 2, &len);
793 upb_arena *arena = lupb_arena_pushnew(L);
794 const google_protobuf_FileDescriptorProto *file;
795 const upb_filedef *file_def;
796 upb_status status;
797
798 upb_status_clear(&status);
799 file = google_protobuf_FileDescriptorProto_parse(str, len, arena);
800
801 if (!file) {
802 luaL_argerror(L, 2, "failed to parse descriptor");
803 }
804
805 file_def = upb_symtab_addfile(s, file, &status);
806 lupb_checkstatus(L, &status);
807
808 lupb_symtab_pushwrapper(L, 1, file_def, LUPB_FILEDEF);
809
810 return 1;
811 }
812
lupb_symtab_addset(lua_State * L)813 static int lupb_symtab_addset(lua_State *L) {
814 size_t i, n, len;
815 const google_protobuf_FileDescriptorProto *const *files;
816 google_protobuf_FileDescriptorSet *set;
817 upb_symtab *s = lupb_symtab_check(L, 1);
818 const char *str = luaL_checklstring(L, 2, &len);
819 upb_arena *arena = lupb_arena_pushnew(L);
820 upb_status status;
821
822 upb_status_clear(&status);
823 set = google_protobuf_FileDescriptorSet_parse(str, len, arena);
824
825 if (!set) {
826 luaL_argerror(L, 2, "failed to parse descriptor");
827 }
828
829 files = google_protobuf_FileDescriptorSet_file(set, &n);
830 for (i = 0; i < n; i++) {
831 upb_symtab_addfile(s, files[i], &status);
832 lupb_checkstatus(L, &status);
833 }
834
835 return 0;
836 }
837
lupb_symtab_lookupmsg(lua_State * L)838 static int lupb_symtab_lookupmsg(lua_State *L) {
839 const upb_symtab *s = lupb_symtab_check(L, 1);
840 const upb_msgdef *m = upb_symtab_lookupmsg(s, luaL_checkstring(L, 2));
841 lupb_symtab_pushwrapper(L, 1, m, LUPB_MSGDEF);
842 return 1;
843 }
844
lupb_symtab_lookupenum(lua_State * L)845 static int lupb_symtab_lookupenum(lua_State *L) {
846 const upb_symtab *s = lupb_symtab_check(L, 1);
847 const upb_enumdef *e = upb_symtab_lookupenum(s, luaL_checkstring(L, 2));
848 lupb_symtab_pushwrapper(L, 1, e, LUPB_ENUMDEF);
849 return 1;
850 }
851
lupb_symtab_tostring(lua_State * L)852 static int lupb_symtab_tostring(lua_State *L) {
853 const upb_symtab *s = lupb_symtab_check(L, 1);
854 lua_pushfstring(L, "<upb.SymbolTable file_count=%d>",
855 (int)upb_symtab_filecount(s));
856 return 1;
857 }
858
859 static const struct luaL_Reg lupb_symtab_m[] = {
860 {"add_file", lupb_symtab_addfile},
861 {"add_set", lupb_symtab_addset},
862 {"lookup_msg", lupb_symtab_lookupmsg},
863 {"lookup_enum", lupb_symtab_lookupenum},
864 {NULL, NULL}
865 };
866
867 static const struct luaL_Reg lupb_symtab_mm[] = {
868 {"__gc", lupb_symtab_gc},
869 {"__tostring", lupb_symtab_tostring},
870 {NULL, NULL}
871 };
872
873 /* lupb toplevel **************************************************************/
874
lupb_setfieldi(lua_State * L,const char * field,int i)875 static void lupb_setfieldi(lua_State *L, const char *field, int i) {
876 lua_pushinteger(L, i);
877 lua_setfield(L, -2, field);
878 }
879
880 static const struct luaL_Reg lupbdef_toplevel_m[] = {
881 {"SymbolTable", lupb_symtab_new},
882 {NULL, NULL}
883 };
884
lupb_def_registertypes(lua_State * L)885 void lupb_def_registertypes(lua_State *L) {
886 lupb_setfuncs(L, lupbdef_toplevel_m);
887
888 /* Register types. */
889 lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm);
890 lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, NULL);
891 lupb_register_type(L, LUPB_FILEDEF, lupb_filedef_m, NULL);
892 lupb_register_type(L, LUPB_MSGDEF, lupb_msgdef_m, lupb_msgdef_mm);
893 lupb_register_type(L, LUPB_ONEOFDEF, lupb_oneofdef_m, lupb_oneofdef_mm);
894 lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, lupb_symtab_mm);
895
896 /* Register constants. */
897 lupb_setfieldi(L, "LABEL_OPTIONAL", UPB_LABEL_OPTIONAL);
898 lupb_setfieldi(L, "LABEL_REQUIRED", UPB_LABEL_REQUIRED);
899 lupb_setfieldi(L, "LABEL_REPEATED", UPB_LABEL_REPEATED);
900
901 lupb_setfieldi(L, "TYPE_DOUBLE", UPB_TYPE_DOUBLE);
902 lupb_setfieldi(L, "TYPE_FLOAT", UPB_TYPE_FLOAT);
903 lupb_setfieldi(L, "TYPE_INT64", UPB_TYPE_INT64);
904 lupb_setfieldi(L, "TYPE_UINT64", UPB_TYPE_UINT64);
905 lupb_setfieldi(L, "TYPE_INT32", UPB_TYPE_INT32);
906 lupb_setfieldi(L, "TYPE_BOOL", UPB_TYPE_BOOL);
907 lupb_setfieldi(L, "TYPE_STRING", UPB_TYPE_STRING);
908 lupb_setfieldi(L, "TYPE_MESSAGE", UPB_TYPE_MESSAGE);
909 lupb_setfieldi(L, "TYPE_BYTES", UPB_TYPE_BYTES);
910 lupb_setfieldi(L, "TYPE_UINT32", UPB_TYPE_UINT32);
911 lupb_setfieldi(L, "TYPE_ENUM", UPB_TYPE_ENUM);
912
913 lupb_setfieldi(L, "DESCRIPTOR_TYPE_DOUBLE", UPB_DESCRIPTOR_TYPE_DOUBLE);
914 lupb_setfieldi(L, "DESCRIPTOR_TYPE_FLOAT", UPB_DESCRIPTOR_TYPE_FLOAT);
915 lupb_setfieldi(L, "DESCRIPTOR_TYPE_INT64", UPB_DESCRIPTOR_TYPE_INT64);
916 lupb_setfieldi(L, "DESCRIPTOR_TYPE_UINT64", UPB_DESCRIPTOR_TYPE_UINT64);
917 lupb_setfieldi(L, "DESCRIPTOR_TYPE_INT32", UPB_DESCRIPTOR_TYPE_INT32);
918 lupb_setfieldi(L, "DESCRIPTOR_TYPE_FIXED64", UPB_DESCRIPTOR_TYPE_FIXED64);
919 lupb_setfieldi(L, "DESCRIPTOR_TYPE_FIXED32", UPB_DESCRIPTOR_TYPE_FIXED32);
920 lupb_setfieldi(L, "DESCRIPTOR_TYPE_BOOL", UPB_DESCRIPTOR_TYPE_BOOL);
921 lupb_setfieldi(L, "DESCRIPTOR_TYPE_STRING", UPB_DESCRIPTOR_TYPE_STRING);
922 lupb_setfieldi(L, "DESCRIPTOR_TYPE_GROUP", UPB_DESCRIPTOR_TYPE_GROUP);
923 lupb_setfieldi(L, "DESCRIPTOR_TYPE_MESSAGE", UPB_DESCRIPTOR_TYPE_MESSAGE);
924 lupb_setfieldi(L, "DESCRIPTOR_TYPE_BYTES", UPB_DESCRIPTOR_TYPE_BYTES);
925 lupb_setfieldi(L, "DESCRIPTOR_TYPE_UINT32", UPB_DESCRIPTOR_TYPE_UINT32);
926 lupb_setfieldi(L, "DESCRIPTOR_TYPE_ENUM", UPB_DESCRIPTOR_TYPE_ENUM);
927 lupb_setfieldi(L, "DESCRIPTOR_TYPE_SFIXED32", UPB_DESCRIPTOR_TYPE_SFIXED32);
928 lupb_setfieldi(L, "DESCRIPTOR_TYPE_SFIXED64", UPB_DESCRIPTOR_TYPE_SFIXED64);
929 lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT32", UPB_DESCRIPTOR_TYPE_SINT32);
930 lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT64", UPB_DESCRIPTOR_TYPE_SINT64);
931
932 lupb_setfieldi(L, "SYNTAX_PROTO2", UPB_SYNTAX_PROTO2);
933 lupb_setfieldi(L, "SYNTAX_PROTO3", UPB_SYNTAX_PROTO3);
934 }
935