diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index c4ef7c6..1e6b014 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -21,3 +21,4 @@ - [Structs](./macros/structs.md) - [`impl`s](./macros/impl.md) - [Constants](./macros/constant.md) +- [Exceptions](./exceptions.md) diff --git a/guide/src/exceptions.md b/guide/src/exceptions.md new file mode 100644 index 0000000..d842d33 --- /dev/null +++ b/guide/src/exceptions.md @@ -0,0 +1,48 @@ +# Exceptions + +Exceptions can be thrown from Rust to PHP. The inverse (catching a PHP exception +in Rust) is currently being worked on. + +## Throwing exceptions + +[`PhpException`] is the type that represents an exception. It contains the +message contained in the exception, the type of exception and a status code to +go along with the exception. + +You can create a new exception with the `new()`, `default()`, or +`from_class::()` methods. `Into` is implemented for `String` +and `&str`, which creates an exception of the type `Exception` with a code of 0. +It may be useful to implement `Into` for your error type. + +Calling the `throw()` method on a `PhpException` attempts to throw the exception +in PHP. This function can fail if the type of exception is invalid (i.e. does +not implement `Exception` or `Throwable`). Upon success, nothing will be +returned. + +`IntoZval` is also implemented for `Result`, where `T: IntoZval` and +`E: Into`. If the result contains the error variant, the exception +is thrown. This allows you to return a result from a PHP function annotated with +the `#[php_function]` attribute. + +### Examples + +```rust +# extern crate ext_php_rs; +use ext_php_rs::prelude::*; +use std::convert::TryInto; + +// Trivial example - PHP represents all integers as `u64` on 64-bit systems +// so the `u32` would be converted back to `u64`, but that's okay for an example. +#[php_function] +pub fn something_fallible(n: u64) -> PhpResult { + let n: u32 = n.try_into().map_err(|_| "Could not convert into u32")?; + Ok(n) +} + +#[php_module] +pub fn module(module: ModuleBuilder) -> ModuleBuilder { + module +} +``` + +[`PhpException`]: https://docs.rs/ext-php-rs/0.5.0/ext_php_rs/php/exceptions/struct.PhpException.html diff --git a/guide/src/macros/function.md b/guide/src/macros/function.md index d18f4e0..9e7c549 100644 --- a/guide/src/macros/function.md +++ b/guide/src/macros/function.md @@ -88,21 +88,8 @@ pub fn greet(name: String, age: Option, description: Option) -> Str } ``` -## Throwing exceptions +## Returning `Result` -Exceptions can be thrown from inside a function which returns a `Result`, -where `E` implements `Into`. The `PhpException` class allows you -to customise the type of exception thrown, along with the exception code and -message. - -By default, `String` and `&str` are both implemented with `Into`, -and in both cases a regular `Exception` is thrown. - -```rust -# extern crate ext_php_rs; -# use ext_php_rs::prelude::*; -#[php_function] -pub fn example_exception() -> Result { - Err("Bad!!!") -} -``` +You can also return a `Result` from the function. The error variant will be +translated into an exception and thrown. See the section on +[exceptions](../exceptions.md) for more details. diff --git a/guide/src/types/closure.md b/guide/src/types/closure.md index 0d53e51..caccf16 100644 --- a/guide/src/types/closure.md +++ b/guide/src/types/closure.md @@ -1,19 +1,24 @@ # Closure Rust closures can be passed to PHP through a wrapper class `PhpClosure`. The -Rust closure must be static (i.e. can only reference things with a `static` +Rust closure must be static (i.e. can only reference things with a `'static` lifetime, so not `self` in methods), and can take up to 8 parameters, all of which must implement `FromZval`. The return type must implement `IntoZval`. Passing closures from Rust to PHP is feature-gated behind the `closure` feature. +Enable it in your `Cargo.toml`: + +```toml +ext-php-rs = { version = "...", features = ["closure"] } +``` PHP callables (which includes closures) can be passed to Rust through the `Callable` type. When calling a callable, you must provide it with a `Vec` of arguemnts, all of which must implement `IntoZval` and `Clone`. -| `T` parameter | `&T` parameter | `T` Return type | `&T` Return type | PHP representation | -| ------------- | -------------- | -------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------ | -| `Callable` | No | `Closure` and `Callable` for functions | No | Callables are implemented in PHP, closures are represented as an instance of `PhpClosure`. | +| `T` parameter | `&T` parameter | `T` Return type | `&T` Return type | PHP representation | +| ------------- | -------------- | ----------------------------------- | ---------------- | ------------------------------------------------------------------------------------------ | +| `Callable` | No | `Closure`, `Callable` for functions | No | Callables are implemented in PHP, closures are represented as an instance of `PhpClosure`. | Internally, when you enable the `closure` feature, a class `PhpClosure` is registered alongside your other classes: diff --git a/guide/src/types/hashmap.md b/guide/src/types/hashmap.md index 4abb686..3b5721e 100644 --- a/guide/src/types/hashmap.md +++ b/guide/src/types/hashmap.md @@ -4,7 +4,7 @@ | `T` parameter | `&T` parameter | `T` Return type | PHP representation | | ------------- | -------------- | --------------- | ------------------ | -| Yes | No | Yes | `ZendHashTable` | +| Yes | No | Yes | `HashTable` | Converting from a zval to a `HashMap` is valid when the key is a `String`, and the value implements `FromZval`. The key and values are copied into Rust types diff --git a/guide/src/types/index.md b/guide/src/types/index.md index 584335a..c367a9b 100644 --- a/guide/src/types/index.md +++ b/guide/src/types/index.md @@ -31,5 +31,4 @@ Return types can also include: as an exception. For a type to be returnable, it must implement `IntoZval`, while for it to be -valid as a parameter, it must implement `FromZval` (and `TryFrom<&Zval>` by -proxy). +valid as a parameter, it must implement `FromZval`. diff --git a/guide/src/types/vec.md b/guide/src/types/vec.md index 078359a..3907e15 100644 --- a/guide/src/types/vec.md +++ b/guide/src/types/vec.md @@ -6,7 +6,7 @@ vector. The internal representation of a PHP array is discussed below. | `T` parameter | `&T` parameter | `T` Return type | PHP representation | | ------------- | -------------- | --------------- | ------------------ | -| Yes | No | Yes | `ZendHashTable` | +| Yes | No | Yes | `HashTable` | Internally, PHP arrays are hash tables where the key can be an unsigned long or a string. Zvals are contained inside arrays therefore the data does not have to