rootcause/report_attachments/iter.rs
1use core::iter::FusedIterator;
2
3use rootcause_internals::RawAttachment;
4
5use crate::{
6 markers::Dynamic,
7 report_attachment::{ReportAttachment, ReportAttachmentMut, ReportAttachmentRef},
8};
9
10/// An iterator over references to report attachments.
11///
12/// This iterator yields [`ReportAttachmentRef`] items and is created by calling
13/// [`ReportAttachments::iter`].
14///
15/// [`ReportAttachmentRef`]: crate::report_attachment::ReportAttachmentRef
16/// [`ReportAttachments::iter`]: crate::report_attachments::ReportAttachments::iter
17///
18/// # Examples
19///
20/// ```
21/// use rootcause::{
22/// report_attachment::ReportAttachment,
23/// report_attachments::{ReportAttachments, ReportAttachmentsIter},
24/// };
25///
26/// let mut attachments = ReportAttachments::new_sendsync();
27/// attachments.push(ReportAttachment::new("debug info").into_dynamic());
28/// attachments.push(ReportAttachment::new(42).into_dynamic());
29///
30/// let iterator: ReportAttachmentsIter<'_> = attachments.iter();
31/// ```
32#[must_use]
33pub struct ReportAttachmentsIter<'a> {
34 raw: core::slice::Iter<'a, RawAttachment>,
35}
36
37impl<'a> ReportAttachmentsIter<'a> {
38 /// Creates a new [`ReportAttachmentsIter`] from an iterator of raw
39 /// attachments
40 pub(crate) fn from_raw(raw: core::slice::Iter<'a, RawAttachment>) -> Self {
41 Self { raw }
42 }
43}
44
45impl<'a> Iterator for ReportAttachmentsIter<'a> {
46 type Item = ReportAttachmentRef<'a, Dynamic>;
47
48 fn next(&mut self) -> Option<Self::Item> {
49 let raw = self.raw.next()?.as_ref();
50
51 // SAFETY:
52 // 1. `A = Dynamic`, so this is trivially satisfied.
53 // 2. `A = Dynamic`, so this is trivially satisfied.
54 let attachment = unsafe {
55 // @add-unsafe-context: Dynamic
56 ReportAttachmentRef::<'a, Dynamic>::from_raw(raw)
57 };
58
59 Some(attachment)
60 }
61
62 fn size_hint(&self) -> (usize, Option<usize>) {
63 self.raw.size_hint()
64 }
65}
66
67impl<'a> DoubleEndedIterator for ReportAttachmentsIter<'a> {
68 fn next_back(&mut self) -> Option<Self::Item> {
69 let raw = self.raw.next_back()?.as_ref();
70
71 // SAFETY:
72 // 1. `A = Dynamic`, so this is trivially satisfied.
73 // 2. `A = Dynamic`, so this is trivially satisfied.
74 let attachment = unsafe {
75 // @add-unsafe-context: Dynamic
76 ReportAttachmentRef::<'a, Dynamic>::from_raw(raw)
77 };
78
79 Some(attachment)
80 }
81}
82
83impl<'a> ExactSizeIterator for ReportAttachmentsIter<'a> {
84 fn len(&self) -> usize {
85 self.raw.len()
86 }
87}
88
89impl<'a> FusedIterator for ReportAttachmentsIter<'a> {}
90
91/// An iterator over mutable references to report attachments.
92///
93/// This iterator yields [`ReportAttachmentMut`] items and is created by calling
94/// [`ReportAttachments::iter_mut`].
95///
96/// [`ReportAttachmentMut`]: crate::report_attachment::ReportAttachmentMut
97/// [`ReportAttachments::iter_mut`]: crate::report_attachments::ReportAttachments::iter_mut
98///
99/// # Examples
100/// ```
101/// use rootcause::{
102/// report_attachment::ReportAttachment,
103/// report_attachments::{ReportAttachments, ReportAttachmentsIterMut},
104/// };
105///
106/// let mut attachments = ReportAttachments::new_sendsync();
107/// attachments.push(ReportAttachment::new(41i32).into_dynamic());
108/// attachments.push(ReportAttachment::new(41i32).into_dynamic());
109///
110/// for mut attachment in attachments.iter_mut() {
111/// if let Some(num) = attachment.downcast_inner_mut::<i32>() {
112/// *num += 1;
113/// }
114/// }
115/// ```
116#[must_use]
117pub struct ReportAttachmentsIterMut<'a> {
118 raw: core::slice::IterMut<'a, RawAttachment>,
119}
120
121impl<'a> ReportAttachmentsIterMut<'a> {
122 /// Creates a new [`ReportAttachmentsIterMut`] from a mutable iterator of
123 /// raw attachments
124 pub(crate) fn from_raw(raw: core::slice::IterMut<'a, RawAttachment>) -> Self {
125 Self { raw }
126 }
127}
128
129impl<'a> Iterator for ReportAttachmentsIterMut<'a> {
130 type Item = ReportAttachmentMut<'a, Dynamic>;
131
132 fn next(&mut self) -> Option<Self::Item> {
133 let raw = self.raw.next()?.as_mut();
134
135 // SAFETY:
136 // 1. `A = Dynamic`, so this is trivially satisfied.
137 // 2. `A = Dynamic`, so this is trivially satisfied.
138 let attachment = unsafe {
139 // @add-unsafe-context: Dynamic
140 ReportAttachmentMut::<'a, Dynamic>::from_raw(raw)
141 };
142
143 Some(attachment)
144 }
145
146 fn size_hint(&self) -> (usize, Option<usize>) {
147 self.raw.size_hint()
148 }
149}
150
151impl<'a> DoubleEndedIterator for ReportAttachmentsIterMut<'a> {
152 fn next_back(&mut self) -> Option<Self::Item> {
153 let raw = self.raw.next_back()?.as_mut();
154
155 // SAFETY:
156 // 1. `A = Dynamic`, so this is trivially satisfied.
157 // 2. `A = Dynamic`, so this is trivially satisfied.
158 let attachment = unsafe {
159 // @add-unsafe-context: Dynamic
160 ReportAttachmentMut::<'a, Dynamic>::from_raw(raw)
161 };
162
163 Some(attachment)
164 }
165}
166
167impl<'a> ExactSizeIterator for ReportAttachmentsIterMut<'a> {
168 fn len(&self) -> usize {
169 self.raw.len()
170 }
171}
172
173impl<'a> FusedIterator for ReportAttachmentsIterMut<'a> {}
174
175/// FIXME: Once rust-lang/rust#132922 gets resolved, we can make the `raw` field
176/// an unsafe field and remove this module.
177mod limit_field_access {
178 use core::marker::PhantomData;
179
180 use rootcause_internals::RawAttachment;
181
182 /// An iterator that consumes report attachments and yields owned values.
183 ///
184 /// This iterator yields [`ReportAttachment`] items and is created by
185 /// calling [`ReportAttachments::into_iter`].
186 ///
187 /// [`ReportAttachment`]: crate::report_attachment::ReportAttachment
188 /// [`ReportAttachments::into_iter`]: crate::report_attachments::ReportAttachments::into_iter
189 ///
190 /// # Examples
191 ///
192 /// ```
193 /// use rootcause::{
194 /// report_attachment::ReportAttachment,
195 /// report_attachments::{ReportAttachments, ReportAttachmentsIntoIter},
196 /// };
197 ///
198 /// let mut attachments = ReportAttachments::new_sendsync();
199 /// attachments.push(ReportAttachment::new("debug info").into_dynamic());
200 /// attachments.push(ReportAttachment::new(42).into_dynamic());
201 ///
202 /// let iterator: ReportAttachmentsIntoIter<_> = attachments.into_iter();
203 /// ```
204 #[must_use]
205 pub struct ReportAttachmentsIntoIter<ThreadMarker: 'static> {
206 /// # Safety
207 ///
208 /// The following safety invariants are guaranteed to be upheld as long
209 /// as this struct exists:
210 ///
211 /// 1. Either the collection must be empty or `T` must either be
212 /// `SendSync` or `Local`.
213 /// 2. If `T = SendSync`: All of the inner attachments must be `Send +
214 /// Sync`.
215 raw: alloc::vec::IntoIter<RawAttachment>,
216 _thread_safety: PhantomData<ThreadMarker>,
217 }
218
219 impl<T> ReportAttachmentsIntoIter<T> {
220 /// Creates a new [`ReportAttachmentsIntoIter`] from an iterator of raw
221 /// attachments
222 ///
223 /// # Safety
224 ///
225 /// The caller must ensure:
226 ///
227 /// 1. Either the collection must be empty or `T` must either be
228 /// `SendSync` or `Local`.
229 /// 2. If `T = SendSync`: All of the inner attachments must be `Send +
230 /// Sync`.
231 pub(crate) unsafe fn from_raw(raw: alloc::vec::IntoIter<RawAttachment>) -> Self {
232 // SAFETY: We must uphold the safety invariants of the raw field:
233 // 1. Guaranteed by the caller
234 // 2. Guaranteed by the caller
235 Self {
236 raw,
237 _thread_safety: PhantomData,
238 }
239 }
240
241 /// Provides access to the inner raw iterator
242 pub(crate) fn as_raw(&self) -> &alloc::vec::IntoIter<RawAttachment> {
243 // SAFETY: We must uphold the safety invariants of the raw field:
244 // 1. Upheld as the type parameters do not change.
245 // 2. No mutation is possible through this reference
246 &self.raw
247 }
248
249 /// Provides mutable access to the inner raw iterator
250 ///
251 /// # Safety
252 ///
253 /// The caller must ensure:
254 ///
255 /// 1. If `T = SendSync`: No mutation is performed that invalidates the
256 /// invariant that either all inner attachments are `Send + Sync` or
257 /// the collection is empty.
258 pub(crate) unsafe fn as_raw_mut(&mut self) -> &mut alloc::vec::IntoIter<RawAttachment> {
259 // SAFETY: We must uphold the safety invariants of the raw field:
260 // 1. Upheld as the type parameters do not change.
261 // 2. Guaranteed by the caller
262 &mut self.raw
263 }
264 }
265}
266pub use limit_field_access::ReportAttachmentsIntoIter;
267
268impl<T> Iterator for ReportAttachmentsIntoIter<T> {
269 type Item = ReportAttachment<Dynamic, T>;
270
271 fn next(&mut self) -> Option<Self::Item> {
272 // SAFETY: We only remove items, we don't mutate them.
273 // 1. If the collection is already empty, this is a no-op and it is still empty
274 // after. On the other hand, if there are items, we are guaranteed by the
275 // invariants of this type that all inner attachments are `Send + Sync` if `T
276 // = SendSync`.
277 let raw = unsafe { self.as_raw_mut() };
278
279 let attachment = raw.next()?;
280
281 // SAFETY:
282 // 1. `A=Dynamic`, so this is trivially satisfied.
283 // 2. Guaranteed by the invariants of this type.
284 // 3. `A=Dynamic`, so this is trivially satisfied.
285 // 4. Guaranteed by the invariants of this type.
286 let attachment = unsafe { ReportAttachment::<Dynamic, T>::from_raw(attachment) };
287
288 Some(attachment)
289 }
290
291 fn size_hint(&self) -> (usize, Option<usize>) {
292 self.as_raw().size_hint()
293 }
294}
295
296impl<T> DoubleEndedIterator for ReportAttachmentsIntoIter<T> {
297 fn next_back(&mut self) -> Option<Self::Item> {
298 // SAFETY: We only remove items, we don't mutate them.
299 // 1. If the collection is already empty, this is a no-op and it is still empty
300 // after. On the other hand, if there are items, we are guaranteed by the
301 // invariants of this type that all inner attachments are `Send + Sync` if `T
302 // = SendSync`.
303 let raw = unsafe { self.as_raw_mut() };
304
305 let attachment = raw.next_back()?;
306
307 // SAFETY:
308 // 1. `A=Dynamic`, so this is trivially satisfied.
309 // 2. Guaranteed by the invariants of this type.
310 // 3. `A=Dynamic`, so this is trivially satisfied.
311 // 4. Guaranteed by the invariants of this type.
312 let attachment = unsafe { ReportAttachment::<Dynamic, T>::from_raw(attachment) };
313
314 Some(attachment)
315 }
316}
317
318impl<T> ExactSizeIterator for ReportAttachmentsIntoIter<T> {
319 fn len(&self) -> usize {
320 self.as_raw().len()
321 }
322}
323
324impl<T> FusedIterator for ReportAttachmentsIntoIter<T> {}
325
326impl<T> Unpin for ReportAttachmentsIntoIter<T> {}