use crate::{bindings::*, session::OwnedSession, *};
use libloading::Library;
use std::{borrow::Cow, ffi::OsStr};
pub struct VM {
ptr: pbvm,
lib: Library
}
impl VM {
pub fn new(file_name: impl AsRef<OsStr>) -> Result<VM> {
unsafe {
let lib = Library::new(file_name).map_err(|_| PBXRESULT::E_GET_PBVM_FAILED)?;
let fn_get_vm = lib
.get::<fn(*mut Option<pbvm>) -> PBXRESULT>(b"PB_GetVM\0")
.map_err(|_| PBXRESULT::E_GET_PBVM_FAILED)?;
let mut pvm = None;
let pbxr = fn_get_vm(&mut pvm);
if pbxr.is_err() {
return Err(pbxr);
}
if pvm.is_none() {
return Err(PBXRESULT::E_GET_PBVM_FAILED);
}
Ok(VM {
ptr: pvm.unwrap(),
lib
})
}
}
pub fn new_session<'a>(
&'a self,
applicationName: impl AsPBStr,
libraryList: &[impl AsPBStr]
) -> Result<OwnedSession<'a>> {
if libraryList.is_empty() {
return Err(PBXRESULT::E_INVALID_ARGUMENT);
}
let applicationName = applicationName.as_pbstr();
if applicationName.is_empty() {
return Err(PBXRESULT::E_INVALID_ARGUMENT);
}
unsafe {
let libraryList: Vec<Cow<'_, PBStr>> = libraryList.iter().map(|item| item.as_pbstr()).collect();
let libraryList: Vec<LPCTSTR> = libraryList.iter().map(|item| item.as_ptr()).collect();
let mut session = NonNull::dangling();
let pbxr = ffi::pbvm_CreateSession(
self.ptr,
applicationName.as_ptr(),
libraryList.as_ptr(),
libraryList.len() as pbuint,
&mut session
);
if pbxr.is_ok() {
Ok(OwnedSession::from_ptr(session))
} else {
Err(pbxr)
}
}
}
pub fn run_application<'a>(
&'a self,
applicationName: impl AsPBStr,
libraryList: &[impl AsPBStr],
commandLine: impl AsPBStr
) -> Result<OwnedSession<'a>> {
if libraryList.is_empty() {
return Err(PBXRESULT::E_INVALID_ARGUMENT);
}
let applicationName = applicationName.as_pbstr();
if applicationName.is_empty() {
return Err(PBXRESULT::E_INVALID_ARGUMENT);
}
unsafe {
let libraryList: Vec<Cow<'_, PBStr>> = libraryList.iter().map(|item| item.as_pbstr()).collect();
let libraryList: Vec<LPCTSTR> = libraryList.iter().map(|item| item.as_ptr()).collect();
let mut session = NonNull::dangling();
let pbxr = ffi::pbvm_RunApplication(
self.ptr,
applicationName.as_ptr(),
libraryList.as_ptr(),
libraryList.len() as pbuint,
commandLine.as_pbstr().as_ptr(),
&mut session
);
if pbxr.is_ok() {
Ok(OwnedSession::from_ptr(session))
} else {
Err(pbxr)
}
}
}
}