|
|
|
//! Extensions
|
|
|
|
use std::{
|
|
|
|
iter,
|
|
|
|
ops::{
|
|
|
|
Range,
|
|
|
|
Deref,DerefMut,
|
|
|
|
},
|
|
|
|
marker::{
|
|
|
|
PhantomData,
|
|
|
|
Send,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait MapTuple2<T,U>
|
|
|
|
{
|
|
|
|
fn map<V,W, F: FnOnce((T,U)) -> (V,W)>(self, fun: F) -> (V,W);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T,U> MapTuple2<T,U> for (T,U)
|
|
|
|
{
|
|
|
|
#[inline] fn map<V,W, F: FnOnce((T,U)) -> (V,W)>(self, fun: F) -> (V,W)
|
|
|
|
{
|
|
|
|
fun(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// To make sure we don't keep this data across an `await` boundary.
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct AssertNotSend<T>(pub T, PhantomData<*const T>);
|
|
|
|
|
|
|
|
impl<T> AssertNotSend<T>
|
|
|
|
{
|
|
|
|
pub const fn new(from :T) -> Self
|
|
|
|
{
|
|
|
|
Self(from, PhantomData)
|
|
|
|
}
|
|
|
|
pub fn into_inner(self) -> T
|
|
|
|
{
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Require a future is Send
|
|
|
|
#[inline(always)] pub fn require_send<T: Send>(t: T) -> T
|
|
|
|
{
|
|
|
|
t
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Deref for AssertNotSend<T>
|
|
|
|
{
|
|
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<T> DerefMut for AssertNotSend<T>
|
|
|
|
{
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|