Skip to content

Commit 524a18d

Browse files
committed
feat(iterator): add documentation
1 parent b95bade commit 524a18d

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed

guide/src/types/iterable.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# `Iterable`
2+
3+
`Iterable`s are represented either by an `array` or `Traversable` type.
4+
5+
| `T` parameter | `&T` parameter | `T` Return type | `&T` Return type | PHP representation |
6+
|---------------|----------------|-----------------| ---------------- |----------------------------------|
7+
| Yes | No | No | No | `ZendHashTable` or `ZendIterator` |
8+
9+
Converting from a zval to a `Iterable` is valid when the value is either an array or an object
10+
that implements the `Traversable` interface. This means that any value that can be used in a
11+
`foreach` loop can be converted into a `Iterable`.
12+
13+
## Rust example
14+
15+
```rust,no_run
16+
# #![cfg_attr(windows, feature(abi_vectorcall))]
17+
# extern crate ext_php_rs;
18+
# use ext_php_rs::prelude::*;
19+
# use ext_php_rs::types::Iterable;
20+
#[php_function]
21+
pub fn test_iterable(mut iterable: Iterable) {
22+
for (k, v) in iterable.iter() {
23+
println!("k: {} v: {}", k, v.string().unwrap());
24+
}
25+
}
26+
# fn main() {}
27+
```
28+
29+
## PHP example
30+
31+
```php
32+
<?php
33+
34+
$generator = function() {
35+
yield 'hello' => 'world';
36+
yield 'rust' => 'php';
37+
yield 'okk';
38+
};
39+
40+
$array = [
41+
'hello' => 'world',
42+
'rust' => 'php',
43+
'okk',
44+
];
45+
46+
test_iterable($generator());
47+
test_iterable($array);
48+
```
49+
50+
Output:
51+
52+
```text
53+
k: hello v: world
54+
k: rust v: php
55+
k: 0 v: okk
56+
k: hello v: world
57+
k: rust v: php
58+
k: 0 v: okk
59+
```

guide/src/types/iterator.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# `ZendIterator`
2+
3+
`ZendIterator`s are represented by the `Traversable` type.
4+
5+
| `T` parameter | `&T` parameter | `T` Return type | `&T` Return type | PHP representation |
6+
|---------------| -------------- |-----------------| ---------------- | ------------------ |
7+
| No | Yes | No | No | `ZendIterator` |
8+
9+
Converting from a zval to a `ZendIterator` is valid when there is an associated iterator to
10+
the variable. This means that any value, at the exception of an `array`, that can be used in
11+
a `foreach` loop can be converted into a `ZendIterator`. As an example, a `Generator` can be
12+
used but also a the result of a `query` call with `PDO`.
13+
14+
## Rust example
15+
16+
```rust,no_run
17+
# #![cfg_attr(windows, feature(abi_vectorcall))]
18+
# extern crate ext_php_rs;
19+
# use ext_php_rs::prelude::*;
20+
# use ext_php_rs::types::ZendIterator;
21+
#[php_function]
22+
pub fn test_iterator(iterator: &mut ZendIterator) {
23+
for (k, v) in iterator.iter() {
24+
println!("k: {} v: {}", k, v.string().unwrap());
25+
}
26+
}
27+
# fn main() {}
28+
```
29+
30+
## PHP example
31+
32+
```php
33+
<?php
34+
35+
$generator = function() {
36+
yield 'hello' => 'world';
37+
yield 'rust' => 'php';
38+
yield 'okk';
39+
};
40+
41+
test_iterator($generator());
42+
```
43+
44+
Output:
45+
46+
```text
47+
k: hello v: world
48+
k: rust v: php
49+
k: 0 v: okk
50+
```

src/types/iterable.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ use crate::flags::DataType;
55
use crate::types::iterator::IterKey;
66
use crate::types::{ZendHashTable, ZendIterator, Zval};
77

8+
/// This type represents a PHP iterable, which can be either an array or an object implementing
9+
/// the Traversable interface.
810
#[derive(Debug)]
911
pub enum Iterable<'a> {
1012
Array(&'a ZendHashTable),
1113
Traversable(&'a mut ZendIterator),
1214
}
1315

1416
impl<'a> Iterable<'a> {
17+
/// Creates a new rust iterator from a PHP iterable.
1518
pub fn iter(&mut self) -> Iter {
1619
match self {
1720
Iterable::Array(array) => Iter::Array(array.iter()),
@@ -36,6 +39,7 @@ impl<'a> FromZval<'a> for Iterable<'a> {
3639
}
3740
}
3841

42+
/// Rust iterator over a PHP iterable.
3943
pub enum Iter<'a> {
4044
Array(ZendHashTableIter<'a>),
4145
Traversable(ZendIteratorIter<'a>),

src/types/iterator.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ use std::fmt::{Debug, Display, Formatter};
1313
pub type ZendIterator = zend_object_iterator;
1414

1515
impl ZendIterator {
16+
/// Creates a new rust iterator from a zend_object_iterator.
17+
///
18+
/// # Returns
19+
///
20+
/// Returns a iterator over the zend_object_iterator.
1621
pub fn iter(&mut self) -> Iter {
1722
self.index = 0;
1823
self.rewind();
1924

2025
Iter { zi: self }
2126
}
2227

28+
/// Check if the current position of the iterator is valid.
29+
///
30+
/// As an example this will call the user defined valid method of the ['\Iterator'] interface.
31+
/// see https://www.php.net/manual/en/iterator.valid.php
2332
pub fn valid(&mut self) -> bool {
2433
if let Some(valid) = unsafe { (*self.funcs).valid } {
2534
unsafe { valid(&mut *self) != 0 }
@@ -28,6 +37,10 @@ impl ZendIterator {
2837
}
2938
}
3039

40+
/// Rewind the iterator to the first element.
41+
///
42+
/// As an example this will call the user defined rewind method of the ['\Iterator'] interface.
43+
/// see https://www.php.net/manual/en/iterator.rewind.php
3144
pub fn rewind(&mut self) {
3245
if let Some(rewind) = unsafe { (*self.funcs).rewind } {
3346
unsafe {
@@ -36,6 +49,10 @@ impl ZendIterator {
3649
}
3750
}
3851

52+
/// Move the iterator forward to the next element.
53+
///
54+
/// As an example this will call the user defined next method of the ['\Iterator'] interface.
55+
/// see https://www.php.net/manual/en/iterator.next.php
3956
pub fn move_forward(&mut self) {
4057
if let Some(move_forward) = unsafe { (*self.funcs).move_forward } {
4158
unsafe {
@@ -44,13 +61,25 @@ impl ZendIterator {
4461
}
4562
}
4663

64+
/// Get the current data of the iterator.
65+
///
66+
/// # Returns
67+
///
68+
/// Returns a reference to the current data of the iterator if available
69+
/// , ['None'] otherwise.
4770
pub fn get_current_data<'a>(&mut self) -> Option<&'a Zval> {
4871
let get_current_data = unsafe { (*self.funcs).get_current_data }?;
4972
let value = unsafe { &*get_current_data(&mut *self) };
5073

5174
Some(value)
5275
}
5376

77+
/// Get the current key of the iterator.
78+
///
79+
/// # Returns
80+
///
81+
/// Returns a new ['Zval'] containing the current key of the iterator if available
82+
/// , ['None'] otherwise.
5483
pub fn get_current_key(&mut self) -> Option<Zval> {
5584
let get_current_key = unsafe { (*self.funcs).get_current_key }?;
5685
let mut key = Zval::new();
@@ -74,7 +103,13 @@ pub enum IterKey {
74103
String(String),
75104
}
76105

106+
/// Represent the key of a PHP iterator, which can be either a long or a string.
77107
impl IterKey {
108+
/// Check if the key is numerical.
109+
///
110+
/// # Returns
111+
///
112+
/// Returns true if the key is numerical, false otherwise.
78113
pub fn is_numerical(&self) -> bool {
79114
match self {
80115
IterKey::Long(_) => true,
@@ -103,6 +138,7 @@ impl FromZval<'_> for IterKey {
103138
}
104139
}
105140

141+
/// Immutable iterator upon a reference to a PHP iterator.
106142
pub struct Iter<'a> {
107143
zi: &'a mut ZendIterator,
108144
}

src/types/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ mod zval;
1616
pub use array::ZendHashTable;
1717
pub use callable::ZendCallable;
1818
pub use class_object::ZendClassObject;
19+
pub use iterable::Iterable;
1920
pub use iterator::ZendIterator;
2021
pub use long::ZendLong;
2122
pub use object::{PropertyQuery, ZendObject};

0 commit comments

Comments
 (0)