[][src]Struct mail_headers::map::HeaderMap

pub struct HeaderMap { /* fields omitted */ }

A header map is a collection representing a number of mail headers in an specific order.

Example


// just import all headers
use mail_headers::HeaderMap;
use mail_headers::headers::*;
use mail_headers::error::ComponentCreationError;

fn create_headers() -> Result<HeaderMap, ComponentCreationError> {
    headers!{
        // from and to can have multiple values
        // until specialization is stable is array
        // is necessary
        _From: [("My Fancy Display Name", "theduck@example.com")],
        _To: [ "unknown@example.com", ],
        Subject: "Who are you?"
    }
}

fn main() {
    let headers = create_headers().unwrap();
    assert_eq!(headers.len(), 3);
}

Note

A number of methods implemented on HeaderMap appear in two variations, one which accepts a type hint (a normally zero sized struct implementing HeaderKind) and on which just accepts the type and needs to be called with the turbofish operator. The later one is prefixed by a _ as the former one is more nice to use, but in some situations, e.g. when wrapping HeaderMap in custom code the only type accepting variations are more useful.

This example is not tested
let _ = map.get(Subject);
//is equivalent to
let _ = map._get::<Subject>();

MaxOne (In-)Consistency

Most headers can only appear up to one time in a header section. They are marked with H::MAX_ONE == true and implement MaxOneMarker, also as object you can use is_max_one to check it.

Not only can they only appear max one time, it is normal for a user who is not aware about the other headers to expect that when you insert them into a header map which already contains them that they replace the existing header. Even more so most headers which can appear more then one time are unlikely to appear in a application of this library like e.g. all Resent-* header which normally get just prepended to existing mail in text format or the Comment header which isn't used that much.

Because of this it was decided that when inserting a "max one" header it will act as expected an replace other headers with the same name and only if a "multi" header is inserted it is added to all headers associated with the same name.

But there is a single problem. If there are multiple implementations implementations for the same header which disagree in wether or not the header is "max one" (which would be a bug anyway!) then this can lead to a tricky situration when you first insert the version which is "max one" and then the one which is "multi". There had been two ways to deal with this:

  1. return a error when inserting in such a situation
  2. simple allow it and check it when running the other validators

Given that a header map contains additionally validators which needs to be run explicitly to make sure that a map is valid before using it as a header section in a mail it was decided to go with the later approach. Originally the first approach was implemented but turned out to be not very ergonomic, and the second approach has little disadvantages as:

  • it's already unlikely to run into the situation
  • you have to run validators anyway before using the header map

So yes, you can not relay on the "max one" constraints to be uphold without running the validators

Methods

impl HeaderMap[src]

pub fn new() -> Self[src]

create a new empty header map

pub fn len(&self) -> usize[src]

returns the number of headers in this map

pub fn clear(&mut self)[src]

clears the header map

This removes all headers and all validators

pub fn values(&self) -> Values[src]

Iterate over all HeaderObj added to the map.

pub fn values_mut(&mut self) -> ValuesMut[src]

Iterate with mut refs over all HeaderObj added to the map.

pub fn use_contextual_validators(&self) -> Result<(), HeaderValidationError>[src]

call each unique contextual validator exactly once with this map as parameter

If multiple Headers provide the same contextual validator (e.g. the resent headers) it's still only called once.

Max One

This will also validate that for any header name for which a header was added with MAX_ONE == true it will be validated that it is the only header for that header name.

pub fn contains<H: HasHeaderName>(&self, name: H) -> bool[src]

Returns true if this map contains a header with the given name.

pub fn get_single<'a, H>(
    &'a self,
    _type_hint: H
) -> Option<Result<&'a Header<H>, HeaderTypeError>> where
    H: MaxOneMarker
[src]

Returns the single header associated with the given header kind.

As this uses the MaxOneMarker trait which should only be implemented for HeaderKind impl with MAX_ONE == true this function can only be used when it's fine to ignore the possible case of more than one header of the given kind being in the same map.

Type Hint

The type hint passed in is for ergonomics, e.g. so that it's possible to write code like map.get_single(Subject) if this gets in the way _get_single can be used which would lead to code like map._get_single::<Subject>().

Error

  • If there are multiple implementations for the same header and the inserted headers is based on a different type some HeaderTypeError is returned

  • If there are multiple implementations for the same header which disagree on the value of H::MAX_ONE (which is a bug) this can in some rare situations lead to be there more then one header for a "max one" header in the map, in which case a HeaderTypeError is returned.

pub fn _get_single<'a, H>(
    &'a self
) -> Option<Result<&'a Header<H>, HeaderTypeError>> where
    H: MaxOneMarker
[src]

A variation of get_single which doesn't require passing in a type hint.

Normally using get_single is more ergonomic, except if you write a function which abstracts over it in which case using _get_single can be better.

pub fn get_single_mut<H>(
    &mut self,
    _type_hint: H
) -> Option<Result<&mut Header<H>, HeaderTypeError>> where
    H: MaxOneMarker
[src]

Returns a a mutable reference to the header associated with the given header kind.__internals

See HeaderMap::get_single for more details.

pub fn _get_single_mut<H>(
    &mut self
) -> Option<Result<&mut Header<H>, HeaderTypeError>> where
    H: MaxOneMarker
[src]

Returns a a mutable reference to the header associated with the given header kind.__internals

See HeaderMap::_get_single for more details.

pub fn get_untyped<H: HasHeaderName>(&self, name: H) -> UntypedBodies[src]

Returns all header bodies for a given header name, without trying to cast them to a concrete type

Accepts both HeaderName or a type implementing HeaderKind.

pub fn get_untyped_mut<H: HasHeaderName>(&mut self, name: H) -> UntypedBodiesMut[src]

Returns all header bodies for a given header name, without trying to cast them to a concrete type

Accepts both HeaderName or a type implementing HeaderKind.

Important traits for TypedBodies<'a, H>
pub fn get<H>(&self, _type_hint: H) -> TypedBodies<H> where
    H: HeaderKind
[src]

Returns all header bodies for a given header

Important traits for TypedBodies<'a, H>
pub fn _get<H>(&self) -> TypedBodies<H> where
    H: HeaderKind
[src]

Returns all header bodies for a given header

Important traits for TypedBodiesMut<'a, H>
pub fn get_mut<H>(&mut self, _type_hint: H) -> TypedBodiesMut<H> where
    H: HeaderKind
[src]

Returns all header bodies for a given header

Important traits for TypedBodiesMut<'a, H>
pub fn _get_mut<H>(&mut self) -> TypedBodiesMut<H> where
    H: HeaderKind
[src]

Returns all header bodies for a given header

pub fn insert<H>(&mut self, header: Header<H>) where
    H: HeaderKind
[src]

Inserts the given header into the map either replacing or adding to existing headers.

  • If H::MAX_ONE is true then it will use "replacing insert" which means all headers previously associated with the given header (name) are removed when adding the new header.

    This behavior is analog to how a normal map works and is what a user which isn't aware that there are some headers which can appear multiple times would expect. Most common headers (Subject, From, To, Sender, etc.) fall into this category.

  • If H::MAX_ONE is false then it will use "adding insert" which means that it will add the header to all headers previously associated with the given header name.

pub fn insert_all(&mut self, other: HeaderMap)[src]

Insert all given headers in order into this header map.

The insertion order of the given headers into this map is the same as the order in which they had been inserted into the header map through which they had been given to this method.

As this uses insertion it also means that headers with MAX_ONE == true in the headers to insert can replace existing headers associated with the same header name.

Example

use mail_headers::headers::*;

let mut map = headers!{
    _From: [("Not Met", "it.s.me@example.com")],
    Subject: "..."
}.unwrap();

map.insert_all(headers! {
    _To: [("You", "someone@example.com")],
    Subject: "expected subject"
}.unwrap());

assert_eq!(map.len(), 3);
let subject = map.get_single(Subject)
    .expect("Subject to be in map (Some)")
    .expect("The type to be correct (Ok)");

assert_eq!(subject.as_str(), "expected subject");
assert!(map.contains(_From));
assert!(map.contains(_To));

pub fn remove<H: HasHeaderName>(&mut self, name: H) -> bool[src]

Remove all headers with the given header name.

Returns true, if at last one header was removed.

pub fn iter(&self) -> Iter[src]

iterate over all (header name, boxed body) pairs in this map

Trait Implementations

impl Default for HeaderMap[src]

impl Clone for HeaderMap[src]

fn clone_from(&mut self, source: &Self)
1.0.0
[src]

Performs copy-assignment from source. Read more

impl IntoIterator for HeaderMap[src]

type Item = (HeaderName, Box<HeaderObj>)

The type of the elements being iterated over.

type IntoIter = IntoIter

Which kind of iterator are we turning this into?

impl Debug for HeaderMap[src]

Auto Trait Implementations

impl Send for HeaderMap

impl Sync for HeaderMap

Blanket Implementations

impl<T> From for T[src]

impl<I> IntoIterator for I where
    I: Iterator
[src]

type Item = <I as Iterator>::Item

The type of the elements being iterated over.

type IntoIter = I

Which kind of iterator are we turning this into?

impl<T, U> Into for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

impl<T, U> TryFrom for T where
    U: Into<T>, 
[src]

type Error = !

🔬 This is a nightly-only experimental API. (try_from)

The type returned in the event of a conversion error.

impl<T> Borrow for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BorrowMut for T where
    T: ?Sized
[src]

impl<T, U> TryInto for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

🔬 This is a nightly-only experimental API. (try_from)

The type returned in the event of a conversion error.

impl<T> Erased for T[src]