use mlua::{AnyUserData, ExternalError, FromLua, Lua, Table, UserData, UserDataMethods, UserDataRef, UserDataRegistry, Value}; use yazi_binding::{impl_file_fields, impl_file_methods}; use crate::file::{File, FileInventory}; pub type FileRef = UserDataRef; const EXPECTED: &str = "expected a table, File, or fs::File"; impl File { pub fn install(lua: &Lua) -> mlua::Result<()> { lua.globals().raw_set("File", lua.create_function(|_, file: Self| Ok(file))?) } } impl TryFrom for File { type Error = mlua::Error; fn try_from(value: Table) -> Result { Ok(Self { url: value.raw_get("url")?, cha: value.raw_get("cha")?, ..Default::default() }) } } impl TryFrom for File { type Error = mlua::Error; fn try_from(value: AnyUserData) -> Result { if let Ok(me) = value.take::() { return Ok(me); } for inv in inventory::iter::() { match (inv.from_lua)(&value) { Ok(file) => return Ok(file), Err(mlua::Error::UserDataTypeMismatch) => continue, Err(e) => return Err(e), } } Err(mlua::Error::UserDataTypeMismatch) } } impl FromLua for File { fn from_lua(value: Value, _: &Lua) -> mlua::Result { match value { Value::Table(tbl) => Self::try_from(tbl), Value::UserData(ud) => Self::try_from(ud), _ => Err(EXPECTED.into_lua_err())?, } } } impl UserData for File { fn register(registry: &mut UserDataRegistry) { impl_file_fields!(registry); impl_file_methods!(registry); for inv in inventory::iter::() { (inv.register)(registry); } } }