diff --git a/Cargo.toml b/Cargo.toml index 0fd59c6..a6455a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "non-empty-string" -version = "0.2.5" +name = "patskovn-non-empty-string" +version = "0.2.6" edition = "2021" -authors = ["Midas Lambrichts "] +authors = ["Midas Lambrichts ", "Nikita Patskov "] license = "MIT OR Apache-2.0" description = "A simple type for non empty Strings, similar to NonZeroUsize and friends." -repository = "https://github.com/MidasLamb/non-empty-string" +repository = "https://github.com/patskovn/non-empty-string.git" keywords = ["nonemptystring", "string", "str", "non-empty", "nonempty"] [package.metadata."docs.rs"] @@ -25,6 +25,7 @@ serde = { version = "1", features = ["derive"] } [features] default = [] +macro = [] serde = ["dep:serde"] diff --git a/src/lib.rs b/src/lib.rs index f225c34..a15228f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,9 @@ use delegate::delegate; #[cfg(feature = "serde")] mod serde_support; +#[cfg(feature = "macro")] +mod macros; + mod trait_impls; /// A simple String wrapper type, similar to NonZeroUsize and friends. diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..a1720fd --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,44 @@ +#[macro_export] +/// Creates a `NonEmptyString` from a string literal at compile time. +/// +/// This macro ensures that the provided string is **not empty** at compile time, +/// preventing runtime errors due to empty strings. +/// +/// # Examples +/// +/// ``` +/// use non_empty_string::{non_empty, NonEmptyString}; +/// +/// let s: NonEmptyString = non_empty!("Hello, Rust!"); +/// assert_eq!(s, NonEmptyString::new("Hello, Rust!".to_string()).unwrap()); +/// ``` +/// +/// # Compile-time Failure +/// +/// If an empty string is provided, this macro will cause a **compile-time error**. +/// +/// ```compile_fail +/// use non_empty_string::non_empty; +/// +/// let s = non_empty!(""); +/// ``` +macro_rules! non_empty { + ($s:expr) => {{ + // Compile-time assertion to ensure the string is non-empty + const _: () = assert!(!$s.is_empty(), "String cannot be empty"); + + // Create a NonEmptyString, unsafely wrapping since we've checked it's valid + unsafe { NonEmptyString::new_unchecked($s.to_string()) } + }}; +} + +#[cfg(test)] +mod tests { + use crate::NonEmptyString; + + #[test] + fn test_non_empty_string_macro_valid() { + let s = non_empty!("Test String"); + assert_eq!(s, NonEmptyString::try_from("Test String").unwrap()); + } +}