]> git.lizzy.rs Git - rust.git/blob - library/core/src/ffi/c_str.rs
Auto merge of #2641 - DrMeepster:init_once_acquire, r=RalfJung
[rust.git] / library / core / src / ffi / c_str.rs
1 use crate::cmp::Ordering;
2 use crate::ffi::c_char;
3 use crate::fmt;
4 use crate::intrinsics;
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 ///     let cstr = unsafe { CStr::from_ptr(my_string()) };
69 ///     // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation
70 ///     String::from_utf8_lossy(cstr.to_bytes()).to_string()
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 #[stable(feature = "core_c_str", since = "1.64.0")]
80 #[rustc_has_incoherent_inherent_impls]
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 #[stable(feature = "core_c_str", since = "1.64.0")]
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     const fn interior_nul(pos: usize) -> FromBytesWithNulError {
124         FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
125     }
126     const 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, "\"{}\"", self.to_bytes().escape_ascii())
164     }
165 }
166
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()) }
173     }
174 }
175
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(())
185     }
186 }
187
188 impl CStr {
189     /// Wraps a raw C string with a safe C string wrapper.
190     ///
191     /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
192     /// allows inspection and interoperation of non-owned C strings. The total
193     /// size of the raw C string must be smaller than `isize::MAX` **bytes**
194     /// in memory due to calling the `slice::from_raw_parts` function.
195     ///
196     /// # Safety
197     ///
198     /// * The memory pointed to by `ptr` must contain a valid nul terminator at the
199     ///   end of the string.
200     ///
201     /// * `ptr` must be [valid] for reads of bytes up to and including the null terminator.
202     ///   This means in particular:
203     ///
204     ///     * The entire memory range of this `CStr` must be contained within a single allocated object!
205     ///     * `ptr` must be non-null even for a zero-length cstr.
206     ///
207     /// * The memory referenced by the returned `CStr` must not be mutated for
208     ///   the duration of lifetime `'a`.
209     ///
210     /// > **Note**: This operation is intended to be a 0-cost cast but it is
211     /// > currently implemented with an up-front calculation of the length of
212     /// > the string. This is not guaranteed to always be the case.
213     ///
214     /// # Caveat
215     ///
216     /// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse,
217     /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context,
218     /// such as by providing a helper function taking the lifetime of a host value for the slice,
219     /// or by explicit annotation.
220     ///
221     /// # Examples
222     ///
223     /// ```ignore (extern-declaration)
224     /// use std::ffi::{c_char, CStr};
225     ///
226     /// extern "C" {
227     ///     fn my_string() -> *const c_char;
228     /// }
229     ///
230     /// unsafe {
231     ///     let slice = CStr::from_ptr(my_string());
232     ///     println!("string returned: {}", slice.to_str().unwrap());
233     /// }
234     /// ```
235     ///
236     /// ```
237     /// #![feature(const_cstr_methods)]
238     ///
239     /// use std::ffi::{c_char, CStr};
240     ///
241     /// const HELLO_PTR: *const c_char = {
242     ///     const BYTES: &[u8] = b"Hello, world!\0";
243     ///     BYTES.as_ptr().cast()
244     /// };
245     /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) };
246     /// ```
247     ///
248     /// [valid]: core::ptr#safety
249     #[inline]
250     #[must_use]
251     #[stable(feature = "rust1", since = "1.0.0")]
252     #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
253     pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
254         // SAFETY: The caller has provided a pointer that points to a valid C
255         // string with a NUL terminator of size less than `isize::MAX`, whose
256         // content remain valid and doesn't change for the lifetime of the
257         // returned `CStr`.
258         //
259         // Thus computing the length is fine (a NUL byte exists), the call to
260         // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
261         // the call to `from_bytes_with_nul_unchecked` is correct.
262         //
263         // The cast from c_char to u8 is ok because a c_char is always one byte.
264         unsafe {
265             const fn strlen_ct(s: *const c_char) -> usize {
266                 let mut len = 0;
267
268                 // SAFETY: Outer caller has provided a pointer to a valid C string.
269                 while unsafe { *s.add(len) } != 0 {
270                     len += 1;
271                 }
272
273                 len
274             }
275
276             fn strlen_rt(s: *const c_char) -> usize {
277                 extern "C" {
278                     /// Provided by libc or compiler_builtins.
279                     fn strlen(s: *const c_char) -> usize;
280                 }
281
282                 // SAFETY: Outer caller has provided a pointer to a valid C string.
283                 unsafe { strlen(s) }
284             }
285
286             let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt);
287             Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1))
288         }
289     }
290
291     /// Creates a C string wrapper from a byte slice.
292     ///
293     /// This method will create a `CStr` from any byte slice that contains at
294     /// least one nul byte. The caller does not need to know or specify where
295     /// the nul byte is located.
296     ///
297     /// If the first byte is a nul character, this method will return an
298     /// empty `CStr`. If multiple nul characters are present, the `CStr` will
299     /// end at the first one.
300     ///
301     /// If the slice only has a single nul byte at the end, this method is
302     /// equivalent to [`CStr::from_bytes_with_nul`].
303     ///
304     /// # Examples
305     /// ```
306     /// #![feature(cstr_from_bytes_until_nul)]
307     ///
308     /// use std::ffi::CStr;
309     ///
310     /// let mut buffer = [0u8; 16];
311     /// unsafe {
312     ///     // Here we might call an unsafe C function that writes a string
313     ///     // into the buffer.
314     ///     let buf_ptr = buffer.as_mut_ptr();
315     ///     buf_ptr.write_bytes(b'A', 8);
316     /// }
317     /// // Attempt to extract a C nul-terminated string from the buffer.
318     /// let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap();
319     /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA");
320     /// ```
321     ///
322     #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
323     #[rustc_const_unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
324     pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> {
325         let nul_pos = memchr::memchr(0, bytes);
326         match nul_pos {
327             Some(nul_pos) => {
328                 let subslice = &bytes[..nul_pos + 1];
329                 // SAFETY: We know there is a nul byte at nul_pos, so this slice
330                 // (ending at the nul byte) is a well-formed C string.
331                 Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) })
332             }
333             None => Err(FromBytesUntilNulError(())),
334         }
335     }
336
337     /// Creates a C string wrapper from a byte slice.
338     ///
339     /// This function will cast the provided `bytes` to a `CStr`
340     /// wrapper after ensuring that the byte slice is nul-terminated
341     /// and does not contain any interior nul bytes.
342     ///
343     /// If the nul byte may not be at the end,
344     /// [`CStr::from_bytes_until_nul`] can be used instead.
345     ///
346     /// # Examples
347     ///
348     /// ```
349     /// use std::ffi::CStr;
350     ///
351     /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
352     /// assert!(cstr.is_ok());
353     /// ```
354     ///
355     /// Creating a `CStr` without a trailing nul terminator is an error:
356     ///
357     /// ```
358     /// use std::ffi::CStr;
359     ///
360     /// let cstr = CStr::from_bytes_with_nul(b"hello");
361     /// assert!(cstr.is_err());
362     /// ```
363     ///
364     /// Creating a `CStr` with an interior nul byte is an error:
365     ///
366     /// ```
367     /// use std::ffi::CStr;
368     ///
369     /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
370     /// assert!(cstr.is_err());
371     /// ```
372     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
373     #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
374     pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
375         let nul_pos = memchr::memchr(0, bytes);
376         match nul_pos {
377             Some(nul_pos) if nul_pos + 1 == bytes.len() => {
378                 // SAFETY: We know there is only one nul byte, at the end
379                 // of the byte slice.
380                 Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
381             }
382             Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
383             None => Err(FromBytesWithNulError::not_nul_terminated()),
384         }
385     }
386
387     /// Unsafely creates a C string wrapper from a byte slice.
388     ///
389     /// This function will cast the provided `bytes` to a `CStr` wrapper without
390     /// performing any sanity checks.
391     ///
392     /// # Safety
393     /// The provided slice **must** be nul-terminated and not contain any interior
394     /// nul bytes.
395     ///
396     /// # Examples
397     ///
398     /// ```
399     /// use std::ffi::{CStr, CString};
400     ///
401     /// unsafe {
402     ///     let cstring = CString::new("hello").expect("CString::new failed");
403     ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
404     ///     assert_eq!(cstr, &*cstring);
405     /// }
406     /// ```
407     #[inline]
408     #[must_use]
409     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
410     #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
411     #[rustc_allow_const_fn_unstable(const_eval_select)]
412     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
413         #[inline]
414         fn rt_impl(bytes: &[u8]) -> &CStr {
415             // Chance at catching some UB at runtime with debug builds.
416             debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
417
418             // SAFETY: Casting to CStr is safe because its internal representation
419             // is a [u8] too (safe only inside std).
420             // Dereferencing the obtained pointer is safe because it comes from a
421             // reference. Making a reference is then safe because its lifetime
422             // is bound by the lifetime of the given `bytes`.
423             unsafe { &*(bytes as *const [u8] as *const CStr) }
424         }
425
426         const fn const_impl(bytes: &[u8]) -> &CStr {
427             // Saturating so that an empty slice panics in the assert with a good
428             // message, not here due to underflow.
429             let mut i = bytes.len().saturating_sub(1);
430             assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated");
431
432             // Ending null byte exists, skip to the rest.
433             while i != 0 {
434                 i -= 1;
435                 let byte = bytes[i];
436                 assert!(byte != 0, "input contained interior nul");
437             }
438
439             // SAFETY: See `rt_impl` cast.
440             unsafe { &*(bytes as *const [u8] as *const CStr) }
441         }
442
443         // SAFETY: The const and runtime versions have identical behavior
444         // unless the safety contract of `from_bytes_with_nul_unchecked` is
445         // violated, which is UB.
446         unsafe { intrinsics::const_eval_select((bytes,), const_impl, rt_impl) }
447     }
448
449     /// Returns the inner pointer to this C string.
450     ///
451     /// The returned pointer will be valid for as long as `self` is, and points
452     /// to a contiguous region of memory terminated with a 0 byte to represent
453     /// the end of the string.
454     ///
455     /// **WARNING**
456     ///
457     /// The returned pointer is read-only; writing to it (including passing it
458     /// to C code that writes to it) causes undefined behavior.
459     ///
460     /// It is your responsibility to make sure that the underlying memory is not
461     /// freed too early. For example, the following code will cause undefined
462     /// behavior when `ptr` is used inside the `unsafe` block:
463     ///
464     /// ```no_run
465     /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
466     /// use std::ffi::CString;
467     ///
468     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
469     /// unsafe {
470     ///     // `ptr` is dangling
471     ///     *ptr;
472     /// }
473     /// ```
474     ///
475     /// This happens because the pointer returned by `as_ptr` does not carry any
476     /// lifetime information and the `CString` is deallocated immediately after
477     /// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
478     /// expression is evaluated.
479     /// To fix the problem, bind the `CString` to a local variable:
480     ///
481     /// ```no_run
482     /// # #![allow(unused_must_use)]
483     /// use std::ffi::CString;
484     ///
485     /// let hello = CString::new("Hello").expect("CString::new failed");
486     /// let ptr = hello.as_ptr();
487     /// unsafe {
488     ///     // `ptr` is valid because `hello` is in scope
489     ///     *ptr;
490     /// }
491     /// ```
492     ///
493     /// This way, the lifetime of the `CString` in `hello` encompasses
494     /// the lifetime of `ptr` and the `unsafe` block.
495     #[inline]
496     #[must_use]
497     #[stable(feature = "rust1", since = "1.0.0")]
498     #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
499     pub const fn as_ptr(&self) -> *const c_char {
500         self.inner.as_ptr()
501     }
502
503     /// Returns `true` if `self.to_bytes()` has a length of 0.
504     ///
505     /// # Examples
506     ///
507     /// ```
508     /// #![feature(cstr_is_empty)]
509     ///
510     /// use std::ffi::CStr;
511     /// # use std::ffi::FromBytesWithNulError;
512     ///
513     /// # fn main() { test().unwrap(); }
514     /// # fn test() -> Result<(), FromBytesWithNulError> {
515     /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?;
516     /// assert!(!cstr.is_empty());
517     ///
518     /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
519     /// assert!(empty_cstr.is_empty());
520     /// # Ok(())
521     /// # }
522     /// ```
523     #[inline]
524     #[unstable(feature = "cstr_is_empty", issue = "102444")]
525     pub const fn is_empty(&self) -> bool {
526         // SAFETY: We know there is at least one byte; for empty strings it
527         // is the NUL terminator.
528         (unsafe { self.inner.get_unchecked(0) }) == &0
529     }
530
531     /// Converts this C string to a byte slice.
532     ///
533     /// The returned slice will **not** contain the trailing nul terminator that this C
534     /// string has.
535     ///
536     /// > **Note**: This method is currently implemented as a constant-time
537     /// > cast, but it is planned to alter its definition in the future to
538     /// > perform the length calculation whenever this method is called.
539     ///
540     /// # Examples
541     ///
542     /// ```
543     /// use std::ffi::CStr;
544     ///
545     /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
546     /// assert_eq!(cstr.to_bytes(), b"foo");
547     /// ```
548     #[inline]
549     #[must_use = "this returns the result of the operation, \
550                   without modifying the original"]
551     #[stable(feature = "rust1", since = "1.0.0")]
552     #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
553     pub const fn to_bytes(&self) -> &[u8] {
554         let bytes = self.to_bytes_with_nul();
555         // SAFETY: to_bytes_with_nul returns slice with length at least 1
556         unsafe { bytes.get_unchecked(..bytes.len() - 1) }
557     }
558
559     /// Converts this C string to a byte slice containing the trailing 0 byte.
560     ///
561     /// This function is the equivalent of [`CStr::to_bytes`] except that it
562     /// will retain the trailing nul terminator instead of chopping it off.
563     ///
564     /// > **Note**: This method is currently implemented as a 0-cost cast, but
565     /// > it is planned to alter its definition in the future to perform the
566     /// > length calculation whenever this method is called.
567     ///
568     /// # Examples
569     ///
570     /// ```
571     /// use std::ffi::CStr;
572     ///
573     /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
574     /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
575     /// ```
576     #[inline]
577     #[must_use = "this returns the result of the operation, \
578                   without modifying the original"]
579     #[stable(feature = "rust1", since = "1.0.0")]
580     #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
581     pub const fn to_bytes_with_nul(&self) -> &[u8] {
582         // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
583         // is safe on all supported targets.
584         unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
585     }
586
587     /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8.
588     ///
589     /// If the contents of the `CStr` are valid UTF-8 data, this
590     /// function will return the corresponding <code>&[str]</code> slice. Otherwise,
591     /// it will return an error with details of where UTF-8 validation failed.
592     ///
593     /// [str]: prim@str "str"
594     ///
595     /// # Examples
596     ///
597     /// ```
598     /// use std::ffi::CStr;
599     ///
600     /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
601     /// assert_eq!(cstr.to_str(), Ok("foo"));
602     /// ```
603     #[stable(feature = "cstr_to_str", since = "1.4.0")]
604     #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
605     pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
606         // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
607         // instead of in `from_ptr()`, it may be worth considering if this should
608         // be rewritten to do the UTF-8 check inline with the length calculation
609         // instead of doing it afterwards.
610         str::from_utf8(self.to_bytes())
611     }
612 }
613
614 #[stable(feature = "rust1", since = "1.0.0")]
615 impl PartialEq for CStr {
616     fn eq(&self, other: &CStr) -> bool {
617         self.to_bytes().eq(other.to_bytes())
618     }
619 }
620 #[stable(feature = "rust1", since = "1.0.0")]
621 impl Eq for CStr {}
622 #[stable(feature = "rust1", since = "1.0.0")]
623 impl PartialOrd for CStr {
624     fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
625         self.to_bytes().partial_cmp(&other.to_bytes())
626     }
627 }
628 #[stable(feature = "rust1", since = "1.0.0")]
629 impl Ord for CStr {
630     fn cmp(&self, other: &CStr) -> Ordering {
631         self.to_bytes().cmp(&other.to_bytes())
632     }
633 }
634
635 #[stable(feature = "cstr_range_from", since = "1.47.0")]
636 impl ops::Index<ops::RangeFrom<usize>> for CStr {
637     type Output = CStr;
638
639     fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
640         let bytes = self.to_bytes_with_nul();
641         // we need to manually check the starting index to account for the null
642         // byte, since otherwise we could get an empty string that doesn't end
643         // in a null.
644         if index.start < bytes.len() {
645             // SAFETY: Non-empty tail of a valid `CStr` is still a valid `CStr`.
646             unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
647         } else {
648             panic!(
649                 "index out of bounds: the len is {} but the index is {}",
650                 bytes.len(),
651                 index.start
652             );
653         }
654     }
655 }
656
657 #[stable(feature = "cstring_asref", since = "1.7.0")]
658 impl AsRef<CStr> for CStr {
659     #[inline]
660     fn as_ref(&self) -> &CStr {
661         self
662     }
663 }