libddwaf/object/
iter.rs

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