diff options
Diffstat (limited to '.config/awesome/quarrel/native/src/util.rs')
-rw-r--r-- | .config/awesome/quarrel/native/src/util.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/.config/awesome/quarrel/native/src/util.rs b/.config/awesome/quarrel/native/src/util.rs new file mode 100644 index 0000000..85a2574 --- /dev/null +++ b/.config/awesome/quarrel/native/src/util.rs @@ -0,0 +1,101 @@ +use std::{ + cell::RefCell, + fs::File, + fs::OpenOptions, + io::{ + Read, + Seek, + Write + }, + rc::Rc, + str::FromStr, +}; + +use html_escape::decode_html_entities_to_string; +use mlua::prelude::*; +use serde::Serialize; + +pub fn decode_html(_: &Lua, string: String) -> LuaResult<String> { + let mut output = String::new(); + decode_html_entities_to_string(string, &mut output); + Ok(output) +} + +enum ReadMode { + Line, + Number, + All, +} + +impl FromStr for ReadMode { + type Err = (); + + fn from_str(value: &str) -> Result<Self, Self::Err> { + Ok(match value { + "l" => Self::Line, + "n" => Self::Number, + _ => Self::All, + }) + } +} + +#[derive(Serialize)] +#[serde(untagged)] +enum StringOrNumber { + String(String), + Number(u64), +} + +pub struct FileHandle(Rc<RefCell<File>>); + +impl LuaUserData for FileHandle { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("read", |lua, this: &FileHandle, mode: String| { + let content = this.read()?; + Ok(lua.to_value(&match ReadMode::from_str(&mode).unwrap() { + ReadMode::Line => StringOrNumber::String( + content + .lines() + .next() + .map_or_else(String::new, |slice| slice.trim().to_owned()), + ), + ReadMode::Number => StringOrNumber::Number( + content.trim().parse::<u64>().map_err(LuaError::external)?, + ), + ReadMode::All => StringOrNumber::String(content), + })) + }); + methods.add_method("write", |_, this: &FileHandle, content: String| { + this.write(content.as_bytes()) + }); + methods.add_method("lines", |_, this: &FileHandle, (): ()| { + Ok(this + .read()? + .lines() + .map(ToOwned::to_owned) + .collect::<Vec<String>>()) + }); + methods.add_method("rewind", |_, this: &FileHandle, (): ()| this.rewind()); + } +} + +impl FileHandle { + pub fn new(_: &Lua, path: String) -> LuaResult<Self> { + Ok(Self(Rc::new(RefCell::new(File::open(path)?)))) + // Ok(Self(Rc::new(RefCell::new(OpenOptions::new().write(true).read(true).open(path)?)))) + } + + fn read(&self) -> LuaResult<String> { + let mut content = String::new(); + self.0.borrow_mut().read_to_string(&mut content)?; + Ok(content) + } + + fn rewind(&self) -> LuaResult<()> { + self.0.borrow_mut().rewind().map_err(LuaError::external) + } + + fn write(&self, buf: &[u8]) -> LuaResult<usize> { + self.0.borrow_mut().write(buf).map_err(LuaError::external) + } +} |