Transforms each element with access to all previously transformed elements. This is a scanning operation where each transformation can observe the accumulated results of all prior transformations. The closure receives two arguments: - `&[T]`: A slice of **already-transformed** elements (the prefix) - `T`: The current element to transform The key distinction from [`try_map`](Self::try_map) is tha
(&mut self, mut closure: impl FnMut(&[T], T) -> F)
| 419 | /// assert!(ptr::eq(finished.as_ptr(), original_ptr)); // Same memory! |
| 420 | /// ``` |
| 421 | pub fn try_scan<F, U>(&mut self, mut closure: impl FnMut(&[T], T) -> F) -> U |
| 422 | where |
| 423 | F: Try<Output = T>, |
| 424 | U: Try<Output = (), Residual = F::Residual>, |
| 425 | { |
| 426 | let (offset, buffer) = match &mut self.0 { |
| 427 | BeefData::Owned(owned) => (0, owned), |
| 428 | BeefData::Interned(interned) => { |
| 429 | let mut index = 0; |
| 430 | let mut outer = None; |
| 431 | |
| 432 | while index < interned.len() { |
| 433 | // Loop through every item (until the end) of the interned slice, if the item |
| 434 | // changed, transition to the smallvec, then use that smallvec instead |
| 435 | let value = interned[index]; |
| 436 | let mapped = closure(&interned[..index], value)?; |
| 437 | |
| 438 | if value != mapped { |
| 439 | // Transition to a smallvec, then use that smallvec in the final iteration |
| 440 | let mut owned = SmallVec::from_slice_copy(interned.0); |
| 441 | owned[index] = mapped; |
| 442 | self.0 = BeefData::Owned(owned); |
| 443 | |
| 444 | outer = Some(match &mut self.0 { |
| 445 | BeefData::Owned(owned) => owned, |
| 446 | BeefData::Interned(_) => unreachable!(), |
| 447 | }); |
| 448 | |
| 449 | index += 1; |
| 450 | break; |
| 451 | } |
| 452 | |
| 453 | index += 1; |
| 454 | } |
| 455 | |
| 456 | let Some(outer) = outer else { |
| 457 | // No changes have occured |
| 458 | return Try::from_output(()); |
| 459 | }; |
| 460 | |
| 461 | (index, outer) |
| 462 | } |
| 463 | }; |
| 464 | |
| 465 | let ptr = buffer.as_mut_ptr(); |
| 466 | let len = buffer.len(); |
| 467 | #[expect(unsafe_code)] |
| 468 | for index in offset..len { |
| 469 | // SAFETY: We're creating a shared reference to `buffer[..index]` |
| 470 | // while holding a mutable reference to `buffer[index]`. |
| 471 | // This is safe because: |
| 472 | // 1. The shared slice `previous` covers [0..index) |
| 473 | // 2. The mutable reference `remaining` is to element [index] |
| 474 | // 3. These ranges are disjoint by construction |
| 475 | // 4. `previous` is only used within the closure call and doesn't escape |
| 476 | let previous = unsafe { core::slice::from_raw_parts(ptr, index) }; |
| 477 | // SAFETY: see above |
| 478 | let remaining = unsafe { &mut *ptr.add(index) }; |