string_literals/
lib.rs

1//! A very tiny crate with Rust macros to more easily create String types.
2//!
3//! When creating string literals in Rust, the given type is `&str`. To create an owned `String` type,
4//! you either need to:
5//!
6//! - pass in the literal to `String::from()`,
7//! - call `.to_owned()`, or `.to_string()` on the `&str` literal
8//!
9//! ### Strings
10//!
11//! ```rust
12//! use string_literals::s;
13//!
14//! let old = "Hello, world!".to_owned();
15//! let new = s!("Hello, world!");
16//! ```
17//!
18//! ### Arrays, vectors
19//!
20//! ```rust
21//! use string_literals::{string_arr, string_vec};
22//!
23//! let old_arr: [String; 3] = ["Banana".to_owned(), "Apple".to_owned(), "Orange".to_owned()];
24//! let new_arr: [String; 3] = string_arr!["Banana", "Apple", "Orange"];
25//!
26//! let old_vec = vec!["Banana".to_owned(), "Apple".to_owned(), "Orange".to_owned()];
27//! let new_vec = string_vec!["Banana", "Apple", "Orange"];
28//! ```
29//!
30//! ### Hash maps
31//!
32//! ```rust
33//! use std::collections::HashMap;
34//! use string_literals::string_hashmap;
35//!
36//! let mut old1: HashMap<String, String> = HashMap::new();
37//! old1.insert("Banana".to_owned(), "Good".to_owned());
38//! old1.insert("Apple".to_owned(), "Okay".to_owned());
39//!
40//! let old2: HashMap<String, String> = HashMap::from([
41//!     ("Banana".to_owned(), "Good".to_owned()),
42//!     ("Apple".to_owned(), "Okay".to_owned()),
43//! ]);
44//!
45//! let new: HashMap<String, String> = string_hashmap! {
46//!     "Banana" => "Good",
47//!     "Apple" => "Okay",
48//! };
49//! ```
50
51/// Create a [`String`] literal
52///
53/// This provides a slightly shorter alternative to creating a `String`
54/// from a literal.
55///
56/// # Examples
57/// Empty strings:
58/// ```
59/// use string_literals::s;
60///
61/// let old = String::new();
62/// let s1 = s!();
63/// let s2 = s!("");
64/// assert!(s1.is_empty());
65/// assert!(s2.is_empty());
66/// ```
67///
68/// Non-empty strings:
69/// ```
70/// use string_literals::s;
71///
72/// let old1 = String::from("Alice");
73/// let old2 = "Alice".to_owned();
74/// let old3 = "Alice".to_string();
75/// let new  = s!("Alice");
76/// assert_eq!(new, String::from("Alice"));
77/// ```
78#[macro_export]
79macro_rules! s {
80	() => {
81		String::new()
82	};
83	("") => {
84		String::new()
85	};
86	($s: expr) => {
87		$s.to_owned()
88	};
89}
90
91/// Create an [`array`] of `[String; N]` with string literals
92///
93/// # Examples
94/// Empty arrays:
95/// ```
96/// use string_literals::string_arr;
97///
98/// let arr: [String; 0] = string_arr![];
99/// assert!(arr.is_empty());
100/// ```
101///
102/// Non-empty arrays:
103/// ```
104/// use string_literals::string_arr;
105///
106/// let old: [String; 2] = [String::from("Alice"), String::from("Bob")];
107/// let new: [String; 2] = string_arr!["Alice", "Bob"];
108/// assert_eq!(new.len(), 2);
109/// assert_eq!(new[0], String::from("Alice"));
110/// assert_eq!(new[1], String::from("Bob"));
111/// ```
112#[macro_export]
113macro_rules! string_arr {
114	() => {
115		[]
116	};
117	($($x:expr),+ $(,)?) => {
118		[$($x.to_owned()),*]
119	}
120}
121
122/// Create a [`Vec`] of `Vec<String>` with string literals.
123///
124/// This macro also allows zero arguments. In this case however, it would be
125/// shorter to call `vec![]` or `Vec::new()`.
126///
127/// # Examples
128/// ```
129/// use string_literals::string_vec;
130///
131/// let old: Vec<String> = vec![String::from("Alice"), String::from("Bob")];
132/// let new: Vec<String> = string_vec!["Alice", "Bob"];
133/// assert_eq!(new.len(), 2);
134/// assert_eq!(new[0], "Alice".to_owned());
135/// assert_eq!(new[1], "Bob".to_owned());
136/// ```
137#[macro_export]
138macro_rules! string_vec {
139	() => {
140		Vec::new()
141	};
142	($($x:expr),+ $(,)?) => {
143		vec![$($x.to_owned()),+]
144	};
145}
146
147/// Create a [`HashMap`](std::collections::HashMap) of `HashMap<String, String>` with string literals
148///
149/// This macro also allows zero arguments (an empty hash map). In this case
150/// however, it would be shorter in length to call `HashMap::new()`.
151///
152/// # Examples
153/// Empty hash maps:
154/// ```
155/// use std::collections::HashMap;
156/// use string_literals::string_hashmap;
157///
158/// let map: HashMap<String, String> = string_hashmap!{};
159/// assert!(map.is_empty());
160/// ```
161///
162/// Non-empty hash maps:
163/// ```
164/// use std::collections::HashMap;
165/// use string_literals::string_hashmap;
166///
167/// let map: HashMap<String, String> = string_hashmap!{
168///     "Banana" => "Good",
169///     "Apple" => "Okay",
170/// };
171/// assert_eq!(map[&"Banana".to_owned()], "Good".to_owned());
172/// assert_eq!(map[&"Apple".to_owned()], "Okay".to_owned());
173/// ```
174#[macro_export]
175macro_rules! string_hashmap {
176	() => {
177		::std::collections::HashMap::new()
178	};
179	($($k:expr => $v:expr),+ $(,)?) => {
180		::std::collections::HashMap::from([
181			$(($k.to_owned(), $v.to_owned())),+
182		])
183	};
184}