| 
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