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}