literator 0.3.0

Efficient conversion of iterators to human-readable strings
Documentation
# Literator: Iterator formatting for literate programmers

This crate provides the `Literator` trait, which provides utilities for
efficiently displaying the items of an iterator without temporary allocations.

Additionally, a few general formatting utilities are provided for convenience,
including a polyfill for the unstable `std::fmt::from_fn()`, simple
Unicode-compatible case conversion display adapters, and repetition.

## Example use cases

Efficient, allocation-free string concatenation:

```rust
# use literator::Literator;
let favorite_things = ["raindrops", "roses", "whiskers", "kittens"];
// This line does not allocate:
let joined = favorite_things.iter().capitalize_first().join(", ");
// Only when explicitly converting to a `String` does any allocation occur:
let message = joined.to_string();
assert_eq!(message, "Raindrops, roses, whiskers, kittens");
```

Some things require special display logic that cannot be represented as slices
without allocation, like paths:

```rust
# use literator::Literator;
# use std::path::Path;
let paths = [Path::new("foo"), Path::new("bar")];
let list = paths.iter().map(|p| p.display()).join(", ").to_string();
assert_eq!(list, "foo, bar");
```

Friendlier error messages with ad-hoc formatting:

```rust
# use literator::Literator;
#[derive(Debug, thiserror::Error)]
enum Crisis<'a> {
    #[error(
        "I need {}",
        .0.iter().oxford_join_and()
    )]
    Craving(&'a [&'a str])
}

assert_eq!(
    Crisis::Craving(&["pizza", "macaroni and cheese", "crackers"]).to_string(),
    "I need pizza, macaroni and cheese, and crackers"
);
```

## Features

- Allocation-free. Custom `Debug`/`Display` implementations for various adapters
  render directly to the output stream.
- General `join()`. The standard library only has
  [`std::slice::join()`]https://doc.rust-lang.org/stable/std/primitive.slice.html#method.join,
  which heap allocates and only works for slices, not iterators.
  [`Itertools::join()`]https://docs.rs/itertools/latest/itertools/fn.join.html
  only works for `Display`, not `Debug`, and only supports using a `&str` as the delimiter.
- General `oxford_join()` for listing items with appropriate punctuation. The
  [`oxford_join`
  crate](https://docs.rs/oxford_join/latest/oxford_join/index.html), while
  great, only works on slices and collections, heap allocates the result, and
  only supports string conjunctions. `Literator::oxford_join_custom()` supports
  using any displayable delimiter, including non-English conjunctions.
- Prefix/suffix/surround each item: Adapters for adding prefixes/suffixes to the
  items of an iterator while displaying them.
- Adapters forward all formatting options to the item being displayed. For
  example, `println!("{:.02}", [1.0, 2.0].iter().join(", "))` prints `"1.00,
  2.00"`.
- Zero dependencies.
- `#![no_std]`
- `#![forbid(unsafe_code)]`