1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
use rlua::prelude::*; use crate::bindings::system::LuaMetadata; use std::{fs, path}; use std::sync::Arc; pub struct LuaPath(path::PathBuf); impl LuaUserData for LuaPath { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_method("file_stem", |_, this: &LuaPath, _:() |{ Ok(this.0.file_stem().map(|p| p.to_str().map(|s| s.to_string()))) }); methods.add_method("file_name", |_, this: &LuaPath, _:() |{ Ok(this.0.file_name().map(|p| p.to_str().map(|s| s.to_string()))) }); methods.add_method("ext", |_, this: &LuaPath, _:() |{ Ok(this.0.extension().map(|p| p.to_str().map(|s| s.to_string()))) }); methods.add_method("exists", |_, this: &LuaPath, _:() |{ Ok(this.0.exists()) }); methods.add_method("is_dir", |_, this: &LuaPath, _:() |{ Ok(this.0.is_dir()) }); methods.add_method("is_file", |_, this: &LuaPath, _:() |{ Ok(this.0.is_file()) }); methods.add_method("create_file", |_, this: &LuaPath, _: ()| { fs::OpenOptions::new() .write(true) .create(true) .open(this.0.as_path()) .map(|_| ()) .map_err(LuaError::external) }); methods.add_method("create_dir", |_, this: &LuaPath, opt: Option<bool>| { match opt { Some(true) => fs::create_dir_all(this.0.as_path()).map_err(LuaError::external), _ => fs::create_dir(this.0.as_path()).map_err(LuaError::external) } }); methods.add_method("remove", |_, this: &LuaPath, opt: Option<bool>| { if this.0.exists() { if this.0.is_file() { return fs::remove_file(&this.0).map_err(LuaError::external); } else if this.0.is_dir() { return match opt { Some(true) => fs::remove_dir_all(&this.0).map_err(LuaError::external), _ => fs::remove_dir(&this.0).map_err(LuaError::external) }; } } Ok(()) }); methods.add_method("is_relative", |_, this: &LuaPath, _:() |{ Ok(this.0.is_relative()) }); methods.add_method("is_absolute", |_, this: &LuaPath, _:() |{ Ok(this.0.is_absolute()) }); methods.add_method("has_root", |_, this: &LuaPath, _:() |{ Ok(this.0.has_root()) }); methods.add_method("parent", |_, this: &LuaPath, _:() |{ Ok(this.0.parent().map(|p| LuaPath(p.to_path_buf()))) }); methods.add_method_mut("push", |_, this: &mut LuaPath, val: String |{ Ok(this.0.push(&val)) }); methods.add_method("join", |_, this: &LuaPath, path: String |{ Ok(LuaPath(this.0.join(path))) }); methods.add_method("metadata", |_, this: &LuaPath, _:() |{ Ok(LuaMetadata(this.0.metadata().map_err(LuaError::external)?)) }); methods.add_method("canonicalize", |_, this: &LuaPath, _:() |{ fs::canonicalize(&this.0).map(|can| can.to_str().map(|s| s.to_string())).map_err(LuaError::external) }); methods.add_method("read_dir", |lua, this: &LuaPath, _: ()| { match this.0.read_dir() { Ok(iter) => { let mut arc_iter = Arc::new(Some(iter)); let f = move |_, _: ()| { let result = match Arc::get_mut(&mut arc_iter).expect("entries iterator is mutably borrowed") { Some(iter) => iter.next().map(|entry| entry.map(|e| LuaPath(e.path())).ok()), None => None }; if result.is_none() { *Arc::get_mut(&mut arc_iter).unwrap() = None; } Ok(result) }; Ok(lua.create_function_mut(f)?) }, Err(err) => Err(LuaError::external(err)) } }); methods.add_meta_method(LuaMetaMethod::ToString, |_, this: &LuaPath, _: ()| { Ok(this.0.to_str().map(|s| s.to_string())) }); } } pub fn init(lua: &Lua) -> crate::Result<()> { let module = lua.create_table()?; module.set("empty", lua.create_function( |_, _: ()| { Ok(LuaPath(path::PathBuf::new())) })? )?; module.set("new", lua.create_function( |_, path: String| { Ok(LuaPath(path::Path::new(&path).to_path_buf())) })? )?; lua.globals().set("path", module)?; Ok(()) }