nt_string/
macros.rs

1// Copyright 2023 Colin Finck <colin@reactos.org>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4// #[macro_export] always exports all macros at the root, even when they better fit to individual modules.
5// This is a current limitation of the Rust macro system.
6//
7// As a consequence, I'm also grouping all public macros here instead of giving people a wrong idea
8// by associating them to modules.
9
10/// Creates an [`NtUnicodeStr`] with `'static` lifetime for a string literal.
11///
12/// The internal buffer of the [`NtUnicodeStr`] will consist entirely of valid UTF-16 characters.
13///
14/// The internal buffer will also be NUL-terminated.
15/// See the [unicode_string module-level documentation](crate::unicode_string) for the implications of that.
16///
17/// [`NtUnicodeStr`]: crate::unicode_string::NtUnicodeStr
18#[macro_export]
19macro_rules! nt_unicode_str {
20    ($text:expr) => {{
21        const U16CSTR: &'static $crate::widestring::U16CStr = $crate::widestring::u16cstr!($text);
22
23        let buffer = U16CSTR.as_slice_with_nul();
24
25        // Include the terminating NUL character in `maximum_length` ...
26        let maximum_length_in_elements = buffer.len();
27        let maximum_length_in_bytes = maximum_length_in_elements * ::core::mem::size_of::<u16>();
28
29        assert!(
30            maximum_length_in_bytes <= ::core::primitive::u16::MAX as usize,
31            "String is too long (resulting byte length exceeds a u16)"
32        );
33
34        let maximum_length = maximum_length_in_bytes as u16;
35
36        // ... but not in `length`
37        assert!(maximum_length >= ::core::mem::size_of::<u16>() as u16);
38        let length = maximum_length - ::core::mem::size_of::<u16>() as u16;
39
40        unsafe {
41            $crate::unicode_string::NtUnicodeStr::from_raw_parts(
42                buffer.as_ptr(),
43                length,
44                maximum_length,
45            )
46        }
47    }};
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::unicode_string::NtUnicodeStr;
53
54    const TEST_STR: NtUnicodeStr<'static> = nt_unicode_str!("Moin");
55
56    #[test]
57    fn test_nt_unicode_str() {
58        assert_eq!(TEST_STR, "Moin");
59        assert_eq!(TEST_STR.len(), 8);
60        assert_eq!(TEST_STR.capacity(), 10);
61    }
62}