Remove lifetime from PhpException (#80)

* Remove lifetime from `PhpException`

All class entries are effectively static (module start to module end) so
it's just a hassle carrying the lifetime everywhere.

* Removed forgotten lifetimes

* Implement `IntoZval` for `Result<T, E>`

Fixes function return error with `PhpResult` as the return type

* Updated changelog
This commit is contained in:
David 2021-09-28 02:23:13 +13:00 committed by GitHub
parent 1e41b50100
commit daef57ba91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 48 additions and 75 deletions

View File

@ -1,5 +1,10 @@
# Changelog
- `PhpException` no longer requires a lifetime [#80].
- Added `PhpException` and `PhpResult` to prelude [#80].
[#80]: https://github.com/davidcole1340/ext-php-rs/pull/80
## Version 0.5.0
### Breaking changes

View File

@ -60,7 +60,6 @@ pub fn parser(args: AttributeArgs, input: ItemFn) -> Result<(TokenStream, Functi
let arg_parser = build_arg_parser(args.iter(), &optional)?;
let arg_accessors = build_arg_accessors(&args);
let return_handler = build_return_handler(output);
let return_type = get_return_type(output)?;
let func = quote! {
@ -75,7 +74,10 @@ pub fn parser(args: AttributeArgs, input: ItemFn) -> Result<(TokenStream, Functi
let result = #ident(#(#arg_accessors, )*);
#return_handler
if let Err(e) = result.set_zval(retval, false) {
let e: ::ext_php_rs::php::exceptions::PhpException = e.into();
e.throw().expect("Failed to throw exception");
}
}
};
@ -202,61 +204,6 @@ fn build_arg_accessors(args: &[Arg]) -> Vec<TokenStream> {
args.iter().map(|arg| arg.get_accessor()).collect()
}
pub fn build_return_handler(output_type: &ReturnType) -> TokenStream {
let handler = match output_type {
ReturnType::Default => Some(quote! { retval.set_null(); }),
ReturnType::Type(_, ref ty) => match **ty {
Type::Path(ref path) => match path.path.segments.last() {
Some(path_seg) => match path_seg.ident.to_string().as_ref() {
"Result" => Some(quote! {
match result {
Ok(result) => match result.set_zval(retval, false) {
Ok(_) => {}
Err(e) => {
let e: ::ext_php_rs::php::exceptions::PhpException = e.into();
e.throw().expect("Failed to throw exception: Failed to set return value.");
},
},
Err(e) => {
let e: ::ext_php_rs::php::exceptions::PhpException = e.into();
e.throw().expect("Failed to throw exception: Error type returned from internal function.");
}
};
}),
"Option" => Some(quote! {
match result {
Some(result) => match result.set_zval(retval, false) {
Ok(_) => {}
Err(e) => {
let e: ::ext_php_rs::php::exceptions::PhpException = e.into();
e.throw().expect("Failed to throw exception: Failed to set return value.");
},
},
None => retval.set_null(),
};
}),
_ => None,
},
_ => None,
},
_ => None,
},
};
match handler {
Some(handler) => handler,
None => quote! {
match result.set_zval(retval, false) {
Ok(_) => {},
Err(e) => {
let e: ::ext_php_rs::php::exceptions::PhpException = e.into();
e.throw().expect("Failed to throw exception: Failed to set return value.");
}
}
},
}
}
pub fn get_return_type(output_type: &ReturnType) -> Result<Option<(String, bool)>> {
Ok(match output_type {
ReturnType::Default => None,

View File

@ -114,7 +114,6 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
let (arg_definitions, is_static) = build_arg_definitions(&args);
let arg_parser = build_arg_parser(args.iter(), &optional)?;
let arg_accessors = build_arg_accessors(&args);
let return_handler = function::build_return_handler(output);
let this = if is_static {
quote! { Self:: }
} else {
@ -133,7 +132,10 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
let result = #this #ident(#(#arg_accessors, )*);
#return_handler
if let Err(e) = result.set_zval(retval, false) {
let e: ::ext_php_rs::php::exceptions::PhpException = e.into();
e.throw().expect("Failed to throw exception");
}
}
};

View File

@ -75,7 +75,7 @@ pub struct RedisException;
// Throw our newly created exception
#[php_function]
pub fn throw_exception() -> Result<i32, PhpException<'static>> {
pub fn throw_exception() -> PhpResult<i32> {
Err(PhpException::from_class::<RedisException>("Not good!".into()))
}
# #[php_module]

View File

@ -95,7 +95,7 @@ impl From<NulError> for Error {
}
}
impl<'a> From<Error> for PhpException<'a> {
impl From<Error> for PhpException {
fn from(err: Error) -> Self {
Self::default(err.to_string())
}

View File

@ -398,7 +398,7 @@ pub use ext_php_rs_derive::php_module;
/// pub struct Example;
///
/// #[php_function]
/// pub fn throw_exception() -> Result<i32, PhpException<'static>> {
/// pub fn throw_exception() -> Result<i32, PhpException> {
/// Err(PhpException::from_class::<Example>("Bad things happen".into()))
/// }
///
@ -439,6 +439,7 @@ pub use ext_php_rs_derive::php_startup;
/// A module typically glob-imported containing the typically required macros and imports.
pub mod prelude {
pub use crate::php::exceptions::{PhpException, PhpResult};
pub use crate::php::module::ModuleBuilder;
pub use crate::php::types::callable::Callable;
#[cfg(any(docs, feature = "closure"))]

View File

@ -15,7 +15,7 @@ use crate::{
};
/// Result type with the error variant as a [`PhpException`].
pub type PhpResult<T = ()> = std::result::Result<T, PhpException<'static>>;
pub type PhpResult<T = ()> = std::result::Result<T, PhpException>;
/// Represents a PHP exception which can be thrown using the `throw()` function. Primarily used to
/// return from a [`Result<T, PhpException>`] which can immediately be thrown by the `ext-php-rs`
@ -25,13 +25,13 @@ pub type PhpResult<T = ()> = std::result::Result<T, PhpException<'static>>;
/// can also be returned from these functions. You can also implement [`From<T>`] for your custom
/// error type.
#[derive(Debug)]
pub struct PhpException<'a> {
pub struct PhpException {
message: String,
code: i32,
ex: &'a ClassEntry,
ex: &'static ClassEntry,
}
impl<'a> PhpException<'a> {
impl PhpException {
/// Creates a new exception instance.
///
/// # Parameters
@ -39,7 +39,7 @@ impl<'a> PhpException<'a> {
/// * `message` - Message to contain in the exception.
/// * `code` - Integer code to go inside the exception.
/// * `ex` - Exception type to throw.
pub fn new(message: String, code: i32, ex: &'a ClassEntry) -> Self {
pub fn new(message: String, code: i32, ex: &'static ClassEntry) -> Self {
Self { message, code, ex }
}
@ -69,13 +69,13 @@ impl<'a> PhpException<'a> {
}
}
impl<'a> From<String> for PhpException<'a> {
impl From<String> for PhpException {
fn from(str: String) -> Self {
Self::default(str)
}
}
impl<'a> From<&str> for PhpException<'a> {
impl From<&str> for PhpException {
fn from(str: &str) -> Self {
Self::default(str.into())
}

View File

@ -26,7 +26,7 @@ use crate::{
php::{
class::ClassEntry,
enums::DataType,
exceptions::PhpException,
exceptions::PhpResult,
flags::ZvalTypeFlags,
types::{array::OwnedHashTable, string::ZendString},
},
@ -649,7 +649,7 @@ impl ZendObjectHandlers {
type_: c_int,
cache_slot: *mut *mut c_void,
rv: *mut Zval,
) -> std::result::Result<*mut Zval, PhpException<'static>> {
) -> PhpResult<*mut Zval> {
let obj = object
.as_ref()
.and_then(|obj| ZendClassObject::<T>::from_zend_obj_ptr(obj))
@ -696,7 +696,7 @@ impl ZendObjectHandlers {
member: *mut zend_string,
value: *mut Zval,
cache_slot: *mut *mut c_void,
) -> std::result::Result<*mut Zval, PhpException<'static>> {
) -> PhpResult<*mut Zval> {
let obj = object
.as_ref()
.and_then(|obj| ZendClassObject::<T>::from_zend_obj_ptr(obj))
@ -734,7 +734,7 @@ impl ZendObjectHandlers {
unsafe fn internal<T: RegisteredClass>(
object: *mut zend_object,
props: &mut HashTable,
) -> std::result::Result<(), PhpException<'static>> {
) -> PhpResult {
let obj = object
.as_ref()
.and_then(|obj| ZendClassObject::<T>::from_zend_obj_ptr(obj))
@ -779,7 +779,7 @@ impl ZendObjectHandlers {
member: *mut zend_string,
has_set_exists: c_int,
cache_slot: *mut *mut c_void,
) -> std::result::Result<c_int, PhpException<'static>> {
) -> PhpResult<c_int> {
let obj = object
.as_ref()
.and_then(|obj| ZendClassObject::<T>::from_zend_obj_ptr(obj))

View File

@ -14,7 +14,7 @@ use crate::{
zend_value, zval, zval_ptr_dtor,
},
errors::{Error, Result},
php::pack::Pack,
php::{exceptions::PhpException, pack::Pack},
};
use crate::php::{
@ -692,6 +692,24 @@ where
}
}
impl<T, E> IntoZval for std::result::Result<T, E>
where
T: IntoZval,
E: Into<PhpException>,
{
const TYPE: DataType = T::TYPE;
fn set_zval(self, zv: &mut Zval, persistent: bool) -> Result<()> {
match self {
Ok(val) => val.set_zval(zv, persistent),
Err(e) => {
let ex: PhpException = e.into();
ex.throw()
}
}
}
}
/// Allows zvals to be converted into Rust types in a fallible way. Reciprocal of the [`IntoZval`]
/// trait.
pub trait FromZval<'a>: Sized {