Impl 'UriDisplay' for 'Vec', maps, nonzero ints.

This commit is contained in:
Sergio Benitez 2021-06-29 03:16:48 -07:00
parent ae796b41ad
commit 7c8c06522c
2 changed files with 81 additions and 5 deletions

View File

@ -215,10 +215,8 @@ impl<'i, P: Part> Formatter<'i, P> {
if P::KIND == Kind::Query && !self.prefixes.is_empty() {
for (i, prefix) in self.prefixes.iter().enumerate() {
if i != 0 { self.inner.write_char('.')? }
self.inner.write_str(prefix)?;
if i < self.prefixes.len() - 1 {
self.inner.write_str(".")?;
}
}
self.inner.write_str("=")?;

View File

@ -1,3 +1,4 @@
use std::collections::{BTreeMap, HashMap};
use std::{fmt, path};
use std::borrow::Cow;
@ -323,7 +324,7 @@ impl UriDisplay<Path> for path::Path {
}
macro_rules! impl_with_display {
($($T:ty),+) => {$(
($($T:ty),+ $(,)?) => {$(
/// This implementation is identical to the `Display` implementation.
impl<P: Part> UriDisplay<P> for $T {
#[inline(always)]
@ -336,12 +337,43 @@ macro_rules! impl_with_display {
}
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::num::{
NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
};
impl_with_display! {
i8, i16, i32, i64, i128, isize,
u8, u16, u32, u64, u128, usize,
f32, f64, bool,
IpAddr, Ipv4Addr, Ipv6Addr
IpAddr, Ipv4Addr, Ipv6Addr,
NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
}
macro_rules! impl_with_string {
($($T:ty => $f:expr),+ $(,)?) => {$(
/// This implementation is identical to a percent-encoded versiono the
/// `Display` implementation.
impl<P: Part> UriDisplay<P> for $T {
#[inline(always)]
fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {
let func: fn(&$T) -> String = $f;
func(self).as_str().fmt(f)
}
}
)+}
}
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
impl_with_string! {
time::Date => |d| d.format("%F"),
time::PrimitiveDateTime => |d| d.format("%FT%T"),
time::Time => |d| d.format("%T"),
SocketAddr => |s| s.to_string(),
SocketAddrV4 => |s| s.to_string(),
SocketAddrV6 => |s| s.to_string(),
}
// These are second level implementations: they all defer to an existing
@ -409,6 +441,52 @@ impl<T: UriDisplay<Query>, E> UriDisplay<Query> for Result<T, E> {
}
}
impl<T: UriDisplay<Query>> UriDisplay<Query> for Vec<T> {
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
for value in self {
f.write_value(value)?;
}
Ok(())
}
}
impl<K: UriDisplay<Query>, V: UriDisplay<Query>> UriDisplay<Query> for HashMap<K, V> {
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
use std::fmt::Write;
let mut field_name = String::with_capacity(8);
for (i, (key, value)) in self.iter().enumerate() {
field_name.truncate(0);
write!(field_name, "k:{}", i)?;
f.write_named_value(&field_name, key)?;
field_name.replace_range(..1, "v");
f.write_named_value(&field_name, value)?;
}
Ok(())
}
}
impl<K: UriDisplay<Query>, V: UriDisplay<Query>> UriDisplay<Query> for BTreeMap<K, V> {
fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {
use std::fmt::Write;
let mut field_name = String::with_capacity(8);
for (i, (key, value)) in self.iter().enumerate() {
field_name.truncate(0);
write!(field_name, "k:{}", i)?;
f.write_named_value(&field_name, key)?;
field_name.replace_range(..1, "v");
f.write_named_value(&field_name, value)?;
}
Ok(())
}
}
#[cfg(feature = "uuid")] impl_with_display!(uuid_::Uuid);
#[cfg(feature = "uuid")] crate::impl_from_uri_param_identity!(uuid_::Uuid);