diff --git a/build.rs b/build.rs index d1b3d4c..4bb8a93 100644 --- a/build.rs +++ b/build.rs @@ -3,7 +3,7 @@ use system_deps; fn main() { let deps = system_deps::Config::new().probe().unwrap(); - cxx_build::bridge("src/mgr.rs") + cxx_build::bridge("src/cxx/mod.rs") .file("src/cxx/mgr.cc") .includes(deps.all_include_paths()) .cpp_link_stdlib("stdc++") diff --git a/src/cxx/mod.rs b/src/cxx/mod.rs new file mode 100644 index 0000000..26e18da --- /dev/null +++ b/src/cxx/mod.rs @@ -0,0 +1,70 @@ +#[cxx::bridge] +pub mod ffi { + unsafe extern "C++" { + include!("sword_rs/src/cxx/mgr.h"); + include!("sword_rs/src/cxx/module.h"); + + type Mgr; + type Module; + + fn new_mgr() -> UniquePtr; + fn new_mgr_with_path(path: &String) -> UniquePtr; + fn get_modules(self: &Mgr) -> Vec; + fn get_module(self: Pin<&mut Mgr>, name: &String) -> UniquePtr; + + fn get_name(self: &Module) -> String; + fn strip_text(self: Pin<&mut Module>) -> String; + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs::{create_dir, File}; + use std::io::Write; + use tempfile; + + #[test] + fn can_create_mgr() { + let mgr = ffi::new_mgr(); + assert!(!mgr.is_null()); + } + + #[test] + fn reads_module_list() { + // Create a temporary directory to isolate tests + let dir = tempfile::tempdir().unwrap(); + // Create a basic SWORD directory + let mods_d = dir.path().join("mods.d"); + create_dir(&mods_d).unwrap(); + // Write a dummy conf file + let kjv_conf = mods_d.join("kjv.conf"); + { + let mut file = File::create(&kjv_conf).unwrap(); + writeln!(file, "[KJVdummy]").unwrap(); + writeln!(file, "DataPath=./modules/texts/ztext/kjv").unwrap(); + writeln!(file, "ModDrv=RawText").unwrap(); + writeln!(file, "Description=Test description").unwrap(); + writeln!(file, "About=A test conf file").unwrap(); + } + let mut mgr = ffi::new_mgr_with_path(&dir.path().to_str().unwrap().to_string()); + assert!(mgr.get_modules().len() == 1); + assert!(mgr.get_modules().contains(&String::from("KJVdummy"))); + + let mut module = mgr.pin_mut().get_module(&String::from("KJVdummy")); + assert!(module.pin_mut().get_name() == "KJVdummy"); + } + + #[test] + fn has_no_modules() { + let mgr = ffi::new_mgr_with_path( + &tempfile::tempdir() + .unwrap() + .path() + .to_str() + .unwrap() + .to_string(), + ); + assert!(mgr.get_modules().len() == 0); + } +} diff --git a/src/lib.rs b/src/lib.rs index 7983903..e39426e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,3 @@ +mod cxx; pub mod mgr; +mod module; diff --git a/src/main.rs b/src/main.rs index a2077b8..e02de51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,10 @@ -use sword_rs::mgr::{new_mgr, Mgr}; +use sword_rs::mgr::Mgr; fn main() { - let mgr = new_mgr(); - println!("{:?}", mgr.get_modules()); + let mut mgr = Mgr::new(); + for mod_name in mgr.get_modules() { + let mut module = mgr.get_module(&mod_name); + println!("Module: {}", module.get_name()); + println!("Text: {}", module.strip_text()); + } } diff --git a/src/mgr.rs b/src/mgr.rs index 4a21028..e83ec7f 100644 --- a/src/mgr.rs +++ b/src/mgr.rs @@ -1,72 +1,29 @@ -pub use ffi::*; +use crate::cxx::ffi; +use crate::module::Module; +use cxx::UniquePtr; -#[cxx::bridge] -mod ffi { - unsafe extern "C++" { - include!("sword_rs/src/cxx/mgr.h"); - include!("sword_rs/src/cxx/module.h"); - - type Mgr; - type Module; - - fn new_mgr() -> UniquePtr; - fn new_mgr_with_path(path: &String) -> UniquePtr; - fn get_modules(self: &Mgr) -> Vec; - fn get_module(self: Pin<&mut Mgr>, name: &String) -> UniquePtr; - - fn get_name(self: &Module) -> String; - fn strip_text(self: Pin<&mut Module>) -> String; - } +pub struct Mgr { + mgr: UniquePtr, } -#[cfg(test)] -mod tests { - use super::*; - use std::fs::{create_dir, File}; - use std::io::Write; - use tempfile; - - #[test] - fn can_create_mgr() { - let mgr = ffi::new_mgr(); - assert!(!mgr.is_null()); - } - - #[test] - fn reads_module_list() { - // Create a temporary directory to isolate tests - let dir = tempfile::tempdir().unwrap(); - // Create a basic SWORD directory - let mods_d = dir.path().join("mods.d"); - create_dir(&mods_d).unwrap(); - // Write a dummy conf file - let kjv_conf = mods_d.join("kjv.conf"); - { - let mut file = File::create(&kjv_conf).unwrap(); - writeln!(file, "[KJVdummy]").unwrap(); - writeln!(file, "DataPath=./modules/texts/ztext/kjv").unwrap(); - writeln!(file, "ModDrv=RawText").unwrap(); - writeln!(file, "Description=Test description").unwrap(); - writeln!(file, "About=A test conf file").unwrap(); +impl Mgr { + pub fn new() -> Self { + Self { + mgr: ffi::new_mgr(), } - let mut mgr = ffi::new_mgr_with_path(&dir.path().to_str().unwrap().to_string()); - assert!(mgr.get_modules().len() == 1); - assert!(mgr.get_modules().contains(&String::from("KJVdummy"))); - - let mut module = mgr.pin_mut().get_module(&String::from("KJVdummy")); - assert!(module.pin_mut().get_name() == "KJVdummy"); } - #[test] - fn has_no_modules() { - let mgr = ffi::new_mgr_with_path( - &tempfile::tempdir() - .unwrap() - .path() - .to_str() - .unwrap() - .to_string(), - ); - assert!(mgr.get_modules().len() == 0); + pub fn new_with_path(path: &String) -> Self { + Self { + mgr: ffi::new_mgr_with_path(path), + } + } + + pub fn get_modules(&self) -> Vec { + self.mgr.get_modules() + } + + pub fn get_module(&mut self, mod_name: &String) -> Module { + Module::new(self.mgr.pin_mut().get_module(mod_name)) } } diff --git a/src/module.rs b/src/module.rs new file mode 100644 index 0000000..1f46705 --- /dev/null +++ b/src/module.rs @@ -0,0 +1,20 @@ +use crate::cxx::ffi; +use cxx::UniquePtr; + +pub struct Module { + module: UniquePtr, +} + +impl Module { + pub fn new(module: UniquePtr) -> Self { + Self { module: module } + } + + pub fn get_name(&self) -> String { + self.module.get_name() + } + + pub fn strip_text(&mut self) -> String { + self.module.pin_mut().strip_text() + } +}