solder/zend/
module.rs

1use std;
2use std::mem;
3use libc::*;
4
5use super::types::*;
6
7type StartupFunc = extern fn (type_: c_int, module_number: c_int) -> c_int;
8type ShutdownFunc = extern fn (type_: c_int, module_number: c_int) -> c_int;
9type InfoFunc = extern fn () ;
10type GlobalsCtorFunc = extern fn (global: *const c_void) -> c_void;
11type GlobalsDtorFunc = extern fn (global: *const c_void) -> c_void;
12type PostDeactivateFunc = extern fn () -> c_int;
13type HandlerFunc = extern fn (execute_data: &ExecuteData, retval: &mut Zval);
14
15#[repr(C)]
16pub struct ArgInfo {
17	name: *const c_char,
18	class_name: *const c_char,
19	type_hint: c_char,
20	pass_by_reference: c_char,
21	allow_null: c_char,
22	is_variadic: c_char,
23}
24
25/// Information about the arguments of a function
26impl ArgInfo {
27	pub fn new(name: *const c_char, allow_null: c_char, is_variadic: c_char, by_reference: c_char) -> ArgInfo {
28		ArgInfo {
29			name: name,
30			class_name: std::ptr::null(),
31			type_hint: 0,
32			pass_by_reference: by_reference,
33			allow_null: allow_null,
34			is_variadic: is_variadic,
35		}
36	}
37}
38
39/// Struct with the functions that will be available inside PHP
40#[repr(C)]
41pub struct Function {
42	fname: *const c_char,
43	handler: Option<HandlerFunc>,
44	arg_info: *const ArgInfo,
45	num_args: u32,
46	flags: u32,
47}
48
49impl Function {
50	pub fn end() -> Function {
51		Function {
52			fname: std::ptr::null(),
53			handler: None,
54			arg_info: std::ptr::null(),
55			num_args: 0,
56			flags: 0,
57		}
58	}
59}
60
61pub struct FunctionBuilder {
62	function: Function,
63	args: Vec<ArgInfo>,
64}
65
66impl FunctionBuilder {
67	/// Create a function with name
68	pub fn new(name: *const c_char, handler: HandlerFunc) -> Self {
69		FunctionBuilder {
70			function: Function {
71				fname: name,
72				handler: Some(handler),
73				arg_info: std::ptr::null(),
74				num_args: 0,
75				flags: 0,
76			},
77			args: Vec::new(),
78		}
79	}
80
81	/// Add an argument to the function
82	pub fn with_arg(mut self, arg: ArgInfo) -> Self {
83		self.args.push(arg);
84		self
85	}
86
87	/// Build the function
88	pub fn build(mut self)-> Function {
89		if self.args.is_empty() {
90			return self.function;
91		}
92		self.function.num_args = self.args.len() as u32 - 1;
93		self.function.arg_info = Box::into_raw(self.args.into_boxed_slice()) as *mut ArgInfo;
94		self.function
95	}
96}
97
98pub struct INI {}
99
100/// Module represents your extension
101#[repr(C)]
102pub struct Module {
103	size: c_ushort,
104	zend_api: c_uint,
105	zend_debug: c_uchar,
106	zts: c_uchar,
107	ini_entry: *const INI,
108	deps: *const ModuleDep,
109	name: *const c_char,
110	functions: *const Function,
111	module_startup_func: Option<StartupFunc>,
112	module_shutdown_func: Option<ShutdownFunc>,
113	request_startup_func: Option<StartupFunc>,
114	request_shutdown_func: Option<ShutdownFunc>,
115	info_func: Option<InfoFunc>,
116	version: *const c_char,
117	globals_size: size_t,
118	globals_ptr: *const c_void,
119	globals_ctor: Option<GlobalsCtorFunc>,
120	globals_dtor: Option<GlobalsDtorFunc>,
121	post_deactivate_func: Option<PostDeactivateFunc>,
122	module_started: c_int,
123	type_: c_uchar,
124	handle: *const c_void,
125	module_number: c_int,
126	build_id: *const c_char,
127}
128
129impl Module {
130	pub fn into_raw(self) -> *mut Self {
131		Box::into_raw(Box::new(self))
132	}
133}
134
135pub struct ModuleBuilder {
136	module: Module,
137	functions: Vec<Function>,
138}
139
140impl ModuleBuilder {
141	/// Create a module with name and version
142	pub fn new(name: *const c_char, version: *const c_char) -> ModuleBuilder {
143		ModuleBuilder {
144			module: Module {
145				size: mem::size_of::<Module>() as u16,
146				zend_api: env!("PHP_API_VERSION").parse::<u32>().unwrap(),
147				zend_debug: 0,
148				zts: 0,
149				ini_entry: std::ptr::null(),
150				deps: std::ptr::null(),
151				name: name,
152				functions: std::ptr::null(),
153				module_startup_func: None,
154				module_shutdown_func: None,
155				request_startup_func: None,
156				request_shutdown_func: None,
157				info_func: None,
158				version: version,
159				globals_size: 0,
160				globals_ptr: std::ptr::null(),
161				globals_ctor: None,
162				globals_dtor: None,
163				post_deactivate_func: None,
164				module_started: 0,
165				type_: 0,
166				handle: std::ptr::null(),
167				module_number: 0,
168				build_id: c_str!(env!("PHP_EXTENSION_BUILD")),
169			},
170			functions: Vec::new(),
171		}
172	}
173
174	/// Set a startup function
175	pub fn with_startup_function(mut self, func: StartupFunc) -> Self {
176		self.module.module_startup_func = Some(func);
177		self
178	}
179
180	/// Set a shutdown function
181	pub fn with_shutdown_function(mut self, func: ShutdownFunc) -> Self {
182		self.module.module_shutdown_func = Some(func);
183		self
184	}
185
186	/// Set a function to print information in PHP Info
187	pub fn with_info_function(mut self, func: InfoFunc) -> Self {
188		self.module.info_func = Some(func);
189		self
190	}
191
192	/// Set functions that will be available from PHP.
193	pub fn with_function(mut self, function: Function) -> Self {
194		self.functions.push(function);
195		self
196	}
197
198	pub fn build(mut self) -> Module {
199		self.functions.push(Function::end());
200		self.module.functions = Box::into_raw(self.functions.into_boxed_slice()) as *const Function;
201		self.module
202	}
203}
204
205unsafe impl Sync for Module {}