5 releases
0.2.0 | Mar 2, 2023 |
---|---|
0.1.3 | Feb 28, 2023 |
0.1.2 | Feb 24, 2023 |
0.1.1 | Feb 24, 2023 |
0.1.0 | Feb 24, 2023 |
#277 in Value formatting
12KB
109 lines
str-cat
This crate provides macros to efficiently concatenate strings without extra side-effect.
lib.rs
:
This crate provides macros to efficiently concatenate strings without extra side-effect.
Usage
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("!");
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");
Implicit borrowing
Just like format!
and println!
,
str_cat
automatically borrows the arguments for you, so you
don't have to type that &
yourself.
let world = "World!".to_owned();
let s = str_cat!("Hello ", world); // no need for `&`
assert_eq!(s, "Hello World!");
assert_eq!(world, "World!"); // not moved, still valid
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!"));