blink_alloc/blink.rs
1//! Provides `Blink` allocator adaptor.
2
3use core::{
4 alloc::Layout,
5 convert::{identity, Infallible},
6 marker::PhantomData,
7 mem::{needs_drop, size_of, ManuallyDrop, MaybeUninit},
8 ptr::{self, NonNull},
9};
10
11#[cfg(all(feature = "nightly",feature = "alloc"))]
12use alloc::alloc::Global;
13
14#[cfg(all(not(feature = "nightly"),feature = "alloc"))]
15use allocator_api2::alloc::Global;
16
17use crate::{
18 api::BlinkAllocator,
19 cold,
20 drop_list::{DropItem, DropList},
21 in_place,
22};
23
24#[cfg(not(no_global_oom_handling))]
25use crate::ResultExt;
26
27#[cfg(feature = "alloc")]
28use crate::local::BlinkAlloc;
29
30#[cfg(not(no_global_oom_handling))]
31use crate::oom::{handle_alloc_error, size_overflow};
32
33type EmplaceType<T, E> = Result<T, ManuallyDrop<E>>;
34type EmplaceSlot<T, E> = MaybeUninit<EmplaceType<T, E>>;
35
36pub trait CoerceFromMut<'a, T: ?Sized> {
37 fn coerce(t: &'a mut T) -> Self;
38}
39
40impl<'a, T: ?Sized> CoerceFromMut<'a, T> for &'a mut T {
41 #[inline(always)]
42 fn coerce(t: &'a mut T) -> Self {
43 t
44 }
45}
46
47impl<'a, T: ?Sized> CoerceFromMut<'a, T> for &'a T {
48 #[inline(always)]
49 fn coerce(t: &'a mut T) -> Self {
50 t
51 }
52}
53
54/// Iterator extension trait for collecting iterators into blink allocator.
55///
56/// # Examples
57///
58/// ```
59/// # #[cfg(feature = "alloc")] fn main() {
60/// # use blink_alloc::{Blink, IteratorExt};
61/// let mut blink = Blink::new();
62/// let slice = (0..10).filter(|x| x % 3 != 0).collect_to_blink(&mut blink);
63/// assert_eq!(slice, [1, 2, 4, 5, 7, 8]);
64/// slice[0] = 10;
65/// assert_eq!(slice, [10, 2, 4, 5, 7, 8]);
66/// # }
67/// # #[cfg(not(feature = "alloc"))] fn main() {}
68/// ```
69///
70/// For non-static data with drop.
71///
72/// ```
73/// # #[cfg(feature = "alloc")] fn main() {
74/// # use blink_alloc::{Blink, IteratorExt};
75/// let mut blink = Blink::new();
76/// let slice = (0..10).filter(|x| x % 3 != 0).collect_to_blink_shared(&mut blink);
77/// assert_eq!(slice, [1, 2, 4, 5, 7, 8]);
78/// # }
79/// # #[cfg(not(feature = "alloc"))] fn main() {}
80/// ```
81///
82/// For non-static data and no drop.
83///
84/// ```
85/// # #[cfg(feature = "alloc")] fn main() {
86/// # use blink_alloc::{Blink, IteratorExt};
87/// let mut blink = Blink::new();
88/// let slice = (0..10).filter(|x| x % 3 != 0).collect_to_blink_no_drop(&mut blink);
89/// assert_eq!(slice, [1, 2, 4, 5, 7, 8]);
90/// slice[0] = 10;
91/// assert_eq!(slice, [10, 2, 4, 5, 7, 8]);
92/// # }
93/// # #[cfg(not(feature = "alloc"))] fn main() {}
94/// ```
95pub trait IteratorExt: Iterator {
96 /// Collect iterator into blink allocator and return slice reference.
97 #[cfg(not(no_global_oom_handling))]
98 #[inline(always)]
99 fn collect_to_blink<A: BlinkAllocator>(self, blink: &mut Blink<A>) -> &mut [Self::Item]
100 where
101 Self: Sized,
102 Self::Item: 'static,
103 {
104 blink.emplace().from_iter(self)
105 }
106
107 /// Collect iterator into blink allocator and return slice reference.
108 #[cfg(not(no_global_oom_handling))]
109 #[inline(always)]
110 fn collect_to_blink_shared<A: BlinkAllocator>(self, blink: &mut Blink<A>) -> &[Self::Item]
111 where
112 Self: Sized,
113 {
114 blink.emplace_shared().from_iter(self)
115 }
116
117 /// Collect iterator into blink allocator and return slice reference.
118 #[cfg(not(no_global_oom_handling))]
119 #[inline(always)]
120 fn collect_to_blink_no_drop<A: BlinkAllocator>(self, blink: &mut Blink<A>) -> &mut [Self::Item]
121 where
122 Self: Sized,
123 {
124 blink.emplace_no_drop().from_iter(self)
125 }
126
127 /// Attempts to collect iterator into blink allocator and return slice reference.
128 #[inline(always)]
129 #[allow(clippy::type_complexity)]
130 fn try_collect_to_blink<A: BlinkAllocator>(
131 self,
132 blink: &mut Blink<A>,
133 ) -> Result<&mut [Self::Item], (&mut [Self::Item], Option<Self::Item>)>
134 where
135 Self: Sized,
136 Self::Item: 'static,
137 {
138 blink.emplace().try_from_iter(self)
139 }
140
141 /// Attempts to collect iterator into blink allocator and return slice reference.
142 #[inline(always)]
143 #[allow(clippy::type_complexity)]
144 fn try_collect_to_blink_shared<A: BlinkAllocator>(
145 self,
146 blink: &mut Blink<A>,
147 ) -> Result<&[Self::Item], (&[Self::Item], Option<Self::Item>)>
148 where
149 Self: Sized,
150 {
151 blink.emplace_shared().try_from_iter(self)
152 }
153
154 /// Attempts to collect iterator into blink allocator and return slice reference.
155 #[inline(always)]
156 #[allow(clippy::type_complexity)]
157 fn try_collect_to_blink_no_drop<A: BlinkAllocator>(
158 self,
159 blink: &mut Blink<A>,
160 ) -> Result<&mut [Self::Item], (&mut [Self::Item], Option<Self::Item>)>
161 where
162 Self: Sized,
163 {
164 blink.emplace_no_drop().try_from_iter(self)
165 }
166}
167
168impl<I> IteratorExt for I where I: Iterator {}
169
170switch_alloc_default! {
171 /// An allocator adaptor for designed for blink allocator.
172 /// Provides user-friendly methods to emplace values into allocated memory.
173 /// Supports emplace existing, constructing value in allocated memory directly or indirectly.
174 /// And also emplacing items yield from iterator into contiguous memory and returning slice reference.
175 ///
176 /// [`Blink`] calls [`Drop::drop`] for emplaced values when reset or dropped.
177 /// This allows to use [`Blink`] instead of collections in some scenarios without needing to enable [`allocation_api`] feature.
178 ///
179 /// A blink-allocator adapter for user-friendly safe allocations
180 /// without use of collections.
181 ///
182 /// Provides an ability to emplace values into allocated memory,
183 /// baked by the associated blink-allocator instance.
184 /// And returns mutable reference to the value.
185 /// Values can be emplaced by move, by construction in allocated memory
186 /// (when compiler likes us), from iterators etc.
187 /// Most operations are provided in two flavors:
188 /// `try_` prefixed methods returns `Result` with allocation errors.
189 /// And non-prefixed methods calls [`handle_alloc_error`] method
190 /// (unless "alloc" feature is not enabled, in this case it panics).
191 /// Non-prefixed methods require "no_global_oom_handling" feature cfg is disabled.
192 ///
193 /// [`Blink`] can be reset by calling `reset` method.
194 /// It drops all emplaced values and resets associated allocator instance.
195 /// If allocator instance is shared, resetting it will have no effect.
196 ///
197 /// [`handle_alloc_error`]: alloc::alloc::handle_alloc_error
198 /// [`allocation_api`]: https://doc.rust-lang.org/beta/unstable-book/library-features/allocator-api.html
199 pub struct Blink<A = +BlinkAlloc<Global>> {
200 drop_list: DropList,
201 alloc: A,
202 }
203}
204
205impl<A> Drop for Blink<A> {
206 #[inline(always)]
207 fn drop(&mut self) {
208 self.drop_all();
209 }
210}
211
212// Safety: `Blink` is not auto-send because of `DropList`.
213// The `DropList` contains pointers to objects allocated from `Blink`.
214// If `Blink` is moved to another thread (or `&mut Blink`) then all returned pointers
215// to allocated objects were invalidated.
216unsafe impl<A> Send for Blink<A> where A: Send {}
217
218impl<A> Default for Blink<A>
219where
220 A: Default,
221{
222 fn default() -> Self {
223 Blink::new_in(Default::default())
224 }
225}
226
227#[cfg(feature = "alloc")]
228impl Blink<BlinkAlloc<Global>> {
229 /// Creates new blink instance with `BlinkAlloc` baked by `Global`
230 /// allocator.
231 ///
232 /// # Examples
233 ///
234 /// ```
235 /// use blink_alloc::Blink;
236 /// let mut blink = Blink::new();
237 ///
238 /// blink.put(42);
239 /// ```
240 #[inline(always)]
241 pub const fn new() -> Self {
242 Blink::new_in(BlinkAlloc::new())
243 }
244
245 /// Creates new blink instance with `BlinkAlloc` baked by `Global`
246 /// allocator.
247 /// `BlinkAlloc` receives starting chunk size.
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// use blink_alloc::Blink;
253 /// let mut blink = Blink::with_chunk_size(16);
254 ///
255 /// blink.put(42);
256 #[inline(always)]
257 pub const fn with_chunk_size(capacity: usize) -> Self {
258 Blink::new_in(BlinkAlloc::with_chunk_size(capacity))
259 }
260}
261
262impl<A> Blink<A> {
263 /// Creates new blink instance with provided allocator instance.
264 #[inline(always)]
265 pub const fn new_in(alloc: A) -> Self {
266 Blink {
267 drop_list: DropList::new(),
268 alloc,
269 }
270 }
271
272 /// Returns reference to allocator instance.
273 #[inline(always)]
274 pub fn allocator(&self) -> &A {
275 &self.alloc
276 }
277
278 /// Drops all allocated values.
279 ///
280 /// Prefer to use `reset` method if associated allocator instance supports it.
281 #[inline(always)]
282 pub fn drop_all(&mut self) {
283 self.drop_list.reset();
284 }
285}
286
287impl<A> Blink<A>
288where
289 A: BlinkAllocator,
290{
291 /// Drops all allocated values.
292 /// And resets associated allocator instance.
293 #[inline(always)]
294 pub fn reset(&mut self) {
295 self.drop_list.reset();
296 self.alloc.reset();
297 }
298
299 /// Allocates memory for a copy of the slice.
300 /// If allocation fails, returns `Err`.
301 /// Otherwise copies the slice into the allocated memory and returns
302 /// mutable reference to the copy.
303 #[inline]
304 unsafe fn _try_copy_slice<'a, T, E>(
305 &'a self,
306 slice: &[T],
307 alloc_err: impl FnOnce(Layout) -> E,
308 ) -> Result<&'a mut [T], E>
309 where
310 T: Copy,
311 {
312 let layout = Layout::for_value(slice);
313 let Ok(ptr) = self.alloc.allocate(layout) else {
314 return Err(alloc_err(layout));
315 };
316
317 let ptr = ptr.as_ptr().cast();
318 core::ptr::copy_nonoverlapping(slice.as_ptr(), ptr, slice.len());
319 Ok(core::slice::from_raw_parts_mut(ptr, slice.len()))
320 }
321
322 unsafe fn _try_emplace_drop<'a, T, I, G: 'a, E>(
323 &'a self,
324 init: I,
325 f: impl FnOnce(&mut EmplaceSlot<T, G>, I),
326 err: impl FnOnce(G) -> E,
327 alloc_err: impl FnOnce(I, Layout) -> E,
328 ) -> Result<&'a mut T, E> {
329 let layout = Layout::new::<DropItem<Result<T, ManuallyDrop<E>>>>();
330
331 let Ok(ptr) = self.alloc.allocate(layout) else {
332 return Err(alloc_err(init, layout));
333 };
334
335 // Safety: `item_ptr` is a valid pointer to allocated memory for type `DropItem<T>`.
336 let item = unsafe { DropItem::init_value(ptr.cast(), init, f) };
337
338 if item.value.is_ok() {
339 match self.drop_list.add(item) {
340 Ok(value) => return Ok(value),
341 _ => unreachable!(),
342 }
343 }
344
345 match &mut item.value {
346 Err(g) => {
347 let err = err(unsafe { ManuallyDrop::take(g) });
348 // Give memory back.
349 self.alloc.deallocate(ptr.cast(), layout);
350 Err(err)
351 }
352 _ => unreachable!(),
353 }
354 }
355
356 unsafe fn _try_emplace_no_drop<'a, T, I, G: 'a, E>(
357 &self,
358 init: I,
359 f: impl FnOnce(&mut EmplaceSlot<T, G>, I),
360 err: impl FnOnce(G) -> E,
361 alloc_err: impl FnOnce(I, Layout) -> E,
362 ) -> Result<&'a mut T, E> {
363 let layout = Layout::new::<T>();
364 let Ok(ptr) = self.alloc.allocate(layout) else {
365 return Err(alloc_err(init, layout));
366 };
367
368 // Safety: `ptr` is a valid pointer to allocated memory.
369 // Allocated with this `T`'s layout.
370 // Duration of the allocation is until next call to [`BlinkAlloc::reset`].
371
372 let uninit = &mut *ptr.as_ptr().cast();
373 f(uninit, init);
374
375 match uninit.assume_init_mut() {
376 Ok(value) => Ok(value),
377 Err(g) => {
378 let err = err(unsafe { ManuallyDrop::take(g) });
379 // Give memory back.
380 self.alloc.deallocate(ptr.cast(), layout);
381 Err(err)
382 }
383 }
384 }
385
386 /// Allocates memory for a value and emplaces value into the memory
387 /// using init value and provided closure.
388 /// If allocation fails, returns `Err(init)`.
389 /// Otherwise calls closure consuming `init`
390 /// and initializes memory with closure result.
391 #[inline(always)]
392 unsafe fn _try_emplace<'a, T, I, G: 'a, E>(
393 &'a self,
394 init: I,
395 f: impl FnOnce(&mut EmplaceSlot<T, G>, I),
396 no_drop: bool,
397 err: impl FnOnce(G) -> E,
398 alloc_err: impl FnOnce(I, Layout) -> E,
399 ) -> Result<&'a mut T, E> {
400 if !needs_drop::<T>() || no_drop {
401 self._try_emplace_no_drop(init, f, err, alloc_err)
402 } else {
403 self._try_emplace_drop(init, f, err, alloc_err)
404 }
405 }
406
407 unsafe fn _try_emplace_drop_from_iter<'a, T: 'a, I, E>(
408 &'a self,
409 mut iter: I,
410 err: impl FnOnce(&'a mut [T], Option<T>, Option<Layout>) -> E,
411 ) -> Result<&'a mut [T], E>
412 where
413 I: Iterator<Item = T>,
414 {
415 if size_of::<T>() == 0 {
416 let item_layout = Layout::new::<DropItem<[T; 0]>>();
417 let Ok(ptr) = self.alloc.allocate(item_layout) else {
418 return Err(err(&mut [], None, Some(item_layout)));
419 };
420 // Drain elements from iterator.
421 // Stop at `usize::MAX`.
422 // Drop exactly this number of elements on reset.
423 let count = saturating_drain_iter(iter);
424 let (item, slice) = DropItem::init_slice(ptr.cast(), count);
425 self.drop_list.add(item);
426 return Ok(slice);
427 }
428
429 struct Guard<'a, T: 'a, A: BlinkAllocator> {
430 ptr: Option<NonNull<DropItem<[T; 0]>>>,
431 count: usize,
432 cap: usize,
433 layout: Layout,
434 alloc: &'a A,
435 drop_list: &'a DropList,
436 }
437
438 impl<'a, T, A> Drop for Guard<'a, T, A>
439 where
440 A: BlinkAllocator,
441 {
442 #[inline(always)]
443 fn drop(&mut self) {
444 self.flush();
445 }
446 }
447
448 impl<'a, T, A> Guard<'a, T, A>
449 where
450 A: BlinkAllocator,
451 {
452 #[inline(always)]
453 fn flush(&mut self) -> &'a mut [T] {
454 match self.ptr.take() {
455 Some(ptr) if self.count != 0 => {
456 // if self.count < self.cap {
457 // // shrink the allocation to the actual size.
458 // // `BlinkAllocator` guarantees that this will not fail
459 // // be a no-op.
460
461 // let item_layout = Layout::new::<DropItem<[T; 0]>>();
462
463 // let (new_layout, _) = Layout::array::<T>(self.count)
464 // .and_then(|array| item_layout.extend(array))
465 // .expect("Smaller than actual allocation");
466
467 // // Safety:
468 // // Shrinking the allocation to the actual used size.
469 // let new_ptr =
470 // unsafe { self.alloc.shrink(ptr.cast(), self.layout, new_layout) }
471 // .expect("BlinkAllocator guarantees this will succeed");
472
473 // ptr = new_ptr.cast();
474 // }
475
476 // Safety: `item` was properly initialized.
477 let (item, slice) = unsafe { DropItem::init_slice(ptr, self.count) };
478 unsafe {
479 self.drop_list.add(item);
480 }
481 slice
482 }
483 Some(ptr) => unsafe {
484 self.alloc.deallocate(ptr.cast(), self.layout);
485 &mut []
486 },
487 None => &mut [],
488 }
489 }
490
491 #[inline(always)]
492 fn fill(
493 &mut self,
494 size_hint: usize,
495 one_more_elem: &mut Option<T>,
496 iter: &mut impl Iterator<Item = T>,
497 ) -> Result<(), Option<Layout>> {
498 let Ok(array_layout) = Layout::array::<T>(size_hint) else {
499 return Err(None);
500 };
501
502 let item_layout = Layout::new::<DropItem<[T; 0]>>();
503 let Ok((full_layout, array_offset)) = item_layout.extend(array_layout) else {
504 return Err(None);
505 };
506
507 debug_assert_eq!(array_offset, size_of::<DropItem<[T; 0]>>());
508
509 let res = match self.ptr {
510 None => self.alloc.allocate(full_layout),
511 Some(ptr) => unsafe { self.alloc.grow(ptr.cast(), self.layout, full_layout) },
512 };
513
514 let Ok(ptr) = res else {
515 return Err(Some(full_layout));
516 };
517 self.layout = full_layout;
518
519 let item_ptr = ptr.cast();
520 self.ptr = Some(item_ptr);
521
522 let len = ptr.len();
523 if len > full_layout.size() {
524 self.cap = (len - size_of::<DropItem<[T; 0]>>()) / size_of::<T>()
525 } else {
526 debug_assert_eq!(len, full_layout.size());
527 self.cap = size_hint;
528 };
529
530 let array_ptr = unsafe { item_ptr.as_ptr().add(1).cast::<T>() };
531
532 if let Some(one_more_elem) = one_more_elem.take() {
533 debug_assert!(self.count < self.cap);
534
535 // Safety: `array_ptr` is a valid pointer to allocated memory for type `[T; hint]`.
536 // And `hint` is larger than `self.count`
537 unsafe {
538 ptr::write(array_ptr.add(self.count), one_more_elem);
539 }
540 self.count += 1;
541 }
542
543 for idx in self.count..self.cap {
544 if Layout::new::<Option<T>>() == Layout::new::<T>() {
545 // Putting elements directly into the array.
546
547 let elem = unsafe {
548 in_place(array_ptr.add(idx).cast(), &mut *iter, Iterator::next)
549 };
550
551 if elem.is_none() {
552 break;
553 }
554 } else {
555 match iter.next() {
556 None => break,
557 Some(elem) => unsafe { ptr::write(array_ptr.add(idx), elem) },
558 }
559 }
560 self.count = idx + 1;
561 }
562
563 Ok(())
564 }
565 }
566
567 let mut guard = Guard {
568 ptr: None,
569 count: 0,
570 cap: 0,
571 layout: Layout::new::<()>(),
572 alloc: &self.alloc,
573 drop_list: &self.drop_list,
574 };
575
576 let (lower, _) = iter.size_hint();
577
578 if lower != 0 {
579 if let Err(layout) = guard.fill(lower.max(FASTER_START), &mut None, &mut iter) {
580 return Err(err(guard.flush(), None, layout));
581 }
582 }
583
584 let mut one_more = iter.next();
585 if one_more.is_none() {
586 return Ok(guard.flush());
587 };
588 cold();
589
590 loop {
591 let (lower, upper) = iter.size_hint();
592 let Some(size_hint) = size_hint_and_one(lower, upper, guard.count.max(FASTER_START))
593 else {
594 return Err(err(guard.flush(), one_more, None));
595 };
596
597 if let Err(layout) = guard.fill(size_hint, &mut one_more, &mut iter) {
598 return Err(err(guard.flush(), one_more, layout));
599 }
600
601 one_more = iter.next();
602 if one_more.is_none() {
603 return Ok(guard.flush());
604 };
605 }
606 }
607
608 unsafe fn _try_emplace_no_drop_from_iter<'a, T: 'a, I, E>(
609 &'a self,
610 mut iter: I,
611 err: impl FnOnce(&'a mut [T], Option<T>, Option<Layout>) -> E,
612 ) -> Result<&'a mut [T], E>
613 where
614 I: Iterator<Item = T>,
615 {
616 if size_of::<T>() == 0 {
617 // Drain elements from iterator.
618 // Stop at `usize::MAX`.
619 // Drop exactly this number of elements on reset.
620 let count = saturating_drain_iter(iter);
621 let ptr = NonNull::<T>::dangling();
622 let slice = core::slice::from_raw_parts_mut(ptr.as_ptr(), count);
623 return Ok(slice);
624 }
625
626 struct Guard<'a, T: 'a, A: BlinkAllocator> {
627 ptr: Option<NonNull<T>>,
628 count: usize,
629 cap: usize,
630 layout: Layout,
631 alloc: &'a A,
632 }
633
634 impl<'a, T, A> Guard<'a, T, A>
635 where
636 A: BlinkAllocator,
637 {
638 #[inline(always)]
639 fn flush(&mut self) -> &'a mut [T] {
640 match self.ptr.take() {
641 Some(ptr) if self.count != 0 => {
642 // if self.count < self.cap {
643 // // shrink the allocation to the actual size.
644 // // `BlinkAllocator` guarantees that this will not fail
645 // // be a no-op.
646
647 // let new_layout = Layout::array::<T>(self.count)
648 // .expect("Smaller than actual allocation");
649
650 // // Safety:
651 // // Shrinking the allocation to the actual used size.
652 // let new_ptr =
653 // unsafe { self.alloc.shrink(ptr.cast(), self.layout, new_layout) }
654 // .expect("BlinkAllocator guarantees this will succeed");
655
656 // ptr = new_ptr.cast();
657 // }
658
659 // Safety: reallocated for slice of size `self.count`
660 unsafe { &mut *core::slice::from_raw_parts_mut(ptr.as_ptr(), self.count) }
661 }
662 Some(ptr) => {
663 unsafe { self.alloc.deallocate(ptr.cast(), self.layout) };
664 &mut []
665 }
666 None => &mut [],
667 }
668 }
669
670 #[inline(always)]
671 fn fill(
672 &mut self,
673 size_hint: usize,
674 one_more_elem: &mut Option<T>,
675 iter: &mut impl Iterator<Item = T>,
676 ) -> Result<(), Option<Layout>> {
677 let Ok(full_layout) = Layout::array::<T>(size_hint) else {
678 return Err(None);
679 };
680
681 let res = match self.ptr {
682 None => self.alloc.allocate(full_layout),
683 Some(ptr) => unsafe { self.alloc.grow(ptr.cast(), self.layout, full_layout) },
684 };
685
686 let Ok(ptr) = res else {
687 return Err(Some(full_layout));
688 };
689
690 self.layout = full_layout;
691 self.ptr = Some(ptr.cast());
692
693 let len = ptr.len();
694 if len > full_layout.size() {
695 self.cap = len / size_of::<T>()
696 } else {
697 debug_assert_eq!(len, full_layout.size());
698 self.cap = size_hint;
699 };
700
701 let array_ptr = ptr.as_ptr().cast::<T>();
702
703 if let Some(one_more_elem) = one_more_elem.take() {
704 debug_assert!(self.count < self.cap);
705
706 // Safety: `array_ptr` is a valid pointer to allocated memory for type `[T; hint]`.
707 // And `hint` is larger than `self.count`
708 unsafe {
709 ptr::write(array_ptr.add(self.count), one_more_elem);
710 }
711 self.count += 1;
712 }
713
714 for idx in self.count..size_hint {
715 if Layout::new::<Option<T>>() == Layout::new::<T>() {
716 // Putting elements directly into the array.
717 let elem = unsafe {
718 in_place(array_ptr.add(idx).cast(), &mut *iter, Iterator::next)
719 };
720 if elem.is_none() {
721 break;
722 }
723 } else {
724 match iter.next() {
725 None => break,
726 Some(elem) => unsafe { ptr::write(array_ptr.add(idx), elem) },
727 }
728 }
729 self.count = idx + 1;
730 }
731
732 Ok(())
733 }
734 }
735
736 let mut guard = Guard {
737 ptr: None,
738 count: 0,
739 cap: 0,
740 layout: Layout::new::<T>(),
741 alloc: &self.alloc,
742 };
743
744 let (lower, _) = iter.size_hint();
745
746 if lower != 0 {
747 if let Err(layout) = guard.fill(lower.max(FASTER_START), &mut None, &mut iter) {
748 return Err(err(guard.flush(), None, layout));
749 }
750 }
751
752 let mut one_more = iter.next();
753 if one_more.is_none() {
754 return Ok(guard.flush());
755 };
756 cold();
757
758 loop {
759 let (lower, upper) = iter.size_hint();
760 let Some(size_hint) = size_hint_and_one(lower, upper, guard.count.max(FASTER_START))
761 else {
762 return Err(err(guard.flush(), one_more, None));
763 };
764
765 if let Err(layout) = guard.fill(size_hint, &mut one_more, &mut iter) {
766 return Err(err(guard.flush(), one_more, layout));
767 }
768
769 one_more = iter.next();
770 if one_more.is_none() {
771 return Ok(guard.flush());
772 };
773 }
774 }
775
776 /// Allocates memory for a value and emplaces value into the memory
777 /// using init value and provided closure.
778 /// If allocation fails, returns `Err(init)`.
779 /// Otherwise calls closure consuming `init`
780 /// and initializes memory with closure result.
781 #[inline(always)]
782 unsafe fn _try_emplace_from_iter<'a, T: 'a, I, E>(
783 &'a self,
784 iter: I,
785 no_drop: bool,
786 err: impl FnOnce(&'a mut [T], Option<T>, Option<Layout>) -> E,
787 ) -> Result<&'a mut [T], E>
788 where
789 I: IntoIterator<Item = T>,
790 {
791 if !needs_drop::<T>() || no_drop {
792 self._try_emplace_no_drop_from_iter(iter.into_iter(), err)
793 } else {
794 self._try_emplace_drop_from_iter(iter.into_iter(), err)
795 }
796 }
797}
798
799/// Provides interface for emplacing values.
800/// Created by [`Blink::emplace`], [`Blink::emplace_no_drop`]
801/// and [`Blink::emplace_unchecked`].
802pub struct Emplace<'a, A, T, R = &'a mut T, S = &'a mut [T]> {
803 blink: &'a Blink<A>,
804 no_drop: bool,
805 marker: PhantomData<fn(T) -> (R, S)>,
806}
807
808impl<'a, A, T, R, S> Emplace<'a, A, T, R, S>
809where
810 A: BlinkAllocator,
811 T: 'a,
812 R: CoerceFromMut<'a, T>,
813 S: CoerceFromMut<'a, [T]>,
814{
815 /// Allocates memory for a value and moves `value` into the memory.
816 /// If allocation fails, returns `Err(value)`.
817 /// On success returns reference to the emplaced value.
818 #[inline(always)]
819 pub fn try_value(&self, value: T) -> Result<R, T> {
820 unsafe {
821 self.blink._try_emplace(
822 value,
823 |slot, value| {
824 slot.write(Ok::<_, ManuallyDrop<Infallible>>(value));
825 },
826 self.no_drop,
827 |never| match never {},
828 |init, _| init,
829 )
830 }
831 .map(R::coerce)
832 }
833
834 /// Allocates memory for a value and moves `value` into the memory.
835 /// Returns reference to the emplaced value.
836 /// If allocation fails, diverges.
837 #[cfg(not(no_global_oom_handling))]
838 #[inline(always)]
839 pub fn value(&self, value: T) -> R {
840 R::coerce(
841 unsafe {
842 self.blink._try_emplace(
843 value,
844 |slot, value| {
845 slot.write(Ok::<_, ManuallyDrop<Infallible>>(value));
846 },
847 self.no_drop,
848 identity,
849 |_, layout| handle_alloc_error(layout),
850 )
851 }
852 .safe_ok(),
853 )
854 }
855
856 /// Allocates memory for a value.
857 /// On success invokes closure and initialize the value.
858 /// Returns reference to the value.
859 /// If allocation fails, returns error with closure.
860 #[inline(always)]
861 pub fn try_with<F>(&self, f: F) -> Result<R, F>
862 where
863 F: FnOnce() -> T,
864 {
865 unsafe {
866 self.blink._try_emplace(
867 f,
868 |slot, f| {
869 slot.write(Ok::<_, ManuallyDrop<Infallible>>(f()));
870 },
871 self.no_drop,
872 never,
873 |f, _| f,
874 )
875 }
876 .map(R::coerce)
877 }
878
879 /// Allocates memory for a value.
880 /// On success invokes closure and initialize the value.
881 /// Returns reference to the value.
882 /// If allocation fails, diverges.
883 #[cfg(not(no_global_oom_handling))]
884 #[inline(always)]
885 pub fn with<F>(&self, f: F) -> R
886 where
887 F: FnOnce() -> T,
888 {
889 R::coerce(
890 unsafe {
891 self.blink._try_emplace(
892 f,
893 |slot, f| {
894 slot.write(Ok::<_, ManuallyDrop<Infallible>>(f()));
895 },
896 self.no_drop,
897 never,
898 |_, layout| handle_alloc_error(layout),
899 )
900 }
901 .safe_ok(),
902 )
903 }
904 /// Allocates memory for a value.
905 /// If allocation fails, returns error with closure.
906 /// On success invokes closure and initialize the value.
907 /// If closure fails, returns the error.
908 /// Returns reference to the value.
909 #[inline(always)]
910 pub fn try_with_fallible<F, E>(&self, f: F) -> Result<R, Result<E, F>>
911 where
912 F: FnOnce() -> Result<T, E>,
913 E: 'a,
914 {
915 unsafe {
916 self.blink._try_emplace(
917 f,
918 |slot, f| {
919 slot.write(f().map_err(ManuallyDrop::new));
920 },
921 self.no_drop,
922 |err| Ok(err),
923 |f, _| Err(f),
924 )
925 }
926 .map(R::coerce)
927 }
928
929 /// Allocates memory for a value.
930 /// If allocation fails, returns error with closure.
931 /// On success invokes closure and initialize the value.
932 /// If closure fails, returns the error.
933 /// Returns reference to the value.
934 #[cfg(not(no_global_oom_handling))]
935 #[inline(always)]
936 pub fn with_fallible<F, E>(&self, f: F) -> Result<R, E>
937 where
938 F: FnOnce() -> Result<T, E>,
939 E: 'a,
940 {
941 unsafe {
942 self.blink._try_emplace(
943 f,
944 |slot, f| {
945 slot.write(f().map_err(ManuallyDrop::new));
946 },
947 self.no_drop,
948 identity,
949 |_, layout| handle_alloc_error(layout),
950 )
951 }
952 .map(R::coerce)
953 }
954
955 /// Allocates memory for an array and initializes it with
956 /// values from iterator.
957 /// Uses iterator hints to allocate memory.
958 /// If iterator yields more values than allocated array can hold,
959 /// grows allocation and moves next values to extended array.
960 /// Repeats until iterator is exhausted.
961 /// Works best on iterators that report accurate upper size hint.
962 /// Grows allocated memory potentially reducing number of allocations
963 /// and copies.
964 /// If allocation fails, returns slice of values emplaced so far.
965 /// And one element that was taken from iterator and not emplaced.
966 #[inline(always)]
967 pub fn try_from_iter<I>(&self, iter: I) -> Result<S, (S, Option<T>)>
968 where
969 I: IntoIterator<Item = T>,
970 {
971 unsafe {
972 self.blink
973 ._try_emplace_from_iter(iter, self.no_drop, |slice: &'a mut [T], value, _| {
974 (S::coerce(slice), value)
975 })
976 }
977 .map(S::coerce)
978 }
979
980 /// Allocates memory for an array and initializes it with
981 /// values from iterator.
982 /// Uses iterator hints to allocate memory.
983 /// If iterator yields more values than allocated array can hold,
984 /// grows allocation and moves next values to extended array.
985 /// Repeats until iterator is exhausted.
986 /// Works best on iterators that report accurate upper size hint.
987 /// Grows allocated memory potentially reducing number of allocations
988 /// and copies.
989 /// If allocation fails, diverges.
990 /// Values already emplaced will be dropped.
991 /// One last value that was taken from iterator and not emplaced
992 /// is dropped before this method returns.
993 #[cfg(not(no_global_oom_handling))]
994 #[inline(always)]
995 pub fn from_iter<I>(&self, iter: I) -> S
996 where
997 I: Iterator<Item = T>,
998 {
999 S::coerce(
1000 unsafe {
1001 self.blink
1002 ._try_emplace_from_iter(iter, self.no_drop, |_, _, layout| match layout {
1003 Some(layout) => handle_alloc_error(layout),
1004 None => size_overflow(),
1005 })
1006 }
1007 .safe_ok(),
1008 )
1009 }
1010}
1011
1012impl<A> Blink<A>
1013where
1014 A: BlinkAllocator,
1015{
1016 /// Puts value into this `Blink` instance.
1017 /// Returns reference to the value.
1018 ///
1019 /// Effectively extends lifetime of the value
1020 /// from local scope to the reset scope.
1021 ///
1022 /// For more flexible value placement see
1023 /// [`Blink::emplace`], [`Blink::emplace_no_drop`] and
1024 /// [`Blink::emplace_unchecked`].
1025 ///
1026 /// # Example
1027 ///
1028 /// ```
1029 /// # #[cfg(feature = "alloc")] fn main() {
1030 /// # use blink_alloc::Blink;
1031 /// let mut blink = Blink::new();
1032 /// let foo = blink.put(42);
1033 /// assert_eq!(*foo, 42);
1034 /// *foo = 24;
1035 /// blink.reset();
1036 /// // assert_eq!(*foo, 24); // Cannot compile. `foo` does not outlive reset.
1037 /// # }
1038 /// # #[cfg(not(feature = "alloc"))] fn main() {}
1039 /// ```
1040 #[cfg(not(no_global_oom_handling))]
1041 #[inline(always)]
1042 #[allow(clippy::mut_from_ref)]
1043 pub fn put<T: 'static>(&self, value: T) -> &mut T {
1044 unsafe {
1045 self._try_emplace(
1046 value,
1047 |slot, value| {
1048 slot.write(Ok::<_, ManuallyDrop<Infallible>>(value));
1049 },
1050 false,
1051 identity,
1052 |_, layout| handle_alloc_error(layout),
1053 )
1054 }
1055 .safe_ok()
1056 }
1057
1058 /// Puts value into this `Blink` instance.
1059 /// Returns reference to the value.
1060 ///
1061 /// The value will not be dropped when `Blink` is reset.
1062 ///
1063 /// Effectively extends lifetime of the value
1064 /// from local scope to the reset scope.
1065 ///
1066 /// For more flexible value placement see
1067 /// [`Blink::emplace`], [`Blink::emplace_no_drop`] and
1068 /// [`Blink::emplace_unchecked`].
1069 ///
1070 /// # Example
1071 ///
1072 /// ```
1073 /// # #[cfg(feature = "alloc")] fn main() {
1074 /// # use blink_alloc::Blink;
1075 /// let mut blink = Blink::new();
1076 /// let foo = blink.put(42);
1077 /// assert_eq!(*foo, 42);
1078 /// *foo = 24;
1079 /// blink.reset();
1080 /// // assert_eq!(*foo, 24); // Cannot compile. `foo` does not outlive reset.
1081 /// # }
1082 /// # #[cfg(not(feature = "alloc"))] fn main() {}
1083 /// ```
1084 #[cfg(not(no_global_oom_handling))]
1085 #[inline(always)]
1086 #[allow(clippy::mut_from_ref)]
1087 pub fn put_no_drop<T>(&self, value: T) -> &mut T {
1088 unsafe {
1089 self._try_emplace(
1090 value,
1091 |slot, value| {
1092 slot.write(Ok::<_, ManuallyDrop<Infallible>>(value));
1093 },
1094 true,
1095 identity,
1096 |_, layout| handle_alloc_error(layout),
1097 )
1098 }
1099 .safe_ok()
1100 }
1101
1102 /// Allocates memory for a value.
1103 /// Returns some reference to the uninitialized value.
1104 /// If allocation fails, returns none.
1105 #[inline(always)]
1106 pub fn try_uninit<T>(&self) -> Option<&mut MaybeUninit<T>> {
1107 let layout = Layout::new::<T>();
1108 let ptr = self.alloc.allocate(layout).ok()?;
1109
1110 // Safety:
1111 // - `ptr` is valid for `layout`.
1112 // - `MaybeUninit` is always initialized.
1113 Some(unsafe { &mut *ptr.as_ptr().cast() })
1114 }
1115
1116 /// Allocates memory for a value.
1117 /// Returns reference to the uninitialized value.
1118 #[cfg(not(no_global_oom_handling))]
1119 #[inline(always)]
1120 #[allow(clippy::mut_from_ref)]
1121 pub fn uninit<T>(&self) -> &mut MaybeUninit<T> {
1122 let layout = Layout::new::<T>();
1123 let ptr = self
1124 .alloc
1125 .allocate(layout)
1126 .unwrap_or_else(|_| handle_alloc_error(layout));
1127
1128 // Safety:
1129 // - `ptr` is valid for `layout`.
1130 // - `MaybeUninit` is always initialized.
1131 unsafe { &mut *ptr.as_ptr().cast() }
1132 }
1133
1134 /// Copies the slice to the allocated memory
1135 /// and returns reference to the new slice.
1136 #[cfg(not(no_global_oom_handling))]
1137 #[inline(always)]
1138 #[allow(clippy::mut_from_ref)]
1139 pub fn copy_slice<T>(&self, slice: &[T]) -> &mut [T]
1140 where
1141 T: Copy,
1142 {
1143 let result = unsafe { self._try_copy_slice(slice, handle_alloc_error) };
1144 match result {
1145 Ok(slice) => slice,
1146 Err(never) => never,
1147 }
1148 }
1149
1150 /// Allocates memory for a copy of the slice.
1151 /// Copies the slice to the allocated memory
1152 /// and returns reference to the new slice.
1153 /// If allocation fails, returns `None`.
1154 #[inline(always)]
1155 pub fn try_copy_slice<T>(&self, slice: &[T]) -> Option<&mut [T]>
1156 where
1157 T: Copy,
1158 {
1159 unsafe { self._try_copy_slice(slice, |_| ()) }.ok()
1160 }
1161
1162 /// Copies the slice to the allocated memory
1163 /// and returns reference to the new slice.
1164 #[cfg(not(no_global_oom_handling))]
1165 #[inline(always)]
1166 #[allow(clippy::mut_from_ref)]
1167 pub fn copy_str(&self, string: &str) -> &mut str {
1168 let result = unsafe { self._try_copy_slice(string.as_bytes(), handle_alloc_error) };
1169 match result {
1170 Ok(slice) => unsafe { core::str::from_utf8_unchecked_mut(slice) },
1171 Err(never) => never,
1172 }
1173 }
1174
1175 /// Allocates memory for a copy of the slice.
1176 /// Copies the slice to the allocated memory
1177 /// and returns reference to the new slice.
1178 /// If allocation fails, returns `None`.
1179 #[inline(always)]
1180 pub fn try_copy_str(&self, string: &str) -> Option<&mut str> {
1181 unsafe { self._try_copy_slice(string.as_bytes(), |_| ()) }
1182 .ok()
1183 .map(|bytes| unsafe { core::str::from_utf8_unchecked_mut(bytes) })
1184 }
1185
1186 /// Returns an `Emplace` adaptor that can emplace values into
1187 /// the blink allocator.
1188 ///
1189 /// This version requires the value type to be `'static`.
1190 /// To use with non-static types consider using one of the following:
1191 ///
1192 /// * [`Blink::emplace_no_drop`]
1193 /// Causes emplaced value to not be dropped on reset.
1194 /// Avoiding potential unsoundness in `Drop` implementation.
1195 /// * [`Blink::emplace_shared`]
1196 /// Returns shared reference to emplaced values.
1197 /// * [`Blink::emplace_unchecked`]
1198 /// Unsafe version of `emplace`.
1199 /// User must guarantee that the value won't have access to references
1200 /// allocated by the blink allocator later.
1201 ///
1202 /// # Example
1203 ///
1204 /// ```
1205 /// # #[cfg(feature = "alloc")] fn main() {
1206 /// # use blink_alloc::Blink;
1207 /// let mut blink = Blink::new();
1208 /// let foo = blink.put(42);
1209 /// assert_eq!(*foo, 42);
1210 /// *foo = 24;
1211 /// blink.reset();
1212 /// // assert_eq!(*foo, 24); // Cannot compile. `foo` does not outlive reset.
1213 /// # }
1214 /// # #[cfg(not(feature = "alloc"))] fn main() {}
1215 /// ```
1216 #[inline(always)]
1217 pub fn emplace<T: 'static>(&self) -> Emplace<'_, A, T> {
1218 Emplace {
1219 blink: self,
1220 no_drop: false,
1221 marker: PhantomData,
1222 }
1223 }
1224
1225 /// Returns an `Emplace` adaptor that can emplace values into
1226 /// the blink allocator.
1227 ///
1228 /// This version causes emplaced value to be not-dropped on reset.
1229 /// To drop returned value on reset, consider one of the following:
1230 ///
1231 /// * [`Blink::emplace`]
1232 /// Requires the value type to be `'static`.
1233 /// * [`Blink::emplace_shared`]
1234 /// Returns shared reference to emplaced values.
1235 /// * [`Blink::emplace_unchecked`]
1236 /// Unsafe version of `emplace`.
1237 /// User must guarantee that the value won't have access to references
1238 /// allocated by the blink allocator later.
1239 ///
1240 /// # Example
1241 ///
1242 /// ```
1243 /// # #[cfg(feature = "alloc")] fn main() {
1244 /// # use blink_alloc::Blink;
1245 /// struct Foo<'a>(&'a String);
1246 ///
1247 /// impl Drop for Foo<'_> {
1248 /// fn drop(&mut self) {
1249 /// println!("{}", self.0);
1250 /// }
1251 /// }
1252 ///
1253 /// let mut blink = Blink::new();
1254 /// let s = "Hello".to_owned();
1255 /// let foo = blink.emplace_no_drop().value(Foo(&s));
1256 /// assert_eq!(foo.0, "Hello");
1257 /// let world = blink.put("World".to_owned());
1258 /// // Would be unsound if `foo` could be dropped.
1259 /// foo.0 = world;
1260 /// blink.reset();
1261 /// // assert_eq!(foo.0, "Universe"); // Cannot compile. `foo` does not outlive reset.
1262 /// # }
1263 /// # #[cfg(not(feature = "alloc"))] fn main() {}
1264 /// ```
1265 #[inline(always)]
1266 pub fn emplace_no_drop<T>(&self) -> Emplace<'_, A, T> {
1267 Emplace {
1268 blink: self,
1269 no_drop: true,
1270 marker: PhantomData,
1271 }
1272 }
1273
1274 /// Returns an `Emplace` adaptor that can emplace values into
1275 /// the blink allocator.
1276 ///
1277 /// This version returns shared references to emplaced values.
1278 /// Lifts the `'static` requirement.
1279 /// Still allows emplaced values to be dropped on reset.
1280 ///
1281 /// To drop returned value on reset, consider one of the following:
1282 ///
1283 /// * [`Blink::emplace`]
1284 /// Requires the value type to be `'static`.
1285 /// * [`Blink::emplace_no_drop`]
1286 /// Causes emplaced value to not be dropped on reset.
1287 /// Avoiding potential unsoundness in `Drop` implementation.
1288 /// * [`Blink::emplace_unchecked`]
1289 /// Unsafe version of `emplace`.
1290 /// User must guarantee that the value won't have access to references
1291 /// allocated by the blink allocator later.
1292 ///
1293 ///
1294 /// ```
1295 /// # #[cfg(feature = "alloc")] fn main() {
1296 /// # use blink_alloc::Blink;
1297 /// struct Foo<'a>(&'a String);
1298 ///
1299 /// impl Drop for Foo<'_> {
1300 /// fn drop(&mut self) {
1301 /// println!("{}", self.0);
1302 /// }
1303 /// }
1304 ///
1305 /// let mut blink = Blink::new();
1306 /// let s = "Hello".to_owned();
1307 /// let foo = blink.emplace_no_drop().value(Foo(&s));
1308 /// assert_eq!(foo.0, "Hello");
1309 /// let world = blink.put("World".to_owned());
1310 /// // Would be unsound if `foo` was mutable.
1311 /// // foo.0 = world;
1312 /// blink.reset();
1313 /// // assert_eq!(foo.0, "Universe"); // Cannot compile. `foo` does not outlive reset.
1314 /// # }
1315 /// # #[cfg(not(feature = "alloc"))] fn main() {}
1316 /// ```
1317 #[inline(always)]
1318 pub fn emplace_shared<T>(&self) -> Emplace<'_, A, T, &T, &[T]> {
1319 Emplace {
1320 blink: self,
1321 no_drop: true,
1322 marker: PhantomData,
1323 }
1324 }
1325
1326 /// Returns an `Emplace` adaptor that can emplace values into
1327 /// the blink allocator.
1328 ///
1329 /// This is unsafe version of [`Blink::emplace`].
1330 /// User must guarantee that values won't attempt to access
1331 /// memory allocated by the blink allocator later in their [`Drop::drop`]
1332 /// For safe code consider using one of the following:
1333 ///
1334 /// * [`Blink::emplace`]
1335 /// Requires the value type to be `'static`.
1336 /// * [`Blink::emplace_no_drop`]
1337 /// Causes emplaced value to not be dropped on reset.
1338 /// Avoiding potential unsoundness in `Drop` implementation.
1339 /// * [`Blink::emplace_shared`]
1340 /// Returns shared reference to emplaced values.
1341 ///
1342 /// # Safety
1343 ///
1344 /// Avoid incorrect usage. See below.
1345 ///
1346 /// # Incorrect usage example
1347 ///
1348 /// Other emplace methods are safe as they guarantee following case
1349 /// is impossible.
1350 ///
1351 /// ```no_run
1352 /// # #[cfg(feature = "alloc")] fn main() {
1353 /// # use blink_alloc::Blink;
1354 /// struct Foo<'a>(&'a String);
1355 ///
1356 /// impl Drop for Foo<'_> {
1357 /// fn drop(&mut self) {
1358 /// println!("{}", self.0);
1359 /// }
1360 /// }
1361 ///
1362 /// let mut blink = Blink::new();
1363 /// let s = "Hello".to_owned();
1364 /// let foo = blink.emplace_no_drop().value(Foo(&s));
1365 /// assert_eq!(foo.0, "Hello");
1366 /// let world = blink.put("World".to_owned());
1367 /// // Unsound since `foo` would access `world` in `Drop`
1368 /// // and `world` is dropped earlier.
1369 /// foo.0 = world;
1370 /// blink.reset();
1371 /// // assert_eq!(foo.0, "Universe"); // Cannot compile. `foo` does not outlive reset.
1372 /// # }
1373 /// # #[cfg(not(feature = "alloc"))] fn main() {}
1374 /// ```
1375 #[inline(always)]
1376 pub unsafe fn emplace_unchecked<T>(&self) -> Emplace<'_, A, T> {
1377 Emplace {
1378 blink: self,
1379 no_drop: false,
1380 marker: PhantomData,
1381 }
1382 }
1383}
1384
1385/// Wrapper for [`Blink`] that implements [`Send`].
1386///
1387/// Normally it is impossible to send [`Blink`] to another thread
1388/// due to the fact that it will drop non-sendable types on reset.
1389///
1390/// This wrapper resets [`Blink`] on construction and thus safe to send.
1391///
1392/// # Example
1393///
1394/// ```
1395/// # #[cfg(feature = "alloc")] fn main() {
1396/// # use blink_alloc::{SendBlink, Blink};
1397/// let mut blink = Blink::new();
1398/// let rc = std::rc::Rc::new(42);
1399/// let rc = blink.put(rc);
1400/// assert_eq!(**rc, 42);
1401/// let send_blink = SendBlink::new(blink);
1402///
1403/// std::thread::scope(move |_| {
1404/// let mut blink = send_blink.into_inner();
1405/// blink.put(42);
1406/// });
1407/// # }
1408/// # #[cfg(not(feature = "alloc"))] fn main() {}
1409/// ````
1410pub struct SendBlink<A> {
1411 blink: Blink<A>,
1412}
1413
1414impl<A> SendBlink<A>
1415where
1416 A: BlinkAllocator,
1417{
1418 /// Creates new [`SendBlink`] from [`Blink`].
1419 /// Resets the blink allocator to avoid dropping non-sendable types on other threads.
1420 #[inline(always)]
1421 pub fn new(mut blink: Blink<A>) -> Self {
1422 blink.reset();
1423 SendBlink { blink }
1424 }
1425
1426 /// Returns inner [`Blink`] value.
1427 #[inline(always)]
1428 pub fn into_inner(self) -> Blink<A> {
1429 self.blink
1430 }
1431}
1432
1433#[inline(always)]
1434fn never<T>(never: Infallible) -> T {
1435 match never {}
1436}
1437
1438const FASTER_START: usize = 8;
1439
1440#[inline]
1441fn size_hint_and_one(lower: usize, upper: Option<usize>, count: usize) -> Option<usize> {
1442 // Upper bound is limited by current size.
1443 // Constant for faster start.
1444 let upper = upper.map_or(count, |upper| upper.min(count));
1445 let size_hint = lower.max(upper);
1446
1447 // Add one more element to size hint.
1448 let size_hint = size_hint.checked_add(1)?;
1449
1450 // Sum with current count.
1451 count.checked_add(size_hint)
1452}
1453
1454#[inline]
1455fn saturating_drain_iter<T>(mut iter: impl Iterator<Item = T>) -> usize {
1456 let mut drained = 0;
1457 loop {
1458 let (lower, _) = iter.size_hint();
1459 if lower == 0 {
1460 match iter.next() {
1461 None => return drained,
1462 Some(_) => drained += 1,
1463 }
1464 continue;
1465 }
1466 // Don't drink too much.
1467 let lower = lower.min(usize::MAX - drained);
1468 match iter.nth(lower - 1) {
1469 None => {
1470 // This bastard lied about lower bound.
1471 // No idea how many elements were actually drained.
1472 return drained;
1473 }
1474 Some(_) => {
1475 drained += lower;
1476 }
1477 }
1478 if drained == usize::MAX {
1479 // Enough is enough.
1480 return usize::MAX;
1481 }
1482 }
1483}
1484
1485#[test]
1486fn test_iter_drain() {
1487 assert_eq!(5, saturating_drain_iter(0..5));
1488 assert_eq!(usize::MAX, saturating_drain_iter(0..usize::MAX));
1489 assert_eq!(usize::MAX, saturating_drain_iter(core::iter::repeat(1)));
1490}