|
|
|
@ -17,6 +17,77 @@ use tokio::{
|
|
|
|
|
};
|
|
|
|
|
use futures::future::Future;
|
|
|
|
|
|
|
|
|
|
pub trait FindSliceBounds
|
|
|
|
|
{
|
|
|
|
|
type SliceType: ?Sized;
|
|
|
|
|
fn slice_bounds(&self, from: &Self::SliceType) -> Range<usize>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait SliceInPlace
|
|
|
|
|
{
|
|
|
|
|
fn slice_in_place(&mut self, slice: Range<usize>);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SliceInPlace for String
|
|
|
|
|
{
|
|
|
|
|
fn slice_in_place(&mut self, slice: Range<usize>) {
|
|
|
|
|
let mut i=0;
|
|
|
|
|
self.retain(|_| (slice.contains(&i), i+=1).0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> SliceInPlace for Vec<T>
|
|
|
|
|
{
|
|
|
|
|
fn slice_in_place(&mut self, slice: Range<usize>) {
|
|
|
|
|
let mut i=0;
|
|
|
|
|
self.retain(|_| (slice.contains(&i), i+=1).0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: ?Sized + AsRef<str>> FindSliceBounds for T
|
|
|
|
|
{
|
|
|
|
|
type SliceType = str;
|
|
|
|
|
fn slice_bounds(&self, from: &Self::SliceType) -> Range<usize>{
|
|
|
|
|
let this = self.as_ref();
|
|
|
|
|
unsafe {
|
|
|
|
|
let sptr = from.as_ptr();
|
|
|
|
|
let eptr = sptr.add(from.len());
|
|
|
|
|
|
|
|
|
|
let ssptr = this.as_ptr();
|
|
|
|
|
let septr = ssptr.add(this.len());
|
|
|
|
|
|
|
|
|
|
let sptr = sptr as usize;
|
|
|
|
|
let ssptr = ssptr as usize;
|
|
|
|
|
let eptr = eptr as usize;
|
|
|
|
|
let septr = septr as usize;
|
|
|
|
|
|
|
|
|
|
assert!(sptr >= ssptr && sptr <= septr, "Start index of slice is outside the bounds of self");
|
|
|
|
|
assert!(eptr >= ssptr && eptr <= septr, "End index of slice is outside the bounds of self");
|
|
|
|
|
|
|
|
|
|
(sptr - ssptr)..(eptr - ssptr)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test_slice_in_place
|
|
|
|
|
{
|
|
|
|
|
use super::*;
|
|
|
|
|
#[test]
|
|
|
|
|
fn slice_in_place_str()
|
|
|
|
|
{
|
|
|
|
|
let mut string = String::from(" hello world ");
|
|
|
|
|
assert_eq!(&string[string.slice_bounds(string.trim())], string.trim());
|
|
|
|
|
assert_eq!(&string[string.slice_bounds(string.trim())], "hello world");
|
|
|
|
|
string.slice_in_place(string.slice_bounds(string.trim()));
|
|
|
|
|
assert_eq!(&string[..], "hello world");
|
|
|
|
|
let string = String::from("hello world");
|
|
|
|
|
assert_eq!(&string[string.slice_bounds(string.trim())], string.trim());
|
|
|
|
|
assert_eq!(&string[string.slice_bounds(string.trim())], "hello world");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct GroupIter<I, T, U=Box<[T]>>(std::iter::Fuse<I>, Vec<T>, usize, PhantomData<U>);
|
|
|
|
|
|
|
|
|
@ -78,7 +149,7 @@ pub trait GroupIterExt<I, T>: Sized
|
|
|
|
|
impl<T: IntoIterator> GroupIterExt<<T as IntoIterator>::IntoIter, <T as IntoIterator>::Item> for T
|
|
|
|
|
{
|
|
|
|
|
fn group_into<U>(self, every: usize) -> GroupIter<<T as IntoIterator>::IntoIter, <T as IntoIterator>::Item, U>
|
|
|
|
|
where U: From<Vec<<T as IntoIterator>::Item>>
|
|
|
|
|
where U: From<Vec<<T as IntoIterator>::Item>>
|
|
|
|
|
{
|
|
|
|
|
GroupIter(self.into_iter().fuse(), Vec::with_capacity(every), every, PhantomData)
|
|
|
|
|
}
|
|
|
|
@ -130,7 +201,7 @@ impl<'a, T: ?Sized> StrChunks<'a, T>
|
|
|
|
|
/// Set the number of chars to break at.
|
|
|
|
|
///
|
|
|
|
|
/// # Note
|
|
|
|
|
/// Probably don't do this unless you know what you're doing.
|
|
|
|
|
/// Probably don't do this as it modifies the iterators internal state weirdly. But it should be fine generally.
|
|
|
|
|
pub fn every_mut(&mut self) -> &mut usize
|
|
|
|
|
{
|
|
|
|
|
&mut self.1
|
|
|
|
|