|  | 
| 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