|
| 1 | +# Z Arr |
| 2 | + |
| 3 | +> An array in PHP is actually an ordered map. A map is a type that associates |
| 4 | +> values to keys. This type is optimized for several different uses; it can be |
| 5 | +> treated as an array, list (vector), hash table (an implementation of a map), |
| 6 | +> dictionary, collection, stack, queue, and probably more. As array values can |
| 7 | +> be other arrays, trees and multidimensional arrays are also possible. |
| 8 | +> |
| 9 | +> Refer: <https://www.php.net/manual/en/language.types.array.php> |
| 10 | +
|
| 11 | +*In fact, I don't agree with PHP's practice of mixing list and map. I prefer* |
| 12 | +*python to separate list and dictionary as two types. For example, when* |
| 13 | +*serializing into json, the serialization function has to judge whether the key* |
| 14 | +*of the array starts from 0 and increment by 1 to confirm whether the array is* |
| 15 | +*a list. I think it is a waste of performance.* |
| 16 | + |
| 17 | +The [`&ZArr`](phper::arrays::ZArr) and [`ZArray`](phper::arrays::ZArray) are |
| 18 | +the wrapper of [`zend_array`](phper::sys::zend_array) (same as `Hashtable`). |
| 19 | + |
| 20 | +[`&ZArr`](phper::arrays::ZArr) acts like [`HashMap`](std::collections::HashMap), |
| 21 | +also has api `insert()`, `get()`, `remove()`, but it's key type is |
| 22 | +[`Key`](phper::arrays::Key) and value type is [`ZVal`](phper::values::ZVal). |
| 23 | + |
| 24 | +Notice that phper prefer to use [`Symtables`](https://www.phpinternalsbook.com/php5/hashtables/array_api.html#symtables) api `zend_symtable_*`, |
| 25 | +so `get(42)` and `get("42")` should be considered the same. |
| 26 | + |
| 27 | +`ZArray` can be dereferenced to `ZArr`. |
| 28 | + |
| 29 | +```rust,no_run |
| 30 | +use phper::arrays::{ZArray, InsertKey}; |
| 31 | +use phper::values::ZVal; |
| 32 | +
|
| 33 | +let mut arr = ZArray::new(); |
| 34 | +
|
| 35 | +arr.insert(InsertKey::NextIndex, ZVal::default()); |
| 36 | +arr.insert(10, ZVal::from(100)); |
| 37 | +arr.insert("foo", ZVal::from("bar")); |
| 38 | +
|
| 39 | +let _i = arr.get("10"); |
| 40 | +
|
| 41 | +arr.remove("foo"); |
| 42 | +``` |
| 43 | + |
| 44 | +`ZArr` can be iterated by `iter()`. |
| 45 | + |
| 46 | +```rust,no_run |
| 47 | +use phper::arrays::ZArray; |
| 48 | +use phper::values::ZVal; |
| 49 | +
|
| 50 | +let arr = ZArray::new(); |
| 51 | +
|
| 52 | +for (_k, _v) in arr.iter() { |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +`ZArr` implements `ToOwned`, can upgrade to `ZArray` by value copy via |
| 57 | +`zend_array_dup`. |
| 58 | + |
| 59 | +Because `zend_array` is reference counting type, so `ZArr` also implements |
| 60 | +[`ToRefOwned`](phper::alloc::ToRefOwned) (just like |
| 61 | +[`RefClone`](phper::alloc::RefClone) for [`ZVal`](phper::values::ZVal)), can |
| 62 | +upgrade to `ZArray` by refcount increment. |
| 63 | + |
| 64 | +```rust,no_run |
| 65 | +use phper::sys; |
| 66 | +use phper::arrays::ZArr; |
| 67 | +use phper::alloc::ToRefOwned; |
| 68 | +
|
| 69 | +extern "C" { |
| 70 | + fn something() -> *mut sys::zend_array; |
| 71 | +} |
| 72 | +
|
| 73 | +let arr = unsafe { ZArr::from_mut_ptr(something()) }; |
| 74 | +
|
| 75 | +// By value copy. |
| 76 | +let _arr = arr.to_owned(); |
| 77 | +
|
| 78 | +// By refcount increment. |
| 79 | +let _arr = arr.to_ref_owned(); |
| 80 | +``` |
| 81 | + |
| 82 | +Note that neither `ZArr` nor `ZArray` implement `Send` and `Sync`, because PHP |
| 83 | +is single-threaded. |
0 commit comments