1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
/// Creates an [`NSString`](foundation/struct.NSString.html) from a static /// string. /// /// # Feature Flag /// /// This macro is defined in [`foundation`](foundation/index.html), /// which requires the **`foundation`** /// [feature flag](index.html#feature-flags). /// /// # Examples /// /// This macro takes a `"string"` literal as the argument: /// /// ``` /// let hello = fruity::nsstring!("hello"); /// /// assert_eq!(hello.to_string(), "hello"); /// ``` /// /// The result of this macro can even be used to create `static` values: /// /// ``` /// # use fruity::foundation::NSString; /// static WORLD: NSString = fruity::nsstring!("world"); /// /// assert_eq!(WORLD.to_string(), "world"); /// ``` /// /// Note that the result cannot be used in a `const` because it refers to /// static data outside of this library. /// /// # Validity Checking /// /// Because the string data must be a valid C string, having null bytes inside /// it causes a compile error: /// /// ```compile_fail /// let s = fruity::nsstring!("ab\0cd"); /// ``` /// /// # Runtime Cost /// /// None. /// /// The result is equivalent to `@"string"` syntax in Objective-C. /// /// Because of that, this should be preferred over /// [`NSString::from_str`](foundation/struct.NSString.html#method.from_str) /// where possible. /// /// # Compile-time Cost /// /// Minimal. /// /// This is implemented entirely with `const` evaluation. It is not a procedural /// macro that requires dependencies for parsing. #[macro_export] macro_rules! nsstring { ($s:expr) => {{ // Note that this always uses full paths to items from `$crate`. This // does not import any items because doing so could cause ambiguity if // the same names are exposed at the call site of this macro. // // The only names directly used are expressions, whose names shadow any // other names outside of this macro. // This can be in the `__cstring` link section, but it doesn't need to. const STR: &str = $crate::_priv::std::concat!($s, "\0"); // Assert that `STR` is a valid C string: // 1. It ends with null. // 2. It has no interior nulls. const _: [(); 1] = [(); $crate::_priv::is_cstr(STR) as usize]; #[link_section = "__DATA,__cfstring,regular"] static DATA: $crate::_priv::__CFString = $crate::_priv::__CFString { isa: unsafe { extern "C" { static __CFConstantStringClassReference: $crate::_priv::std::ffi::c_void; } &__CFConstantStringClassReference }, // This is a magic constant I came across when inspecting // Objective-C binaries. This is probably the CFTypeID? flags: 0x07c8, data: STR.as_ptr(), // The length does not include the null byte. len: STR.len() - 1, }; #[allow(unused_unsafe)] let nsstring = unsafe { $crate::foundation::NSString::from_ptr(&DATA as *const _ as *mut _) }; nsstring }}; }