You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
genmarkov/src/ext.rs

97 lines
2.1 KiB

//! Extensions
use std::{
iter,
ops::Range,
};
pub trait StringJoinExt: Sized
{
fn join<P: AsRef<str>>(self, sep: P) -> String;
}
impl<I,T> StringJoinExt for I
where I: IntoIterator<Item=T>,
T: AsRef<str>
{
fn join<P: AsRef<str>>(self, sep: P) -> String
{
let mut string = String::new();
for (first, s) in iter::successors(Some(true), |_| Some(false)).zip(self.into_iter())
{
if !first {
string.push_str(sep.as_ref());
}
string.push_str(s.as_ref());
}
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
}
}