You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.7 KiB
Rust

use rlua::{FromLua, Context, Value, Error, ToLua};
use std::convert::TryFrom;
#[derive(Hash, Ord, PartialOrd, Eq, PartialEq, Debug, Clone)]
pub enum Bind {
Mouse(u32),
Key(u32),
Ping(String),
}
#[derive(Debug, Clone)]
pub struct Handler {
pub passthrough: bool,
pub action: Action,
}
#[derive(Debug, Clone)]
pub enum Action {
Sync(Bind),
Press(Bind),
Release(Bind),
Sleep(u32),
List(Vec<Action>),
}
impl<'lua> FromLua<'lua> for Bind {
fn from_lua(lua_value: Value<'lua>, _: Context<'lua>) -> Result<Self, Error> {
if let Value::Integer(n) = lua_value {
return Ok(Bind::Key(u32::try_from(n).map_err(|e| Error::external(e))?));
}
if let Value::String(c) = lua_value {
return Ok(Bind::Ping(String::from(c.to_str()?)));
}
if let Value::Table(table) = lua_value {
let typ: String = table.get("type")?;
let bind = match typ.as_str() {
"mouse" => Bind::Mouse(table.get("code")?),
"key" => Bind::Key(table.get("code")?),
"ping" => Bind::Ping(table.get("code")?),
_ => return Err(Error::RuntimeError("Type should be one of mouse, key or ping".to_string()))
};
return Ok(bind);
}
Err(Error::RuntimeError("Can't create Bind from non-table".to_string()))
}
}
impl<'lua> ToLua<'lua> for Bind {
fn to_lua(self, lua: Context<'lua>) -> Result<Value<'lua>, Error> {
let table = lua.create_table()?;
table.set("type", match self {
Bind::Key(_) => "key",
Bind::Ping(_) => "ping",
Bind::Mouse(_) => "mouse",
})?;
match self {
Bind::Key(n) => table.set("code", n)?,
Bind::Mouse(n) => table.set("code", n)?,
Bind::Ping(c) => table.set("code", c)?,
}
Ok(table.to_lua(lua)?)
}
}
impl<'lua> FromLua<'lua> for Action {
fn from_lua(lua_value: Value<'lua>, _: Context<'lua>) -> Result<Self, Error> {
let table = if let Value::Table(table) = lua_value {
table
} else {
return Err(Error::RuntimeError("Action should be a table".to_string()));
};
let res = match table.get::<&str, String>("type")?.as_str() {
"sync" => Action::Sync(table.get("bind")?),
"press" => Action::Press(table.get("bind")?),
"release" => Action::Release(table.get("bind")?),
"sleep" => Action::Sleep(table.get("time")?),
"list" => Action::List(table.get("items")?),
_ => return Err(Error::RuntimeError("Action type is invalid, should be one of sync, release, press, sleep, list".to_string()))
};
Ok(res)
}
}