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