Expand description
This crate provides macros to efficiently concatenate strings without extra side-effect.
Usage
Basic usage
use str_cat::str_cat;
let world = "World".to_owned(); // not a literal, so you can't use `concat!`
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("!");No extra side-effect
The macro runs without extra side-effect, which means all involved expressions are evaluated exactly 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);which is roughly equivalent to
let world = get_world(); // evaluate the expression and store it for later use
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("!");Append to an existing string
let mut s = "Hello".to_owned();
str_cat!(&mut s; " ", "World!");
assert_eq!(s, "Hello World!");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; "Hello");
assert_eq!(s, "Hello");
// Did not grow
assert_eq!(s.as_ptr(), ptr);
assert_eq!(s.capacity(), cap);Custom minimum capacity
let s = str_cat!(String::with_capacity(16); "foo", "bar");
assert_eq!(s, "foobar");
assert!(s.capacity() >= 16);Argument types
Works with any expressions that can dereference to str when
evaluated. Although it should 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");Variants
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!"));