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