Krys4lide/crates/fsv-sys/src/lib.rs

131 lines
4.5 KiB
Rust
Raw Normal View History

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
pub mod BINDINGS {
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
// We need to keep the this use statement to get `ssv_function` macro working well
use BINDINGS::*;
/// Macro to generate a function that implements a call to an external function in BINDINGS
macro_rules! ssv_function {
($binding:ty, $func_name:ident, {$($arg_name:ident: $arg_type:ty),*}) => {
/// # Safety
/// This function is unsafe because it calls an external function through FFI.
/// The caller must ensure that the provided arguments are valid and that the
/// external function is safe to call.
pub unsafe fn $func_name(&self, $($arg_name: $arg_type),*) -> Result<u16, Error> {
let func_struct: libloading::Symbol<'_, $binding> =
unsafe { self.library.get(stringify!($binding).as_bytes())? };
let func = match *func_struct {
Some(func) => func,
None => return Err(Error::SymbolMissing(stringify!($binding))),
};
Ok(func($($arg_name),*))
}
};
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
LibLoading(#[from] libloading::Error),
#[error("Symbol missing: {0}")]
SymbolMissing(&'static str),
}
/// Wrapper around the SESAM-VITALE library
/// This struct is responsible for loading the library and providing an interface to call its functions.
/// The library is loaded at creation and kept in memory until the struct is dropped.
#[derive(Debug)]
pub struct SSVLibrary {
library: libloading::Library,
}
pub fn get_library_path() -> String {
// TODO : Use libloading::library_filename to get platform-specific filename ?
"/opt/santesocial/fsv/1.40.13/lib/libssvlux64.so".to_string()
}
impl SSVLibrary {
pub fn new(library_path: &str) -> Result<Self, Error> {
let library = unsafe { libloading::Library::new(library_path)? };
Ok(SSVLibrary { library })
}
pub fn library(&self) -> &libloading::Library {
&self.library
}
ssv_function!(SSV_InitLIB2, ssv_init_lib2, {
pcFichierSesam: *const i8
});
ssv_function!(SSV_LireConfig, ssv_lire_config, {
pZDataOut: *mut *mut libc::c_void,
psTailleDataOut: *mut usize
});
ssv_function!(SSV_LireCartePS, ssv_lire_carte_ps, {
NomRessourcePS: *const i8,
NomRessourceLecteur: *const i8,
CodePorteurPS: *const i8,
pZDataOut: *mut *mut libc::c_void,
pTailleZone: *mut usize
});
}
#[cfg(test)]
mod test {
use std::{ffi::CString, ptr};
use super::*;
#[test]
fn test_initlib2() {
let library_path = get_library_path();
let ssv_library = SSVLibrary::new(&library_path).expect("SSVLibrary::new failed");
let sesam_ini_str = CString::new("/etc/opt/santesocial/fsv/1.40.13/conf/sesam.ini")
.expect("CString::new failed");
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
assert_eq!(result, 0);
}
#[test]
fn test_lire_config_and_carte_ps() {
let library_path = get_library_path();
let ssv_library = SSVLibrary::new(&library_path).expect("SSVLibrary::new failed");
let sesam_ini_str = CString::new("/etc/opt/santesocial/fsv/1.40.13/conf/sesam.ini")
.expect("CString::new failed");
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
assert_eq!(result, 0);
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut size: libc::size_t = 0;
let result = unsafe { ssv_library.ssv_lire_config(&mut buffer_ptr, &mut size) }.unwrap();
assert_eq!(result, 0);
let nom_ressource_ps = CString::new("Gemalto PC Twin Reader (645D94C3) 00 00")
.expect("CString::new failed");
let nom_ressource_lecteur = CString::new("Gemalto PC Twin Reader (645D94C3) 00 00")
.expect("CString::new failed");
let code_porteur_ps = CString::new("1234").expect("CString::new failed");
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut size: libc::size_t = 0;
let result = unsafe {
ssv_library.ssv_lire_carte_ps(
nom_ressource_ps.as_ptr(),
nom_ressource_lecteur.as_ptr(),
code_porteur_ps.as_ptr(),
&mut buffer_ptr,
&mut size,
)
}.unwrap();
assert_eq!(result, 0);
}
}