safe_http 0.1.0-beta.4

Simple and safe HTTP types.
Documentation
mod entry;
mod iter;

pub use self::entry::{Entry, OccupiedEntry, VacantEntry};
pub use self::iter::{
    Drain, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut,
};

use crate::{HeaderName, HeaderValue, HeaderValues};
use std::{
    borrow::Borrow,
    collections::{hash_map, HashMap, TryReserveError},
    hash::Hash,
};

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct HeaderMap(HashMap<HeaderName, HeaderValues>);

impl HeaderMap {
    /// Creates a new empty `HeaderMap`.
    pub fn new() -> Self {
        Self(HashMap::new())
    }

    /// Appends the values if the key is already present or inserts the key-value pair into the map.
    ///
    /// Returns `true` if the map had the key present already.
    // We should add a note about not updating the key, if we add a is_sensitive_value marker to HeaderName.
    pub fn append<V>(&mut self, key: HeaderName, value: V) -> bool
    where
        V: Into<HeaderValues>,
    {
        self.append_values(key, value.into())
    }

    /// Appends the values if the key is already present or inserts the key-values pair into the map.
    ///
    /// Returns `true` if the map had the key present already.
    // We should add a note about not updating the key, if we add a is_sensitive_value marker to HeaderName.
    fn append_values(&mut self, key: HeaderName, values: HeaderValues) -> bool {
        match self.0.entry(key) {
            hash_map::Entry::Occupied(mut occupied) => {
                occupied.get_mut().extend(values);
                true
            }
            hash_map::Entry::Vacant(vacant) => {
                vacant.insert(values);
                false
            }
        }
    }

    pub fn clear(&mut self) {
        self.0.clear()
    }

    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.contains_key(k)
    }

    pub fn drain(&mut self) -> Drain {
        Drain(self.0.drain())
    }

    pub fn entry(&mut self, key: HeaderName) -> Entry {
        match self.0.entry(key) {
            hash_map::Entry::Occupied(x) => Entry::Occupied(OccupiedEntry(x)),
            hash_map::Entry::Vacant(x) => Entry::Vacant(VacantEntry(x)),
        }
    }

    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&HeaderValues>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.get(k)
    }

    pub fn get_first<Q: ?Sized>(&self, k: &Q) -> Option<&HeaderValue>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.get(k).map(HeaderValues::first)
    }

    pub fn get_key_values<Q: ?Sized>(&self, k: &Q) -> Option<(&HeaderName, &HeaderValues)>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.get_key_value(k)
    }

    pub fn get_first_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&HeaderName, &HeaderValue)>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.get_key_value(k).map(|(n, v)| (n, v.first()))
    }

    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut HeaderValues>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.get_mut(k)
    }

    pub fn get_first_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut HeaderValue>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.get_mut(k).map(HeaderValues::first_mut)
    }

    /// Inserts a key-values pair into the map.
    ///
    /// If the map did not have this key present, None is returned.
    ///
    /// If the map did have this key present, the values are replaced, and the old values are returned.
    // We should add a note about not updating the key, if we add a is_sensitive_value marker to HeaderName.
    pub fn insert<V>(&mut self, key: HeaderName, values: V) -> Option<HeaderValues>
    where
        V: Into<HeaderValues>,
    {
        self.insert_values(key, values.into())
    }

    /// Inserts a key-values pair into the map.
    ///
    /// If the map did not have this key present, None is returned.
    ///
    /// If the map did have this key present, the values are replaced, and the old values are returned.
    // We should add a note about not updating the key, if we add a is_sensitive_value marker to HeaderName.
    fn insert_values(&mut self, key: HeaderName, values: HeaderValues) -> Option<HeaderValues> {
        self.0.insert(key, values)
    }

    pub fn into_keys(self) -> IntoKeys {
        IntoKeys(self.0.into_keys())
    }

    pub fn into_values(self) -> IntoValues {
        IntoValues(self.0.into_values())
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn iter(&self) -> Iter {
        Iter(self.0.iter())
    }

    pub fn iter_mut(&mut self) -> IterMut {
        IterMut(self.0.iter_mut())
    }

    pub fn keys(&self) -> Keys {
        Keys(self.0.keys())
    }

    pub fn len(&self) -> usize {
        self.0.len()
    }

    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<HeaderValues>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.remove(k)
    }

    pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(HeaderName, HeaderValues)>
    where
        HeaderName: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.0.remove_entry(k)
    }

    /// Reserves capacity for at least `additional` more elements to be inserted in the `HeaderMap`.
    /// The collection may reserve more space to avoid frequent reallocations.
    pub fn reserve(&mut self, additional: usize) {
        self.0.reserve(additional)
    }

    pub fn retain<F>(&mut self, f: F)
    where
        F: FnMut(&HeaderName, &mut HeaderValues) -> bool,
    {
        self.0.retain(f)
    }

    pub fn shrink_to(&mut self, min_capacity: usize) {
        self.0.shrink_to(min_capacity)
    }

    pub fn shrink_to_fit(&mut self) {
        self.0.shrink_to_fit()
    }

    /// Tries to reserve capacity for at least `additional` more elements to be inserted in the `HeaderMap`.
    /// The collection may reserve more space to avoid frequent reallocations.
    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
        self.0.try_reserve(additional)
    }

    pub fn values(&self) -> Values {
        Values(self.0.values())
    }

    pub fn values_mut(&mut self) -> ValuesMut {
        ValuesMut(self.0.values_mut())
    }

    pub fn with_capacity(capacity: usize) -> Self {
        Self(HashMap::with_capacity(capacity))
    }
}

impl Extend<(HeaderName, HeaderValue)> for HeaderMap {
    fn extend<T: IntoIterator<Item = (HeaderName, HeaderValue)>>(&mut self, iter: T) {
        let iter = iter.into_iter();
        self.reserve(iter.size_hint().0);
        for (key, value) in iter {
            self.append(key, value);
        }
    }
}

impl Extend<(HeaderName, HeaderValues)> for HeaderMap {
    fn extend<T: IntoIterator<Item = (HeaderName, HeaderValues)>>(&mut self, iter: T) {
        let iter = iter.into_iter();
        self.reserve(iter.size_hint().0);
        for (key, values) in iter {
            self.append_values(key, values);
        }
    }
}

impl FromIterator<(HeaderName, HeaderValue)> for HeaderMap {
    #[inline]
    fn from_iter<T: IntoIterator<Item = (HeaderName, HeaderValue)>>(iter: T) -> Self {
        let mut this = Self::new();
        this.extend(iter);
        this
    }
}

impl FromIterator<(HeaderName, HeaderValues)> for HeaderMap {
    #[inline]
    fn from_iter<T: IntoIterator<Item = (HeaderName, HeaderValues)>>(iter: T) -> Self {
        let mut this = Self::new();
        this.extend(iter);
        this
    }
}

impl<'a, const N: usize> From<[(HeaderName, HeaderValue); N]> for HeaderMap {
    #[inline]
    fn from(array: [(HeaderName, HeaderValue); N]) -> Self {
        Self::from_iter(array)
    }
}

impl<'a, const N: usize> From<[(HeaderName, HeaderValues); N]> for HeaderMap {
    #[inline]
    fn from(array: [(HeaderName, HeaderValues); N]) -> Self {
        Self::from_iter(array)
    }
}

impl IntoIterator for HeaderMap {
    type Item = (HeaderName, HeaderValues);

    type IntoIter = IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter(self.0.into_iter())
    }
}

impl<'map> IntoIterator for &'map HeaderMap {
    type Item = (&'map HeaderName, &'map HeaderValues);

    type IntoIter = Iter<'map>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'map> IntoIterator for &'map mut HeaderMap {
    type Item = (&'map HeaderName, &'map mut HeaderValues);

    type IntoIter = IterMut<'map>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}