//! Extensions use super::*; use std::{ iter, ops::{ Range, Deref,DerefMut, }, marker::{ PhantomData, Send, }, }; pub trait StringJoinExt: Sized { fn join>(self, sep: P) -> String; } impl StringJoinExt for I where I: IntoIterator, T: AsRef { fn join>(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; } impl> FindSliceBounds for T { type SliceType = str; fn slice_bounds(&self, from: &Self::SliceType) -> Range{ 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>(&mut self, slice: R); } impl SliceInPlace for String { fn drain_inverse>(&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 { fn map (V,W)>(self, fun: F) -> (V,W); } impl MapTuple2 for (T,U) { #[inline] fn map (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(pub T, PhantomData<*const T>); impl AssertNotSend { 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: T) -> T { t } /// Require a value implements a specific trait #[macro_export] macro_rules! require_impl { ($t:path: $val:expr) => { { #[inline(always)] fn require_impl(val: T) -> T { val } require_impl($val) } } } impl Deref for AssertNotSend { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for AssertNotSend { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } pub trait ChunkStreamExt: Sized { fn chunk_into>>(self, sz: usize) -> chunking::ChunkingStream; fn chunk(self, sz: usize) -> chunking::ChunkingStream { self.chunk_into(sz) } } impl ChunkStreamExt for S where S: Stream { fn chunk_into>>(self, sz: usize) -> chunking::ChunkingStream { chunking::ChunkingStream::new(self, sz) } }