• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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