Skip to content

Commit 6a0c368

Browse files
committed
Add cstr! macro.
1 parent 2b91cbe commit 6a0c368

File tree

4 files changed

+58
-16
lines changed

4 files changed

+58
-16
lines changed

library/core/src/ffi/c_str.rs

+50-16
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,14 @@ impl FromBytesWithNulError {
123123
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
124124
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
125125
}
126+
126127
const fn not_nul_terminated() -> FromBytesWithNulError {
127128
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
128129
}
129130

130131
#[doc(hidden)]
131132
#[unstable(feature = "cstr_internals", issue = "none")]
132-
pub fn __description(&self) -> &str {
133+
pub const fn __description(&self) -> &str {
133134
match self.kind {
134135
FromBytesWithNulErrorKind::InteriorNul(..) => {
135136
"data provided contains an interior nul byte"
@@ -139,6 +140,18 @@ impl FromBytesWithNulError {
139140
}
140141
}
141142

143+
#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
144+
impl fmt::Display for FromBytesWithNulError {
145+
#[allow(deprecated, deprecated_in_future)]
146+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147+
f.write_str(self.__description())?;
148+
if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
149+
write!(f, " at byte pos {pos}")?;
150+
}
151+
Ok(())
152+
}
153+
}
154+
142155
/// An error indicating that no nul byte was present.
143156
///
144157
/// A slice used to create a [`CStr`] must contain a nul byte somewhere
@@ -164,24 +177,45 @@ impl fmt::Debug for CStr {
164177
}
165178
}
166179

167-
#[stable(feature = "cstr_default", since = "1.10.0")]
168-
impl Default for &CStr {
169-
fn default() -> Self {
170-
const SLICE: &[c_char] = &[0];
171-
// SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string.
172-
unsafe { CStr::from_ptr(SLICE.as_ptr()) }
180+
/// Converts a string literal to a `&'static Cstr`.
181+
///
182+
/// # Panics
183+
///
184+
/// `cstr!` panics if the input contains any interior nul bytes.
185+
///
186+
/// # Examples
187+
///
188+
/// ```
189+
/// #![feature(cstr_macro)]
190+
///
191+
/// use core::ffi::CStr;
192+
///
193+
/// const HELLO: &CStr = cstr!("Hello, world!");
194+
/// assert_eq!(HELLO.to_bytes_with_nul(), b"Hello, world!\0");
195+
/// ```
196+
#[macro_export]
197+
#[unstable(feature = "cstr_macro", issue = "101607")]
198+
#[rustc_diagnostic_item = "core_cstr_macro"]
199+
macro_rules! cstr {
200+
($($s:expr),*) => {
201+
$crate::ffi::__cstr_macro_impl(concat!($($s,)* "\0").as_bytes())
173202
}
174203
}
175204

176-
#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
177-
impl fmt::Display for FromBytesWithNulError {
178-
#[allow(deprecated, deprecated_in_future)]
179-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180-
f.write_str(self.__description())?;
181-
if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
182-
write!(f, " at byte pos {pos}")?;
183-
}
184-
Ok(())
205+
#[unstable(feature = "cstr_macro", issue = "101607")]
206+
#[doc(hidden)]
207+
pub const fn __cstr_macro_impl(bytes: &[u8]) -> &CStr {
208+
match CStr::from_bytes_with_nul(bytes) {
209+
Ok(cstr) => cstr,
210+
Err(err) => panic!("{}", err.__description()),
211+
}
212+
}
213+
214+
#[stable(feature = "cstr_default", since = "1.10.0")]
215+
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
216+
impl const Default for &CStr {
217+
fn default() -> Self {
218+
cstr!()
185219
}
186220
}
187221

library/core/src/ffi/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError};
1919

2020
mod c_str;
2121

22+
#[unstable(feature = "cstr_macro", issue = "101607")]
23+
#[doc(hidden)]
24+
pub use self::c_str::__cstr_macro_impl;
25+
2226
macro_rules! type_alias_no_nz {
2327
{
2428
$Docfile:tt, $Alias:ident = $Real:ty;

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
#![feature(const_is_char_boundary)]
167167
#![feature(const_cstr_methods)]
168168
#![feature(is_ascii_octdigit)]
169+
#![feature(cstr_macro)]
169170
//
170171
// Language features:
171172
#![feature(abi_unadjusted)]

library/std/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ pub use core::{
616616
module_path, option_env, stringify, trace_macros,
617617
};
618618

619+
#[unstable(feature = "cstr_macro", issue = "101607")]
620+
pub use core::cstr;
621+
619622
#[unstable(
620623
feature = "concat_bytes",
621624
issue = "87555",

0 commit comments

Comments
 (0)