Skip to main content

libddwaf/object/
iter.rs

1use std::alloc::Layout;
2
3use crate::object::{Keyed, WafArray, WafMap, WafObject};
4
5impl IntoIterator for WafArray {
6    type Item = WafObject;
7    type IntoIter = WafIter<Self::Item>;
8
9    fn into_iter(self) -> Self::IntoIter {
10        let array: *mut Self::Item = self.raw.array_ptr().cast();
11        let len = self.len();
12        let capacity = self.capacity();
13        // Forget about self, since the iterator is now the owner of the memory.
14        std::mem::forget(self);
15        WafIter {
16            array,
17            len,
18            capacity,
19            pos: 0,
20        }
21    }
22}
23
24impl IntoIterator for Keyed<WafArray> {
25    type Item = WafObject;
26    type IntoIter = WafIter<Self::Item>;
27
28    fn into_iter(mut self) -> Self::IntoIter {
29        let arr = std::mem::take(self.value_mut());
30        arr.into_iter()
31    }
32}
33
34impl IntoIterator for WafMap {
35    type Item = Keyed<WafObject>;
36    type IntoIter = WafIter<Self::Item>;
37
38    fn into_iter(self) -> Self::IntoIter {
39        let array: *mut Keyed<WafObject> = self.raw.map_ptr().cast();
40        let len = self.len();
41        let capacity = self.capacity();
42        // Forget about self, since the iterator is now the owner of the memory.
43        std::mem::forget(self);
44        WafIter {
45            array,
46            len,
47            capacity,
48            pos: 0,
49        }
50    }
51}
52
53impl IntoIterator for Keyed<WafMap> {
54    type Item = Keyed<WafObject>;
55    type IntoIter = WafIter<Self::Item>;
56
57    fn into_iter(mut self) -> Self::IntoIter {
58        let arr = std::mem::take(self.value_mut());
59        arr.into_iter()
60    }
61}
62
63/// An iterator over an [`WafArray`] or [`WafMap`].
64pub struct WafIter<T> {
65    array: *mut T,
66    len: usize,
67    capacity: usize,
68    pos: usize,
69}
70impl<T: Default> Iterator for WafIter<T> {
71    type Item = T;
72
73    fn next(&mut self) -> Option<Self::Item> {
74        if self.pos >= self.len {
75            return None;
76        }
77
78        let obj = unsafe { &mut *self.array.add(self.pos) };
79        self.pos += 1;
80        Some(std::mem::take(obj))
81    }
82}
83impl<T> Drop for WafIter<T> {
84    fn drop(&mut self) {
85        // Drop the remaining elements in the array...
86        for i in self.pos..self.len {
87            let elem = unsafe { self.array.add(i) };
88            unsafe { elem.drop_in_place() };
89        }
90        if self.capacity != 0 {
91            // Finally, drop the array itself.
92            let layout = Layout::array::<T>(self.capacity).unwrap();
93            unsafe { std::alloc::dealloc(self.array.cast(), layout) }
94        }
95    }
96}