[][src]Macro mail_headers::def_headers

macro_rules! def_headers {
    (
        test_name: $tn:ident,
        scope: $scope:ident,
        $(
            $(#[$attr:meta])*
            $name:ident, unchecked { $hname:tt }, $component:ident,
              $maxOne:ident, $validator:ident
        ),+
    ) => { ... };
    (_PRIV_mk_marker_impl $name:ident, multi) => { ... };
    (_PRIV_mk_marker_impl $name:ident, maxOne) => { ... };
    (_PRIV_mk_marker_impl $name:ident, $other:ident) => { ... };
    (_PRIV_mk_validator None) => { ... };
    (_PRIV_mk_validator $validator:ident) => { ... };
    (_PRIV_mk_max_one multi) => { ... };
    (_PRIV_mk_max_one maxOne) => { ... };
    (_PRIV_mk_max_one $other:ident) => { ... };
    (_PRIV_max_one_err $other:ident) => { ... };
}

Defines a new header types with given type name, filed name and component

Note that the name is not checked/validated, it has to be ascii, a valid header field name AND has to comply with the naming schema (each word separated by '-' starts with a capital letter and no capital letter follow, e.g. "Message-Id" is ok but "Message-ID" isn't).

This macro will create a test which will check if the used field names are actually valid and appears only once (per def_header macro call) so as long as test's are run any invalid name will be found.

Note that even if a invalid name was used and test where ignored/not run this will not cause an rust safety issue, but can still cause bugs under some circumstances (e.g. if you have multiple differing definitions of the same header with different spelling (at last one failed the test) like e.g. when you override default implementations of fields).

The macros expects following items:

  1. test_name, which is the name the auto-generated test will have

  2. scope, the scope all components are used with, this helps with some name collisions. Use self to use the current scope.

  3. a list of header definitions consisting of:

    1. <typename> the name the type of the header will have, i.e. the name of a zero-sized struct which will be generated
    2. unchecked a hint to make people read the documentation and not forget the the folowing data is unchecked / only vaidated in the auto-generated test
    3. "<header_name>" the header name in a syntax using '-' to serperate words, also each word has to start with a capital letter and be followed by lowercase letters additionaly to being a valid header field name. E.g. "Message-Id" is ok, but "Message-ID" is not. (Note that header field name are on itself ignore case, but by enforcing a specific case in the encoder equality checks can be done on byte level, which is especially usefull for e.g. placing them as keys into a HashMap or for performance reasons.
    4. <component> the name of the type to use ing scope a the component type of the header. E.g. Unstructured for an unstructured header field (which still support Utf8 through encoded words)
    5. None/maxOne/<name>, None, maxOne or the name of a validator function. The validator function is used to validate some contextual limitations a header field might have, like that it can appear at most one time, or that if a From with multiple mailboxes is given a Sender field needs to be given too. If maxOne is used it will automatically generate a function which makes sure that the header appears at most one time. This validator functions are used after creating a header map but before using it to encode a mail (or anywhere in between if you want to). Note that validators are kept separate from the headers and might be run even if the header does not appear in the header map passed to the validator, as such if a validator can not find the header it should validate or if it finds it but it has an unexpected type it must not create an error.

Example

def_headers! {
    // the name of the auto-generated test
    test_name: validate_header_names,
    // the scope from which all components should be imported
    // E.g. `DateTime` refers to `components::DateTime`.
    scope: components,
    // definitions of the headers or the form
    // <type_name>, unchecked { <struct_name> }, <component>, <validator>
    Date,     unchecked { "Date"          },  DateTime,       maxOne,
    From,     unchecked { "From"          },  MailboxList,    validator_from,
    Subject,  unchecked { "Subject"       },  Unstructured,   maxOne,
    Comments, unchecked { "Comments"      },  Unstructured,   None,
}