use anyhow::{anyhow, bail};
use rhai::{Dynamic, Engine, Scope};
use std::env;
use std::path::Path;
pub fn find_by(
patch_dir: &Path,
path: &Path,
content: &str,
start_pos: Option<usize>,
end_pos: Option<usize>,
) -> anyhow::Result<(usize, usize, bool)> {
let patch_path = patch_dir.to_path_buf().join(path);
if !patch_path.is_file() {
bail!("Rhai script path ({:?}) has to be a file.", patch_path)
}
let engine = Engine::new();
let rev = env::current_dir()?;
env::set_current_dir(patch_dir)?;
let script_content = std::fs::read_to_string(patch_path)?;
let ast = engine.compile(&script_content)?;
let result: Dynamic = engine
.call_fn(
&mut Scope::new(),
&ast,
"find",
(
content.to_owned(),
start_pos.unwrap_or(0),
end_pos.unwrap_or(content.len()),
),
)
.map_err(|e| anyhow!("Call function error: {}", e))?;
let result_array = result
.into_array()
.map_err(|e| anyhow!("Convert into array error: {}", e))?;
if result_array.len() != 3 {
bail!("Expected 3 values from find function");
}
let start = result_array[0]
.clone()
.try_cast::<usize>()
.ok_or(anyhow!("Cast into `Option<usize>` error"))?;
let end = result_array[1]
.clone()
.try_cast::<usize>()
.ok_or(anyhow!("Cast into `Option<usize>` error"))?;
let found = result_array[2]
.clone()
.try_cast::<bool>()
.ok_or(anyhow!("Cast into `Option<usize>` error"))?;
env::set_current_dir(rev)?;
Ok((start, end, found))
}
pub fn replace_by(patch_dir: &Path, path: &Path, content: &str) -> anyhow::Result<String> {
let patch_path = patch_dir.to_path_buf().join(path);
if !patch_path.is_file() {
bail!("Rhai script path ({:?}) has to be a file.", patch_path)
}
let engine = Engine::new();
let rev = env::current_dir()?;
env::set_current_dir(patch_dir)?;
let script_content = std::fs::read_to_string(patch_path)?;
let ast = engine.compile(&script_content)?;
let result: Dynamic = engine
.call_fn(&mut Scope::new(), &ast, "replace", (content.to_owned(),))
.map_err(|e| anyhow!("Call function error: {}", e))?;
let result_str = result
.into_string()
.map_err(|e| anyhow!("Convert into string error: {}", e))?;
env::set_current_dir(rev)?;
Ok(result_str)
}
pub fn decode_by(patch_dir: &Path, path: &Path, content: &[u8]) -> anyhow::Result<String> {
let patch_path = patch_dir.to_path_buf().join(path);
if !patch_path.is_file() {
bail!("Rhai script path ({:?}) has to be a file.", patch_path)
}
let engine = Engine::new();
let rev = env::current_dir()?;
env::set_current_dir(patch_dir)?;
let script_content = std::fs::read_to_string(patch_path)?;
let ast = engine.compile(&script_content)?;
let result: Dynamic = engine
.call_fn(&mut Scope::new(), &ast, "decode", (content.to_owned(),))
.map_err(|e| anyhow!("Call function error: {}", e))?;
let result_str = result
.into_string()
.map_err(|e| anyhow!("Convert into string error: {}", e))?;
env::set_current_dir(rev)?;
Ok(result_str)
}
pub fn encode_by(patch_dir: &Path, path: &Path, content: &str) -> anyhow::Result<Vec<u8>> {
let patch_path = patch_dir.to_path_buf().join(path);
if !patch_path.is_file() {
bail!("Rhai script path ({:?}) has to be a file.", patch_path)
}
let engine = Engine::new();
let rev = env::current_dir()?;
env::set_current_dir(patch_dir)?;
let script_content = std::fs::read_to_string(patch_path)?;
let ast = engine.compile(&script_content)?;
let result: Dynamic = engine
.call_fn(&mut Scope::new(), &ast, "encode", (content.to_owned(),))
.map_err(|e| anyhow!("Call function error: {}", e))?;
let result_vec = result
.into_typed_array::<u8>()
.map_err(|e| anyhow!("Convert into `Vec<u8>` error: {}", e))?;
env::set_current_dir(rev)?;
Ok(result_vec)
}