diff options
| author | Mark-Simulacrum <mark.simulacrum@gmail.com> | 2016-11-02 22:33:35 -0600 |
|---|---|---|
| committer | Mark-Simulacrum <mark.simulacrum@gmail.com> | 2016-11-11 07:38:48 -0700 |
| commit | 7bbebb1f542e4431249faa1138da4cfcb6b9269a (patch) | |
| tree | 670a2512abae6206e3d6f8623d1302c839066346 /src/libsyntax/util/move_map.rs | |
| parent | 4da129d98419733bb408141ca53610bb77368cf0 (diff) | |
Change implementation of syntax::util::SmallVector to use data_structures::SmallVec.
Diffstat (limited to 'src/libsyntax/util/move_map.rs')
| -rw-r--r-- | src/libsyntax/util/move_map.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/libsyntax/util/move_map.rs b/src/libsyntax/util/move_map.rs index e1078b719bf..fe05e2958b3 100644 --- a/src/libsyntax/util/move_map.rs +++ b/src/libsyntax/util/move_map.rs @@ -10,6 +10,8 @@ use std::ptr; +use util::small_vector::SmallVector; + pub trait MoveMap<T>: Sized { fn move_map<F>(self, mut f: F) -> Self where F: FnMut(T) -> T { self.move_flat_map(|e| Some(f(e))) @@ -75,3 +77,50 @@ impl<T> MoveMap<T> for ::ptr::P<[T]> { ::ptr::P::from_vec(self.into_vec().move_flat_map(f)) } } + +impl<T> MoveMap<T> for SmallVector<T> { + fn move_flat_map<F, I>(mut self, mut f: F) -> Self + where F: FnMut(T) -> I, + I: IntoIterator<Item=T> + { + let mut read_i = 0; + let mut write_i = 0; + unsafe { + let mut old_len = self.len(); + self.set_len(0); // make sure we just leak elements in case of panic + + while read_i < old_len { + // move the read_i'th item out of the vector and map it + // to an iterator + let e = ptr::read(self.get_unchecked(read_i)); + let mut iter = f(e).into_iter(); + read_i += 1; + + while let Some(e) = iter.next() { + if write_i < read_i { + ptr::write(self.get_unchecked_mut(write_i), e); + write_i += 1; + } else { + // If this is reached we ran out of space + // in the middle of the vector. + // However, the vector is in a valid state here, + // so we just do a somewhat inefficient insert. + self.set_len(old_len); + self.insert(write_i, e); + + old_len = self.len(); + self.set_len(0); + + read_i += 1; + write_i += 1; + } + } + } + + // write_i tracks the number of actually written new items. + self.set_len(write_i); + } + + self + } +} |
