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