Impl 'IntoCollection' for '[T; N]'.

This introduces const generics into the codebase for a more efficient,
clone-free 'IntoCollection' for arrays.
This commit is contained in:
Sergio Benitez 2021-05-21 22:48:44 -07:00
parent 824edef3fc
commit 28ba04b47b
3 changed files with 32 additions and 33 deletions

View File

@ -89,10 +89,10 @@ fn test_custom_formats() {
let client = Client::debug(rocket).unwrap(); let client = Client::debug(rocket).unwrap();
let foo_a = Accept::new(&[MediaType::new("application", "foo").into()]); let foo_a = Accept::new([MediaType::new("application", "foo").into()]);
let foo_ct = ContentType::new("application", "foo"); let foo_ct = ContentType::new("application", "foo");
let bar_baz_ct = ContentType::new("bar", "baz"); let bar_baz_ct = ContentType::new("bar", "baz");
let bar_baz_a = Accept::new(&[MediaType::new("bar", "baz").into()]); let bar_baz_a = Accept::new([MediaType::new("bar", "baz").into()]);
let response = client.get("/").header(foo_a).dispatch(); let response = client.get("/").header(foo_a).dispatch();
assert_eq!(response.into_string().unwrap(), "get_foo"); assert_eq!(response.into_string().unwrap(), "get_foo");

View File

@ -46,35 +46,33 @@ impl<T> IntoCollection<T> for Vec<T> {
} }
} }
macro_rules! impl_for_slice { impl<T: Clone> IntoCollection<T> for &[T] {
($($size:tt)*) => ( #[inline(always)]
impl<T: Clone> IntoCollection<T> for &[T $($size)*] { fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> {
#[inline(always)] self.iter().cloned().collect()
fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> { }
self.iter().cloned().collect()
}
#[inline] #[inline]
fn mapped<U, F, A: Array<Item=U>>(self, f: F) -> SmallVec<A> fn mapped<U, F, A: Array<Item=U>>(self, f: F) -> SmallVec<A>
where F: FnMut(T) -> U where F: FnMut(T) -> U
{ {
self.iter().cloned().map(f).collect() self.iter().cloned().map(f).collect()
} }
}
)
} }
impl_for_slice!(); impl<T, const N: usize> IntoCollection<T> for [T; N] {
impl_for_slice!(; 1); #[inline(always)]
impl_for_slice!(; 2); fn into_collection<A: Array<Item=T>>(self) -> SmallVec<A> {
impl_for_slice!(; 3); std::array::IntoIter::new(self).collect()
impl_for_slice!(; 4); }
impl_for_slice!(; 5);
impl_for_slice!(; 6); #[inline]
impl_for_slice!(; 7); fn mapped<U, F, A: Array<Item=U>>(self, f: F) -> SmallVec<A>
impl_for_slice!(; 8); where F: FnMut(T) -> U
impl_for_slice!(; 9); {
impl_for_slice!(; 10); std::array::IntoIter::new(self).map(f).collect()
}
}
use std::borrow::Cow; use std::borrow::Cow;

View File

@ -85,9 +85,10 @@ macro_rules! accept_constructor {
impl Accept { impl Accept {
/// Constructs a new `Accept` header from one or more media types. /// Constructs a new `Accept` header from one or more media types.
/// ///
/// The `items` parameter may be of type `QMediaType`, `&[QMediaType]`, or /// The `items` parameter may be of type `QMediaType`, `[QMediaType]`,
/// `Vec<QMediaType>`. To prevent additional allocations, prefer to provide /// `&[QMediaType]` or `Vec<QMediaType>`. To prevent additional allocations,
/// inputs of type `QMediaType` and `Vec<QMediaType>`. /// prefer to provide inputs of type `QMediaType`, `[QMediaType]`, or
/// `Vec<QMediaType>`.
/// ///
/// # Example /// # Example
/// ///
@ -100,8 +101,8 @@ impl Accept {
/// let accept = Accept::new(json_then_html); /// let accept = Accept::new(json_then_html);
/// assert_eq!(accept.preferred().media_type(), &MediaType::JSON); /// assert_eq!(accept.preferred().media_type(), &MediaType::JSON);
/// ///
/// // Construct an `Accept` via an `&[QMediaType]`. /// // Construct an `Accept` via an `[QMediaType]`.
/// let accept = Accept::new(&[MediaType::JSON.into(), MediaType::HTML.into()]); /// let accept = Accept::new([MediaType::JSON.into(), MediaType::HTML.into()]);
/// assert_eq!(accept.preferred().media_type(), &MediaType::JSON); /// assert_eq!(accept.preferred().media_type(), &MediaType::JSON);
/// ///
/// // Construct an `Accept` via a `QMediaType`. /// // Construct an `Accept` via a `QMediaType`.