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