1 //! Extension traits implemented by several HTTP types. 2 3 use smallvec::{Array, SmallVec}; 4 5 // TODO: It would be nice if we could somehow have one trait that could give us 6 // either SmallVec or Vec. 7 /// Trait implemented by types that can be converted into a collection. 8 pub trait IntoCollection<T> { 9 /// Converts `self` into a collection. into_collection<A: Array<Item=T>>(self) -> SmallVec<A>10 fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A>; 11 12 #[doc(hidden)] mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, f: F) -> SmallVec<A>13 fn mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, f: F) -> SmallVec<A>; 14 } 15 16 impl<T> IntoCollection<T> for T { 17 #[inline] into_collection<A: Array<Item=T>>(self) -> SmallVec<A>18 fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> { 19 let mut vec = SmallVec::new(); 20 vec.push(self); 21 vec 22 } 23 24 #[inline(always)] mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, mut f: F) -> SmallVec<A>25 fn mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, mut f: F) -> SmallVec<A> { 26 f(self).into_collection() 27 } 28 } 29 30 impl<T> IntoCollection<T> for Vec<T> { 31 #[inline(always)] into_collection<A: Array<Item=T>>(self) -> SmallVec<A>32 fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> { 33 SmallVec::from_vec(self) 34 } 35 36 #[inline] mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, f: F) -> SmallVec<A>37 fn mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, f: F) -> SmallVec<A> { 38 self.into_iter().map(f).collect() 39 } 40 } 41 42 macro_rules! impl_for_slice { 43 ($($size:tt)*) => ( 44 impl<T: Clone> IntoCollection<T> for &[T $($size)*] { 45 #[inline(always)] 46 fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> { 47 self.iter().cloned().collect() 48 } 49 50 #[inline] 51 fn mapped<U, F, A: Array<Item=U>>(self, f: F) -> SmallVec<A> 52 where F: FnMut(T) -> U 53 { 54 self.iter().cloned().map(f).collect() 55 } 56 } 57 ) 58 } 59 60 impl_for_slice!(); 61 impl_for_slice!(; 1); 62 impl_for_slice!(; 2); 63 impl_for_slice!(; 3); 64 impl_for_slice!(; 4); 65 impl_for_slice!(; 5); 66 impl_for_slice!(; 6); 67 impl_for_slice!(; 7); 68 impl_for_slice!(; 8); 69 impl_for_slice!(; 9); 70 impl_for_slice!(; 10); 71 72 use std::borrow::Cow; 73 74 /// Trait implemented by types that can be converted into owned versions of 75 /// themselves. 76 pub trait IntoOwned { 77 /// The owned version of the type. 78 type Owned: 'static; 79 80 /// Converts `self` into an owned version of itself. into_owned(self) -> Self::Owned81 fn into_owned(self) -> Self::Owned; 82 } 83 84 impl<T: IntoOwned> IntoOwned for Option<T> { 85 type Owned = Option<T::Owned>; 86 87 #[inline(always)] into_owned(self) -> Self::Owned88 fn into_owned(self) -> Self::Owned { 89 self.map(|inner| inner.into_owned()) 90 } 91 } 92 93 impl<B: 'static + ToOwned + ?Sized> IntoOwned for Cow<'_, B> { 94 type Owned = Cow<'static, B>; 95 96 #[inline(always)] into_owned(self) -> <Self as IntoOwned>::Owned97 fn into_owned(self) -> <Self as IntoOwned>::Owned { 98 Cow::Owned(self.into_owned()) 99 } 100 } 101 102 use std::path::Path; 103 104 // Outside of http, this is used by a test. 105 #[doc(hidden)] 106 pub trait Normalize { normalized_str(&self) -> Cow<'_, str>107 fn normalized_str(&self) -> Cow<'_, str>; 108 } 109 110 impl<T: AsRef<Path>> Normalize for T { 111 #[cfg(windows)] normalized_str(&self) -> Cow<'_, str>112 fn normalized_str(&self) -> Cow<'_, str> { 113 self.as_ref().to_string_lossy().replace('\\', "/").into() 114 } 115 116 #[cfg(not(windows))] normalized_str(&self) -> Cow<'_, str>117 fn normalized_str(&self) -> Cow<'_, str> { 118 self.as_ref().to_string_lossy() 119 } 120 } 121