diff --git a/CHANGELOG.md b/CHANGELOG.md index 938d313..06367a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/ext-php-rs-derive/src/function.rs b/ext-php-rs-derive/src/function.rs index fd3b019..b9fbae6 100644 --- a/ext-php-rs-derive/src/function.rs +++ b/ext-php-rs-derive/src/function.rs @@ -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 { 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> { Ok(match output_type { ReturnType::Default => None, diff --git a/ext-php-rs-derive/src/method.rs b/ext-php-rs-derive/src/method.rs index 79fd1e1..a645a47 100644 --- a/ext-php-rs-derive/src/method.rs +++ b/ext-php-rs-derive/src/method.rs @@ -114,7 +114,6 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result Result Result> { +pub fn throw_exception() -> PhpResult { Err(PhpException::from_class::("Not good!".into())) } # #[php_module] diff --git a/src/errors.rs b/src/errors.rs index 57ab29b..8a6fd73 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -95,7 +95,7 @@ impl From for Error { } } -impl<'a> From for PhpException<'a> { +impl From for PhpException { fn from(err: Error) -> Self { Self::default(err.to_string()) } diff --git a/src/lib.rs b/src/lib.rs index 3681628..caed5a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -398,7 +398,7 @@ pub use ext_php_rs_derive::php_module; /// pub struct Example; /// /// #[php_function] -/// pub fn throw_exception() -> Result> { +/// pub fn throw_exception() -> Result { /// Err(PhpException::from_class::("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"))] diff --git a/src/php/exceptions.rs b/src/php/exceptions.rs index e5302f5..87ce1b3 100644 --- a/src/php/exceptions.rs +++ b/src/php/exceptions.rs @@ -15,7 +15,7 @@ use crate::{ }; /// Result type with the error variant as a [`PhpException`]. -pub type PhpResult = std::result::Result>; +pub type PhpResult = std::result::Result; /// Represents a PHP exception which can be thrown using the `throw()` function. Primarily used to /// return from a [`Result`] which can immediately be thrown by the `ext-php-rs` @@ -25,13 +25,13 @@ pub type PhpResult = std::result::Result>; /// can also be returned from these functions. You can also implement [`From`] 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 for PhpException<'a> { +impl From 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()) } diff --git a/src/php/types/object.rs b/src/php/types/object.rs index ab68fd0..65d49df 100644 --- a/src/php/types/object.rs +++ b/src/php/types/object.rs @@ -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::::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::::from_zend_obj_ptr(obj)) @@ -734,7 +734,7 @@ impl ZendObjectHandlers { unsafe fn internal( object: *mut zend_object, props: &mut HashTable, - ) -> std::result::Result<(), PhpException<'static>> { + ) -> PhpResult { let obj = object .as_ref() .and_then(|obj| ZendClassObject::::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> { + ) -> PhpResult { let obj = object .as_ref() .and_then(|obj| ZendClassObject::::from_zend_obj_ptr(obj)) diff --git a/src/php/types/zval.rs b/src/php/types/zval.rs index c88b232..28334a8 100644 --- a/src/php/types/zval.rs +++ b/src/php/types/zval.rs @@ -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 IntoZval for std::result::Result +where + T: IntoZval, + E: Into, +{ + 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 {