seanmonstar/hyper — pull request #19 by reem (2014-09-08 21:40:39+00:00)
Title: Statically track the status of a Response by splitting UnwrittenResponse

and StreamingResponse

Introduces a Response trait, which includes functionality common to both
forms of Response so that downstream uses that don't care about the
distinction between the two types of Response.

UnwrittenResponse::start translates an UnwrittenResponse into a
StreamingResponse by writing the StatusCode and Headers.

UnwrittenResponse allows modification of Headers and StatusCode, but does
not allow writing to the body. StreamingResponse has the opposite
privileges.

Disadvantages:

Introduces two ways to immutably access Headers: `get_header_*` and
`headers.get_*`, which are redundant.

Introduces two new representations of StatusCode and Headers: StatusView
and HeadersView, which provides slight code duplication. This could be remedied
by the addition of immutable fields in Rust itself, but there is otherwise
no way to do this. The addition of StatusView is particularly burdensome as
it turns `res.status` into `res.status()` or `res.status.status()` (we should
prefer the former).

Introduces a new trait even though it is only used for two structs.

Alternatives:

Continue to track this dynamically and provide publicly accessible methods for
conditionally updating Headers and StatusCode and disallow direct access or
mutation.

Keep doing what we do now, but expose headers_written.

Use a phantom type to track the status of Headers, like so:

```rust
struct Unwritten; struct Written;

struct Response { current fields }

impl Response { unwritten methods, including fn start(self) -> Response }

impl Response { written methods }

impl Response { common methods }
```

and disallow mutation except through explicit helpers. I just came up with the
above, so let me know what you think and I might change this PR to use it
instead.

Fixes #6