Skip to main content

Formatter

Trait Formatter 

Source
pub trait Formatter {
    // Required methods
    fn begin_line_folding(&mut self);
    fn end_line_folding(&mut self);
    fn push_new_boundary(&mut self);
    fn write_current_boundary(&mut self);
    fn pop_boundary(&mut self);
    fn write_bytes(&mut self, buf: &[u8]);
    fn write_fws_bytes(&mut self, buf: &[u8]);
    fn write_crlf(&mut self);
    fn flush(self) -> Vec<u8> ;

    // Provided method
    fn write_fws(&mut self) { ... }
}
Expand description

An output formatter that can perform line folding and compute multipart boundaries.

The Formatter API is (unfortunately) quite imperative and tricky to use. At a high level, the trickiness comes from two aspects: formatter modes and multipart boundaries.

§Formatter modes

A Formatter can switch between two modes: a “line folding” mode (for writing email headers) or a “direct” mode (for writing email bodies).

Initially, a newly created Formatter is in “direct” mode. Switching to and out of “line folding” mode is done using the begin_line_folding and end_line_folding functions.

Depending on the mode, some functions of the API cannot be called or come with extra usage restrictions, including basic text-printing functions. (See the per-function documentation for more details.)

§Multipart boundaries

When in “direct” mode, a Formatter can generate and output multipart boundaries. These are randomly generated to (probabilistically) ensure that they do not clash with the rest of the output.

A boundary can be “registered” using push_new_boundary, then printed to the output using write_current_boundary. Finally, the boundary should be discarded when the corresponding multipart body ends, with pop_boundary.

Because multipart data can be nested, it is possible to have several “active” boundaries at a given time. However, boundary-related functions must be called in a way that is “well-bracketed”: conceptually, a Formatter maintains a stack of active boundaries, only the boundary on the top of the stack can be written to the output, and push_new_boundary and pop_boundary must be used in a well-bracketed fashion. (See the per-function documentation for more details.)

§Writing to the formatter

Data can be written to the output using the following functions:

  • write_fws_bytes and write_fws output white space; in “line folding” mode, it can be used for folding;
  • write_bytes outputs text; in “line folding” mode, it cannot be used for folding;
  • write_crlf outputs a line break;
  • write_current_boundary outputs the boundary at the top of the boundary stack.

All other functions of the API modify the internal state of the Formatter but do not produce output.

In “line folding” mode, write_ functions must obey additional requirements:

  • A line must never start with whitespace. This includes both whitespace written using write_bytes or write_fws.
  • Text written with write_bytes must never contain CRLF. /!\ Successive calls to write_bytes that result in a CRLF when concatenated are also forbidden! /!\

In exchange, in line folding mode, a Formatter provides the following guarantees:

  • does not output “folds” that contain only folding whitespace;
  • maximizes the length of folds within the line limit;
  • keeps folds under the line limit, unless there is no space to fold on; in that case, fold as soon as possible after the line limit.

Note that the line limit (if any) is determined by each Formatter implementation.

Required Methods§

Source

fn begin_line_folding(&mut self)

Switches the Formatter mode to “line folding”. The Formatter must be currently in “direct” mode.

Source

fn end_line_folding(&mut self)

Switches the Formatter mode to “direct”. The Formatter must be currently in “line folding” mode.

Source

fn push_new_boundary(&mut self)

Registers a new boundary. This pushes the boundary on top of the internal “boundary stack”.

Source

fn write_current_boundary(&mut self)

Write the current declared boundary to the output (the one on top of the internal boundary stack). The Formatter can be either in “direct” or “line folding” mode.

A boundary must have been registered previously.

Source

fn pop_boundary(&mut self)

Pop the current boundary from the top of the “boundary stack”.

Source

fn write_bytes(&mut self, buf: &[u8])

Write bytes from buf; they cannot be used for line folding.

In line folding mode, buf must not contain CRLF and consecutive calls to write_bytes must not result in CRLF being emitted in the output (e.g. fmt.write_bytes(b"\r"); fmt.write_bytes(b"\n")).

It is fine for buf to include whitespace characters.

Source

fn write_fws_bytes(&mut self, buf: &[u8])

Write whitespace bytes from buf. In “line folding” mode, they can be used for line folding.

buf must only contain whitespace characters ’ ’ and ‘\t’.

Source

fn write_crlf(&mut self)

Terminate the current line, writing CRLF (“\r\n”).

Source

fn flush(self) -> Vec<u8>

Consumes the Formatter and returns the data that was printed to it.

Provided Methods§

Source

fn write_fws(&mut self)

Write a single folding white space character.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§