Skip to content

Commit 66ff234

Browse files
authored
Add document Zval. (#81)
1 parent c92cb8e commit 66ff234

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

phper-doc/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ rust-version = { workspace = true }
1919
repository = { workspace = true }
2020
license = { workspace = true }
2121

22-
[dev-dependencies]
22+
[dependencies]
2323
phper = { version = "0.7.0", path = "../phper" }
24+
25+
[dev-dependencies]
2426
thiserror = "1.0.37"
2527
reqwest = { version = "0.11.13", features = ["blocking", "cookies"] }

phper-doc/doc/_04_zval/index.md

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Zval
2+
3+
> Refer to: <https://www.phpinternalsbook.com/php7/zvals/basic_structure.html#the-zval-struct>
4+
>
5+
> A zval (short for “Zend value”) represents an arbitrary PHP value.
6+
> As such it is likely the most important structure in all of PHP and
7+
> you’ll be working with it a lot.
8+
9+
The [`phper::values::ZVal`] is the wrapper of php zval.
10+
11+
## Actual type of ZVal
12+
13+
PHP is a dynamically typed language, zval can represent multiple types,
14+
but there is only one type at a time, you can use
15+
[`phper::values::ZVal::get_type_info`] to get the actual type.
16+
17+
## Convert Rust type to ZVal
18+
19+
The [`phper::values::ZVal`] implements a lot of [`std::convert::From`] for the
20+
conversion.
21+
22+
Here is the mapping relationship of Rust type and base PHP type.
23+
24+
| Trait | Rust type | PHP type |
25+
| --------------- | --------------------------- | -------- |
26+
| `From<()>` | `()` | null |
27+
| `From<bool>` | `bool` | bool |
28+
| `From<i64>` | `i64` | long |
29+
| `From<f64>` | `f64` | double |
30+
| `From<&str>` | `&str` | string |
31+
| `From<&CStr>` | `&CStr` | string |
32+
| `From<&[u8]>` | `&[u8]` | string |
33+
| `From<Vec<u8>>` | `Vec<u8>` | string |
34+
| `From<ZString>` | [`phper::strings::ZString`] | string |
35+
| `From<ZArray>` | [`phper::arrays::ZArray`] | array |
36+
| `From<ZObject>` | [`phper::objects::ZObject`] | object |
37+
38+
Otherwise, there are also composite types that implement `From`.
39+
40+
- `From<Option<T>>`: if Some(T), T will be converted to PHP type like `From<T>`,
41+
or `None` wll be converted to `null`.
42+
43+
- `From<Result<T, E>>`: if Ok(T), T will be converted to PHP type like `From<T>`,
44+
or `Err(e)` will throw an Exception by calling `zend_throw_exception`.
45+
46+
### Example
47+
48+
```rust,no_run
49+
use phper::values::ZVal;
50+
51+
assert!(ZVal::from(()).get_type_info().is_null());
52+
assert!(ZVal::from(100i64).get_type_info().is_long());
53+
```
54+
55+
## Convert ZVal to Rust type
56+
57+
Now you can use `as_*` or `expect_*` methods to convert ZVal to Rust types.
58+
59+
- The `as_*` returns `Option<T>`.
60+
61+
- The `expect_*` returns `phper::Result<T>`, if convert failed,
62+
[phper::errors::ExpectTypeError] will be returned, with the message:
63+
`type error: must be of type {expect_type}, {actual_type} given")`.
64+
65+
66+
### Example
67+
68+
```rust,no_run
69+
use phper::echo;
70+
use phper::values::ZVal;
71+
72+
fn say_hello(arguments: &mut [ZVal]) -> phper::Result<()> {
73+
// Get the first argument, expect the type `ZStr`, and convert to Rust utf-8
74+
// str.
75+
let name = arguments[0].expect_z_str()?.to_str()?;
76+
77+
// Macro which do php internal `echo`.
78+
echo!("Hello, {}!\n", name);
79+
80+
Ok(())
81+
}
82+
```
83+
84+
## Value copy & reference counting copy
85+
86+
The [`phper::values::ZVal`] both implements [`std::clone::Clone`] and
87+
[`phper::alloc::RefClone`].
88+
89+
- [`std::clone::Clone`]: represent value copy (Type ZObject is excluded because it is always passed by reference).
90+
91+
- [`phper::alloc::RefClone`]: represent reference counting copy (Type (), bool,
92+
i64, f64 is excluded because they are not reference counting types).
93+
94+
## PHP internal cast
95+
96+
> Refer to: <https://www.phpinternalsbook.com/php7/zvals/casts_and_operations.html#casts>
97+
98+
PHP is a weakly typed language, supports type cast internally.
99+
100+
The zend engine provides `convert_to_*` functions to do the type cast, and
101+
`ZVal` wraps them directly.
102+
103+
## Callable
104+
105+
The [`phper::values::ZVal`] can be call via [`phper::values::ZVal::call`], make
106+
sure the actual type is callable (string or array or closure).
107+
108+
```rust,no_run
109+
use phper::values::ZVal;
110+
use phper::arrays::ZArray;
111+
112+
let mut arr = ZArray::new();
113+
arr.insert("a", ZVal::from(1));
114+
arr.insert("b", ZVal::from(2));
115+
let ret = ZVal::from("json_encode").call(&mut [ZVal::from(arr)]).unwrap();
116+
assert_eq!(ret.expect_z_str().unwrap().to_str(), Ok(r#"{"a":1,"b":2}"#));
117+
```

phper-doc/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#![warn(rust_2018_idioms, clippy::dbg_macro)]
1212
#![doc = include_str!("../README.md")]
1313

14+
pub use phper;
15+
1416
#[doc = include_str!("../doc/_01_introduction/index.md")]
1517
pub mod _01_introduction {}
1618

@@ -27,7 +29,7 @@ pub mod _02_quick_start {
2729
#[doc = include_str!("../doc/_03_integrate_with_pecl/index.md")]
2830
pub mod _03_integrate_with_pecl {}
2931

30-
/// TODO
32+
#[doc = include_str!("../doc/_04_zval/index.md")]
3133
pub mod _04_zval {}
3234

3335
/// TODO

0 commit comments

Comments
 (0)