format-bytes 0.4.0

A macro to format bytestrings
Documentation
use format_bytes::{ArgName, Message, Piece, format_bytes, join, message};

#[test]
fn template() {
    let rev = 42;
    let msg = message!("{} {{at}} {rev}{path}", 1, path = b"p".to_vec());
    let template = msg.template();
    assert_eq!(template.source, "{} {{at}} {rev}{path}");
    assert_eq!(
        template.pieces,
        [
            Piece::Arg(0),
            Piece::Literal(" {at} "),
            Piece::Arg(2),
            Piece::Arg(1),
        ]
    );
    assert_eq!(
        template.args,
        [
            ArgName::Index(0),
            ArgName::Name("path"),
            ArgName::Name("rev")
        ]
    );
}

#[test]
fn rendering() {
    let rev = 42;
    let paths = vec![b"a".to_vec(), b"caf\xe9".to_vec()];
    let msg = message!("{rev}: {paths}", paths = join(paths, b", "));

    let mut out = vec![];
    msg.write_to(&mut out).unwrap();
    assert_eq!(out, b"42: a, caf\xe9");
    assert_eq!(format_bytes!("{msg}"), b"42: a, caf\xe9");
    assert_eq!(format!("{:?}", msg), "Message(\"42: a, caf\u{fffd}\")");
}

#[test]
fn owned() {
    fn error_like(_: &(impl Send + Sync + 'static)) {}
    let name = String::from("x");
    let msg = message!("{name}", name = format_bytes::Utf8(name));
    error_like(&msg);

    let mut count = 0;
    let mut next = || {
        count += 1;
        count
    };
    let msg: Message = message!("{n}{n}", n = next());
    assert_eq!(format_bytes!("{msg}"), b"11");
    assert_eq!(count, 1);
}