|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
//! Extensions
|
|
|
|
|
use std::{
|
|
|
|
|
iter,
|
|
|
|
|
ops::Range,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub trait StringJoinExt: Sized
|
|
|
|
@ -25,3 +26,71 @@ where I: IntoIterator<Item=T>,
|
|
|
|
|
string
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait FindSliceBounds
|
|
|
|
|
{
|
|
|
|
|
type SliceType: ?Sized;
|
|
|
|
|
fn slice_bounds(&self, from: &Self::SliceType) -> Range<usize>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait SliceInPlace
|
|
|
|
|
{
|
|
|
|
|
fn drain_inverse<R: std::ops::RangeBounds<usize>>(&mut self, slice: R);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SliceInPlace for String
|
|
|
|
|
{
|
|
|
|
|
fn drain_inverse<R: std::ops::RangeBounds<usize>>(&mut self, slice: R)
|
|
|
|
|
{
|
|
|
|
|
use std::ops::Bound;
|
|
|
|
|
match slice.end_bound() {
|
|
|
|
|
Bound::Excluded(&ex) => drop(self.drain(ex..)),
|
|
|
|
|
Bound::Included(&inc) => drop(self.drain(inc+1..)),
|
|
|
|
|
_ => (),
|
|
|
|
|
};
|
|
|
|
|
match slice.start_bound() {
|
|
|
|
|
Bound::Included(&ex) => drop(self.drain(..ex)),
|
|
|
|
|
Bound::Excluded(&ex) => drop(..ex+1),
|
|
|
|
|
_ => ()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait TrimInPlace
|
|
|
|
|
{
|
|
|
|
|
fn trim_in_place(&mut self) -> &mut Self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl TrimInPlace for String
|
|
|
|
|
{
|
|
|
|
|
fn trim_in_place(&mut self) -> &mut Self {
|
|
|
|
|
let bounds = self.slice_bounds(self.trim());
|
|
|
|
|
self.drain_inverse(bounds);
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|