use crate::rfs::{
get_mount_info, list_contents, list_mounts, pack_directory, unmount, unmount_all, unpack,
verify, MountType, RfsBuilder, StoreSpec,
};
use rhai::{Array, Engine, EvalAltResult, Map};
pub fn register_rfs_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
engine.register_fn("rfs_mount", rfs_mount);
engine.register_fn("rfs_unmount", rfs_unmount);
engine.register_fn("rfs_list_mounts", rfs_list_mounts);
engine.register_fn("rfs_unmount_all", rfs_unmount_all);
engine.register_fn("rfs_get_mount_info", rfs_get_mount_info);
engine.register_fn("rfs_pack", rfs_pack);
engine.register_fn("rfs_unpack", rfs_unpack);
engine.register_fn("rfs_list_contents", rfs_list_contents);
engine.register_fn("rfs_verify", rfs_verify);
Ok(())
}
fn rfs_mount(
source: &str,
target: &str,
mount_type: &str,
options: Map,
) -> Result<Map, Box<EvalAltResult>> {
let mount_type_enum = MountType::from_string(mount_type);
let mut builder = RfsBuilder::new(source, target, mount_type_enum);
for (key, value) in options.iter() {
if let Ok(value_str) = value.clone().into_string() {
builder = builder.with_option(key, &value_str);
}
}
let mount = builder.mount().map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to mount filesystem: {}", e).into(),
rhai::Position::NONE,
))
})?;
let mut result = Map::new();
result.insert("id".into(), mount.id.into());
result.insert("source".into(), mount.source.into());
result.insert("target".into(), mount.target.into());
result.insert("fs_type".into(), mount.fs_type.into());
let options_array: Array = mount.options.iter().map(|opt| opt.clone().into()).collect();
result.insert("options".into(), options_array.into());
Ok(result)
}
fn rfs_unmount(target: &str) -> Result<(), Box<EvalAltResult>> {
unmount(target).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to unmount filesystem: {}", e).into(),
rhai::Position::NONE,
))
})
}
fn rfs_list_mounts() -> Result<Array, Box<EvalAltResult>> {
let mounts = list_mounts().map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to list mounts: {}", e).into(),
rhai::Position::NONE,
))
})?;
let mut result = Array::new();
for mount in mounts {
let mut mount_map = Map::new();
mount_map.insert("id".into(), mount.id.into());
mount_map.insert("source".into(), mount.source.into());
mount_map.insert("target".into(), mount.target.into());
mount_map.insert("fs_type".into(), mount.fs_type.into());
let options_array: Array = mount.options.iter().map(|opt| opt.clone().into()).collect();
mount_map.insert("options".into(), options_array.into());
result.push(mount_map.into());
}
Ok(result)
}
fn rfs_unmount_all() -> Result<(), Box<EvalAltResult>> {
unmount_all().map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to unmount all filesystems: {}", e).into(),
rhai::Position::NONE,
))
})
}
fn rfs_get_mount_info(target: &str) -> Result<Map, Box<EvalAltResult>> {
let mount = get_mount_info(target).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to get mount info: {}", e).into(),
rhai::Position::NONE,
))
})?;
let mut result = Map::new();
result.insert("id".into(), mount.id.into());
result.insert("source".into(), mount.source.into());
result.insert("target".into(), mount.target.into());
result.insert("fs_type".into(), mount.fs_type.into());
let options_array: Array = mount.options.iter().map(|opt| opt.clone().into()).collect();
result.insert("options".into(), options_array.into());
Ok(result)
}
fn rfs_pack(directory: &str, output: &str, store_specs: &str) -> Result<(), Box<EvalAltResult>> {
let specs = parse_store_specs(store_specs);
pack_directory(directory, output, &specs).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to pack directory: {}", e).into(),
rhai::Position::NONE,
))
})
}
fn rfs_unpack(input: &str, directory: &str) -> Result<(), Box<EvalAltResult>> {
unpack(input, directory).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to unpack filesystem layer: {}", e).into(),
rhai::Position::NONE,
))
})
}
fn rfs_list_contents(input: &str) -> Result<String, Box<EvalAltResult>> {
list_contents(input).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to list contents: {}", e).into(),
rhai::Position::NONE,
))
})
}
fn rfs_verify(input: &str) -> Result<bool, Box<EvalAltResult>> {
verify(input).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Failed to verify filesystem layer: {}", e).into(),
rhai::Position::NONE,
))
})
}
fn parse_store_specs(specs_str: &str) -> Vec<StoreSpec> {
let mut result = Vec::new();
for spec_str in specs_str.split(',') {
if spec_str.trim().is_empty() {
continue;
}
let parts: Vec<&str> = spec_str.split(':').collect();
if parts.is_empty() {
continue;
}
let spec_type = parts[0].trim();
let mut store_spec = StoreSpec::new(spec_type);
if parts.len() > 1 {
let options_str = parts[1];
for option in options_str.split(',') {
let option_parts: Vec<&str> = option.split('=').collect();
if option_parts.len() == 2 {
store_spec =
store_spec.with_option(option_parts[0].trim(), option_parts[1].trim());
}
}
}
result.push(store_spec);
}
result
}