mirror of
https://github.com/danog/ext-php-rs.git
synced 2024-11-30 04:39:04 +01:00
Added argument overloading (#8)
* Added argument overloading If a double is requested but a long is available, we can cast the long into a double. This is required if the user gives an integer into a double field. As well as this, if a string is requested but a long or double is available, we can cast both of these into a string. * Check if zval is present before setting in arg * Added optional argument example * Updated documentation for ZendLong * WIP: added null checks
This commit is contained in:
parent
9fbe186098
commit
0dd1a3f80f
@ -36,16 +36,23 @@ pub extern "C" fn get_module() -> *mut php_rs::php::module::ModuleEntry {
|
||||
pub extern "C" fn skeleton_version(execute_data: *mut ExecutionData, _retval: *mut Zval) {
|
||||
let mut x = Arg::new("x", DataType::Long);
|
||||
let mut y = Arg::new("y", DataType::Double);
|
||||
let mut z = Arg::new("z", DataType::Double);
|
||||
|
||||
let result = ArgParser::new(execute_data).arg(&mut x).arg(&mut y).parse();
|
||||
let result = ArgParser::new(execute_data)
|
||||
.arg(&mut x)
|
||||
.arg(&mut y)
|
||||
.not_required()
|
||||
.arg(&mut z)
|
||||
.parse();
|
||||
|
||||
if let Err(_) = result {
|
||||
return;
|
||||
}
|
||||
|
||||
println!(
|
||||
"x: {}, y: {}",
|
||||
"x: {}, y: {}, z: {}",
|
||||
x.val::<ZendLong>().unwrap_or_default(),
|
||||
y.val::<f64>().unwrap_or_default()
|
||||
y.val::<f64>().unwrap_or_default(),
|
||||
z.val::<f64>().unwrap_or_default()
|
||||
);
|
||||
}
|
||||
|
@ -1,8 +1,18 @@
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
convert::{TryFrom, TryInto},
|
||||
};
|
||||
|
||||
use super::{enums::DataType, execution_data::ExecutionData, zval::Zval};
|
||||
|
||||
use crate::bindings::{zend_internal_arg_info, zend_wrong_parameters_count_error};
|
||||
use crate::bindings::{
|
||||
_zend_expected_type, _zend_expected_type_Z_EXPECTED_ARRAY, _zend_expected_type_Z_EXPECTED_BOOL,
|
||||
_zend_expected_type_Z_EXPECTED_DOUBLE, _zend_expected_type_Z_EXPECTED_LONG,
|
||||
_zend_expected_type_Z_EXPECTED_OBJECT, _zend_expected_type_Z_EXPECTED_RESOURCE,
|
||||
_zend_expected_type_Z_EXPECTED_STRING, zend_internal_arg_info, zend_wrong_parameter_error,
|
||||
zend_wrong_parameters_count_error, ZPP_ERROR_WRONG_CLASS_OR_NULL,
|
||||
};
|
||||
use crate::functions::c_str;
|
||||
|
||||
/// Represents an argument to a function.
|
||||
pub struct Arg<'a> {
|
||||
@ -73,6 +83,27 @@ impl<'a> Arg<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Arg<'_>> for _zend_expected_type {
|
||||
fn from(arg: Arg) -> Self {
|
||||
let err = match arg._type {
|
||||
DataType::False | DataType::True => _zend_expected_type_Z_EXPECTED_BOOL,
|
||||
DataType::Long => _zend_expected_type_Z_EXPECTED_LONG,
|
||||
DataType::Double => _zend_expected_type_Z_EXPECTED_DOUBLE,
|
||||
DataType::String => _zend_expected_type_Z_EXPECTED_STRING,
|
||||
DataType::Array => _zend_expected_type_Z_EXPECTED_ARRAY,
|
||||
DataType::Object => _zend_expected_type_Z_EXPECTED_OBJECT,
|
||||
DataType::Resource => _zend_expected_type_Z_EXPECTED_RESOURCE,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if arg.allow_null {
|
||||
err + 1
|
||||
} else {
|
||||
err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal argument information used by Zend.
|
||||
pub type ArgInfo = zend_internal_arg_info;
|
||||
|
||||
@ -142,7 +173,26 @@ impl<'a, 'b> ArgParser<'a, 'b> {
|
||||
|
||||
for (i, arg) in self.args.iter_mut().enumerate() {
|
||||
let zval = unsafe { execute_data.zend_call_arg(i) };
|
||||
arg.zval = Some(zval.unwrap());
|
||||
|
||||
if let Some(zval) = zval {
|
||||
// if !arg.allow_null && zval.is_null() {
|
||||
// unsafe {
|
||||
// zend_wrong_parameter_error(
|
||||
// ZPP_ERROR_WRONG_CLASS_OR_NULL as i32,
|
||||
// i as u32,
|
||||
// c_str(arg.name) as *mut i8,
|
||||
// _zend_expected_type::from(**arg),
|
||||
// &mut *zval,
|
||||
// );
|
||||
// }
|
||||
// return Err(format!(
|
||||
// "Argument at index {} was null but is non-nullable.",
|
||||
// i
|
||||
// ));
|
||||
// }
|
||||
|
||||
arg.zval = Some(zval);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -9,6 +9,7 @@ use super::types::ZendLong;
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum DataType {
|
||||
Undef = IS_UNDEF as isize,
|
||||
|
||||
Null = IS_NULL as isize,
|
||||
False = IS_FALSE as isize,
|
||||
True = IS_TRUE as isize,
|
||||
@ -19,8 +20,8 @@ pub enum DataType {
|
||||
Object = IS_OBJECT as isize,
|
||||
Resource = IS_RESOURCE as isize,
|
||||
Reference = IS_REFERENCE as isize,
|
||||
ConstantExpression = IS_CONSTANT_AST as isize,
|
||||
|
||||
ConstantExpression = IS_CONSTANT_AST as isize,
|
||||
Void = IS_VOID as isize,
|
||||
}
|
||||
|
||||
|
@ -86,4 +86,6 @@ impl ZendType {
|
||||
}
|
||||
|
||||
/// Internal identifier used for a long.
|
||||
/// The size depends on the system architecture. On 32-bit systems,
|
||||
/// a ZendLong is 32-bits, while on a 64-bit system it is 64-bits.
|
||||
pub type ZendLong = zend_long;
|
||||
|
@ -33,6 +33,8 @@ impl Zval {
|
||||
pub fn double(&self) -> Option<f64> {
|
||||
if self.is_double() {
|
||||
Some(unsafe { self.value.dval })
|
||||
} else if let Some(long) = self.long() {
|
||||
Some(long as f64)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -53,6 +55,8 @@ impl Zval {
|
||||
|
||||
Some(_str.to_string())
|
||||
}
|
||||
} else if let Some(double) = self.double() {
|
||||
Some(double.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user