ext_php_rs/zend/
linked_list.rs

1use std::{marker::PhantomData, ptr};
2
3use crate::ffi::{zend_llist, zend_llist_element, zend_llist_get_next_ex};
4
5/// PHP linked list
6pub type ZendLinkedList = zend_llist;
7
8impl ZendLinkedList {
9    /// Create an iterator over the linked list
10    #[must_use]
11    pub fn iter<T>(&self) -> ZendLinkedListIterator<'_, T> {
12        ZendLinkedListIterator::new(self)
13    }
14}
15
16pub struct ZendLinkedListIterator<'a, T> {
17    list: &'a zend_llist,
18    position: *mut zend_llist_element,
19    _marker: PhantomData<T>,
20}
21
22impl<'a, T> ZendLinkedListIterator<'a, T> {
23    fn new(list: &'a ZendLinkedList) -> Self {
24        ZendLinkedListIterator {
25            list,
26            position: list.head,
27            _marker: PhantomData,
28        }
29    }
30}
31
32impl<'a, T: 'a> Iterator for ZendLinkedListIterator<'a, T> {
33    type Item = &'a T;
34
35    fn next(&mut self) -> Option<Self::Item> {
36        if self.position.is_null() {
37            return None;
38        }
39        let ptr = unsafe { (*self.position).data.as_mut_ptr() };
40        let value = unsafe { &*((ptr as *const T).cast_mut()) };
41        unsafe {
42            zend_llist_get_next_ex(
43                ptr::from_ref::<ZendLinkedList>(self.list).cast_mut(),
44                &raw mut self.position,
45            )
46        };
47        Some(value)
48    }
49}