|
1 |
| -use std::ptr; |
| 1 | +use std::{mem, ptr}; |
2 | 2 |
|
3 | 3 | use smallvec::{Array, SmallVec};
|
4 | 4 | use thin_vec::ThinVec;
|
@@ -69,5 +69,55 @@ impl<T, A: Array<Item = T>> FlatMapInPlace<T> for SmallVec<A> {
|
69 | 69 | }
|
70 | 70 |
|
71 | 71 | impl<T> FlatMapInPlace<T> for ThinVec<T> {
|
72 |
| - flat_map_in_place!(); |
| 72 | + fn flat_map_in_place<F, I>(&mut self, mut f: F) |
| 73 | + where |
| 74 | + F: FnMut(T) -> I, |
| 75 | + I: IntoIterator<Item = T>, |
| 76 | + { |
| 77 | + struct LeakGuard<'a, T>(&'a mut ThinVec<T>); |
| 78 | + |
| 79 | + impl<'a, T> Drop for LeakGuard<'a, T> { |
| 80 | + fn drop(&mut self) { |
| 81 | + unsafe { |
| 82 | + self.0.set_len(0); // make sure we just leak elements in case of panic |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + let this = LeakGuard(self); |
| 88 | + |
| 89 | + let mut read_i = 0; |
| 90 | + let mut write_i = 0; |
| 91 | + unsafe { |
| 92 | + while read_i < this.0.len() { |
| 93 | + // move the read_i'th item out of the vector and map it |
| 94 | + // to an iterator |
| 95 | + let e = ptr::read(this.0.as_ptr().add(read_i)); |
| 96 | + let iter = f(e).into_iter(); |
| 97 | + read_i += 1; |
| 98 | + |
| 99 | + for e in iter { |
| 100 | + if write_i < read_i { |
| 101 | + ptr::write(this.0.as_mut_ptr().add(write_i), e); |
| 102 | + write_i += 1; |
| 103 | + } else { |
| 104 | + // If this is reached we ran out of space |
| 105 | + // in the middle of the vector. |
| 106 | + // However, the vector is in a valid state here, |
| 107 | + // so we just do a somewhat inefficient insert. |
| 108 | + this.0.insert(write_i, e); |
| 109 | + |
| 110 | + read_i += 1; |
| 111 | + write_i += 1; |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + // write_i tracks the number of actually written new items. |
| 117 | + this.0.set_len(write_i); |
| 118 | + |
| 119 | + // The ThinVec is in a sane state again. Prevent the LeakGuard from leaking the data. |
| 120 | + mem::forget(this); |
| 121 | + } |
| 122 | + } |
73 | 123 | }
|
0 commit comments