R"( local M = {} M.__Content = true M.new = function(source) local result = {} result.__nameIndex = {} for i, v in ipairs(source) do if type(v) ~= 'table' then error("Content can only contain tables") end result[i] = v if type(v.name) == 'string' then result.__nameIndex[v.name] = i end end return setmetatable(result, M) end local function validateIndex(self, index) if type(index) ~= 'number' then error('Unexpected Content key: ' .. tostring(index)) end if index < 1 or (#self + 1) < index then error('Invalid Content index: ' .. tostring(index)) end end local function getIndexFromKey(self, key) local index = key if type(key) == 'string' then index = self.__nameIndex[key] if not index then error("Unexpected content key:" .. key) end end validateIndex(self, index) return index end local function nameAt(self, index) local v = rawget(self, index) return v and type(v.name) == 'string' and v.name end local methods = { insert = function(self, index, value) validateIndex(self, index) if type(value) ~= 'table' then error('Content can only contain tables') end for i = #self, index, -1 do rawset(self, i + 1, rawget(self, i)) local name = rawget(self, i + 1) if name then self.__nameIndex[name] = i + 1 end end rawset(self, index, value) if value.name then self.__nameIndex[value.name] = index end end, indexOf = function(self, value) if type(value) == 'string' then return self.__nameIndex[value] elseif type(value) == 'table' then for i = 1, #self do if rawget(self, i) == value then return i end end end return nil end, add = function(self, value) self:insert(#self + 1, value) return #self end, } M.__index = function(self, key) if methods[key] then return methods[key] end local index = getIndexFromKey(self, key) return rawget(self, index) end local function remove(self, index) print('remove', #self, index) local oldName = nameAt(self, index) if oldName then self.__nameIndex[oldName] = nil end if index > #self then error('Invalid Content index:' .. tostring(index)) end for i = index, #self - 1 do local v = rawget(self, i + 1) rawset(self, i, v) if type(v.name) == 'string' then self.__nameIndex[v.name] = i end end rawset(self, #self, nil) print('removed', #self) end local function assign(self, index, value) local oldName = nameAt(self, index) if oldName then self.__nameIndex[oldName] = nil end rawset(self, index, value) if value.name then self.__nameIndex[value.name] = index end end M.__newindex = function(self, key, value) print('__newindex ', key, value) local index = getIndexFromKey(self, key) if value == nil then remove(self, index) elseif type(value) == 'table' then assign(self, index, value) else error('Content can only contain tables') end end local function next(self, index) local v = rawget(self, index) if v then return index + 1, v else return nil, nil end end M.__pairs = function(self) return next, self, 1 end M.__ipairs = M.__pairs local test = M.new({}) test:insert(1, {}) test[2] = {} assert(#test == 2, "Wrong size") test:add({ name = 'a' }) assert(getIndexFromKey(test, 'a') == 3, getIndexFromKey(test, 'a')) assert(type(test.a) == 'table', type(test.a)) assert(test.a.name == 'a', 'wrong table') return M )"