blob: 801003f7c7e29f228fbd22969537957d18d5f185 [file] [log] [blame] [raw]
package li.cil.oc.util
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.machine.Value
import li.cil.repack.org.luaj.vm2.LuaString
import li.cil.repack.org.luaj.vm2.LuaValue
import li.cil.repack.org.luaj.vm2.Varargs
import li.cil.repack.org.luaj.vm2.lib.VarArgFunction
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
import scala.language.implicitConversions
import scala.math.ScalaNumber
import scala.runtime.BoxedUnit
class ScalaClosure(val f: (Varargs) => Varargs) extends VarArgFunction {
override def invoke(args: Varargs) = f(args)
}
object ScalaClosure {
implicit def wrapClosure(f: (Varargs) => LuaValue): ScalaClosure = new ScalaClosure(args => f(args) match {
case varargs: Varargs => varargs
case LuaValue.NONE => LuaValue.NONE
case result => LuaValue.varargsOf(Array(result))
})
implicit def wrapVarArgClosure(f: (Varargs) => Varargs): ScalaClosure = new ScalaClosure(f)
def toLuaValue(value: Any): LuaValue = {
(value match {
case number: ScalaNumber => number.underlying
case reference: AnyRef => reference
case null => null
case primitive => primitive.asInstanceOf[AnyRef]
}) match {
case null | Unit | _: BoxedUnit => LuaValue.NIL
case value: java.lang.Boolean => LuaValue.valueOf(value.booleanValue)
case value: java.lang.Byte => LuaValue.valueOf(value.byteValue)
case value: java.lang.Character => LuaValue.valueOf(String.valueOf(value))
case value: java.lang.Short => LuaValue.valueOf(value.shortValue)
case value: java.lang.Integer => LuaValue.valueOf(value.intValue)
case value: java.lang.Long => LuaValue.valueOf(value.longValue)
case value: java.lang.Float => LuaValue.valueOf(value.floatValue)
case value: java.lang.Double => LuaValue.valueOf(value.doubleValue)
case value: java.lang.String => LuaValue.valueOf(value)
case value: Array[Byte] => LuaValue.valueOf(value)
case value: Array[_] => toLuaList(value)
case value: Value if Settings.get.allowUserdata => LuaValue.userdataOf(value)
case value: Product => toLuaList(value.productIterator.toIterable)
case value: Seq[_] => toLuaList(value)
case value: java.util.Map[_, _] => toLuaTable(value.toMap)
case value: Map[_, _] => toLuaTable(value)
case value: mutable.Map[_, _] => toLuaTable(value.toMap)
case _ =>
OpenComputers.log.warn("Tried to push an unsupported value of type to Lua: " + value.getClass.getName + ".")
LuaValue.NIL
}
}
def toLuaList(value: Iterable[Any]): LuaValue = {
val table = LuaValue.listOf(value.map(toLuaValue).toArray)
table.set("n", table.length())
table
}
def toLuaTable(value: Map[_, _]): LuaValue = {
LuaValue.tableOf(value.flatMap {
case (k, v) => Seq(toLuaValue(k), toLuaValue(v))
}.toArray)
}
def toSimpleJavaObject(value: LuaValue): AnyRef = value.`type`() match {
case LuaValue.TBOOLEAN => Boolean.box(value.toboolean())
case LuaValue.TNUMBER => Double.box(value.todouble())
case LuaValue.TSTRING => value match {
case s: LuaString => s.m_bytes.slice(s.m_offset, s.m_offset + s.m_length)
case _ => value.tojstring() // Waddafaq?
}
case LuaValue.TTABLE =>
val table = value.checktable()
table.keys.map(key => toSimpleJavaObject(key) -> toSimpleJavaObject(table.get(key))).toMap
case LuaValue.TUSERDATA => value.touserdata()
case _ => null
}
def toSimpleJavaObjects(args: Varargs, start: Int = 1) =
for (index <- start to args.narg()) yield toSimpleJavaObject(args.arg(index))
}