Crate str_cat

source ·
Expand description

This crate provides macros to efficiently concatenate strings without extra side-effects.

Basic usage:

use str_cat::str_cat;

let s = str_cat!("Hello", " ", "World", "!");
assert_eq!(s, "Hello World!");

Which is roughly equivalent to

let mut s = String::with_capacity("Hello".len() + " ".len() + "World".len() + "!".len());
s.push_str("Hello");
s.push_str(" ");
s.push_str("World");
s.push_str("!");

The macro runs without extra side-effects, which means all involved expressions are evaluated only once.

let mut get_world_calls = 0;
let mut get_world = || {
    get_world_calls += 1;
    "World"
};
let s = str_cat!("Hello", " ", get_world(), "!");
assert_eq!(s, "Hello World!");
assert_eq!(get_world_calls, 1);

Custom minimum capacity.

let s = str_cat!(String::with_capacity(16); "foo", "bar");
assert_eq!(s, "foobar");
assert_eq!(s.capacity(), 16);

Reuse existing allocation.

let mut s = "Hello World!".to_owned();
let ptr = s.as_ptr();
let cap = s.capacity();

s.clear();
str_cat!(&mut s; "World!");
assert_eq!(s, "World!");
// Did not grow
assert_eq!(s.as_ptr(), ptr);
assert_eq!(s.capacity(), cap);

Works with any expressions that can dereference to str when evaluated. Although it would be more simple and efficient to use format! instead when you can’t avoid explicit .to_string() calls.

// Just an example. It's better to use `format!` in this case.
let s = str_cat!(
    "Hello".to_owned(),
    Box::new(" "),
    ['W', 'o', 'r', 'l', 'd'].iter().collect::<String>(),
    '!'.to_string(),
    123456.to_string(),
);
assert_eq!(s, "Hello World!123456");

There are also variants for PathBuf, OsString and Vec.

use str_cat::os_str_cat;

// Works for anything that implements AsRef<OsStr>.
let s = os_str_cat!(
    OsStr::new("Hello"),
    OsStr::new(" ").to_owned(),
    Path::new("World"),
    "!",
);
assert_eq!(s, OsStr::new("Hello World!"));

Macros