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.
distant/distant-lua/src/session/opts.rs

209 lines
7.2 KiB
Rust

use distant_ssh2::{Ssh2AuthHandler, Ssh2SessionOpts};
use mlua::prelude::*;
use serde::Deserialize;
use std::{fmt, io, time::Duration};
#[derive(Clone, Debug, Default)]
pub struct ConnectOpts {
pub host: String,
pub port: u16,
pub key: String,
pub timeout: Duration,
}
impl<'lua> FromLua<'lua> for ConnectOpts {
fn from_lua(lua_value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
match lua_value {
LuaValue::Table(tbl) => Ok(Self {
host: tbl.get("host")?,
port: tbl.get("port")?,
key: tbl.get("key")?,
timeout: {
let milliseconds: u64 = tbl.get("timeout")?;
Duration::from_millis(milliseconds)
},
}),
LuaValue::Nil => Err(LuaError::FromLuaConversionError {
from: "Nil",
to: "ConnectOpts",
message: None,
}),
LuaValue::Boolean(_) => Err(LuaError::FromLuaConversionError {
from: "Boolean",
to: "ConnectOpts",
message: None,
}),
LuaValue::LightUserData(_) => Err(LuaError::FromLuaConversionError {
from: "LightUserData",
to: "ConnectOpts",
message: None,
}),
LuaValue::Integer(_) => Err(LuaError::FromLuaConversionError {
from: "Integer",
to: "ConnectOpts",
message: None,
}),
LuaValue::Number(_) => Err(LuaError::FromLuaConversionError {
from: "Number",
to: "ConnectOpts",
message: None,
}),
LuaValue::String(_) => Err(LuaError::FromLuaConversionError {
from: "String",
to: "ConnectOpts",
message: None,
}),
LuaValue::Function(_) => Err(LuaError::FromLuaConversionError {
from: "Function",
to: "ConnectOpts",
message: None,
}),
LuaValue::Thread(_) => Err(LuaError::FromLuaConversionError {
from: "Thread",
to: "ConnectOpts",
message: None,
}),
LuaValue::UserData(_) => Err(LuaError::FromLuaConversionError {
from: "UserData",
to: "ConnectOpts",
message: None,
}),
LuaValue::Error(_) => Err(LuaError::FromLuaConversionError {
from: "Error",
to: "ConnectOpts",
message: None,
}),
}
}
}
#[derive(Default)]
pub struct LaunchOpts<'a> {
pub host: String,
pub mode: Mode,
pub handler: Ssh2AuthHandler<'a>,
pub ssh: Ssh2SessionOpts,
pub timeout: Duration,
}
impl fmt::Debug for LaunchOpts<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LaunchOpts")
.field("host", &self.host)
.field("mode", &self.mode)
.field("handler", &"...")
.field("ssh", &self.ssh)
.field("timeout", &self.timeout)
.finish()
}
}
impl<'lua> FromLua<'lua> for LaunchOpts<'lua> {
fn from_lua(lua_value: LuaValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> {
match lua_value {
LuaValue::Table(tbl) => Ok(Self {
host: tbl.get("host")?,
mode: lua.from_value(tbl.get("mode")?)?,
handler: Ssh2AuthHandler {
on_authenticate: {
let f: LuaFunction = tbl.get("on_authenticate")?;
Box::new(move |ev| {
let value = to_value!(lua, &ev)
.map_err(|x| io::Error::new(io::ErrorKind::InvalidData, x))?;
f.call::<LuaValue, Vec<String>>(value)
.map_err(|x| io::Error::new(io::ErrorKind::Other, x))
})
},
on_banner: {
let f: LuaFunction = tbl.get("on_banner")?;
Box::new(move |banner| {
let _ = f.call::<String, ()>(banner.to_string());
})
},
on_host_verify: {
let f: LuaFunction = tbl.get("on_host_verify")?;
Box::new(move |host| {
f.call::<String, bool>(host.to_string())
.map_err(|x| io::Error::new(io::ErrorKind::Other, x))
})
},
on_error: {
let f: LuaFunction = tbl.get("on_error")?;
Box::new(move |err| {
let _ = f.call::<String, ()>(err.to_string());
})
},
},
ssh: lua.from_value(tbl.get("ssh")?)?,
timeout: {
let milliseconds: u64 = tbl.get("timeout")?;
Duration::from_millis(milliseconds)
},
}),
LuaValue::Nil => Err(LuaError::FromLuaConversionError {
from: "Nil",
to: "LaunchOpts",
message: None,
}),
LuaValue::Boolean(_) => Err(LuaError::FromLuaConversionError {
from: "Boolean",
to: "LaunchOpts",
message: None,
}),
LuaValue::LightUserData(_) => Err(LuaError::FromLuaConversionError {
from: "LightUserData",
to: "LaunchOpts",
message: None,
}),
LuaValue::Integer(_) => Err(LuaError::FromLuaConversionError {
from: "Integer",
to: "LaunchOpts",
message: None,
}),
LuaValue::Number(_) => Err(LuaError::FromLuaConversionError {
from: "Number",
to: "LaunchOpts",
message: None,
}),
LuaValue::String(_) => Err(LuaError::FromLuaConversionError {
from: "String",
to: "LaunchOpts",
message: None,
}),
LuaValue::Function(_) => Err(LuaError::FromLuaConversionError {
from: "Function",
to: "LaunchOpts",
message: None,
}),
LuaValue::Thread(_) => Err(LuaError::FromLuaConversionError {
from: "Thread",
to: "LaunchOpts",
message: None,
}),
LuaValue::UserData(_) => Err(LuaError::FromLuaConversionError {
from: "UserData",
to: "LaunchOpts",
message: None,
}),
LuaValue::Error(_) => Err(LuaError::FromLuaConversionError {
from: "Error",
to: "LaunchOpts",
message: None,
}),
}
}
}
#[derive(Copy, Clone, Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Mode {
Distant,
Ssh,
}
impl Default for Mode {
fn default() -> Self {
Self::Distant
}
}