smart-format 0.2.0

Composable, zero-allocation Display formatting combinators for Rust.
Documentation
use smart_format::prelude::*;

// --- Multi-combinator chains ---

#[test]
fn chain_truncate_pad_wrap() {
    let result = "hello world"
        .display_truncate(5)
        .display_pad_right(10, '.')
        .display_wrap("[", "]")
        .to_string();
    assert_eq!("[hello.....]", result);
}

#[test]
fn chain_pad_left_suffix() {
    let result = 42.display_pad_left(5, '0').display_suffix("!").to_string();
    assert_eq!("00042!", result);
}

#[test]
fn chain_if_wrap_prefix() {
    let show = true;
    let result = "item"
        .display_if(show)
        .display_wrap("<li>", "</li>")
        .display_prefix("  ")
        .to_string();
    assert_eq!("  <li>item</li>", result);
}

#[test]
fn chain_if_false_wrap() {
    let show = false;
    let result = "item"
        .display_if(show)
        .display_wrap("<li>", "</li>")
        .to_string();
    assert_eq!("<li></li>", result);
}

#[test]
fn chain_or_truncate() {
    let missing = true;
    let result = "very long value"
        .display_or_if(missing, "N/A")
        .display_truncate(5)
        .to_string();
    assert_eq!("N/A", result);
}

#[test]
fn chain_truncate_with_pad_left() {
    let result = "abcdefgh"
        .display_truncate_with(5, "..")
        .display_pad_left(8, ' ')
        .to_string();
    assert_eq!("   abc..", result);
}

#[test]
fn chain_four_combinators() {
    let result = "hello world"
        .display_truncate(5)
        .display_suffix("...")
        .display_wrap("[", "]")
        .display_pad_right(15, ' ')
        .to_string();
    assert_eq!("[hello...]     ", result);
}

// --- Combinator + case ---

#[test]
fn chain_capitalize_wrap() {
    let result = "hello".capitalize().display_wrap("(", ")").to_string();
    assert_eq!("(Hello)", result);
}

#[test]
fn chain_uppercase_truncate() {
    let result = "hello world".uppercase().display_truncate(5).to_string();
    assert_eq!("HELLO", result);
}

// --- Combinator + filter (html) ---

#[cfg(feature = "html")]
#[test]
fn chain_html_escape_truncate_wrap() {
    let result = "<script>alert('xss')</script>"
        .html_escape()
        .display_truncate(20)
        .display_wrap("<span>", "</span>")
        .to_string();
    assert_eq!(result, "<span>&lt;script&gt;alert(</span>");
}

#[cfg(feature = "html")]
#[test]
fn chain_html_escape_pad_right() {
    let result = "a&b".html_escape().display_pad_right(10, '.').to_string();
    assert_eq!(result, "a&amp;b...");
}

// --- &dyn Display ---

#[test]
fn combinator_on_dyn_display() {
    let value: &dyn core::fmt::Display = &"hello";
    let result = value.display_wrap("[", "]").to_string();
    assert_eq!("[hello]", result);
}

#[test]
fn combinator_chain_on_dyn_display() {
    let value: &dyn core::fmt::Display = &42;
    let result = value
        .display_pad_left(5, '0')
        .display_suffix("!")
        .to_string();
    assert_eq!("00042!", result);
}

// --- Iterator + combinator ---

#[test]
fn iter_join_then_wrap() {
    let items = ["a", "b", "c"];
    let result = items
        .iter()
        .display_join(", ")
        .display_wrap("[", "]")
        .to_string();
    assert_eq!("[a, b, c]", result);
}

#[test]
fn iter_join_truncate() {
    let items = ["alpha", "beta", "gamma"];
    let result = items
        .iter()
        .display_join(", ")
        .display_truncate(10)
        .to_string();
    assert_eq!("alpha, bet", result);
}