#![cfg(feature="std")]
use range::IndexRange;
use std::ptr;
use std::slice;
use slice::SliceFind;
pub fn vec<I>(iterable: I) -> Vec<I::Item>
where I: IntoIterator
{
iterable.into_iter().collect()
}
pub trait VecExt<T> {
fn splice<R, I>(&mut self, r: R, iter: I)
where I: IntoIterator<Item=T>,
I::IntoIter: ExactSizeIterator,
R: IndexRange;
fn retain_mut<F>(&mut self, f: F)
where F: FnMut(&mut T) -> bool;
}
impl<T> VecExt<T> for Vec<T> {
fn splice<R, I>(&mut self, r: R, iter: I)
where I: IntoIterator<Item=T>,
I::IntoIter: ExactSizeIterator,
R: IndexRange,
{
let v = self;
let mut iter = iter.into_iter();
let (input_len, _) = iter.size_hint();
let old_len = v.len();
let r = r.start().unwrap_or(0)..r.end().unwrap_or(old_len);
assert!(r.start <= r.end);
assert!(r.end <= v.len());
let rm_len = r.end - r.start;
v.reserve(input_len.saturating_sub(rm_len));
unsafe {
let ptr = v.as_mut_ptr();
v.set_len(r.start);
{
let mslc = slice::from_raw_parts_mut(ptr.offset(r.start as isize), rm_len);
for elt_ptr in mslc {
ptr::read(elt_ptr); }
}
if rm_len != input_len {
ptr::copy(ptr.offset(r.end as isize),
ptr.offset((r.start + input_len) as isize),
old_len - r.end);
}
{
let grow_slc = slice::from_raw_parts_mut(ptr.offset(r.start as isize), input_len);
let mut len = r.start;
for slot_ptr in grow_slc {
if let Some(input_elt) = iter.next() { ptr::write(slot_ptr, input_elt);
} else {
panic!("splice: iterator too short");
}
len += 1;
v.set_len(len);
}
v.set_len(old_len - rm_len + input_len);
}
}
}
fn retain_mut<F>(&mut self, mut f: F)
where F: FnMut(&mut T) -> bool
{
let len = self.len();
let mut del = 0;
{
let v = &mut **self;
for i in 0..len {
if !f(&mut v[i]) {
del += 1;
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del > 0 {
self.truncate(len - del);
}
}
}
pub trait VecFindRemove {
type Item;
fn find_remove<U>(&mut self, elt: &U) -> Option<(usize, Self::Item)>
where Self::Item: PartialEq<U>;
fn rfind_remove<U>(&mut self, elt: &U) -> Option<(usize, Self::Item)>
where Self::Item: PartialEq<U>;
}
impl<T> VecFindRemove for Vec<T> {
type Item = T;
fn find_remove<U>(&mut self, elt: &U) -> Option<(usize, Self::Item)>
where Self::Item: PartialEq<U>
{
self.find(elt).map(|i| (i, self.remove(i)))
}
fn rfind_remove<U>(&mut self, elt: &U) -> Option<(usize, Self::Item)>
where Self::Item: PartialEq<U>
{
self.rfind(elt).map(|i| (i, self.remove(i)))
}
}
#[test]
fn test_splice() {
use std::iter::once;
let mut v = vec![1, 2, 3, 4];
v.splice(1..1, vec![9, 9]);
assert_eq!(v, &[1, 9, 9, 2, 3, 4]);
let mut v = vec![1, 2, 3, 4];
v.splice(1..2, vec![9, 9]);
assert_eq!(v, &[1, 9, 9, 3, 4]);
let mut v = vec![1, 2, 3, 4, 5];
v.splice(1..4, vec![9, 9]);
assert_eq!(v, &[1, 9, 9, 5]);
let mut v = vec![1, 2, 3, 4];
v.splice(0..4, once(9));
assert_eq!(v, &[9]);
let mut v = vec![1, 2, 3, 4];
v.splice(0..4, None);
assert_eq!(v, &[]);
let mut v = vec![1, 2, 3, 4];
v.splice(1.., Some(9));
assert_eq!(v, &[1, 9]);
}
#[test]
fn test_find() {
let mut v = vec![0, 1, 2, 3, 1, 2, 1];
assert_eq!(v.rfind_remove(&1), Some((6, 1)));
assert_eq!(v.find_remove(&2), Some((2, 2)));
assert_eq!(v.find_remove(&7), None);
assert_eq!(&v, &[0, 1, 3, 1, 2]);
}