rocket_http/
ext.rs

1//! Extension traits implemented by several HTTP types.
2
3use smallvec::{Array, SmallVec};
4use state::InitCell;
5
6// TODO: It would be nice if we could somehow have one trait that could give us
7// either SmallVec or Vec.
8/// Trait implemented by types that can be converted into a collection.
9pub trait IntoCollection<T>: Sized {
10    /// Converts `self` into a collection.
11    fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A>;
12
13    #[doc(hidden)]
14    fn mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, f: F) -> SmallVec<A>;
15}
16
17impl<T> IntoCollection<T> for T {
18    #[inline]
19    fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> {
20        let mut vec = SmallVec::new();
21        vec.push(self);
22        vec
23    }
24
25    #[inline(always)]
26    fn mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, mut f: F) -> SmallVec<A> {
27        f(self).into_collection()
28    }
29}
30
31impl<T> IntoCollection<T> for Vec<T> {
32    #[inline(always)]
33    fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> {
34        SmallVec::from_vec(self)
35    }
36
37    #[inline]
38    fn mapped<U, F: FnMut(T) -> U, A: Array<Item=U>>(self, f: F) -> SmallVec<A> {
39        self.into_iter().map(f).collect()
40    }
41}
42
43impl<T: Clone> IntoCollection<T> for &[T] {
44    #[inline(always)]
45    fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> {
46        self.iter().cloned().collect()
47    }
48
49    #[inline]
50    fn mapped<U, F, A: Array<Item=U>>(self, f: F) -> SmallVec<A>
51        where F: FnMut(T) -> U
52    {
53        self.iter().cloned().map(f).collect()
54    }
55}
56
57impl<T, const N: usize> IntoCollection<T> for [T; N] {
58    #[inline(always)]
59    fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> {
60        self.into_iter().collect()
61    }
62
63    #[inline]
64    fn mapped<U, F, A: Array<Item=U>>(self, f: F) -> SmallVec<A>
65        where F: FnMut(T) -> U
66    {
67        self.into_iter().map(f).collect()
68    }
69}
70
71use std::borrow::Cow;
72
73/// Trait implemented by types that can be converted into owned versions of
74/// themselves.
75pub trait IntoOwned {
76    /// The owned version of the type.
77    type Owned: 'static;
78
79    /// Converts `self` into an owned version of itself.
80    fn into_owned(self) -> Self::Owned;
81}
82
83impl<T: IntoOwned> IntoOwned for Option<T> {
84    type Owned = Option<T::Owned>;
85
86    #[inline(always)]
87    fn into_owned(self) -> Self::Owned {
88        self.map(|inner| inner.into_owned())
89    }
90}
91
92impl<T: IntoOwned> IntoOwned for Vec<T> {
93    type Owned = Vec<T::Owned>;
94
95    #[inline(always)]
96    fn into_owned(self) -> Self::Owned {
97        self.into_iter()
98            .map(|inner| inner.into_owned())
99            .collect()
100    }
101}
102
103impl<T: IntoOwned + Send + Sync> IntoOwned for InitCell<T>
104    where T::Owned: Send + Sync
105{
106    type Owned = InitCell<T::Owned>;
107
108    #[inline(always)]
109    fn into_owned(self) -> Self::Owned {
110        self.map(|inner| inner.into_owned())
111    }
112}
113
114impl<A: IntoOwned, B: IntoOwned> IntoOwned for (A, B) {
115    type Owned = (A::Owned, B::Owned);
116
117    #[inline(always)]
118    fn into_owned(self) -> Self::Owned {
119        (self.0.into_owned(), self.1.into_owned())
120    }
121}
122
123
124impl<B: 'static + ToOwned + ?Sized> IntoOwned for Cow<'_, B> {
125    type Owned = Cow<'static, B>;
126
127    #[inline(always)]
128    fn into_owned(self) -> <Self as IntoOwned>::Owned {
129        Cow::Owned(self.into_owned())
130    }
131}
132
133macro_rules! impl_into_owned_self {
134    ($($T:ty),*) => ($(
135        impl IntoOwned for $T {
136            type Owned = Self;
137
138            #[inline(always)]
139            fn into_owned(self) -> <Self as IntoOwned>::Owned {
140                self
141            }
142        }
143    )*)
144}
145
146impl_into_owned_self!(u8, u16, u32, u64, usize);
147impl_into_owned_self!(i8, i16, i32, i64, isize);
148
149use std::path::Path;
150
151// Outside of http, this is used by a test.
152#[doc(hidden)]
153pub trait Normalize {
154    fn normalized_str(&self) -> Cow<'_, str>;
155}
156
157impl<T: AsRef<Path>> Normalize for T {
158    #[cfg(windows)]
159    fn normalized_str(&self) -> Cow<'_, str> {
160        self.as_ref().to_string_lossy().replace('\\', "/").into()
161    }
162
163    #[cfg(not(windows))]
164    fn normalized_str(&self) -> Cow<'_, str> {
165        self.as_ref().to_string_lossy()
166    }
167}