core/ffi/
c_str.rs

1//! [`CStr`] and its related types.
2
3use crate::cmp::Ordering;
4use crate::error::Error;
5use crate::ffi::c_char;
6use crate::intrinsics::const_eval_select;
7use crate::iter::FusedIterator;
8use crate::marker::PhantomData;
9use crate::ptr::NonNull;
10use crate::slice::memchr;
11use crate::{fmt, ops, slice, str};
12
13// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link
14//   depends on where the item is being documented. however, since this is libcore, we can't
15//   actually reference libstd or liballoc in intra-doc links. so, the best we can do is remove the
16//   links to `CString` and `String` for now until a solution is developed
17
18/// Representation of a borrowed C string.
19///
20/// This type represents a borrowed reference to a nul-terminated
21/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
22/// slice, or unsafely from a raw `*const c_char`. It can be expressed as a
23/// literal in the form `c"Hello world"`.
24///
25/// The `CStr` can then be converted to a Rust <code>&[str]</code> by performing
26/// UTF-8 validation, or into an owned `CString`.
27///
28/// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former
29/// in each pair are borrowed references; the latter are owned
30/// strings.
31///
32/// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)`
33/// notwithstanding) and should not be placed in the signatures of FFI functions.
34/// Instead, safe wrappers of FFI functions may leverage [`CStr::as_ptr`] and the unsafe
35/// [`CStr::from_ptr`] constructor to provide a safe interface to other consumers.
36///
37/// # Examples
38///
39/// Inspecting a foreign C string:
40///
41/// ```
42/// use std::ffi::CStr;
43/// use std::os::raw::c_char;
44///
45/// # /* Extern functions are awkward in doc comments - fake it instead
46/// extern "C" { fn my_string() -> *const c_char; }
47/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() }
48///
49/// unsafe {
50///     let slice = CStr::from_ptr(my_string());
51///     println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
52/// }
53/// ```
54///
55/// Passing a Rust-originating C string:
56///
57/// ```
58/// use std::ffi::CStr;
59/// use std::os::raw::c_char;
60///
61/// fn work(data: &CStr) {
62///     unsafe extern "C" fn work_with(s: *const c_char) {}
63///     unsafe { work_with(data.as_ptr()) }
64/// }
65///
66/// let s = c"Hello world!";
67/// work(&s);
68/// ```
69///
70/// Converting a foreign C string into a Rust `String`:
71///
72/// ```
73/// use std::ffi::CStr;
74/// use std::os::raw::c_char;
75///
76/// # /* Extern functions are awkward in doc comments - fake it instead
77/// extern "C" { fn my_string() -> *const c_char; }
78/// # */ unsafe extern "C" fn my_string() -> *const c_char { c"hello".as_ptr() }
79///
80/// fn my_string_safe() -> String {
81///     let cstr = unsafe { CStr::from_ptr(my_string()) };
82///     // Get a copy-on-write Cow<'_, str>, then extract the
83///     // allocated String (or allocate a fresh one if needed).
84///     cstr.to_string_lossy().into_owned()
85/// }
86///
87/// println!("string: {}", my_string_safe());
88/// ```
89///
90/// [str]: prim@str "str"
91#[derive(PartialEq, Eq, Hash)]
92#[stable(feature = "core_c_str", since = "1.64.0")]
93#[rustc_diagnostic_item = "cstr_type"]
94#[rustc_has_incoherent_inherent_impls]
95#[lang = "CStr"]
96// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
97// on `CStr` being layout-compatible with `[u8]`.
98// However, `CStr` layout is considered an implementation detail and must not be relied upon. We
99// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
100// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
101#[repr(transparent)]
102pub struct CStr {
103    // FIXME: this should not be represented with a DST slice but rather with
104    //        just a raw `c_char` along with some form of marker to make
105    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
106    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
107    inner: [c_char],
108}
109
110/// An error indicating that a nul byte was not in the expected position.
111///
112/// The slice used to create a [`CStr`] must have one and only one nul byte,
113/// positioned at the end.
114///
115/// This error is created by the [`CStr::from_bytes_with_nul`] method.
116/// See its documentation for more.
117///
118/// # Examples
119///
120/// ```
121/// use std::ffi::{CStr, FromBytesWithNulError};
122///
123/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
124/// ```
125#[derive(Clone, Copy, PartialEq, Eq, Debug)]
126#[stable(feature = "core_c_str", since = "1.64.0")]
127pub enum FromBytesWithNulError {
128    /// Data provided contains an interior nul byte at byte `position`.
129    InteriorNul {
130        /// The position of the interior nul byte.
131        position: usize,
132    },
133    /// Data provided is not nul terminated.
134    NotNulTerminated,
135}
136
137#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
138impl fmt::Display for FromBytesWithNulError {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        match self {
141            Self::InteriorNul { position } => {
142                write!(f, "data provided contains an interior nul byte at byte position {position}")
143            }
144            Self::NotNulTerminated => write!(f, "data provided is not nul terminated"),
145        }
146    }
147}
148
149#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
150impl Error for FromBytesWithNulError {}
151
152/// An error indicating that no nul byte was present.
153///
154/// A slice used to create a [`CStr`] must contain a nul byte somewhere
155/// within the slice.
156///
157/// This error is created by the [`CStr::from_bytes_until_nul`] method.
158#[derive(Clone, PartialEq, Eq, Debug)]
159#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
160pub struct FromBytesUntilNulError(());
161
162#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
163impl fmt::Display for FromBytesUntilNulError {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        write!(f, "data provided does not contain a nul")
166    }
167}
168
169/// Shows the underlying bytes as a normal string, with invalid UTF-8
170/// presented as hex escape sequences.
171#[stable(feature = "cstr_debug", since = "1.3.0")]
172impl fmt::Debug for CStr {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        fmt::Debug::fmt(crate::bstr::ByteStr::from_bytes(self.to_bytes()), f)
175    }
176}
177
178#[stable(feature = "cstr_default", since = "1.10.0")]
179impl Default for &CStr {
180    #[inline]
181    fn default() -> Self {
182        const SLICE: &[c_char] = &[0];
183        // SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string.
184        unsafe { CStr::from_ptr(SLICE.as_ptr()) }
185    }
186}
187
188impl 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 terminated buffer must be smaller than [`isize::MAX`] **bytes**
194    /// in memory (a restriction from [`slice::from_raw_parts`]).
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 nul terminator.
202    ///   This means in particular:
203    ///
204    ///     * The entire memory range of this `CStr` must be contained within a single allocation!
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    /// * The nul terminator must be within `isize::MAX` from `ptr`
211    ///
212    /// > **Note**: This operation is intended to be a 0-cost cast but it is
213    /// > currently implemented with an up-front calculation of the length of
214    /// > the string. This is not guaranteed to always be the case.
215    ///
216    /// # Caveat
217    ///
218    /// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse,
219    /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context,
220    /// such as by providing a helper function taking the lifetime of a host value for the slice,
221    /// or by explicit annotation.
222    ///
223    /// # Examples
224    ///
225    /// ```
226    /// use std::ffi::{c_char, CStr};
227    ///
228    /// fn my_string() -> *const c_char {
229    ///     c"hello".as_ptr()
230    /// }
231    ///
232    /// unsafe {
233    ///     let slice = CStr::from_ptr(my_string());
234    ///     assert_eq!(slice.to_str().unwrap(), "hello");
235    /// }
236    /// ```
237    ///
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    /// assert_eq!(c"Hello, world!", HELLO);
248    /// ```
249    ///
250    /// [valid]: core::ptr#safety
251    #[inline] // inline is necessary for codegen to see strlen.
252    #[must_use]
253    #[stable(feature = "rust1", since = "1.0.0")]
254    #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
255    pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
256        // SAFETY: The caller has provided a pointer that points to a valid C
257        // string with a NUL terminator less than `isize::MAX` from `ptr`.
258        let len = unsafe { strlen(ptr) };
259
260        // SAFETY: The caller has provided a valid pointer with length less than
261        // `isize::MAX`, so `from_raw_parts` is safe. The content remains valid
262        // and doesn't change for the lifetime of the returned `CStr`. This
263        // means the call to `from_bytes_with_nul_unchecked` is correct.
264        //
265        // The cast from c_char to u8 is ok because a c_char is always one byte.
266        unsafe { Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) }
267    }
268
269    /// Creates a C string wrapper from a byte slice with any number of nuls.
270    ///
271    /// This method will create a `CStr` from any byte slice that contains at
272    /// least one nul byte. Unlike with [`CStr::from_bytes_with_nul`], the caller
273    /// does not need to know where 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    /// use std::ffi::CStr;
285    ///
286    /// let mut buffer = [0u8; 16];
287    /// unsafe {
288    ///     // Here we might call an unsafe C function that writes a string
289    ///     // into the buffer.
290    ///     let buf_ptr = buffer.as_mut_ptr();
291    ///     buf_ptr.write_bytes(b'A', 8);
292    /// }
293    /// // Attempt to extract a C nul-terminated string from the buffer.
294    /// let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap();
295    /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA");
296    /// ```
297    ///
298    #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
299    #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
300    pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> {
301        let nul_pos = memchr::memchr(0, bytes);
302        match nul_pos {
303            Some(nul_pos) => {
304                // FIXME(const-hack) replace with range index
305                // SAFETY: nul_pos + 1 <= bytes.len()
306                let subslice = unsafe { crate::slice::from_raw_parts(bytes.as_ptr(), nul_pos + 1) };
307                // SAFETY: We know there is a nul byte at nul_pos, so this slice
308                // (ending at the nul byte) is a well-formed C string.
309                Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) })
310            }
311            None => Err(FromBytesUntilNulError(())),
312        }
313    }
314
315    /// Creates a C string wrapper from a byte slice with exactly one nul
316    /// terminator.
317    ///
318    /// This function will cast the provided `bytes` to a `CStr`
319    /// wrapper after ensuring that the byte slice is nul-terminated
320    /// and does not contain any interior nul bytes.
321    ///
322    /// If the nul byte may not be at the end,
323    /// [`CStr::from_bytes_until_nul`] can be used instead.
324    ///
325    /// # Examples
326    ///
327    /// ```
328    /// use std::ffi::CStr;
329    ///
330    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
331    /// assert_eq!(cstr, Ok(c"hello"));
332    /// ```
333    ///
334    /// Creating a `CStr` without a trailing nul terminator is an error:
335    ///
336    /// ```
337    /// use std::ffi::{CStr, FromBytesWithNulError};
338    ///
339    /// let cstr = CStr::from_bytes_with_nul(b"hello");
340    /// assert_eq!(cstr, Err(FromBytesWithNulError::NotNulTerminated));
341    /// ```
342    ///
343    /// Creating a `CStr` with an interior nul byte is an error:
344    ///
345    /// ```
346    /// use std::ffi::{CStr, FromBytesWithNulError};
347    ///
348    /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
349    /// assert_eq!(cstr, Err(FromBytesWithNulError::InteriorNul { position: 2 }));
350    /// ```
351    #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
352    #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
353    pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
354        let nul_pos = memchr::memchr(0, bytes);
355        match nul_pos {
356            Some(nul_pos) if nul_pos + 1 == bytes.len() => {
357                // SAFETY: We know there is only one nul byte, at the end
358                // of the byte slice.
359                Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
360            }
361            Some(position) => Err(FromBytesWithNulError::InteriorNul { position }),
362            None => Err(FromBytesWithNulError::NotNulTerminated),
363        }
364    }
365
366    /// Unsafely creates a C string wrapper from a byte slice.
367    ///
368    /// This function will cast the provided `bytes` to a `CStr` wrapper without
369    /// performing any sanity checks.
370    ///
371    /// # Safety
372    /// The provided slice **must** be nul-terminated and not contain any interior
373    /// nul bytes.
374    ///
375    /// # Examples
376    ///
377    /// ```
378    /// use std::ffi::CStr;
379    ///
380    /// let bytes = b"Hello world!\0";
381    ///
382    /// let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(bytes) };
383    /// assert_eq!(cstr.to_bytes_with_nul(), bytes);
384    /// ```
385    #[inline]
386    #[must_use]
387    #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
388    #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
389    #[rustc_allow_const_fn_unstable(const_eval_select)]
390    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
391        const_eval_select!(
392            @capture { bytes: &[u8] } -> &CStr:
393            if const {
394                // Saturating so that an empty slice panics in the assert with a good
395                // message, not here due to underflow.
396                let mut i = bytes.len().saturating_sub(1);
397                assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated");
398
399                // Ending nul byte exists, skip to the rest.
400                while i != 0 {
401                    i -= 1;
402                    let byte = bytes[i];
403                    assert!(byte != 0, "input contained interior nul");
404                }
405
406                // SAFETY: See runtime cast comment below.
407                unsafe { &*(bytes as *const [u8] as *const CStr) }
408            } else {
409                // Chance at catching some UB at runtime with debug builds.
410                debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
411
412                // SAFETY: Casting to CStr is safe because its internal representation
413                // is a [u8] too (safe only inside std).
414                // Dereferencing the obtained pointer is safe because it comes from a
415                // reference. Making a reference is then safe because its lifetime
416                // is bound by the lifetime of the given `bytes`.
417                unsafe { &*(bytes as *const [u8] as *const CStr) }
418            }
419        )
420    }
421
422    /// Returns the inner pointer to this C string.
423    ///
424    /// The returned pointer will be valid for as long as `self` is, and points
425    /// to a contiguous region of memory terminated with a 0 byte to represent
426    /// the end of the string.
427    ///
428    /// The type of the returned pointer is
429    /// [`*const c_char`][crate::ffi::c_char], and whether it's
430    /// an alias for `*const i8` or `*const u8` is platform-specific.
431    ///
432    /// **WARNING**
433    ///
434    /// The returned pointer is read-only; writing to it (including passing it
435    /// to C code that writes to it) causes undefined behavior.
436    ///
437    /// It is your responsibility to make sure that the underlying memory is not
438    /// freed too early. For example, the following code will cause undefined
439    /// behavior when `ptr` is used inside the `unsafe` block:
440    ///
441    /// ```no_run
442    /// # #![expect(dangling_pointers_from_temporaries)]
443    /// use std::ffi::{CStr, CString};
444    ///
445    /// // 💀 The meaning of this entire program is undefined,
446    /// // 💀 and nothing about its behavior is guaranteed,
447    /// // 💀 not even that its behavior resembles the code as written,
448    /// // 💀 just because it contains a single instance of undefined behavior!
449    ///
450    /// // 🚨 creates a dangling pointer to a temporary `CString`
451    /// // 🚨 that is deallocated at the end of the statement
452    /// let ptr = CString::new("Hi!".to_uppercase()).unwrap().as_ptr();
453    ///
454    /// // without undefined behavior, you would expect that `ptr` equals:
455    /// dbg!(CStr::from_bytes_with_nul(b"HI!\0").unwrap());
456    ///
457    /// // 🙏 Possibly the program behaved as expected so far,
458    /// // 🙏 and this just shows `ptr` is now garbage..., but
459    /// // 💀 this violates `CStr::from_ptr`'s safety contract
460    /// // 💀 leading to a dereference of a dangling pointer,
461    /// // 💀 which is immediate undefined behavior.
462    /// // 💀 *BOOM*, you're dead, your entire program has no meaning.
463    /// dbg!(unsafe { CStr::from_ptr(ptr) });
464    /// ```
465    ///
466    /// This happens because, the pointer returned by `as_ptr` does not carry any
467    /// lifetime information, and the `CString` is deallocated immediately after
468    /// the expression that it is part of has been evaluated.
469    /// To fix the problem, bind the `CString` to a local variable:
470    ///
471    /// ```
472    /// use std::ffi::{CStr, CString};
473    ///
474    /// let c_str = CString::new("Hi!".to_uppercase()).unwrap();
475    /// let ptr = c_str.as_ptr();
476    ///
477    /// assert_eq!(unsafe { CStr::from_ptr(ptr) }, c"HI!");
478    /// ```
479    #[inline]
480    #[must_use]
481    #[stable(feature = "rust1", since = "1.0.0")]
482    #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
483    #[rustc_as_ptr]
484    #[rustc_never_returns_null_ptr]
485    pub const fn as_ptr(&self) -> *const c_char {
486        self.inner.as_ptr()
487    }
488
489    /// We could eventually expose this publicly, if we wanted.
490    #[inline]
491    #[must_use]
492    const fn as_non_null_ptr(&self) -> NonNull<c_char> {
493        // FIXME(const_trait_impl) replace with `NonNull::from`
494        // SAFETY: a reference is never null
495        unsafe { NonNull::new_unchecked(&self.inner as *const [c_char] as *mut [c_char]) }
496            .as_non_null_ptr()
497    }
498
499    /// Returns the length of `self`. Like C's `strlen`, this does not include the nul terminator.
500    ///
501    /// > **Note**: This method is currently implemented as a constant-time
502    /// > cast, but it is planned to alter its definition in the future to
503    /// > perform the length calculation whenever this method is called.
504    ///
505    /// # Examples
506    ///
507    /// ```
508    /// assert_eq!(c"foo".count_bytes(), 3);
509    /// assert_eq!(c"".count_bytes(), 0);
510    /// ```
511    #[inline]
512    #[must_use]
513    #[doc(alias("len", "strlen"))]
514    #[stable(feature = "cstr_count_bytes", since = "1.79.0")]
515    #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
516    pub const fn count_bytes(&self) -> usize {
517        self.inner.len() - 1
518    }
519
520    /// Returns `true` if `self.to_bytes()` has a length of 0.
521    ///
522    /// # Examples
523    ///
524    /// ```
525    /// assert!(!c"foo".is_empty());
526    /// assert!(c"".is_empty());
527    /// ```
528    #[inline]
529    #[stable(feature = "cstr_is_empty", since = "1.71.0")]
530    #[rustc_const_stable(feature = "cstr_is_empty", since = "1.71.0")]
531    pub const fn is_empty(&self) -> bool {
532        // SAFETY: We know there is at least one byte; for empty strings it
533        // is the NUL terminator.
534        // FIXME(const-hack): use get_unchecked
535        unsafe { *self.inner.as_ptr() == 0 }
536    }
537
538    /// Converts this C string to a byte slice.
539    ///
540    /// The returned slice will **not** contain the trailing nul terminator that this C
541    /// string has.
542    ///
543    /// > **Note**: This method is currently implemented as a constant-time
544    /// > cast, but it is planned to alter its definition in the future to
545    /// > perform the length calculation whenever this method is called.
546    ///
547    /// # Examples
548    ///
549    /// ```
550    /// assert_eq!(c"foo".to_bytes(), b"foo");
551    /// ```
552    #[inline]
553    #[must_use = "this returns the result of the operation, \
554                  without modifying the original"]
555    #[stable(feature = "rust1", since = "1.0.0")]
556    #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
557    pub const fn to_bytes(&self) -> &[u8] {
558        let bytes = self.to_bytes_with_nul();
559        // FIXME(const-hack) replace with range index
560        // SAFETY: to_bytes_with_nul returns slice with length at least 1
561        unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
562    }
563
564    /// Converts this C string to a byte slice containing the trailing 0 byte.
565    ///
566    /// This function is the equivalent of [`CStr::to_bytes`] except that it
567    /// will retain the trailing nul terminator instead of chopping it off.
568    ///
569    /// > **Note**: This method is currently implemented as a 0-cost cast, but
570    /// > it is planned to alter its definition in the future to perform the
571    /// > length calculation whenever this method is called.
572    ///
573    /// # Examples
574    ///
575    /// ```
576    /// assert_eq!(c"foo".to_bytes_with_nul(), b"foo\0");
577    /// ```
578    #[inline]
579    #[must_use = "this returns the result of the operation, \
580                  without modifying the original"]
581    #[stable(feature = "rust1", since = "1.0.0")]
582    #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
583    pub const fn to_bytes_with_nul(&self) -> &[u8] {
584        // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
585        // is safe on all supported targets.
586        unsafe { &*((&raw const self.inner) as *const [u8]) }
587    }
588
589    /// Iterates over the bytes in this C string.
590    ///
591    /// The returned iterator will **not** contain the trailing nul terminator
592    /// that this C string has.
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// #![feature(cstr_bytes)]
598    ///
599    /// assert!(c"foo".bytes().eq(*b"foo"));
600    /// ```
601    #[inline]
602    #[unstable(feature = "cstr_bytes", issue = "112115")]
603    pub fn bytes(&self) -> Bytes<'_> {
604        Bytes::new(self)
605    }
606
607    /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8.
608    ///
609    /// If the contents of the `CStr` are valid UTF-8 data, this
610    /// function will return the corresponding <code>&[str]</code> slice. Otherwise,
611    /// it will return an error with details of where UTF-8 validation failed.
612    ///
613    /// [str]: prim@str "str"
614    ///
615    /// # Examples
616    ///
617    /// ```
618    /// assert_eq!(c"foo".to_str(), Ok("foo"));
619    /// ```
620    #[stable(feature = "cstr_to_str", since = "1.4.0")]
621    #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
622    pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
623        // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
624        // instead of in `from_ptr()`, it may be worth considering if this should
625        // be rewritten to do the UTF-8 check inline with the length calculation
626        // instead of doing it afterwards.
627        str::from_utf8(self.to_bytes())
628    }
629
630    /// Returns an object that implements [`Display`] for safely printing a [`CStr`] that may
631    /// contain non-Unicode data.
632    ///
633    /// Behaves as if `self` were first lossily converted to a `str`, with invalid UTF-8 presented
634    /// as the Unicode replacement character: �.
635    ///
636    /// [`Display`]: fmt::Display
637    ///
638    /// # Examples
639    ///
640    /// ```
641    /// #![feature(cstr_display)]
642    ///
643    /// let cstr = c"Hello, world!";
644    /// println!("{}", cstr.display());
645    /// ```
646    #[unstable(feature = "cstr_display", issue = "139984")]
647    #[must_use = "this does not display the `CStr`; \
648                  it returns an object that can be displayed"]
649    #[inline]
650    pub fn display(&self) -> impl fmt::Display {
651        crate::bstr::ByteStr::from_bytes(self.to_bytes())
652    }
653}
654
655#[stable(feature = "c_string_eq_c_str", since = "CURRENT_RUSTC_VERSION")]
656impl PartialEq<&Self> for CStr {
657    #[inline]
658    fn eq(&self, other: &&Self) -> bool {
659        *self == **other
660    }
661
662    #[inline]
663    fn ne(&self, other: &&Self) -> bool {
664        *self != **other
665    }
666}
667
668// `.to_bytes()` representations are compared instead of the inner `[c_char]`s,
669// because `c_char` is `i8` (not `u8`) on some platforms.
670// That is why this is implemented manually and not derived.
671#[stable(feature = "rust1", since = "1.0.0")]
672impl PartialOrd for CStr {
673    #[inline]
674    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
675        self.to_bytes().partial_cmp(&other.to_bytes())
676    }
677}
678
679#[stable(feature = "rust1", since = "1.0.0")]
680impl Ord for CStr {
681    #[inline]
682    fn cmp(&self, other: &CStr) -> Ordering {
683        self.to_bytes().cmp(&other.to_bytes())
684    }
685}
686
687#[stable(feature = "cstr_range_from", since = "1.47.0")]
688impl ops::Index<ops::RangeFrom<usize>> for CStr {
689    type Output = CStr;
690
691    #[inline]
692    fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
693        let bytes = self.to_bytes_with_nul();
694        // we need to manually check the starting index to account for the null
695        // byte, since otherwise we could get an empty string that doesn't end
696        // in a null.
697        if index.start < bytes.len() {
698            // SAFETY: Non-empty tail of a valid `CStr` is still a valid `CStr`.
699            unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
700        } else {
701            panic!(
702                "index out of bounds: the len is {} but the index is {}",
703                bytes.len(),
704                index.start
705            );
706        }
707    }
708}
709
710#[stable(feature = "cstring_asref", since = "1.7.0")]
711impl AsRef<CStr> for CStr {
712    #[inline]
713    fn as_ref(&self) -> &CStr {
714        self
715    }
716}
717
718/// Calculate the length of a nul-terminated string. Defers to C's `strlen` when possible.
719///
720/// # Safety
721///
722/// The pointer must point to a valid buffer that contains a NUL terminator. The NUL must be
723/// located within `isize::MAX` from `ptr`.
724#[inline]
725#[unstable(feature = "cstr_internals", issue = "none")]
726#[rustc_allow_const_fn_unstable(const_eval_select)]
727const unsafe fn strlen(ptr: *const c_char) -> usize {
728    const_eval_select!(
729        @capture { s: *const c_char = ptr } -> usize:
730        if const {
731            let mut len = 0;
732
733            // SAFETY: Outer caller has provided a pointer to a valid C string.
734            while unsafe { *s.add(len) } != 0 {
735                len += 1;
736            }
737
738            len
739        } else {
740            unsafe extern "C" {
741                /// Provided by libc or compiler_builtins.
742                fn strlen(s: *const c_char) -> usize;
743            }
744
745            // SAFETY: Outer caller has provided a pointer to a valid C string.
746            unsafe { strlen(s) }
747        }
748    )
749}
750
751/// An iterator over the bytes of a [`CStr`], without the nul terminator.
752///
753/// This struct is created by the [`bytes`] method on [`CStr`].
754/// See its documentation for more.
755///
756/// [`bytes`]: CStr::bytes
757#[must_use = "iterators are lazy and do nothing unless consumed"]
758#[unstable(feature = "cstr_bytes", issue = "112115")]
759#[derive(Clone, Debug)]
760pub struct Bytes<'a> {
761    // since we know the string is nul-terminated, we only need one pointer
762    ptr: NonNull<u8>,
763    phantom: PhantomData<&'a [c_char]>,
764}
765
766#[unstable(feature = "cstr_bytes", issue = "112115")]
767unsafe impl Send for Bytes<'_> {}
768
769#[unstable(feature = "cstr_bytes", issue = "112115")]
770unsafe impl Sync for Bytes<'_> {}
771
772impl<'a> Bytes<'a> {
773    #[inline]
774    fn new(s: &'a CStr) -> Self {
775        Self { ptr: s.as_non_null_ptr().cast(), phantom: PhantomData }
776    }
777
778    #[inline]
779    fn is_empty(&self) -> bool {
780        // SAFETY: We uphold that the pointer is always valid to dereference
781        // by starting with a valid C string and then never incrementing beyond
782        // the nul terminator.
783        unsafe { self.ptr.read() == 0 }
784    }
785}
786
787#[unstable(feature = "cstr_bytes", issue = "112115")]
788impl Iterator for Bytes<'_> {
789    type Item = u8;
790
791    #[inline]
792    fn next(&mut self) -> Option<u8> {
793        // SAFETY: We only choose a pointer from a valid C string, which must
794        // be non-null and contain at least one value. Since we always stop at
795        // the nul terminator, which is guaranteed to exist, we can assume that
796        // the pointer is non-null and valid. This lets us safely dereference
797        // it and assume that adding 1 will create a new, non-null, valid
798        // pointer.
799        unsafe {
800            let ret = self.ptr.read();
801            if ret == 0 {
802                None
803            } else {
804                self.ptr = self.ptr.add(1);
805                Some(ret)
806            }
807        }
808    }
809
810    #[inline]
811    fn size_hint(&self) -> (usize, Option<usize>) {
812        if self.is_empty() { (0, Some(0)) } else { (1, None) }
813    }
814
815    #[inline]
816    fn count(self) -> usize {
817        // SAFETY: We always hold a valid pointer to a C string
818        unsafe { strlen(self.ptr.as_ptr().cast()) }
819    }
820}
821
822#[unstable(feature = "cstr_bytes", issue = "112115")]
823impl FusedIterator for Bytes<'_> {}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy