non_empty_string/macros.rs
1#[macro_export]
2/// Creates a `NonEmptyString` from a string literal at compile time.
3///
4/// This macro ensures that the provided string is **not empty** at compile time,
5/// preventing runtime errors due to empty strings.
6///
7/// # Examples
8///
9/// ```
10/// use non_empty_string::{non_empty_string, NonEmptyString};
11///
12/// let s: NonEmptyString = non_empty_string!("Hello, Rust!");
13/// assert_eq!(s, NonEmptyString::new("Hello, Rust!".to_string()).unwrap());
14/// ```
15///
16/// # Compile-time Failure
17///
18/// If an empty string is provided, this macro will cause a **compile-time error**.
19///
20/// ```compile_fail
21/// use non_empty_string::non_empty_string;
22///
23/// let s = non_empty_string!("");
24/// ```
25macro_rules! non_empty_string {
26 ($s:expr) => {{
27 // Compile-time assertion to ensure the string is non-empty
28 const _: () = assert!(!$s.is_empty(), "String cannot be empty");
29
30 // Create a NonEmptyString, unsafely wrapping since we've checked it's valid
31 unsafe { $crate::NonEmptyString::new_unchecked($s.to_string()) }
32 }};
33}
34
35#[cfg(test)]
36mod tests {
37 // We explicitely DO NOT do `use crate::NonEmptyString` or anything of the sorts to ensure the macro has proper hygiene.
38 // Otherwise tests might pass, but if a user does `non_empty_string::non_empty_string!("A")`, they might get compilation
39 // errors that `NonEmptyString` is not in scope.
40
41 const NON_EMPTY_STRING: &'static str = "non-empty-string";
42
43 #[test]
44 fn test_const_non_empty_string_macro_valid() {
45 let s = non_empty_string!(NON_EMPTY_STRING);
46 assert_eq!(
47 s,
48 crate::NonEmptyString::try_from(NON_EMPTY_STRING).unwrap()
49 );
50 }
51
52 #[test]
53 fn test_inline_non_empty_string_macro_valid() {
54 let s = non_empty_string!("Test String");
55 assert_eq!(s, crate::NonEmptyString::try_from("Test String").unwrap());
56 }
57}