222 lines
5.4 KiB
Lua
222 lines
5.4 KiB
Lua
local PeripheralAPIFake = {}
|
|
PeripheralAPIFake.__index = PeripheralAPIFake
|
|
|
|
local expect = require("cc.expect").expect
|
|
|
|
local function isPeripheral(peripheral)
|
|
if type(peripheral) ~= "table" then return false end
|
|
local meta = getmetatable(peripheral)
|
|
|
|
if type(meta) ~= "table" then return false end
|
|
if meta.__name ~= "peripheral" then return false end
|
|
if type(meta.name) ~= "string" then return false end
|
|
if type(meta.type) ~= "string" then return false end
|
|
if type(meta.types) ~= "table" then return false end
|
|
for _, ty in ipairs(meta.types) do
|
|
if not meta.types[ty] then return false end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
-- TODO: Add descriptive error messages to asserts
|
|
local function expectPeripheral(index, peripheral)
|
|
if not isPeripheral(peripheral) then
|
|
error(("bad argument #%d (table is not a peripheral)"):format(index), 3)
|
|
end
|
|
end
|
|
|
|
--- Performs a deep clone of a table.
|
|
local function cloneTable(t)
|
|
local mt = getmetatable(t)
|
|
setmetatable(t, nil)
|
|
local cloned = {}
|
|
for k, v in pairs(t) do
|
|
if type(v) == "table" then
|
|
cloned[k] = cloneTable(v)
|
|
else
|
|
cloned[k] = v
|
|
end
|
|
end
|
|
setmetatable(t, mt)
|
|
return cloned
|
|
end
|
|
|
|
local function doesTableContain(t, value)
|
|
for _, v in pairs(t) do
|
|
if v == value then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function getPeripheralName(peripheral)
|
|
return getmetatable(peripheral).name
|
|
end
|
|
|
|
local function getPeripheralTypes(peripheral)
|
|
return getmetatable(peripheral).types
|
|
end
|
|
|
|
function PeripheralAPIFake.new(peripherals)
|
|
expect(1, peripherals, "table", "nil")
|
|
|
|
local self = setmetatable({}, PeripheralAPIFake)
|
|
self.peripherals = {}
|
|
|
|
if peripherals then
|
|
for _, peripheral in ipairs(peripherals) do
|
|
self:addPeripehral(peripheral)
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
function PeripheralAPIFake:newExternalAPI()
|
|
local api = {}
|
|
|
|
function api.call(name, method, ...)
|
|
expect(1, name, "string")
|
|
expect(2, method, "string")
|
|
local peripheral = self.peripherals[name]
|
|
if not peripheral then return end
|
|
local func = peripheral[method]
|
|
if type(func) ~= "function" then
|
|
error(("No such method %s"):format(method), 2)
|
|
end
|
|
return func(...)
|
|
end
|
|
|
|
function api.find(ty, filter)
|
|
expect(1, ty, "string")
|
|
expect(2, filter, "function", "nil")
|
|
local peripherals = {}
|
|
for name, peripheral in pairs(self.peripherals) do
|
|
local types = getPeripheralTypes(peripheral)
|
|
if doesTableContain(types, ty) then
|
|
local wrapped = api.wrap(name)
|
|
if not filter or filter(name, wrapped) then
|
|
table.insert(peripherals, wrapped)
|
|
end
|
|
end
|
|
end
|
|
return peripherals
|
|
end
|
|
|
|
function api.getMethods(name)
|
|
expect(1, name, "string")
|
|
local peripheral = self:getPeripheral(name)
|
|
if not peripheral then return end
|
|
|
|
local methods = {}
|
|
for methodName, method in pairs(peripheral) do
|
|
if type(method) == "function" then
|
|
table.insert(methods, methodName)
|
|
end
|
|
end
|
|
return methods
|
|
end
|
|
|
|
function api.getName(peripheral)
|
|
expect(1, peripheral, "table", "string")
|
|
expectPeripheral(1, peripheral)
|
|
return getPeripheralName(peripheral)
|
|
end
|
|
|
|
function api.getNames()
|
|
return self:listPeripherals()
|
|
end
|
|
|
|
function api.getType(peripheral)
|
|
expect(1, peripheral, "table", "string")
|
|
if type(peripheral) == "table" then
|
|
expectPeripheral(1, peripheral)
|
|
end
|
|
local p = self:getPeripheral(peripheral)
|
|
return table.unpack(getPeripheralTypes(p))
|
|
end
|
|
|
|
function api.hasType(peripheral, peripheral_type)
|
|
expect(1, peripheral, "table", "string")
|
|
if type(peripheral) == "table" then
|
|
expectPeripheral(1, peripheral)
|
|
end
|
|
expect(2, peripheral_type, "string")
|
|
local p = self:getPeripheral(peripheral)
|
|
if not p then return end
|
|
|
|
local types = getPeripheralTypes(peripheral)
|
|
return doesTableContain(types, peripheral_type)
|
|
end
|
|
|
|
function api.isPresent(name)
|
|
expect(1, name, "string")
|
|
return self:hasPeripheral(name)
|
|
end
|
|
|
|
function api.wrap(name)
|
|
expect(1, name, "string")
|
|
local peripheral = self.peripherals[name]
|
|
if not peripheral then return end
|
|
return cloneTable(peripheral)
|
|
end
|
|
|
|
return api
|
|
end
|
|
|
|
function PeripheralAPIFake:addPeripehral(peripheral)
|
|
expect(1, peripheral, "table")
|
|
expectPeripheral(1, peripheral)
|
|
|
|
local name = getPeripheralName(peripheral)
|
|
assert(not self.peripherals[name], "Expected peripheral name to be unique, it's not unique")
|
|
assert(not self:hasPeripheral(peripheral), "Peripheral already added to system")
|
|
|
|
self.peripherals[name] = peripheral
|
|
end
|
|
|
|
function PeripheralAPIFake:removePeripheral(peripheral)
|
|
expect(1, peripheral, "table", "string")
|
|
|
|
if type(peripheral) == "string" then
|
|
self.peripherals[peripheral] = nil
|
|
else
|
|
expectPeripheral(1, peripheral)
|
|
local name = getPeripheralName(peripheral)
|
|
self.peripherals[name] = nil
|
|
end
|
|
end
|
|
|
|
function PeripheralAPIFake:hasPeripheral(peripheral)
|
|
expect(1, peripheral, "table", "string")
|
|
return self:getPeripheral(peripheral) ~= nil
|
|
end
|
|
|
|
function PeripheralAPIFake:getPeripheral(peripheral)
|
|
expect(1, peripheral, "table", "string")
|
|
|
|
if type(peripheral) == "string" then
|
|
return self.peripherals[peripheral]
|
|
else
|
|
expectPeripheral(1, peripheral)
|
|
local name = getPeripheralName(peripheral)
|
|
return self.peripherals[name]
|
|
end
|
|
end
|
|
|
|
function PeripheralAPIFake:getPeripheralName(peripheral)
|
|
return getPeripheralName(self:getPeripheral(peripheral))
|
|
end
|
|
|
|
function PeripheralAPIFake:listPeripherals()
|
|
local names = {}
|
|
for _, peripheral in pairs(self.peripherals) do
|
|
table.insert(names, getPeripheralName(peripheral))
|
|
end
|
|
return names
|
|
end
|
|
|
|
return PeripheralAPIFake
|