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