Built motion from commit 44377920.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / third_party / upb / upb / bindings / lua / msg.c
1 /*
2 ** lupb_msg -- Message/Array/Map objects in Lua/C that wrap upb/msg.h
3 */
4
5 #include <float.h>
6 #include <math.h>
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "lauxlib.h"
12 #include "upb/bindings/lua/upb.h"
13 #include "upb/handlers.h"
14 #include "upb/legacy_msg_reflection.h"
15 #include "upb/msg.h"
16
17 #include "upb/port_def.inc"
18
19 /*
20  * Message/Array/Map objects can be constructed in one of two ways:
21  *
22  * 1. To point to existing msg/array/map data inside an arena.
23  * 2. To create and uniquely own some brand new data.
24  *
25  * Case (1) is for when we've parsed some data into an arena (which is faster
26  * than parsing directly into Lua objects) or when we're pointing at some
27  * read-only data (like custom options in a def).
28  *
29  * Case (2) is for when a user creates the object directly in Lua.
30  *
31  * We use the userval of container objects (Message/Array/Map) to store
32  * references to sub-objects (Strings/Messages/Arrays/Maps).  But we need to
33  * keep the userval in sync with the underlying upb_msg/upb_array/upb_map.
34  * We populate the userval lazily from the underlying data.
35  *
36  * This means that no one may remove/replace any String/Message/Array/Map
37  * field/entry in the underlying upb_{msg,array,map} behind our back.  It's ok
38  * for entries to be added or for primitives to be modified, but *replacing*
39  * sub-containers is not.
40  *
41  * Luckily parse/merge follow this rule.  However clear does not, so it's not
42  * safe to clear behind our back.
43  */
44
45 #define LUPB_ARENA "lupb.arena"
46
47 #define LUPB_MSGCLASS "lupb.msgclass"
48 #define LUPB_MSGFACTORY "lupb.msgfactory"
49
50 #define LUPB_ARRAY "lupb.array"
51 #define LUPB_MAP "lupb.map"
52 #define LUPB_MSG "lupb.msg"
53 #define LUPB_STRING "lupb.string"
54
55 static int lupb_msg_pushnew(lua_State *L, int narg);
56
57 /* Lazily creates the uservalue if it doesn't exist. */
58 static void lupb_getuservalue(lua_State *L, int index) {
59   lua_getuservalue(L, index);
60   if (lua_isnil(L, -1)) {
61     /* Lazily create and set userval. */
62     lua_pop(L, 1);  /* nil. */
63     lua_pushvalue(L, index); /* userdata copy. */
64     lua_newtable(L);
65     lua_setuservalue(L, -2);
66     lua_pop(L, 1);  /* userdata copy. */
67     lua_getuservalue(L, index);
68   }
69   assert(!lua_isnil(L, -1));
70 }
71
72 static void lupb_uservalseti(lua_State *L, int userdata, int index, int val) {
73   lupb_getuservalue(L, userdata);
74   lua_pushvalue(L, val);
75   lua_rawseti(L, -2, index);
76   lua_pop(L, 1);  /* Uservalue. */
77 }
78
79 static void lupb_uservalgeti(lua_State *L, int userdata, int index) {
80   lupb_getuservalue(L, userdata);
81   lua_rawgeti(L, -1, index);
82   lua_insert(L, -2);
83   lua_pop(L, 1);  /* Uservalue. */
84 }
85
86 /* Pushes a new userdata with the given metatable. */
87 static void *lupb_newuserdata(lua_State *L, size_t size, const char *type) {
88   void *ret = lua_newuserdata(L, size);
89
90   /* Set metatable. */
91   luaL_getmetatable(L, type);
92   UPB_ASSERT(!lua_isnil(L, -1));  /* Should have been created by luaopen_upb. */
93   lua_setmetatable(L, -2);
94
95   /* We don't set a uservalue here -- we lazily create it later if necessary. */
96
97   return ret;
98 }
99
100
101 /* lupb_arena *****************************************************************/
102
103 /* lupb_arena only exists to wrap a upb_arena.  It is never exposed to users;
104  * it is an internal memory management detail.  Other objects refer to this
105  * object from their userdata to keep the arena-owned data alive. */
106
107 typedef struct {
108   upb_arena *arena;
109 } lupb_arena;
110
111 upb_arena *lupb_arena_check(lua_State *L, int narg) {
112   lupb_arena *a = luaL_checkudata(L, narg, LUPB_ARENA);
113   return a ? a->arena : NULL;
114 }
115
116 int lupb_arena_new(lua_State *L) {
117   lupb_arena *a = lupb_newuserdata(L, sizeof(lupb_arena), LUPB_ARENA);
118
119   /* TODO(haberman): use Lua alloc func as block allocator?  Would need to
120    * verify that all cases of upb_malloc in msg/table are longjmp-safe. */
121   a->arena = upb_arena_new();
122
123   return 1;
124 }
125
126 char lupb_arena_cache_key;
127
128 /* Returns the global lupb_arena func that was created in our luaopen().
129  * Callers can be guaranteed that it will be alive as long as |L| is.
130  * TODO(haberman): we shouldn't use a global arena!  We should have
131  * one arena for a parse, or per independently-created message. */
132 upb_arena *lupb_arena_get(lua_State *L) {
133   upb_arena *arena;
134
135   lua_pushlightuserdata(L, &lupb_arena_cache_key);
136   lua_gettable(L, LUA_REGISTRYINDEX);
137   arena = lua_touserdata(L, -1);
138   UPB_ASSERT(arena);
139   lua_pop(L, 1);
140
141   return arena;
142 }
143
144 static void lupb_arena_initsingleton(lua_State *L) {
145   lua_pushlightuserdata(L, &lupb_arena_cache_key);
146   lupb_arena_new(L);
147   lua_settable(L, LUA_REGISTRYINDEX);
148 }
149
150 static int lupb_arena_gc(lua_State *L) {
151   upb_arena *a = lupb_arena_check(L, 1);
152   upb_arena_free(a);
153   return 0;
154 }
155
156 static const struct luaL_Reg lupb_arena_mm[] = {
157   {"__gc", lupb_arena_gc},
158   {NULL, NULL}
159 };
160
161
162 /* lupb_msgfactory ************************************************************/
163
164 /* Userval contains a map of:
165  *   [1] -> SymbolTable (to keep GC-reachable)
166  *   [const upb_msgdef*] -> [lupb_msgclass userdata]
167  */
168
169 #define LUPB_MSGFACTORY_SYMTAB 1
170
171 typedef struct lupb_msgfactory {
172   upb_msgfactory *factory;
173 } lupb_msgfactory;
174
175 static int lupb_msgclass_pushnew(lua_State *L, int factory,
176                                  const upb_msgdef *md);
177
178 /* lupb_msgfactory helpers. */
179
180 static lupb_msgfactory *lupb_msgfactory_check(lua_State *L, int narg) {
181   return luaL_checkudata(L, narg, LUPB_MSGFACTORY);
182 }
183
184 static void lupb_msgfactory_pushmsgclass(lua_State *L, int narg,
185                                          const upb_msgdef *md) {
186   lupb_getuservalue(L, narg);
187   lua_pushlightuserdata(L, (void*)md);
188   lua_rawget(L, -2);
189
190   if (lua_isnil(L, -1)) {
191     lua_pop(L, 1);
192     /* TODO: verify md is in symtab? */
193     lupb_msgclass_pushnew(L, narg, md);
194
195     /* Set in userval. */
196     lua_pushlightuserdata(L, (void*)md);
197     lua_pushvalue(L, -2);
198     lua_rawset(L, -4);
199   }
200 }
201
202 static int lupb_msgfactory_gc(lua_State *L) {
203   lupb_msgfactory *lfactory = lupb_msgfactory_check(L, 1);
204
205   if (lfactory->factory) {
206     upb_msgfactory_free(lfactory->factory);
207     lfactory->factory = NULL;
208   }
209
210   return 0;
211 }
212
213 /* lupb_msgfactory Public API. */
214
215 /**
216  * lupb_msgfactory_new()
217  *
218  * Handles:
219  *   msgfactory = upb.MessageFactory(symtab)
220  *
221  * Creates a new, empty MessageFactory for the given SymbolTable.
222  * Message classes will be created on demand when the user calls
223  * msgfactory.get_message_class().
224  */
225 static int lupb_msgfactory_new(lua_State *L) {
226   const upb_symtab *symtab = lupb_symtab_check(L, 1);
227
228   lupb_msgfactory *lmsgfactory =
229       lupb_newuserdata(L, sizeof(lupb_msgfactory), LUPB_MSGFACTORY);
230   lmsgfactory->factory = upb_msgfactory_new(symtab);
231   lupb_uservalseti(L, -1, LUPB_MSGFACTORY_SYMTAB, 1);
232
233   return 1;
234 }
235
236 /**
237  * lupb_msgfactory_getmsgclass()
238  *
239  * Handles:
240  *   MessageClass = factory.get_message_class(message_name)
241  */
242 static int lupb_msgfactory_getmsgclass(lua_State *L) {
243   lupb_msgfactory *lfactory = lupb_msgfactory_check(L, 1);
244   const upb_symtab *symtab = upb_msgfactory_symtab(lfactory->factory);
245   const upb_msgdef *m = upb_symtab_lookupmsg(symtab, luaL_checkstring(L, 2));
246
247   if (!m) {
248     luaL_error(L, "No such message type: %s\n", lua_tostring(L, 2));
249   }
250
251   lupb_msgfactory_pushmsgclass(L, 1, m);
252
253   return 1;
254 }
255
256 static const struct luaL_Reg lupb_msgfactory_m[] = {
257   {"get_message_class", lupb_msgfactory_getmsgclass},
258   {NULL, NULL}
259 };
260
261 static const struct luaL_Reg lupb_msgfactory_mm[] = {
262   {"__gc", lupb_msgfactory_gc},
263   {NULL, NULL}
264 };
265
266
267 /* lupb_msgclass **************************************************************/
268
269 /* Userval contains a map of:
270  *   [1] -> MessageFactory (to keep GC-reachable)
271  *   [const upb_msgdef*] -> [lupb_msgclass userdata]
272  */
273
274 #define LUPB_MSGCLASS_FACTORY 1
275
276 struct lupb_msgclass {
277   const upb_msglayout *layout;
278   const upb_msgdef *msgdef;
279   const lupb_msgfactory *lfactory;
280 };
281
282 /* Type-checks for assigning to a message field. */
283 static upb_msgval lupb_array_typecheck(lua_State *L, int narg, int msg,
284                                        const upb_fielddef *f);
285 static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg,
286                                      const upb_fielddef *f);
287 static const lupb_msgclass *lupb_msg_getsubmsgclass(lua_State *L, int narg,
288                                                     const upb_fielddef *f);
289 static const lupb_msgclass *lupb_msg_msgclassfor(lua_State *L, int narg,
290                                                  const upb_msgdef *md);
291
292 const lupb_msgclass *lupb_msgclass_check(lua_State *L, int narg) {
293   return luaL_checkudata(L, narg, LUPB_MSGCLASS);
294 }
295
296 const upb_msglayout *lupb_msgclass_getlayout(lua_State *L, int narg) {
297   return lupb_msgclass_check(L, narg)->layout;
298 }
299
300 const upb_msgdef *lupb_msgclass_getmsgdef(const lupb_msgclass *lmsgclass) {
301   return lmsgclass->msgdef;
302 }
303
304 upb_msgfactory *lupb_msgclass_getfactory(const lupb_msgclass *lmsgclass) {
305   return lmsgclass->lfactory->factory;
306 }
307
308 /**
309  * lupb_msgclass_typecheck()
310  *
311  * Verifies that the expected msgclass matches the actual.  If not, raises a Lua
312  * error.
313  */
314 static void lupb_msgclass_typecheck(lua_State *L, const lupb_msgclass *expected,
315                                     const lupb_msgclass *actual) {
316   if (expected != actual) {
317     luaL_error(L, "Message had incorrect type, expected '%s', got '%s'",
318                upb_msgdef_fullname(expected->msgdef),
319                upb_msgdef_fullname(actual->msgdef));
320   }
321 }
322
323 static const lupb_msgclass *lupb_msgclass_msgclassfor(lua_State *L, int narg,
324                                                       const upb_msgdef *md) {
325   lupb_uservalgeti(L, narg, LUPB_MSGCLASS_FACTORY);
326   lupb_msgfactory_pushmsgclass(L, -1, md);
327   return lupb_msgclass_check(L, -1);
328 }
329
330 /**
331  * lupb_msgclass_getsubmsgclass()
332  *
333  * Given a MessageClass at index |narg| and the submessage field |f|, returns
334  * the message class for this field.
335  *
336  * Currently we do a hash table lookup for this.  If we wanted we could try to
337  * optimize this by caching these pointers in our msgclass, in an array indexed
338  * by field index.  We would still need to fall back to calling msgclassfor(),
339  * unless we wanted to eagerly create message classes for all submessages.  But
340  * for big schemas that might be a lot of things to build, and we might end up
341  * not using most of them. */
342 static const lupb_msgclass *lupb_msgclass_getsubmsgclass(lua_State *L, int narg,
343                                                          const upb_fielddef *f) {
344   if (upb_fielddef_type(f) != UPB_TYPE_MESSAGE) {
345     return NULL;
346   }
347
348   return lupb_msgclass_msgclassfor(L, narg, upb_fielddef_msgsubdef(f));
349 }
350
351 static int lupb_msgclass_pushnew(lua_State *L, int factory,
352                                  const upb_msgdef *md) {
353   const lupb_msgfactory *lfactory = lupb_msgfactory_check(L, factory);
354   lupb_msgclass *lmc = lupb_newuserdata(L, sizeof(*lmc), LUPB_MSGCLASS);
355
356   lupb_uservalseti(L, -1, LUPB_MSGCLASS_FACTORY, factory);
357   lmc->layout = upb_msgfactory_getlayout(lfactory->factory, md);
358   lmc->lfactory = lfactory;
359   lmc->msgdef = md;
360
361   return 1;
362 }
363
364 /* MessageClass Public API. */
365
366 /**
367  * lupb_msgclass_call()
368  *
369  * Handles:
370  *   msg = MessageClass()
371  *
372  * Creates a new message from the given MessageClass.
373  */
374 static int lupb_msgclass_call(lua_State *L) {
375   lupb_msg_pushnew(L, 1);
376   return 1;
377 }
378
379 static const struct luaL_Reg lupb_msgclass_mm[] = {
380   {"__call", lupb_msgclass_call},
381   {NULL, NULL}
382 };
383
384
385 /* upb <-> Lua type conversion ************************************************/
386
387 static bool lupb_istypewrapped(upb_fieldtype_t type) {
388   return type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
389          type == UPB_TYPE_MESSAGE;
390 }
391
392 static upb_msgval lupb_tomsgval(lua_State *L, upb_fieldtype_t type, int narg,
393                                 const lupb_msgclass *lmsgclass) {
394   switch (type) {
395     case UPB_TYPE_INT32:
396     case UPB_TYPE_ENUM:
397       return upb_msgval_int32(lupb_checkint32(L, narg));
398     case UPB_TYPE_INT64:
399       return upb_msgval_int64(lupb_checkint64(L, narg));
400     case UPB_TYPE_UINT32:
401       return upb_msgval_uint32(lupb_checkuint32(L, narg));
402     case UPB_TYPE_UINT64:
403       return upb_msgval_uint64(lupb_checkuint64(L, narg));
404     case UPB_TYPE_DOUBLE:
405       return upb_msgval_double(lupb_checkdouble(L, narg));
406     case UPB_TYPE_FLOAT:
407       return upb_msgval_float(lupb_checkfloat(L, narg));
408     case UPB_TYPE_BOOL:
409       return upb_msgval_bool(lupb_checkbool(L, narg));
410     case UPB_TYPE_STRING:
411     case UPB_TYPE_BYTES: {
412       size_t len;
413       const char *ptr = lupb_checkstring(L, narg, &len);
414       return upb_msgval_makestr(ptr, len);
415     }
416     case UPB_TYPE_MESSAGE:
417       UPB_ASSERT(lmsgclass);
418       return upb_msgval_msg(lupb_msg_checkmsg(L, narg, lmsgclass));
419   }
420   UPB_UNREACHABLE();
421 }
422
423 static void lupb_pushmsgval(lua_State *L, upb_fieldtype_t type,
424                             upb_msgval val) {
425   switch (type) {
426     case UPB_TYPE_INT32:
427     case UPB_TYPE_ENUM:
428       lupb_pushint32(L, upb_msgval_getint32(val));
429       return;
430     case UPB_TYPE_INT64:
431       lupb_pushint64(L, upb_msgval_getint64(val));
432       return;
433     case UPB_TYPE_UINT32:
434       lupb_pushuint32(L, upb_msgval_getuint32(val));
435       return;
436     case UPB_TYPE_UINT64:
437       lupb_pushuint64(L, upb_msgval_getuint64(val));
438       return;
439     case UPB_TYPE_DOUBLE:
440       lupb_pushdouble(L, upb_msgval_getdouble(val));
441       return;
442     case UPB_TYPE_FLOAT:
443       lupb_pushfloat(L, upb_msgval_getfloat(val));
444       return;
445     case UPB_TYPE_BOOL:
446       lua_pushboolean(L, upb_msgval_getbool(val));
447       return;
448     case UPB_TYPE_STRING:
449     case UPB_TYPE_BYTES:
450     case UPB_TYPE_MESSAGE:
451       break;  /* Shouldn't call this function. */
452   }
453   UPB_UNREACHABLE();
454 }
455
456
457 /* lupb_array *****************************************************************/
458
459 /* A strongly typed array.  Implemented by wrapping upb_array.
460  *
461  * - we only allow integer indices.
462  * - all entries must have the correct type.
463  * - we do not allow "holes" in the array; you can only assign to an existing
464  *   index or one past the end (which will grow the array by one).
465  *
466  * For string/submessage entries we keep in the userval:
467  *
468  *   [number index] -> [lupb_string/lupb_msg userdata]
469  */
470
471 typedef struct {
472   /* Only needed for array of message.  This wastes space in the non-message
473    * case but simplifies the code.  Could optimize away if desired. */
474   const lupb_msgclass *lmsgclass;
475   upb_array *arr;
476   upb_fieldtype_t type;
477 } lupb_array;
478
479 #define ARRAY_MSGCLASS_INDEX 0
480
481 static lupb_array *lupb_array_check(lua_State *L, int narg) {
482   return luaL_checkudata(L, narg, LUPB_ARRAY);
483 }
484
485 /**
486  * lupb_array_typecheck()
487  *
488  * Verifies that the lupb_array object at index |narg| can be safely assigned
489  * to the field |f| of the lupb_msg object at index |msg|.  If this is safe,
490  * returns a upb_msgval representing the array.  Otherwise, throws a Lua error.
491  */
492 static upb_msgval lupb_array_typecheck(lua_State *L, int narg, int msg,
493                                        const upb_fielddef *f) {
494   lupb_array *larray = lupb_array_check(L, narg);
495
496   if (upb_array_type(larray->arr) != upb_fielddef_type(f) ||
497       lupb_msg_getsubmsgclass(L, msg, f) != larray->lmsgclass) {
498     luaL_error(L, "Array had incorrect type (expected: %d, got: %d)",
499                (int)upb_fielddef_type(f), (int)upb_array_type(larray->arr));
500   }
501
502   if (upb_array_type(larray->arr) == UPB_TYPE_MESSAGE) {
503     lupb_msgclass_typecheck(L, lupb_msg_getsubmsgclass(L, msg, f),
504                             larray->lmsgclass);
505   }
506
507   return upb_msgval_arr(larray->arr);
508 }
509
510 /**
511  * lupb_array_checkindex()
512  *
513  * Checks the array index at Lua stack index |narg| to verify that it is an
514  * integer between 1 and |max|, inclusively.  Also corrects it to be zero-based
515  * for C.
516  *
517  * We use "int" because of lua_rawseti/lua_rawgeti -- can re-evaluate if we want
518  * arrays bigger than 2^31.
519  */
520 static int lupb_array_checkindex(lua_State *L, int narg, uint32_t max) {
521   uint32_t n = lupb_checkuint32(L, narg);
522   if (n == 0 || n > max || n > INT_MAX) {
523     luaL_error(L, "Invalid array index: expected between 1 and %d", (int)max);
524   }
525   return n - 1;  /* Lua uses 1-based indexing. :( */
526 }
527
528 /* lupb_array Public API */
529
530 static int lupb_array_new(lua_State *L) {
531   lupb_array *larray;
532   upb_fieldtype_t type;
533   const lupb_msgclass *lmsgclass = NULL;
534
535   if (lua_type(L, 1) == LUA_TNUMBER) {
536     type = lupb_checkfieldtype(L, 1);
537   } else {
538     type = UPB_TYPE_MESSAGE;
539     lmsgclass = lupb_msgclass_check(L, 1);
540     lupb_uservalseti(L, -1, ARRAY_MSGCLASS_INDEX, 1);  /* GC-root lmsgclass. */
541   }
542
543   larray = lupb_newuserdata(L, sizeof(*larray), LUPB_ARRAY);
544   larray->type = type;
545   larray->lmsgclass = lmsgclass;
546   larray->arr = upb_array_new(lupb_arena_get(L));
547
548   return 1;
549 }
550
551 static int lupb_array_newindex(lua_State *L) {
552   lupb_array *larray = lupb_array_check(L, 1);
553   upb_fieldtype_t type = upb_array_type(larray->arr);
554   uint32_t n = lupb_array_checkindex(L, 2, upb_array_size(larray->arr) + 1);
555   upb_msgval msgval = lupb_tomsgval(L, type, 3, larray->lmsgclass);
556
557   upb_array_set(larray->arr, larray->type, n, msgval, lupb_arena_get(L));
558
559   if (lupb_istypewrapped(type)) {
560     lupb_uservalseti(L, 1, n, 3);
561   }
562
563   return 0;  /* 1 for chained assignments? */
564 }
565
566 static int lupb_array_index(lua_State *L) {
567   lupb_array *larray = lupb_array_check(L, 1);
568   upb_array *array = larray->arr;
569   uint32_t n = lupb_array_checkindex(L, 2, upb_array_size(array));
570   upb_fieldtype_t type = upb_array_type(array);
571
572   if (lupb_istypewrapped(type)) {
573     lupb_uservalgeti(L, 1, n);
574   } else {
575     lupb_pushmsgval(L, upb_array_type(array),
576                     upb_array_get(array, larray->type, n));
577   }
578
579   return 1;
580 }
581
582 static int lupb_array_len(lua_State *L) {
583   lupb_array *larray = lupb_array_check(L, 1);
584   lua_pushnumber(L, upb_array_size(larray->arr));
585   return 1;
586 }
587
588 static const struct luaL_Reg lupb_array_mm[] = {
589   {"__index", lupb_array_index},
590   {"__len", lupb_array_len},
591   {"__newindex", lupb_array_newindex},
592   {NULL, NULL}
593 };
594
595
596 /* lupb_map *******************************************************************/
597
598 /* A map object.  Implemented by wrapping upb_map.
599  *
600  * When the value type is string/bytes/message, the userval consists of:
601  *
602  *   [Lua number/string] -> [lupb_string/lupb_msg userdata]
603  *
604  * For other value types we don't use the userdata.
605  */
606
607 typedef struct {
608   const lupb_msgclass *value_lmsgclass;
609   upb_map *map;
610 } lupb_map;
611
612 #define MAP_MSGCLASS_INDEX 0
613
614 /* lupb_map internal functions */
615
616 static lupb_map *lupb_map_check(lua_State *L, int narg) {
617   return luaL_checkudata(L, narg, LUPB_ARRAY);
618 }
619
620 /**
621  * lupb_map_typecheck()
622  *
623  * Checks that the lupb_map at index |narg| can be safely assigned to the
624  * field |f| of the message at index |msg|.  If so, returns a upb_msgval for
625  * this map.  Otherwise, raises a Lua error.
626  */
627 static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg,
628                                      const upb_fielddef *f) {
629   lupb_map *lmap = lupb_map_check(L, narg);
630   upb_map *map = lmap->map;
631   const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
632   const upb_fielddef *key_field = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
633   const upb_fielddef *value_field = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
634
635   UPB_ASSERT(entry && key_field && value_field);
636
637   if (upb_map_keytype(map) != upb_fielddef_type(key_field)) {
638     luaL_error(L, "Map key type invalid");
639   }
640
641   if (upb_map_valuetype(map) != upb_fielddef_type(value_field)) {
642     luaL_error(L, "Map had incorrect value type (expected: %s, got: %s)",
643                upb_fielddef_type(value_field), upb_map_valuetype(map));
644   }
645
646   if (upb_map_valuetype(map) == UPB_TYPE_MESSAGE) {
647     lupb_msgclass_typecheck(
648         L, lupb_msg_msgclassfor(L, msg, upb_fielddef_msgsubdef(value_field)),
649         lmap->value_lmsgclass);
650   }
651
652   return upb_msgval_map(map);
653 }
654
655 /* lupb_map Public API */
656
657 /**
658  * lupb_map_new
659  *
660  * Handles:
661  *   new_map = upb.Map(key_type, value_type)
662  */
663 static int lupb_map_new(lua_State *L) {
664   lupb_map *lmap;
665   upb_fieldtype_t key_type = lupb_checkfieldtype(L, 1);
666   upb_fieldtype_t value_type;
667   const lupb_msgclass *value_lmsgclass = NULL;
668
669   if (lua_type(L, 2) == LUA_TNUMBER) {
670     value_type = lupb_checkfieldtype(L, 2);
671   } else {
672     value_type = UPB_TYPE_MESSAGE;
673   }
674
675   lmap = lupb_newuserdata(L, sizeof(*lmap), LUPB_MAP);
676
677   if (value_type == UPB_TYPE_MESSAGE) {
678     value_lmsgclass = lupb_msgclass_check(L, 2);
679     lupb_uservalseti(L, -1, MAP_MSGCLASS_INDEX, 2);  /* GC-root lmsgclass. */
680   }
681
682   lmap->value_lmsgclass = value_lmsgclass;
683   lmap->map = upb_map_new(key_type, value_type, lupb_arena_get(L));
684
685   return 1;
686 }
687
688 /**
689  * lupb_map_index
690  *
691  * Handles:
692  *   map[key]
693  */
694 static int lupb_map_index(lua_State *L) {
695   lupb_map *lmap = lupb_map_check(L, 1);
696   upb_map *map = lmap->map;
697   upb_fieldtype_t valtype = upb_map_valuetype(map);
698   /* We don't always use "key", but this call checks the key type. */
699   upb_msgval key = lupb_tomsgval(L, upb_map_keytype(map), 2, NULL);
700
701   if (lupb_istypewrapped(valtype)) {
702     /* Userval contains the full map, lookup there by key. */
703     lupb_getuservalue(L, 1);
704     lua_pushvalue(L, 2);
705     lua_rawget(L, -2);
706
707     if (lua_isnil(L, -1)) {
708       /* TODO: lazy read from upb_map */
709     }
710   } else {
711     /* Lookup in upb_map. */
712     upb_msgval val;
713     if (upb_map_get(map, key, &val)) {
714       lupb_pushmsgval(L, upb_map_valuetype(map), val);
715     } else {
716       lua_pushnil(L);
717     }
718   }
719
720   return 1;
721 }
722
723 /**
724  * lupb_map_len
725  *
726  * Handles:
727  *   map_len = #map
728  */
729 static int lupb_map_len(lua_State *L) {
730   lupb_map *lmap = lupb_map_check(L, 1);
731   lua_pushnumber(L, upb_map_size(lmap->map));
732   return 1;
733 }
734
735 /**
736  * lupb_map_newindex
737  *
738  * Handles:
739  *   map[key] = val
740  *   map[key] = nil  # to remove from map
741  */
742 static int lupb_map_newindex(lua_State *L) {
743   lupb_map *lmap = lupb_map_check(L, 1);
744   upb_map *map = lmap->map;
745   upb_msgval key = lupb_tomsgval(L, upb_map_keytype(map), 2, NULL);
746
747   if (lua_isnil(L, 3)) {
748     /* Delete from map. */
749     upb_map_del(map, key);
750
751     if (lupb_istypewrapped(upb_map_valuetype(map))) {
752       /* Delete in userval. */
753       lupb_getuservalue(L, 1);
754       lua_pushvalue(L, 2);
755       lua_pushnil(L);
756       lua_rawset(L, -3);
757       lua_pop(L, 1);
758     }
759   } else {
760     /* Set in map. */
761     upb_msgval val =
762         lupb_tomsgval(L, upb_map_valuetype(map), 3, lmap->value_lmsgclass);
763
764     upb_map_set(map, key, val, NULL);
765
766     if (lupb_istypewrapped(upb_map_valuetype(map))) {
767       /* Set in userval. */
768       lupb_getuservalue(L, 1);
769       lua_pushvalue(L, 2);
770       lua_pushvalue(L, 3);
771       lua_rawset(L, -3);
772       lua_pop(L, 1);
773     }
774   }
775
776   return 0;
777 }
778
779 /* upb_mapiter [[[ */
780
781 static int lupb_mapiter_next(lua_State *L) {
782   upb_mapiter *i = lua_touserdata(L, lua_upvalueindex(1));
783   lupb_map *lmap = lupb_map_check(L, 1);
784   upb_map *map = lmap->map;
785
786   if (upb_mapiter_done(i)) {
787     return 0;
788   }
789
790   lupb_pushmsgval(L, upb_map_keytype(map), upb_mapiter_key(i));
791   lupb_pushmsgval(L, upb_map_valuetype(map), upb_mapiter_value(i));
792   upb_mapiter_next(i);
793
794   return 2;
795 }
796
797 static int lupb_map_pairs(lua_State *L) {
798   lupb_map *lmap = lupb_map_check(L, 1);
799
800   if (lupb_istypewrapped(upb_map_keytype(lmap->map)) ||
801       lupb_istypewrapped(upb_map_valuetype(lmap->map))) {
802     /* Complex key or value type.
803      * Sync upb_map to userval if necessary, then iterate over userval. */
804
805     /* TODO: Lua tables don't know how many entries they have, gah!. */
806     return 1;
807   } else {
808     /* Simple key and value type, iterate over the upb_map directly. */
809     upb_mapiter *i = lua_newuserdata(L, upb_mapiter_sizeof());
810
811     upb_mapiter_begin(i, lmap->map);
812     lua_pushvalue(L, 1);
813
814     /* Upvalues are [upb_mapiter, lupb_map]. */
815     lua_pushcclosure(L, &lupb_mapiter_next, 2);
816
817     return 1;
818   }
819 }
820
821 /* upb_mapiter ]]] */
822
823 static const struct luaL_Reg lupb_map_mm[] = {
824   {"__index", lupb_map_index},
825   {"__len", lupb_map_len},
826   {"__newindex", lupb_map_newindex},
827   {"__pairs", lupb_map_pairs},
828   {NULL, NULL}
829 };
830
831
832 /* lupb_msg *******************************************************************/
833
834 /* A message object.  Implemented by wrapping upb_msg.
835  *
836  * Our userval contains:
837  *
838  * - [0] -> our message class
839  * - [lupb_fieldindex(f)] -> [lupb_{string,array,map,msg} userdata]
840  *
841  * Fields with scalar number/bool types don't go in the userval.
842  */
843
844 #define LUPB_MSG_MSGCLASSINDEX 0
845 #define LUPB_MSG_ARENA -1
846
847 int lupb_fieldindex(const upb_fielddef *f) {
848   return upb_fielddef_index(f) + 1;  /* 1-based Lua arrays. */
849 }
850
851
852 typedef struct {
853   const lupb_msgclass *lmsgclass;
854   upb_msg *msg;
855 } lupb_msg;
856
857 /* lupb_msg helpers */
858
859 static bool in_userval(const upb_fielddef *f) {
860   return lupb_istypewrapped(upb_fielddef_type(f)) || upb_fielddef_isseq(f) ||
861          upb_fielddef_ismap(f);
862 }
863
864 lupb_msg *lupb_msg_check(lua_State *L, int narg) {
865   lupb_msg *msg = luaL_checkudata(L, narg, LUPB_MSG);
866   if (!msg->lmsgclass) luaL_error(L, "called into dead msg");
867   return msg;
868 }
869
870 const upb_msg *lupb_msg_checkmsg(lua_State *L, int narg,
871                                  const lupb_msgclass *lmsgclass) {
872   lupb_msg *lmsg = lupb_msg_check(L, narg);
873   lupb_msgclass_typecheck(L, lmsgclass, lmsg->lmsgclass);
874   return lmsg->msg;
875 }
876
877 upb_msg *lupb_msg_checkmsg2(lua_State *L, int narg,
878                             const upb_msglayout **layout) {
879   lupb_msg *lmsg = lupb_msg_check(L, narg);
880   *layout = lmsg->lmsgclass->layout;
881   return lmsg->msg;
882 }
883
884 const upb_msgdef *lupb_msg_checkdef(lua_State *L, int narg) {
885   return lupb_msg_check(L, narg)->lmsgclass->msgdef;
886 }
887
888 static const upb_fielddef *lupb_msg_checkfield(lua_State *L,
889                                                const lupb_msg *msg,
890                                                int fieldarg) {
891   size_t len;
892   const char *fieldname = luaL_checklstring(L, fieldarg, &len);
893   const upb_msgdef *msgdef = msg->lmsgclass->msgdef;
894   const upb_fielddef *f = upb_msgdef_ntof(msgdef, fieldname, len);
895
896   if (!f) {
897     const char *msg = lua_pushfstring(L, "no such field: %s", fieldname);
898     luaL_argerror(L, fieldarg, msg);
899     return NULL;  /* Never reached. */
900   }
901
902   return f;
903 }
904
905 static const lupb_msgclass *lupb_msg_msgclassfor(lua_State *L, int narg,
906                                                  const upb_msgdef *md) {
907   lupb_uservalgeti(L, narg, LUPB_MSG_MSGCLASSINDEX);
908   return lupb_msgclass_msgclassfor(L, -1, md);
909 }
910
911 static const lupb_msgclass *lupb_msg_getsubmsgclass(lua_State *L, int narg,
912                                                     const upb_fielddef *f) {
913   lupb_uservalgeti(L, narg, LUPB_MSG_MSGCLASSINDEX);
914   return lupb_msgclass_getsubmsgclass(L, -1, f);
915 }
916
917 int lupb_msg_pushref(lua_State *L, int msgclass, upb_msg *msg) {
918   const lupb_msgclass *lmsgclass = lupb_msgclass_check(L, msgclass);
919   lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), LUPB_MSG);
920
921   lmsg->lmsgclass = lmsgclass;
922   lmsg->msg = msg;
923
924   lupb_uservalseti(L, -1, LUPB_MSG_MSGCLASSINDEX, msgclass);
925   lupb_uservalseti(L, -1, LUPB_MSG_ARENA, -2);
926
927   return 1;
928 }
929
930 /* lupb_msg Public API */
931
932 /**
933  * lupb_msg_pushnew
934  *
935  * Handles:
936  *   new_msg = MessageClass()
937  */
938 static int lupb_msg_pushnew(lua_State *L, int narg) {
939   const lupb_msgclass *lmsgclass = lupb_msgclass_check(L, narg);
940   lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), LUPB_MSG);
941
942   lmsg->lmsgclass = lmsgclass;
943   lmsg->msg = upb_msg_new(lmsgclass->layout, lupb_arena_get(L));
944
945   lupb_uservalseti(L, -1, LUPB_MSG_MSGCLASSINDEX, narg);
946
947   return 1;
948 }
949
950 /**
951  * lupb_msg_index
952  *
953  * Handles:
954  *   msg.foo
955  *   msg["foo"]
956  *   msg[field_descriptor]  # (for extensions) (TODO)
957  */
958 static int lupb_msg_index(lua_State *L) {
959   lupb_msg *lmsg = lupb_msg_check(L, 1);
960   const upb_fielddef *f = lupb_msg_checkfield(L, lmsg, 2);
961   const upb_msglayout *l = lmsg->lmsgclass->layout;
962   int field_index = upb_fielddef_index(f);
963
964   if (in_userval(f)) {
965     lupb_uservalgeti(L, 1, lupb_fieldindex(f));
966
967     if (lua_isnil(L, -1)) {
968       /* Check if we need to lazily create wrapper. */
969       if (upb_fielddef_isseq(f)) {
970         /* TODO(haberman) */
971       } else if (upb_fielddef_issubmsg(f)) {
972         /* TODO(haberman) */
973       } else {
974         UPB_ASSERT(upb_fielddef_isstring(f));
975         if (upb_msg_has(lmsg->msg, field_index, l)) {
976           upb_msgval val = upb_msg_get(lmsg->msg, field_index, l);
977           lua_pop(L, 1);
978           lua_pushlstring(L, val.str.data, val.str.size);
979           lupb_uservalseti(L, 1, lupb_fieldindex(f), -1);
980         }
981       }
982     }
983   } else {
984     upb_msgval val = upb_msg_get(lmsg->msg, field_index, l);
985     lupb_pushmsgval(L, upb_fielddef_type(f), val);
986   }
987
988   return 1;
989 }
990
991 /**
992  * lupb_msg_newindex()
993  *
994  * Handles:
995  *   msg.foo = bar
996  *   msg["foo"] = bar
997  *   msg[field_descriptor] = bar  # (for extensions) (TODO)
998  */
999 static int lupb_msg_newindex(lua_State *L) {
1000   lupb_msg *lmsg = lupb_msg_check(L, 1);
1001   const upb_fielddef *f = lupb_msg_checkfield(L, lmsg, 2);
1002   upb_fieldtype_t type = upb_fielddef_type(f);
1003   int field_index = upb_fielddef_index(f);
1004   upb_msgval msgval;
1005
1006   /* Typecheck and get msgval. */
1007
1008   if (upb_fielddef_isseq(f)) {
1009     msgval = lupb_array_typecheck(L, 3, 1, f);
1010   } else if (upb_fielddef_ismap(f)) {
1011     msgval = lupb_map_typecheck(L, 3, 1, f);
1012   } else {
1013     const lupb_msgclass *lmsgclass = NULL;
1014
1015     if (type == UPB_TYPE_MESSAGE) {
1016       lmsgclass = lupb_msg_getsubmsgclass(L, 1, f);
1017     }
1018
1019     msgval = lupb_tomsgval(L, type, 3, lmsgclass);
1020   }
1021
1022   /* Set in upb_msg and userval (if necessary). */
1023
1024   upb_msg_set(lmsg->msg, field_index, msgval, lmsg->lmsgclass->layout);
1025
1026   if (in_userval(f)) {
1027     lupb_uservalseti(L, 1, lupb_fieldindex(f), 3);
1028   }
1029
1030   return 0;  /* 1 for chained assignments? */
1031 }
1032
1033 static const struct luaL_Reg lupb_msg_mm[] = {
1034   {"__index", lupb_msg_index},
1035   {"__newindex", lupb_msg_newindex},
1036   {NULL, NULL}
1037 };
1038
1039
1040 /* lupb_msg toplevel **********************************************************/
1041
1042 static const struct luaL_Reg lupb_msg_toplevel_m[] = {
1043   {"Array", lupb_array_new},
1044   {"Map", lupb_map_new},
1045   {"MessageFactory", lupb_msgfactory_new},
1046   {NULL, NULL}
1047 };
1048
1049 void lupb_msg_registertypes(lua_State *L) {
1050   lupb_setfuncs(L, lupb_msg_toplevel_m);
1051
1052   lupb_register_type(L, LUPB_ARENA,      NULL,              lupb_arena_mm);
1053   lupb_register_type(L, LUPB_MSGCLASS,   NULL,              lupb_msgclass_mm);
1054   lupb_register_type(L, LUPB_MSGFACTORY, lupb_msgfactory_m, lupb_msgfactory_mm);
1055   lupb_register_type(L, LUPB_ARRAY,      NULL,              lupb_array_mm);
1056   lupb_register_type(L, LUPB_MAP,        NULL,              lupb_map_mm);
1057   lupb_register_type(L, LUPB_MSG,        NULL,              lupb_msg_mm);
1058
1059   lupb_arena_initsingleton(L);
1060 }