Skip to content

Commit a5a3ec1

Browse files
uefi: Add new cstr16 implementation
Instead of importing the `cstr16` proc macro from `uefi_macros`, add a new declarative macro. This makes use of the new `ucs2::ucs2_cstr` declarative macro, so bump the minimum version of `ucs2` to 0.3.3.
1 parent 2e5dea4 commit a5a3ec1

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

uefi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ log.workspace = true
3030
ptr_meta.workspace = true
3131
uguid.workspace = true
3232
cfg-if = "1.0.0"
33-
ucs2 = "0.3.2"
33+
ucs2 = "0.3.3"
3434
uefi-macros = "0.13.0"
3535
uefi-raw = "0.5.2"
3636
qemu-exit = { version = "3.0.2", optional = true }

uefi/src/lib.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ extern crate alloc;
100100
// see https://github.com/rust-lang/rust/issues/54647
101101
extern crate self as uefi;
102102

103+
/// Re-export ucs2_cstr so that it can be used in the implementation of the
104+
/// cstr16 macro. It is hidden since it's not intended to be used directly.
105+
#[doc(hidden)]
106+
pub use ucs2::ucs2_cstr;
107+
103108
#[macro_use]
104109
extern crate uefi_raw;
105110

@@ -108,7 +113,7 @@ pub mod data_types;
108113
#[cfg(feature = "alloc")]
109114
pub use data_types::CString16;
110115
pub use data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify};
111-
pub use uefi_macros::{cstr16, cstr8, entry};
116+
pub use uefi_macros::{cstr8, entry};
112117
pub use uguid::guid;
113118

114119
mod result;
@@ -133,25 +138,19 @@ pub(crate) mod polyfill;
133138

134139
pub mod helpers;
135140

141+
mod macros;
136142
mod util;
137143

138144
#[cfg(test)]
139145
// Crates that create procedural macros can't unit test the macros they export.
140146
// Therefore, we do some tests here.
141147
mod macro_tests {
142-
use crate::{cstr16, cstr8};
148+
use crate::cstr8;
143149

144150
#[test]
145151
fn cstr8_macro_literal() {
146152
let _empty1 = cstr8!();
147153
let _empty2 = cstr8!("");
148154
let _regular = cstr8!("foobar");
149155
}
150-
151-
#[test]
152-
fn cstr16_macro_literal() {
153-
let _empty1 = cstr16!();
154-
let _empty2 = cstr16!("");
155-
let _regular = cstr16!("foobar");
156-
}
157156
}

uefi/src/macros.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/// Encode a string literal as a [`&CStr16`].
2+
///
3+
/// The encoding is done at compile time, so the result can be used in a
4+
/// `const` item.
5+
///
6+
/// An empty string containing just a null character can be created with either
7+
/// `cstr16!()` or `cstr16!("")`.
8+
///
9+
/// # Example
10+
///
11+
/// ```
12+
/// use uefi::{CStr16, cstr16};
13+
///
14+
/// const S: &CStr16 = cstr16!("abc");
15+
/// assert_eq!(S.to_u16_slice_with_nul(), [97, 98, 99, 0]);
16+
///
17+
/// const EMPTY: &CStr16 = cstr16!();
18+
/// assert_eq!(EMPTY.to_u16_slice_with_nul(), [0]);
19+
/// assert_eq!(cstr16!(""), EMPTY);
20+
/// ```
21+
///
22+
/// [`&CStr16`]: crate::CStr16
23+
#[macro_export]
24+
macro_rules! cstr16 {
25+
() => {{
26+
const S: &[u16] = &[0];
27+
// SAFETY: `S` is a trivially correct UCS-2 C string.
28+
unsafe { $crate::CStr16::from_u16_with_nul_unchecked(S) }
29+
}};
30+
($s:literal) => {{
31+
const S: &[u16] = &$crate::ucs2_cstr!($s);
32+
// SAFETY: the ucs2_cstr macro always produces a valid UCS-2 string with
33+
// a trailing null character.
34+
unsafe { $crate::CStr16::from_u16_with_nul_unchecked(S) }
35+
}};
36+
}

0 commit comments

Comments
 (0)