concat_string/
lib.rs

1// Copyright (c) 2017-2018 FaultyRAM
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be copied, modified, or
6// distributed except according to those terms.
7
8//! Macros for concatenating string slices into owned strings.
9//!
10//! This crate provides the `concat_string!` macro for efficiently concatenating string slices into
11//! owned strings. `concat_string!` accepts any number of arguments that implement `AsRef<str>` and
12//! creates a `String` with the appropriate capacity, without the need for format strings and their
13//! associated runtime overhead.
14//!
15//! # Example
16//!
17//! ```rust
18//! #[macro_use(concat_string)]
19//! extern crate concat_string;
20//!
21//! fn main() {
22//!     println!("{}", concat_string!("Hello", String::from(" "), "world"));
23//! }
24//! ```
25
26#![forbid(warnings)]
27#![forbid(unused)]
28#![forbid(box_pointers)]
29#![forbid(missing_copy_implementations)]
30#![forbid(missing_debug_implementations)]
31#![forbid(missing_docs)]
32#![forbid(trivial_casts)]
33#![forbid(trivial_numeric_casts)]
34#![forbid(unsafe_code)]
35#![forbid(unused_extern_crates)]
36#![forbid(unused_import_braces)]
37#![forbid(unused_qualifications)]
38#![forbid(unused_results)]
39#![forbid(variant_size_differences)]
40#![cfg_attr(feature = "cargo-clippy", forbid(clippy))]
41#![cfg_attr(feature = "cargo-clippy", forbid(clippy_pedantic))]
42#![cfg_attr(feature = "cargo-clippy", forbid(clippy_cargo))]
43#![cfg_attr(feature = "cargo-clippy", forbid(clippy_complexity))]
44#![cfg_attr(feature = "cargo-clippy", forbid(clippy_correctness))]
45#![cfg_attr(feature = "cargo-clippy", forbid(clippy_perf))]
46#![cfg_attr(feature = "cargo-clippy", forbid(clippy_style))]
47
48#[macro_export]
49/// Concatenates a series of string slices into an owned string.
50///
51/// This macro accepts zero or more arguments, where each argument implements `AsRef<str>`, and
52/// efficiently combines their string representations into a `String` in order of declaration.
53///
54/// This is mainly useful for cases where the cost of parsing a format string outweighs the cost
55/// of converting its arguments. Because `concat_string` avoids format strings entirely, it can
56/// achieve a higher level of performance than using `format!` or other formatting utilities that
57/// return a `String`.
58///
59/// # Example
60///
61/// ```rust
62/// #[macro_use(concat_string)]
63/// extern crate concat_string;
64///
65/// fn main() {
66///     println!("{}", concat_string!("Hello", String::from(" "), "world"));
67/// }
68/// ```
69macro_rules! concat_string {
70    () => { String::with_capacity(0) };
71    ($($s:expr),+) => {{
72        use std::ops::AddAssign;
73        let mut len = 0;
74        $(len.add_assign(AsRef::<str>::as_ref(&$s).len());)+
75        let mut buf = String::with_capacity(len);
76        $(buf.push_str($s.as_ref());)+
77        buf
78    }};
79}
80
81#[cfg(test)]
82mod tests {
83    #[test]
84    fn concat_string_0_args() {
85        let s = concat_string!();
86        assert_eq!(s, String::from(""));
87    }
88
89    #[test]
90    fn concat_string_1_arg() {
91        let s = concat_string!("foo");
92        assert_eq!(s, String::from("foo"));
93    }
94
95    #[test]
96    fn concat_string_str_string() {
97        let s = concat_string!("foo", String::from("bar"));
98        assert_eq!(s, String::from("foobar"));
99    }
100}