]>
Commit | Line | Data |
---|---|---|
04454e1e FG |
1 | use crate::ascii; |
2 | use crate::cmp::Ordering; | |
3 | use crate::ffi::c_char; | |
4 | use crate::fmt::{self, Write}; | |
5 | use crate::ops; | |
6 | use crate::slice; | |
7 | use crate::slice::memchr; | |
8 | use crate::str; | |
9 | ||
10 | /// Representation of a borrowed C string. | |
11 | /// | |
12 | /// This type represents a borrowed reference to a nul-terminated | |
13 | /// array of bytes. It can be constructed safely from a <code>&[[u8]]</code> | |
14 | /// slice, or unsafely from a raw `*const c_char`. It can then be | |
15 | /// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or | |
16 | /// into an owned `CString`. | |
17 | /// | |
18 | /// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former | |
19 | /// in each pair are borrowed references; the latter are owned | |
20 | /// strings. | |
21 | /// | |
22 | /// Note that this structure is **not** `repr(C)` and is not recommended to be | |
23 | /// placed in the signatures of FFI functions. Instead, safe wrappers of FFI | |
24 | /// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide | |
25 | /// a safe interface to other consumers. | |
26 | /// | |
27 | /// # Examples | |
28 | /// | |
29 | /// Inspecting a foreign C string: | |
30 | /// | |
31 | /// ```ignore (extern-declaration) | |
32 | /// use std::ffi::CStr; | |
33 | /// use std::os::raw::c_char; | |
34 | /// | |
35 | /// extern "C" { fn my_string() -> *const c_char; } | |
36 | /// | |
37 | /// unsafe { | |
38 | /// let slice = CStr::from_ptr(my_string()); | |
39 | /// println!("string buffer size without nul terminator: {}", slice.to_bytes().len()); | |
40 | /// } | |
41 | /// ``` | |
42 | /// | |
43 | /// Passing a Rust-originating C string: | |
44 | /// | |
45 | /// ```ignore (extern-declaration) | |
46 | /// use std::ffi::{CString, CStr}; | |
47 | /// use std::os::raw::c_char; | |
48 | /// | |
49 | /// fn work(data: &CStr) { | |
50 | /// extern "C" { fn work_with(data: *const c_char); } | |
51 | /// | |
52 | /// unsafe { work_with(data.as_ptr()) } | |
53 | /// } | |
54 | /// | |
55 | /// let s = CString::new("data data data data").expect("CString::new failed"); | |
56 | /// work(&s); | |
57 | /// ``` | |
58 | /// | |
59 | /// Converting a foreign C string into a Rust `String`: | |
60 | /// | |
61 | /// ```ignore (extern-declaration) | |
62 | /// use std::ffi::CStr; | |
63 | /// use std::os::raw::c_char; | |
64 | /// | |
65 | /// extern "C" { fn my_string() -> *const c_char; } | |
66 | /// | |
67 | /// fn my_string_safe() -> String { | |
68 | /// unsafe { | |
69 | /// CStr::from_ptr(my_string()).to_string_lossy().into_owned() | |
70 | /// } | |
71 | /// } | |
72 | /// | |
73 | /// println!("string: {}", my_string_safe()); | |
74 | /// ``` | |
75 | /// | |
76 | /// [str]: prim@str "str" | |
77 | #[derive(Hash)] | |
78 | #[cfg_attr(not(test), rustc_diagnostic_item = "CStr")] | |
79 | #[unstable(feature = "core_c_str", issue = "94079")] | |
923072b8 | 80 | #[rustc_has_incoherent_inherent_impls] |
04454e1e FG |
81 | // FIXME: |
82 | // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies | |
83 | // on `CStr` being layout-compatible with `[u8]`. | |
84 | // When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`. | |
85 | // Anyway, `CStr` representation and layout are considered implementation detail, are | |
86 | // not documented and must not be relied upon. | |
87 | pub struct CStr { | |
88 | // FIXME: this should not be represented with a DST slice but rather with | |
89 | // just a raw `c_char` along with some form of marker to make | |
90 | // this an unsized type. Essentially `sizeof(&CStr)` should be the | |
91 | // same as `sizeof(&c_char)` but `CStr` should be an unsized type. | |
92 | inner: [c_char], | |
93 | } | |
94 | ||
95 | /// An error indicating that a nul byte was not in the expected position. | |
96 | /// | |
97 | /// The slice used to create a [`CStr`] must have one and only one nul byte, | |
98 | /// positioned at the end. | |
99 | /// | |
100 | /// This error is created by the [`CStr::from_bytes_with_nul`] method. | |
101 | /// See its documentation for more. | |
102 | /// | |
103 | /// # Examples | |
104 | /// | |
105 | /// ``` | |
106 | /// use std::ffi::{CStr, FromBytesWithNulError}; | |
107 | /// | |
108 | /// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err(); | |
109 | /// ``` | |
110 | #[derive(Clone, PartialEq, Eq, Debug)] | |
111 | #[unstable(feature = "core_c_str", issue = "94079")] | |
112 | pub struct FromBytesWithNulError { | |
113 | kind: FromBytesWithNulErrorKind, | |
114 | } | |
115 | ||
116 | #[derive(Clone, PartialEq, Eq, Debug)] | |
117 | enum FromBytesWithNulErrorKind { | |
118 | InteriorNul(usize), | |
119 | NotNulTerminated, | |
120 | } | |
121 | ||
122 | impl FromBytesWithNulError { | |
123 | fn interior_nul(pos: usize) -> FromBytesWithNulError { | |
124 | FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } | |
125 | } | |
126 | fn not_nul_terminated() -> FromBytesWithNulError { | |
127 | FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } | |
128 | } | |
129 | ||
130 | #[doc(hidden)] | |
131 | #[unstable(feature = "cstr_internals", issue = "none")] | |
132 | pub fn __description(&self) -> &str { | |
133 | match self.kind { | |
134 | FromBytesWithNulErrorKind::InteriorNul(..) => { | |
135 | "data provided contains an interior nul byte" | |
136 | } | |
137 | FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated", | |
138 | } | |
139 | } | |
140 | } | |
141 | ||
142 | /// An error indicating that no nul byte was present. | |
143 | /// | |
144 | /// A slice used to create a [`CStr`] must contain a nul byte somewhere | |
145 | /// within the slice. | |
146 | /// | |
147 | /// This error is created by the [`CStr::from_bytes_until_nul`] method. | |
148 | /// | |
149 | #[derive(Clone, PartialEq, Eq, Debug)] | |
150 | #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] | |
151 | pub struct FromBytesUntilNulError(()); | |
152 | ||
153 | #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] | |
154 | impl fmt::Display for FromBytesUntilNulError { | |
155 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
156 | write!(f, "data provided does not contain a nul") | |
157 | } | |
158 | } | |
159 | ||
160 | #[stable(feature = "cstr_debug", since = "1.3.0")] | |
161 | impl fmt::Debug for CStr { | |
162 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
163 | write!(f, "\"")?; | |
164 | for byte in self.to_bytes().iter().flat_map(|&b| ascii::escape_default(b)) { | |
165 | f.write_char(byte as char)?; | |
166 | } | |
167 | write!(f, "\"") | |
168 | } | |
169 | } | |
170 | ||
171 | #[stable(feature = "cstr_default", since = "1.10.0")] | |
172 | impl Default for &CStr { | |
173 | fn default() -> Self { | |
174 | const SLICE: &[c_char] = &[0]; | |
175 | // SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string. | |
176 | unsafe { CStr::from_ptr(SLICE.as_ptr()) } | |
177 | } | |
178 | } | |
179 | ||
180 | #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] | |
181 | impl fmt::Display for FromBytesWithNulError { | |
182 | #[allow(deprecated, deprecated_in_future)] | |
183 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
184 | f.write_str(self.__description())?; | |
185 | if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind { | |
186 | write!(f, " at byte pos {pos}")?; | |
187 | } | |
188 | Ok(()) | |
189 | } | |
190 | } | |
191 | ||
192 | impl CStr { | |
193 | /// Wraps a raw C string with a safe C string wrapper. | |
194 | /// | |
195 | /// This function will wrap the provided `ptr` with a `CStr` wrapper, which | |
196 | /// allows inspection and interoperation of non-owned C strings. The total | |
197 | /// size of the raw C string must be smaller than `isize::MAX` **bytes** | |
198 | /// in memory due to calling the `slice::from_raw_parts` function. | |
04454e1e | 199 | /// |
923072b8 FG |
200 | /// # Safety |
201 | /// | |
202 | /// * The memory pointed to by `ptr` must contain a valid nul terminator at the | |
203 | /// end of the string. | |
204 | /// | |
205 | /// * `ptr` must be [valid] for reads of bytes up to and including the null terminator. | |
206 | /// This means in particular: | |
207 | /// | |
208 | /// * The entire memory range of this `CStr` must be contained within a single allocated object! | |
209 | /// * `ptr` must be non-null even for a zero-length cstr. | |
210 | /// | |
211 | /// * The memory referenced by the returned `CStr` must not be mutated for | |
212 | /// the duration of lifetime `'a`. | |
04454e1e FG |
213 | /// |
214 | /// > **Note**: This operation is intended to be a 0-cost cast but it is | |
215 | /// > currently implemented with an up-front calculation of the length of | |
216 | /// > the string. This is not guaranteed to always be the case. | |
217 | /// | |
923072b8 FG |
218 | /// # Caveat |
219 | /// | |
220 | /// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse, | |
221 | /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, | |
222 | /// such as by providing a helper function taking the lifetime of a host value for the slice, | |
223 | /// or by explicit annotation. | |
224 | /// | |
04454e1e FG |
225 | /// # Examples |
226 | /// | |
227 | /// ```ignore (extern-declaration) | |
228 | /// # fn main() { | |
229 | /// use std::ffi::CStr; | |
230 | /// use std::os::raw::c_char; | |
231 | /// | |
232 | /// extern "C" { | |
233 | /// fn my_string() -> *const c_char; | |
234 | /// } | |
235 | /// | |
236 | /// unsafe { | |
237 | /// let slice = CStr::from_ptr(my_string()); | |
238 | /// println!("string returned: {}", slice.to_str().unwrap()); | |
239 | /// } | |
240 | /// # } | |
241 | /// ``` | |
923072b8 FG |
242 | /// |
243 | /// [valid]: core::ptr#safety | |
04454e1e FG |
244 | #[inline] |
245 | #[must_use] | |
246 | #[stable(feature = "rust1", since = "1.0.0")] | |
247 | pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { | |
248 | // SAFETY: The caller has provided a pointer that points to a valid C | |
249 | // string with a NUL terminator of size less than `isize::MAX`, whose | |
250 | // content remain valid and doesn't change for the lifetime of the | |
251 | // returned `CStr`. | |
252 | // | |
253 | // Thus computing the length is fine (a NUL byte exists), the call to | |
254 | // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning | |
255 | // the call to `from_bytes_with_nul_unchecked` is correct. | |
256 | // | |
257 | // The cast from c_char to u8 is ok because a c_char is always one byte. | |
258 | unsafe { | |
259 | extern "C" { | |
260 | /// Provided by libc or compiler_builtins. | |
261 | fn strlen(s: *const c_char) -> usize; | |
262 | } | |
263 | let len = strlen(ptr); | |
264 | let ptr = ptr as *const u8; | |
265 | CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) | |
266 | } | |
267 | } | |
268 | ||
269 | /// Creates a C string wrapper from a byte slice. | |
270 | /// | |
271 | /// This method will create a `CStr` from any byte slice that contains at | |
272 | /// least one nul byte. The caller does not need to know or specify where | |
273 | /// the nul byte is located. | |
274 | /// | |
275 | /// If the first byte is a nul character, this method will return an | |
276 | /// empty `CStr`. If multiple nul characters are present, the `CStr` will | |
277 | /// end at the first one. | |
278 | /// | |
279 | /// If the slice only has a single nul byte at the end, this method is | |
280 | /// equivalent to [`CStr::from_bytes_with_nul`]. | |
281 | /// | |
282 | /// # Examples | |
283 | /// ``` | |
284 | /// #![feature(cstr_from_bytes_until_nul)] | |
285 | /// | |
286 | /// use std::ffi::CStr; | |
287 | /// | |
288 | /// let mut buffer = [0u8; 16]; | |
289 | /// unsafe { | |
290 | /// // Here we might call an unsafe C function that writes a string | |
291 | /// // into the buffer. | |
292 | /// let buf_ptr = buffer.as_mut_ptr(); | |
293 | /// buf_ptr.write_bytes(b'A', 8); | |
294 | /// } | |
295 | /// // Attempt to extract a C nul-terminated string from the buffer. | |
296 | /// let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap(); | |
297 | /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA"); | |
298 | /// ``` | |
299 | /// | |
300 | #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] | |
301 | pub fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { | |
302 | let nul_pos = memchr::memchr(0, bytes); | |
303 | match nul_pos { | |
304 | Some(nul_pos) => { | |
305 | let subslice = &bytes[..nul_pos + 1]; | |
306 | // SAFETY: We know there is a nul byte at nul_pos, so this slice | |
307 | // (ending at the nul byte) is a well-formed C string. | |
308 | Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) }) | |
309 | } | |
310 | None => Err(FromBytesUntilNulError(())), | |
311 | } | |
312 | } | |
313 | ||
314 | /// Creates a C string wrapper from a byte slice. | |
315 | /// | |
316 | /// This function will cast the provided `bytes` to a `CStr` | |
317 | /// wrapper after ensuring that the byte slice is nul-terminated | |
318 | /// and does not contain any interior nul bytes. | |
319 | /// | |
320 | /// If the nul byte may not be at the end, | |
321 | /// [`CStr::from_bytes_until_nul`] can be used instead. | |
322 | /// | |
323 | /// # Examples | |
324 | /// | |
325 | /// ``` | |
326 | /// use std::ffi::CStr; | |
327 | /// | |
328 | /// let cstr = CStr::from_bytes_with_nul(b"hello\0"); | |
329 | /// assert!(cstr.is_ok()); | |
330 | /// ``` | |
331 | /// | |
332 | /// Creating a `CStr` without a trailing nul terminator is an error: | |
333 | /// | |
334 | /// ``` | |
335 | /// use std::ffi::CStr; | |
336 | /// | |
337 | /// let cstr = CStr::from_bytes_with_nul(b"hello"); | |
338 | /// assert!(cstr.is_err()); | |
339 | /// ``` | |
340 | /// | |
341 | /// Creating a `CStr` with an interior nul byte is an error: | |
342 | /// | |
343 | /// ``` | |
344 | /// use std::ffi::CStr; | |
345 | /// | |
346 | /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0"); | |
347 | /// assert!(cstr.is_err()); | |
348 | /// ``` | |
349 | #[stable(feature = "cstr_from_bytes", since = "1.10.0")] | |
350 | pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { | |
351 | let nul_pos = memchr::memchr(0, bytes); | |
352 | match nul_pos { | |
353 | Some(nul_pos) if nul_pos + 1 == bytes.len() => { | |
354 | // SAFETY: We know there is only one nul byte, at the end | |
355 | // of the byte slice. | |
356 | Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) | |
357 | } | |
358 | Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), | |
359 | None => Err(FromBytesWithNulError::not_nul_terminated()), | |
360 | } | |
361 | } | |
362 | ||
363 | /// Unsafely creates a C string wrapper from a byte slice. | |
364 | /// | |
365 | /// This function will cast the provided `bytes` to a `CStr` wrapper without | |
923072b8 FG |
366 | /// performing any sanity checks. |
367 | /// | |
368 | /// # Safety | |
369 | /// The provided slice **must** be nul-terminated and not contain any interior | |
370 | /// nul bytes. | |
04454e1e FG |
371 | /// |
372 | /// # Examples | |
373 | /// | |
374 | /// ``` | |
375 | /// use std::ffi::{CStr, CString}; | |
376 | /// | |
377 | /// unsafe { | |
378 | /// let cstring = CString::new("hello").expect("CString::new failed"); | |
379 | /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()); | |
380 | /// assert_eq!(cstr, &*cstring); | |
381 | /// } | |
382 | /// ``` | |
383 | #[inline] | |
384 | #[must_use] | |
385 | #[stable(feature = "cstr_from_bytes", since = "1.10.0")] | |
386 | #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] | |
387 | pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { | |
388 | // We're in a const fn, so this is the best we can do | |
389 | debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); | |
390 | // SAFETY: Calling an inner function with the same prerequisites. | |
391 | unsafe { Self::_from_bytes_with_nul_unchecked(bytes) } | |
392 | } | |
393 | ||
394 | #[inline] | |
395 | const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { | |
396 | // SAFETY: Casting to CStr is safe because its internal representation | |
397 | // is a [u8] too (safe only inside std). | |
398 | // Dereferencing the obtained pointer is safe because it comes from a | |
399 | // reference. Making a reference is then safe because its lifetime | |
400 | // is bound by the lifetime of the given `bytes`. | |
401 | unsafe { &*(bytes as *const [u8] as *const CStr) } | |
402 | } | |
403 | ||
404 | /// Returns the inner pointer to this C string. | |
405 | /// | |
406 | /// The returned pointer will be valid for as long as `self` is, and points | |
407 | /// to a contiguous region of memory terminated with a 0 byte to represent | |
408 | /// the end of the string. | |
409 | /// | |
410 | /// **WARNING** | |
411 | /// | |
412 | /// The returned pointer is read-only; writing to it (including passing it | |
413 | /// to C code that writes to it) causes undefined behavior. | |
414 | /// | |
415 | /// It is your responsibility to make sure that the underlying memory is not | |
416 | /// freed too early. For example, the following code will cause undefined | |
417 | /// behavior when `ptr` is used inside the `unsafe` block: | |
418 | /// | |
419 | /// ```no_run | |
420 | /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)] | |
421 | /// use std::ffi::CString; | |
422 | /// | |
423 | /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr(); | |
424 | /// unsafe { | |
425 | /// // `ptr` is dangling | |
426 | /// *ptr; | |
427 | /// } | |
428 | /// ``` | |
429 | /// | |
430 | /// This happens because the pointer returned by `as_ptr` does not carry any | |
431 | /// lifetime information and the `CString` is deallocated immediately after | |
432 | /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` | |
433 | /// expression is evaluated. | |
434 | /// To fix the problem, bind the `CString` to a local variable: | |
435 | /// | |
436 | /// ```no_run | |
437 | /// # #![allow(unused_must_use)] | |
438 | /// use std::ffi::CString; | |
439 | /// | |
440 | /// let hello = CString::new("Hello").expect("CString::new failed"); | |
441 | /// let ptr = hello.as_ptr(); | |
442 | /// unsafe { | |
443 | /// // `ptr` is valid because `hello` is in scope | |
444 | /// *ptr; | |
445 | /// } | |
446 | /// ``` | |
447 | /// | |
448 | /// This way, the lifetime of the `CString` in `hello` encompasses | |
449 | /// the lifetime of `ptr` and the `unsafe` block. | |
450 | #[inline] | |
451 | #[must_use] | |
452 | #[stable(feature = "rust1", since = "1.0.0")] | |
453 | #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] | |
454 | pub const fn as_ptr(&self) -> *const c_char { | |
455 | self.inner.as_ptr() | |
456 | } | |
457 | ||
458 | /// Converts this C string to a byte slice. | |
459 | /// | |
460 | /// The returned slice will **not** contain the trailing nul terminator that this C | |
461 | /// string has. | |
462 | /// | |
463 | /// > **Note**: This method is currently implemented as a constant-time | |
464 | /// > cast, but it is planned to alter its definition in the future to | |
465 | /// > perform the length calculation whenever this method is called. | |
466 | /// | |
467 | /// # Examples | |
468 | /// | |
469 | /// ``` | |
470 | /// use std::ffi::CStr; | |
471 | /// | |
472 | /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); | |
473 | /// assert_eq!(cstr.to_bytes(), b"foo"); | |
474 | /// ``` | |
475 | #[inline] | |
476 | #[must_use = "this returns the result of the operation, \ | |
477 | without modifying the original"] | |
478 | #[stable(feature = "rust1", since = "1.0.0")] | |
479 | pub fn to_bytes(&self) -> &[u8] { | |
480 | let bytes = self.to_bytes_with_nul(); | |
481 | // SAFETY: to_bytes_with_nul returns slice with length at least 1 | |
482 | unsafe { bytes.get_unchecked(..bytes.len() - 1) } | |
483 | } | |
484 | ||
485 | /// Converts this C string to a byte slice containing the trailing 0 byte. | |
486 | /// | |
487 | /// This function is the equivalent of [`CStr::to_bytes`] except that it | |
488 | /// will retain the trailing nul terminator instead of chopping it off. | |
489 | /// | |
490 | /// > **Note**: This method is currently implemented as a 0-cost cast, but | |
491 | /// > it is planned to alter its definition in the future to perform the | |
492 | /// > length calculation whenever this method is called. | |
493 | /// | |
494 | /// # Examples | |
495 | /// | |
496 | /// ``` | |
497 | /// use std::ffi::CStr; | |
498 | /// | |
499 | /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); | |
500 | /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0"); | |
501 | /// ``` | |
502 | #[inline] | |
503 | #[must_use = "this returns the result of the operation, \ | |
504 | without modifying the original"] | |
505 | #[stable(feature = "rust1", since = "1.0.0")] | |
506 | pub fn to_bytes_with_nul(&self) -> &[u8] { | |
507 | // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s | |
508 | // is safe on all supported targets. | |
509 | unsafe { &*(&self.inner as *const [c_char] as *const [u8]) } | |
510 | } | |
511 | ||
512 | /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8. | |
513 | /// | |
514 | /// If the contents of the `CStr` are valid UTF-8 data, this | |
515 | /// function will return the corresponding <code>&[str]</code> slice. Otherwise, | |
516 | /// it will return an error with details of where UTF-8 validation failed. | |
517 | /// | |
518 | /// [str]: prim@str "str" | |
519 | /// | |
520 | /// # Examples | |
521 | /// | |
522 | /// ``` | |
523 | /// use std::ffi::CStr; | |
524 | /// | |
525 | /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); | |
526 | /// assert_eq!(cstr.to_str(), Ok("foo")); | |
527 | /// ``` | |
528 | #[stable(feature = "cstr_to_str", since = "1.4.0")] | |
529 | pub fn to_str(&self) -> Result<&str, str::Utf8Error> { | |
530 | // N.B., when `CStr` is changed to perform the length check in `.to_bytes()` | |
531 | // instead of in `from_ptr()`, it may be worth considering if this should | |
532 | // be rewritten to do the UTF-8 check inline with the length calculation | |
533 | // instead of doing it afterwards. | |
534 | str::from_utf8(self.to_bytes()) | |
535 | } | |
536 | } | |
537 | ||
538 | #[stable(feature = "rust1", since = "1.0.0")] | |
539 | impl PartialEq for CStr { | |
540 | fn eq(&self, other: &CStr) -> bool { | |
541 | self.to_bytes().eq(other.to_bytes()) | |
542 | } | |
543 | } | |
544 | #[stable(feature = "rust1", since = "1.0.0")] | |
545 | impl Eq for CStr {} | |
546 | #[stable(feature = "rust1", since = "1.0.0")] | |
547 | impl PartialOrd for CStr { | |
548 | fn partial_cmp(&self, other: &CStr) -> Option<Ordering> { | |
549 | self.to_bytes().partial_cmp(&other.to_bytes()) | |
550 | } | |
551 | } | |
552 | #[stable(feature = "rust1", since = "1.0.0")] | |
553 | impl Ord for CStr { | |
554 | fn cmp(&self, other: &CStr) -> Ordering { | |
555 | self.to_bytes().cmp(&other.to_bytes()) | |
556 | } | |
557 | } | |
558 | ||
559 | #[stable(feature = "cstr_range_from", since = "1.47.0")] | |
560 | impl ops::Index<ops::RangeFrom<usize>> for CStr { | |
561 | type Output = CStr; | |
562 | ||
563 | fn index(&self, index: ops::RangeFrom<usize>) -> &CStr { | |
564 | let bytes = self.to_bytes_with_nul(); | |
565 | // we need to manually check the starting index to account for the null | |
566 | // byte, since otherwise we could get an empty string that doesn't end | |
567 | // in a null. | |
568 | if index.start < bytes.len() { | |
569 | // SAFETY: Non-empty tail of a valid `CStr` is still a valid `CStr`. | |
570 | unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } | |
571 | } else { | |
572 | panic!( | |
573 | "index out of bounds: the len is {} but the index is {}", | |
574 | bytes.len(), | |
575 | index.start | |
576 | ); | |
577 | } | |
578 | } | |
579 | } | |
580 | ||
581 | #[stable(feature = "cstring_asref", since = "1.7.0")] | |
582 | impl AsRef<CStr> for CStr { | |
583 | #[inline] | |
584 | fn as_ref(&self) -> &CStr { | |
585 | self | |
586 | } | |
587 | } |