use crate::{
error::Result,
ffi::{ext_php_rs_php_build_id, ZEND_MODULE_API_NO},
zend::{FunctionEntry, ModuleEntry},
PHP_DEBUG, PHP_ZTS,
};
use std::{ffi::CString, mem, ptr};
#[derive(Debug, Clone)]
pub struct ModuleBuilder {
name: String,
version: String,
module: ModuleEntry,
functions: Vec<FunctionEntry>,
}
impl ModuleBuilder {
pub fn new<T: Into<String>, U: Into<String>>(name: T, version: U) -> Self {
Self {
name: name.into(),
version: version.into(),
module: ModuleEntry {
size: mem::size_of::<ModuleEntry>() as u16,
zend_api: ZEND_MODULE_API_NO,
zend_debug: u8::from(PHP_DEBUG),
zts: u8::from(PHP_ZTS),
ini_entry: ptr::null(),
deps: ptr::null(),
name: ptr::null(),
functions: ptr::null(),
module_startup_func: None,
module_shutdown_func: None,
request_startup_func: None,
request_shutdown_func: None,
info_func: None,
version: ptr::null(),
globals_size: 0,
#[cfg(not(php_zts))]
globals_ptr: ptr::null_mut(),
#[cfg(php_zts)]
globals_id_ptr: ptr::null_mut(),
globals_ctor: None,
globals_dtor: None,
post_deactivate_func: None,
module_started: 0,
type_: 0,
handle: ptr::null_mut(),
module_number: 0,
build_id: unsafe { ext_php_rs_php_build_id() },
},
functions: vec![],
}
}
pub fn startup_function(mut self, func: StartupShutdownFunc) -> Self {
self.module.module_startup_func = Some(func);
self
}
pub fn shutdown_function(mut self, func: StartupShutdownFunc) -> Self {
self.module.module_shutdown_func = Some(func);
self
}
pub fn request_startup_function(mut self, func: StartupShutdownFunc) -> Self {
self.module.request_startup_func = Some(func);
self
}
pub fn request_shutdown_function(mut self, func: StartupShutdownFunc) -> Self {
self.module.request_shutdown_func = Some(func);
self
}
pub fn post_deactivate_function(mut self, func: extern "C" fn() -> i32) -> Self {
self.module.post_deactivate_func = Some(func);
self
}
pub fn info_function(mut self, func: InfoFunc) -> Self {
self.module.info_func = Some(func);
self
}
pub fn function(mut self, func: FunctionEntry) -> Self {
self.functions.push(func);
self
}
pub fn build(mut self) -> Result<ModuleEntry> {
self.functions.push(FunctionEntry::end());
self.module.functions =
Box::into_raw(self.functions.into_boxed_slice()) as *const FunctionEntry;
self.module.name = CString::new(self.name)?.into_raw();
self.module.version = CString::new(self.version)?.into_raw();
Ok(self.module)
}
}
pub type StartupShutdownFunc = extern "C" fn(_type: i32, _module_number: i32) -> i32;
pub type InfoFunc = extern "C" fn(zend_module: *mut ModuleEntry);