reusable_memory/borrow/
drain.rs

1use std::{
2	fmt,
3	ops::{Bound, Range, RangeBounds}
4};
5
6use super::ReusableMemoryBorrow;
7
8// Most of this code is copied from std Vec
9
10pub struct BorrowDrainIter<'bor, 'mem, T: 'mem> {
11	borrow: &'bor mut ReusableMemoryBorrow<'mem, T>,
12	drain_range: Range<usize>,
13
14	/// Start of the tail after the drained items
15	tail_start: usize,
16	/// Length of tail after the drained items
17	tail_len: usize
18}
19impl<'bor, 'mem: 'bor, T: 'mem> BorrowDrainIter<'bor, 'mem, T> {
20	pub(super) fn new(
21		borrow: &'bor mut ReusableMemoryBorrow<'mem, T>, range: impl RangeBounds<usize>
22	) -> Self {
23		let len = borrow.len();
24		let start = match range.start_bound() {
25			Bound::Included(&n) => n,
26			Bound::Excluded(&n) => n + 1,
27			Bound::Unbounded => 0
28		};
29		let end = match range.end_bound() {
30			Bound::Included(&n) => n + 1,
31			Bound::Excluded(&n) => n,
32			Bound::Unbounded => len
33		};
34		assert!(start <= end);
35		assert!(end <= len);
36
37		unsafe {
38			// Safety in case Drain is leaked
39			borrow.set_len(start);
40
41			Self { borrow, drain_range: start .. end, tail_start: end, tail_len: len - end }
42		}
43	}
44}
45impl<T: fmt::Debug> fmt::Debug for BorrowDrainIter<'_, '_, T> {
46	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47		f.debug_tuple("BorrowDrainIter")
48			.field(unsafe {
49				&std::slice::from_raw_parts(
50					self.borrow.as_ptr().add(self.drain_range.start),
51					self.drain_range.end - self.drain_range.start
52				)
53			})
54			.finish()
55	}
56}
57impl<T> Iterator for BorrowDrainIter<'_, '_, T> {
58	type Item = T;
59
60	fn next(&mut self) -> Option<T> {
61		self.drain_range
62			.next()
63			.map(|offset| unsafe { std::ptr::read(self.borrow.as_ptr().add(offset)) })
64	}
65
66	fn size_hint(&self) -> (usize, Option<usize>) { self.drain_range.size_hint() }
67}
68impl<T> DoubleEndedIterator for BorrowDrainIter<'_, '_, T> {
69	fn next_back(&mut self) -> Option<T> {
70		self.drain_range
71			.next_back()
72			.map(|offset| unsafe { std::ptr::read(self.borrow.as_ptr().add(offset)) })
73	}
74}
75impl<T> ExactSizeIterator for BorrowDrainIter<'_, '_, T> {}
76impl<T> Drop for BorrowDrainIter<'_, '_, T> {
77	fn drop(&mut self) {
78		// exhaust self first
79		self.for_each(drop);
80
81		if self.tail_len > 0 {
82			unsafe {
83				let start = self.borrow.len();
84				let tail = self.tail_start;
85				// There is some tail left and we need to memmove it
86				if start != tail {
87					let src = self.borrow.as_ptr().add(tail);
88					let dst = self.borrow.as_mut_ptr().add(start);
89					std::ptr::copy(src, dst, self.tail_len);
90				}
91
92				self.borrow.set_len(start + self.tail_len);
93			}
94		}
95	}
96}