Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expose header::map module #2470

Merged
merged 3 commits into from Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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