rustc_data_structures/
flat_map_in_place.rs1use std::{mem, ptr};
2
3use smallvec::{Array, SmallVec};
4use thin_vec::ThinVec;
5
6pub trait FlatMapInPlace<T>: Sized {
7 fn flat_map_in_place<F, I>(&mut self, f: F)
8 where
9 F: FnMut(T) -> I,
10 I: IntoIterator<Item = T>;
11}
12
13macro_rules! flat_map_in_place {
16 ($vec:ident $( where T: $bound:path)?) => {
17 fn flat_map_in_place<F, I>(&mut self, mut f: F)
18 where
19 F: FnMut(T) -> I,
20 I: IntoIterator<Item = T>,
21 {
22 struct LeakGuard<'a, T $(: $bound)?>(&'a mut $vec<T>);
23
24 impl<'a, T $(: $bound)?> Drop for LeakGuard<'a, T> {
25 fn drop(&mut self) {
26 unsafe {
27 self.0.set_len(0); }
29 }
30 }
31
32 let this = LeakGuard(self);
33
34 let mut read_i = 0;
35 let mut write_i = 0;
36 unsafe {
37 while read_i < this.0.len() {
38 let e = ptr::read(this.0.as_ptr().add(read_i));
41 let iter = f(e).into_iter();
42 read_i += 1;
43
44 for e in iter {
45 if write_i < read_i {
46 ptr::write(this.0.as_mut_ptr().add(write_i), e);
47 write_i += 1;
48 } else {
49 this.0.insert(write_i, e);
54
55 read_i += 1;
56 write_i += 1;
57 }
58 }
59 }
60
61 this.0.set_len(write_i);
63
64 mem::forget(this);
66 }
67 }
68 };
69}
70
71impl<T> FlatMapInPlace<T> for Vec<T> {
72 flat_map_in_place!(Vec);
73}
74
75impl<T, A: Array<Item = T>> FlatMapInPlace<T> for SmallVec<A> {
76 flat_map_in_place!(SmallVec where T: Array);
77}
78
79impl<T> FlatMapInPlace<T> for ThinVec<T> {
80 flat_map_in_place!(ThinVec);
81}