Skip to content

Commit

Permalink
expose header::map module (#2470)
Browse files Browse the repository at this point in the history
  • Loading branch information
robjtede committed Nov 29, 2021
1 parent 654dc64 commit fc4cdf8
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 24 deletions.
4 changes: 3 additions & 1 deletion actix-http/CHANGES.md
Expand Up @@ -3,9 +3,11 @@
## Unreleased - 2021-xx-xx
### Changed
* Guarantee ordering of `header::GetAll` iterator to be same as insertion order. [#2467]
* Expose `header::{GetAll, Removed}` iterators. [#2467]
* Expose `header::map` module. [#2467]
* Implement `ExactSizeIterator` and `FusedIterator` for all `HeaderMap` iterators. [#2470]

[#2467]: https://github.com/actix/actix-web/pull/2467
[#2470]: https://github.com/actix/actix-web/pull/2470


## 3.0.0-beta.13 - 2021-11-22
Expand Down
9 changes: 5 additions & 4 deletions actix-http/src/header/as_name.rs
@@ -1,11 +1,12 @@
//! Helper trait for types that can be effectively borrowed as a [HeaderValue].
//!
//! [HeaderValue]: crate::http::HeaderValue
//! Sealed [`AsHeaderName`] trait and implementations.

use std::{borrow::Cow, str::FromStr};
use std::{borrow::Cow, str::FromStr as _};

use http::header::{HeaderName, InvalidHeaderName};

/// Sealed trait implemented for types that can be effectively borrowed as a [`HeaderValue`].
///
/// [`HeaderValue`]: crate::http::HeaderValue
pub trait AsHeaderName: Sealed {}

pub struct Seal;
Expand Down
9 changes: 7 additions & 2 deletions actix-http/src/header/into_pair.rs
@@ -1,4 +1,6 @@
use std::convert::TryFrom;
//! [`IntoHeaderPair`] trait and implementations.

use std::convert::TryFrom as _;

use http::{
header::{HeaderName, InvalidHeaderName, InvalidHeaderValue},
Expand All @@ -7,7 +9,10 @@ use http::{

use super::{Header, IntoHeaderValue};

/// Transforms structures into header K/V pairs for inserting into `HeaderMap`s.
/// An interface for types that can be converted into a [`HeaderName`]/[`HeaderValue`] pair for
/// insertion into a [`HeaderMap`].
///
/// [`HeaderMap`]: crate::http::HeaderMap
pub trait IntoHeaderPair: Sized {
type Error: Into<HttpError>;

Expand Down
6 changes: 4 additions & 2 deletions actix-http/src/header/into_value.rs
@@ -1,10 +1,12 @@
use std::convert::TryFrom;
//! [`IntoHeaderValue`] trait and implementations.

use std::convert::TryFrom as _;

use bytes::Bytes;
use http::{header::InvalidHeaderValue, Error as HttpError, HeaderValue};
use mime::Mime;

/// A trait for any object that can be Converted to a `HeaderValue`
/// An interface for types that can be converted into a [`HeaderValue`].
pub trait IntoHeaderValue: Sized {
/// The type returned in the event of a conversion error.
type Error: Into<HttpError>;
Expand Down
54 changes: 47 additions & 7 deletions actix-http/src/header/map.rs
@@ -1,6 +1,6 @@
//! A multi-value [`HeaderMap`] and its iterators.

use std::{borrow::Cow, collections::hash_map, ops};
use std::{borrow::Cow, collections::hash_map, iter, ops};

use ahash::AHashMap;
use http::header::{HeaderName, HeaderValue};
Expand Down Expand Up @@ -581,7 +581,8 @@ impl HeaderMap {
}
}

/// Note that this implementation will clone a [HeaderName] for each value.
/// Note that this implementation will clone a [HeaderName] for each value. Consider using
/// [`drain`](Self::drain) to control header name cloning.
impl IntoIterator for HeaderMap {
type Item = (HeaderName, HeaderValue);
type IntoIter = IntoIter;
Expand All @@ -602,7 +603,7 @@ impl<'a> IntoIterator for &'a HeaderMap {
}
}

/// Iterator for references of [`HeaderValue`]s with the same associated [`HeaderName`].
/// Iterator over borrowed values with the same associated name.
///
/// See [`HeaderMap::get_all`].
#[derive(Debug)]
Expand Down Expand Up @@ -644,10 +645,14 @@ impl<'a> Iterator for GetAll<'a> {
}
}

/// Iterator for owned [`HeaderValue`]s with the same associated [`HeaderName`] returned from
/// methods that remove or replace items.
impl ExactSizeIterator for GetAll<'_> {}

impl iter::FusedIterator for GetAll<'_> {}

/// Iterator over removed, owned values with the same associated name.
///
/// See [`HeaderMap::insert`] and [`HeaderMap::remove`].
/// Returned from methods that remove or replace items. See [`HeaderMap::insert`]
/// and [`HeaderMap::remove`].
#[derive(Debug)]
pub struct Removed {
inner: Option<smallvec::IntoIter<[HeaderValue; 4]>>,
Expand Down Expand Up @@ -689,7 +694,11 @@ impl Iterator for Removed {
}
}

/// Iterator over all [`HeaderName`]s in the map.
impl ExactSizeIterator for Removed {}

impl iter::FusedIterator for Removed {}

/// Iterator over all names in the map.
#[derive(Debug)]
pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);

Expand All @@ -707,6 +716,11 @@ impl<'a> Iterator for Keys<'a> {
}
}

impl ExactSizeIterator for Keys<'_> {}

impl iter::FusedIterator for Keys<'_> {}

/// Iterator over borrowed name-value pairs.
#[derive(Debug)]
pub struct Iter<'a> {
inner: hash_map::Iter<'a, HeaderName, Value>,
Expand Down Expand Up @@ -758,6 +772,10 @@ impl<'a> Iterator for Iter<'a> {
}
}

impl ExactSizeIterator for Iter<'_> {}

impl iter::FusedIterator for Iter<'_> {}

/// Iterator over drained name-value pairs.
///
/// Iterator items are `(Option<HeaderName>, HeaderValue)` to avoid cloning.
Expand Down Expand Up @@ -809,6 +827,10 @@ impl<'a> Iterator for Drain<'a> {
}
}

impl ExactSizeIterator for Drain<'_> {}

impl iter::FusedIterator for Drain<'_> {}

/// Iterator over owned name-value pairs.
///
/// Implementation necessarily clones header names for each value.
Expand Down Expand Up @@ -859,12 +881,27 @@ impl Iterator for IntoIter {
}
}

impl ExactSizeIterator for IntoIter {}

impl iter::FusedIterator for IntoIter {}

#[cfg(test)]
mod tests {
use std::iter::FusedIterator;

use http::header;
use static_assertions::assert_impl_all;

use super::*;

assert_impl_all!(HeaderMap: IntoIterator);
assert_impl_all!(Keys<'_>: Iterator, ExactSizeIterator, FusedIterator);
assert_impl_all!(GetAll<'_>: Iterator, ExactSizeIterator, FusedIterator);
assert_impl_all!(Removed: Iterator, ExactSizeIterator, FusedIterator);
assert_impl_all!(Iter<'_>: Iterator, ExactSizeIterator, FusedIterator);
assert_impl_all!(IntoIter: Iterator, ExactSizeIterator, FusedIterator);
assert_impl_all!(Drain<'_>: Iterator, ExactSizeIterator, FusedIterator);

#[test]
fn create() {
let map = HeaderMap::new();
Expand Down Expand Up @@ -1035,6 +1072,9 @@ mod tests {
assert_eq!(vals.next().unwrap().as_bytes(), b"8");
assert_eq!(vals.next().unwrap().as_bytes(), b"9");
assert!(vals.next().is_none());

// check for fused-ness
assert!(vals.next().is_none());
}

fn owned_pair<'a>(
Expand Down
6 changes: 3 additions & 3 deletions actix-http/src/header/mod.rs
Expand Up @@ -34,7 +34,7 @@ use crate::{error::ParseError, HttpMessage};
mod as_name;
mod into_pair;
mod into_value;
pub(crate) mod map;
pub mod map;
mod shared;
mod utils;

Expand All @@ -44,12 +44,12 @@ pub use self::shared::*;
pub use self::as_name::AsHeaderName;
pub use self::into_pair::IntoHeaderPair;
pub use self::into_value::IntoHeaderValue;
pub use self::map::{GetAll, HeaderMap, Removed};
pub use self::map::HeaderMap;
pub use self::utils::{
fmt_comma_delimited, from_comma_delimited, from_one_raw_str, http_percent_encode,
};

/// A trait for any object that already represents a valid header field and value.
/// An interface for types that already represent a valid header.
pub trait Header: IntoHeaderValue {
/// Returns the name of the header field
fn name() -> HeaderName;
Expand Down
11 changes: 7 additions & 4 deletions actix-http/src/header/shared/content_encoding.rs
Expand Up @@ -9,14 +9,17 @@ use crate::{
HttpMessage,
};

/// Error return when a content encoding is unknown.
///
/// Example: 'compress'
/// Error returned when a content encoding is unknown.
#[derive(Debug, Display, Error)]
#[display(fmt = "unsupported content encoding")]
pub struct ContentEncodingParseError;

/// Represents a supported content encoding.
///
/// Includes a commonly-used subset of media types appropriate for use as HTTP content encodings.
/// See [IANA HTTP Content Coding Registry].
///
/// [IANA HTTP Content Coding Registry]: https://www.iana.org/assignments/http-parameters/http-parameters.xhtml
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum ContentEncoding {
Expand All @@ -32,7 +35,7 @@ pub enum ContentEncoding {
/// Gzip algorithm.
Gzip,

// Zstd algorithm.
/// Zstd algorithm.
Zstd,

/// Indicates the identity function (i.e. no compression, nor modification).
Expand Down
2 changes: 2 additions & 0 deletions actix-http/src/header/utils.rs
@@ -1,3 +1,5 @@
//! Header parsing utilities.

use std::{fmt, str::FromStr};

use super::HeaderValue;
Expand Down
2 changes: 1 addition & 1 deletion src/response/response.rs
Expand Up @@ -296,7 +296,7 @@ impl Future for HttpResponse<AnyBody> {

#[cfg(feature = "cookies")]
pub struct CookieIter<'a> {
iter: header::GetAll<'a>,
iter: header::map::GetAll<'a>,
}

#[cfg(feature = "cookies")]
Expand Down

0 comments on commit fc4cdf8

Please sign in to comment.