MCPcopy Create free account
hub / github.com/hashintel/hash / try_scan

Method try_scan

libs/@local/hashql/core/src/intern/beef.rs:421–483  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

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) };

Callers 7

try_scan_emptyFunction · 0.80
try_scan_cumulative_sumFunction · 0.80
try_scan_no_changesFunction · 0.80
try_scan_already_ownedFunction · 0.80

Calls 2

lenMethod · 0.45
addMethod · 0.45

Tested by 7

try_scan_emptyFunction · 0.64
try_scan_cumulative_sumFunction · 0.64
try_scan_no_changesFunction · 0.64
try_scan_already_ownedFunction · 0.64