Just looping back here since there was a mention of it:
`pairs`, `next` and others all do a check on the object to see if its a table in 5.1, the requirements seems(?) to have been dropped in Lua 5.2/5.3. LuaJIT has not adopted the changes to not have that be apart of it, for LuaJIT 2.0.4 (but I didn't build with the LUAJIT_52_COMPAT flag or whatever it specifically is). `ipairs` seems to do a table check no matter what version I'm in (up to Lua 5.3.3), which is strange because you'd think it wouldn't have that restriction since it was explicitly made to obey the __index and __newindex rules? It could be that there's a compat flag I have on that's making that happen.
By overriding `__len`, `__index`, `__newindex` and `__pairs` on a userdata, I was able to get a really close-to-table implementation using userdata. The problem has been, of course, older versions of Lua forcing checks when iterating / checking for tables, which makes the userdata approach less ideal than the serialize-to-table and deserialize-from-table approach I used to take. For all other purposes and for up-to-date Lua, the userdata approach seems ideal. I'm still keeping the option for my users to serialize to a table, if only because its very, very convenient for older APIs...