Skip to content

Commit 059bc64

Browse files
committed
Add Location::file_with_nul
This is useful for C/C++ APIs which expect the const char* returned from __FILE__ or std::source_location::file_name.
1 parent 8c92e32 commit 059bc64

File tree

1 file changed

+25
-16
lines changed

1 file changed

+25
-16
lines changed

core/src/panic/location.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::ffi::CStr;
12
use crate::fmt;
23

34
/// A struct containing information about the location of a panic.
@@ -32,7 +33,12 @@ use crate::fmt;
3233
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
3334
#[stable(feature = "panic_hooks", since = "1.10.0")]
3435
pub struct Location<'a> {
35-
file: &'a str,
36+
// Note: this filename will have exactly one nul byte at its end, but otherwise
37+
// it must never contain interior nul bytes. This is relied on for the conversion
38+
// to `CStr` below.
39+
//
40+
// The prefix of the string without the trailing nul byte will be a regular UTF8 `str`.
41+
file_bytes_with_nul: &'a [u8],
3642
line: u32,
3743
col: u32,
3844
}
@@ -125,9 +131,24 @@ impl<'a> Location<'a> {
125131
#[must_use]
126132
#[stable(feature = "panic_hooks", since = "1.10.0")]
127133
#[rustc_const_stable(feature = "const_location_fields", since = "1.79.0")]
128-
#[inline]
129134
pub const fn file(&self) -> &str {
130-
self.file
135+
let str_len = self.file_bytes_with_nul.len() - 1;
136+
// SAFETY: `file_bytes_with_nul` without the trailing nul byte is guaranteed to be
137+
// valid UTF8.
138+
unsafe { crate::str::from_raw_parts(self.file_bytes_with_nul.as_ptr(), str_len) }
139+
}
140+
141+
/// Returns the name of the source file as a nul-terminated `CStr`.
142+
///
143+
/// This is useful for interop with APIs that expect C/C++ `__FILE__` or
144+
/// `std::source_location::file_name`, both of which return a nul-terminated `const char*`.
145+
#[must_use]
146+
#[unstable(feature = "file_with_nul", issue = "141727")]
147+
#[inline]
148+
pub const fn file_with_nul(&self) -> &CStr {
149+
// SAFETY: `file_bytes_with_nul` is guaranteed to have a trailing nul byte and no
150+
// interior nul bytes.
151+
unsafe { CStr::from_bytes_with_nul_unchecked(self.file_bytes_with_nul) }
131152
}
132153

133154
/// Returns the line number from which the panic originated.
@@ -181,22 +202,10 @@ impl<'a> Location<'a> {
181202
}
182203
}
183204

184-
#[unstable(
185-
feature = "panic_internals",
186-
reason = "internal details of the implementation of the `panic!` and related macros",
187-
issue = "none"
188-
)]
189-
impl<'a> Location<'a> {
190-
#[doc(hidden)]
191-
pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
192-
Location { file, line, col }
193-
}
194-
}
195-
196205
#[stable(feature = "panic_hook_display", since = "1.26.0")]
197206
impl fmt::Display for Location<'_> {
198207
#[inline]
199208
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
200-
write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
209+
write!(formatter, "{}:{}:{}", self.file(), self.line, self.col)
201210
}
202211
}

0 commit comments

Comments
 (0)