cstr_core/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![warn(rust_2018_idioms)]
3#![cfg_attr(feature = "nightly", feature(const_raw_ptr_deref))]
4#![cfg_attr(feature = "nightly", feature(const_slice_from_raw_parts))]
5#![cfg_attr(feature = "nightly", feature(const_str_from_utf8))]
6#![cfg_attr(feature = "nightly", feature(const_eval_select))]
7#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
8
9#[cfg(test)]
10extern crate std;
11
12#[cfg(feature = "alloc")]
13extern crate alloc;
14
15#[cfg(feature = "alloc")]
16use alloc::borrow::{Borrow, Cow, ToOwned};
17#[cfg(feature = "alloc")]
18use alloc::boxed::Box;
19#[cfg(feature = "alloc")]
20use alloc::rc::Rc;
21#[cfg(feature = "alloc")]
22use alloc::string::String;
23#[cfg(feature = "alloc")]
24#[cfg(feature = "arc")]
25use alloc::sync::Arc;
26#[cfg(feature = "alloc")]
27use alloc::vec::Vec;
28#[cfg(feature = "alloc")]
29use core::{mem, ops, ptr};
30
31use core::ascii;
32use core::cmp::Ordering;
33use core::fmt::{self, Write};
34use core::slice;
35use core::str::{self, Utf8Error};
36
37/// Re-export c_char
38pub use cty::c_char;
39
40#[inline]
41unsafe fn strlen(p: *const c_char) -> usize {
42    let mut n = 0;
43    while *p.offset(n as isize) != 0 {
44        n += 1;
45    }
46    n
47}
48
49/// A drop-in implementation of `memchr` that is const.
50///
51/// This is expected to perform way worse than any version the `memchr` crate provides.
52#[cfg(feature = "nightly")]
53const fn memchr_const(needle: u8, haystack: &[u8]) -> Option<usize> {
54    let mut i = 0;
55    loop {
56        i += 1;
57        if haystack.len() == i {
58            return None;
59        }
60        if haystack[i] == needle {
61            return Some(i);
62        }
63    }
64}
65
66/// Wrapper around memchr that is const, but still fast at runtime by dispatching through
67/// const_eval_select.
68#[inline]
69#[cfg(feature = "nightly")]
70const fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
71    // unsafe: Both versions provide the same functionality
72    unsafe { core::intrinsics::const_eval_select((needle, haystack), memchr_const, memchr::memchr) }
73}
74
75#[cfg(not(feature = "nightly"))]
76use memchr::memchr;
77
78/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
79/// middle.
80///
81/// This type serves the purpose of being able to safely generate a
82/// C-compatible string from a Rust byte slice or vector. An instance of this
83/// type is a static guarantee that the underlying bytes contain no interior 0
84/// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
85///
86/// `CString` is to [`&CStr`] as [`String`] is to [`&str`]: the former
87/// in each pair are owned strings; the latter are borrowed
88/// references.
89///
90/// # Creating a `CString`
91///
92/// A `CString` is created from either a byte slice or a byte vector,
93/// or anything that implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>` (for
94/// example, you can build a `CString` straight out of a [`String`] or
95/// a [`&str`], since both implement that trait).
96///
97/// The [`new`] method will actually check that the provided `&[u8]`
98/// does not have 0 bytes in the middle, and return an error if it
99/// finds one.
100///
101/// # Extracting a raw pointer to the whole C string
102///
103/// `CString` implements a [`as_ptr`] method through the [`Deref`]
104/// trait. This method will give you a `*const c_char` which you can
105/// feed directly to extern functions that expect a nul-terminated
106/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a
107/// read-only pointer; if the C code writes to it, that causes
108/// undefined behavior.
109///
110/// # Extracting a slice of the whole C string
111///
112/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
113/// `CString` with the [`as_bytes`] method. Slices produced in this
114/// way do *not* contain the trailing nul terminator. This is useful
115/// when you will be calling an extern function that takes a `*const
116/// u8` argument which is not necessarily nul-terminated, plus another
117/// argument with the length of the string — like C's `strndup()`.
118/// You can of course get the slice's length with its
119/// [`len`][slice.len] method.
120///
121/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
122/// can use [`as_bytes_with_nul`] instead.
123///
124/// Once you have the kind of slice you need (with or without a nul
125/// terminator), you can call the slice's own
126/// [`as_ptr`][slice.as_ptr] method to get a read-only raw pointer to pass to
127/// extern functions. See the documentation for that function for a
128/// discussion on ensuring the lifetime of the raw pointer.
129///
130/// [`new`]: #method.new
131/// [`as_bytes`]: #method.as_bytes
132/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
133/// [`as_ptr`]: #method.as_ptr
134/// [slice.len]: ../primitive.slice.html#method.len
135/// [`Deref`]: core::ops::Deref
136/// [`CStr`]: struct.CStr.html
137/// [`&CStr`]: struct.CStr.html
138///
139/// # Examples
140///
141/// ```ignore (extern-declaration)
142/// # fn main() {
143/// use cstr_core::CString;
144/// use cstr_core::c_char;
145///
146/// extern {
147///     fn my_printer(s: *const c_char);
148/// }
149///
150/// // We are certain that our string doesn't have 0 bytes in the middle,
151/// // so we can .expect()
152/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
153/// unsafe {
154///     my_printer(c_to_print.as_ptr());
155/// }
156/// # }
157/// ```
158///
159/// # Safety
160///
161/// `CString` is intended for working with traditional C-style strings
162/// (a sequence of non-nul bytes terminated by a single nul byte); the
163/// primary use case for these kinds of strings is interoperating with C-like
164/// code. Often you will need to transfer ownership to/from that external
165/// code. It is strongly recommended that you thoroughly read through the
166/// documentation of `CString` before use, as improper ownership management
167/// of `CString` instances can lead to invalid memory accesses, memory leaks,
168/// and other memory errors.
169
170#[cfg(feature = "alloc")]
171#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
172pub struct CString {
173    // Invariant 1: the slice ends with a zero byte and has a length of at least one.
174    // Invariant 2: the slice contains only one zero byte.
175    // Improper usage of unsafe function can break Invariant 2, but not Invariant 1.
176    inner: Box<[u8]>,
177}
178
179/// Representation of a borrowed C string.
180///
181/// This type represents a borrowed reference to a nul-terminated
182/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]`
183/// slice, or unsafely from a raw `*const c_char`. It can then be
184/// converted to a Rust [`&str`] by performing UTF-8 validation, or
185/// into an owned [`CString`].
186///
187/// `&CStr` is to [`CString`] as [`&str`] is to [`String`]: the former
188/// in each pair are borrowed references; the latter are owned
189/// strings.
190///
191/// Note that this structure is **not** `repr(C)` and is not recommended to be
192/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
193/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
194/// interface to other consumers.
195///
196/// # Examples
197///
198/// Inspecting a foreign C string:
199///
200/// ```ignore (extern-declaration)
201/// use cstr_core::CStr;
202/// use cstr_core::c_char;
203///
204/// extern { fn my_string() -> *const c_char; }
205///
206/// unsafe {
207///     let slice = CStr::from_ptr(my_string());
208///     println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
209/// }
210/// ```
211///
212/// Passing a Rust-originating C string:
213///
214/// ```ignore (extern-declaration)
215/// use cstr_core::{CString, CStr};
216/// use cstr_core::c_char;
217///
218/// fn work(data: &CStr) {
219///     extern { fn work_with(data: *const c_char); }
220///
221///     unsafe { work_with(data.as_ptr()) }
222/// }
223///
224/// let s = CString::new("data data data data").expect("CString::new failed");
225/// work(&s);
226/// ```
227///
228/// Converting a foreign C string into a Rust [`String`]:
229///
230/// ```ignore (extern-declaration)
231/// use cstr_core::CStr;
232/// use cstr_core::c_char;
233///
234/// extern { fn my_string() -> *const c_char; }
235///
236/// fn my_string_safe() -> String {
237///     unsafe {
238///         CStr::from_ptr(my_string()).to_string_lossy().into_owned()
239///     }
240/// }
241///
242/// println!("string: {}", my_string_safe());
243/// ```
244///
245/// [`CString`]: struct.CString.html
246/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
247/// [`from_ptr`]: #method.from_ptr
248#[derive(Hash)]
249// FIXME:
250// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
251// on `CStr` being layout-compatible with `[u8]`.
252// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`.
253// Anyway, `CStr` representation and layout are considered implementation detail, are
254// not documented and must not be relied upon.
255pub struct CStr {
256    // FIXME: this should not be represented with a DST slice but rather with
257    //        just a raw `c_char` along with some form of marker to make
258    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
259    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
260    inner: [c_char],
261}
262
263/// An error indicating that an interior nul byte was found.
264///
265/// While Rust strings may contain nul bytes in the middle, C strings
266/// can't, as that byte would effectively truncate the string.
267///
268/// This error is created by the [`new`][`CString::new`] method on
269/// [`CString`]. See its documentation for more.
270///
271/// [`CString`]: struct.CString.html
272/// [`CString::new`]: struct.CString.html#method.new
273///
274/// # Examples
275///
276/// ```
277/// use cstr_core::{CString, NulError};
278///
279/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
280/// ```
281#[cfg(feature = "alloc")]
282#[derive(Clone, PartialEq, Eq, Debug)]
283pub struct NulError(usize, Vec<u8>);
284
285/// An error indicating that a nul byte was not in the expected position.
286///
287/// The slice used to create a [`CStr`] must have one and only one nul
288/// byte at the end of the slice.
289///
290/// This error is created by the
291/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
292/// [`CStr`]. See its documentation for more.
293///
294/// [`CStr`]: struct.CStr.html
295/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
296///
297/// # Examples
298///
299/// ```
300/// use cstr_core::{CStr, FromBytesWithNulError};
301///
302/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
303/// ```
304#[derive(Clone, PartialEq, Eq, Debug)]
305pub struct FromBytesWithNulError {
306    kind: FromBytesWithNulErrorKind,
307}
308
309#[derive(Clone, PartialEq, Eq, Debug)]
310enum FromBytesWithNulErrorKind {
311    InteriorNul(usize),
312    NotNulTerminated,
313}
314
315impl FromBytesWithNulError {
316    const fn interior_nul(pos: usize) -> FromBytesWithNulError {
317        FromBytesWithNulError {
318            kind: FromBytesWithNulErrorKind::InteriorNul(pos),
319        }
320    }
321    const fn not_nul_terminated() -> FromBytesWithNulError {
322        FromBytesWithNulError {
323            kind: FromBytesWithNulErrorKind::NotNulTerminated,
324        }
325    }
326}
327
328/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
329///
330/// `CString` is just a wrapper over a buffer of bytes with a nul
331/// terminator; [`into_string`][`CString::into_string`] performs UTF-8
332/// validation on those bytes and may return this error.
333///
334/// This `struct` is created by the
335/// [`into_string`][`CString::into_string`] method on [`CString`]. See
336/// its documentation for more.
337///
338/// [`CString`]: struct.CString.html
339/// [`CString::into_string`]: struct.CString.html#method.into_string
340#[cfg(feature = "alloc")]
341#[derive(Clone, PartialEq, Eq, Debug)]
342pub struct IntoStringError {
343    inner: CString,
344    error: Utf8Error,
345}
346
347#[cfg(feature = "alloc")]
348impl CString {
349    /// Creates a new C-compatible string from a container of bytes.
350    ///
351    /// This function will consume the provided data and use the
352    /// underlying bytes to construct a new string, ensuring that
353    /// there is a trailing 0 byte. This trailing 0 byte will be
354    /// appended by this function; the provided data should *not*
355    /// contain any 0 bytes in it.
356    ///
357    /// # Examples
358    ///
359    /// ```ignore (extern-declaration)
360    /// use cstr_core::CString;
361    /// use cstr_core::c_char;
362    ///
363    /// extern { fn puts(s: *const c_char); }
364    ///
365    /// let to_print = CString::new("Hello!").expect("CString::new failed");
366    /// unsafe {
367    ///     puts(to_print.as_ptr());
368    /// }
369    /// ```
370    ///
371    /// # Errors
372    ///
373    /// This function will return an error if the supplied bytes contain an
374    /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
375    /// the position of the nul byte.
376    ///
377    /// [`NulError`]: struct.NulError.html
378    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
379        Self::_new(t.into())
380    }
381
382    fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
383        match memchr::memchr(0, &bytes) {
384            Some(i) => Err(NulError(i, bytes)),
385            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
386        }
387    }
388
389    /// Creates a C-compatible string from a byte vector without checking for
390    /// interior 0 bytes.
391    ///
392    /// This method is equivalent to [`new`] except that no runtime assertion
393    /// is made that `v` contains no 0 bytes, and it requires an actual
394    /// byte vector, not anything that can be converted to one with Into.
395    ///
396    /// [`new`]: #method.new
397    ///
398    /// # Examples
399    ///
400    /// ```
401    /// use cstr_core::CString;
402    ///
403    /// let raw = b"foo".to_vec();
404    /// unsafe {
405    ///     let c_string = CString::from_vec_unchecked(raw);
406    /// }
407    /// ```
408    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
409        v.reserve_exact(1);
410        v.push(0);
411        CString {
412            inner: v.into_boxed_slice(),
413        }
414    }
415
416    /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`].
417    ///
418    /// Additionally, the length of the string will be recalculated from the pointer.
419    ///
420    /// # Safety
421    ///
422    /// This should only ever be called with a pointer that was earlier
423    /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g., trying to take
424    /// ownership of a string that was allocated by foreign code) is likely to lead
425    /// to undefined behavior or allocator corruption.
426    ///
427    /// > **Note:** If you need to borrow a string that was allocated by
428    /// > foreign code, use [`CStr`]. If you need to take ownership of
429    /// > a string that was allocated by foreign code, you will need to
430    /// > make your own provisions for freeing it appropriately, likely
431    /// > with the foreign code's API to do that.
432    ///
433    /// [`into_raw`]: #method.into_raw
434    /// [`CStr`]: struct.CStr.html
435    ///
436    /// # Examples
437    ///
438    /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
439    /// ownership with `from_raw`:
440    ///
441    /// ```ignore (extern-declaration)
442    /// use cstr_core::CString;
443    /// use cstr_core::c_char;
444    ///
445    /// extern {
446    ///     fn some_extern_function(s: *mut c_char);
447    /// }
448    ///
449    /// let c_string = CString::new("Hello!").expect("CString::new failed");
450    /// let raw = c_string.into_raw();
451    /// unsafe {
452    ///     some_extern_function(raw);
453    ///     let c_string = CString::from_raw(raw);
454    /// }
455    /// ```
456    pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
457        let len = strlen(ptr) + 1; // Including the NUL byte
458        let slice = slice::from_raw_parts_mut(ptr, len as usize);
459        CString {
460            inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]),
461        }
462    }
463
464    /// Consumes the `CString` and transfers ownership of the string to a C caller.
465    ///
466    /// The pointer which this function returns must be returned to Rust and reconstituted using
467    /// [`from_raw`] to be properly deallocated. Specifically, one
468    /// should *not* use the standard C `free()` function to deallocate
469    /// this string.
470    ///
471    /// Failure to call [`from_raw`] will lead to a memory leak.
472    ///
473    /// [`from_raw`]: #method.from_raw
474    ///
475    /// # Examples
476    ///
477    /// ```
478    /// use cstr_core::CString;
479    ///
480    /// let c_string = CString::new("foo").expect("CString::new failed");
481    ///
482    /// let ptr = c_string.into_raw();
483    ///
484    /// unsafe {
485    ///     assert_eq!(b'f', *ptr as u8);
486    ///     assert_eq!(b'o', *ptr.offset(1) as u8);
487    ///     assert_eq!(b'o', *ptr.offset(2) as u8);
488    ///     assert_eq!(b'\0', *ptr.offset(3) as u8);
489    ///
490    ///     // retake pointer to free memory
491    ///     let _ = CString::from_raw(ptr);
492    /// }
493    /// ```
494    #[inline]
495    pub fn into_raw(self) -> *mut c_char {
496        Box::into_raw(self.into_inner()) as *mut c_char
497    }
498    /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data.
499    ///
500    /// On failure, ownership of the original `CString` is returned.
501    ///
502    /// # Examples
503    ///
504    /// ```
505    /// use cstr_core::CString;
506    ///
507    /// let valid_utf8 = vec![b'f', b'o', b'o'];
508    /// let cstring = CString::new(valid_utf8).expect("CString::new failed");
509    /// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo");
510    ///
511    /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
512    /// let cstring = CString::new(invalid_utf8).expect("CString::new failed");
513    /// let err = cstring.into_string().err().expect("into_string().err() failed");
514    /// assert_eq!(err.utf8_error().valid_up_to(), 1);
515    /// ```
516    pub fn into_string(self) -> Result<String, IntoStringError> {
517        String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
518            error: e.utf8_error(),
519            inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
520        })
521    }
522
523    /// Consumes the `CString` and returns the underlying byte buffer.
524    ///
525    /// The returned buffer does **not** contain the trailing nul
526    /// terminator, and it is guaranteed to not have any interior nul
527    /// bytes.
528    ///
529    /// # Examples
530    ///
531    /// ```
532    /// use cstr_core::CString;
533    ///
534    /// let c_string = CString::new("foo").expect("CString::new failed");
535    /// let bytes = c_string.into_bytes();
536    /// assert_eq!(bytes, vec![b'f', b'o', b'o']);
537    /// ```
538    pub fn into_bytes(self) -> Vec<u8> {
539        let mut vec = self.into_inner().into_vec();
540        let _nul = vec.pop();
541        debug_assert_eq!(_nul, Some(0u8));
542        vec
543    }
544
545    /// Equivalent to the [`into_bytes`] function except that the returned vector
546    /// includes the trailing nul terminator.
547    ///
548    /// [`into_bytes`]: #method.into_bytes
549    ///
550    /// # Examples
551    ///
552    /// ```
553    /// use cstr_core::CString;
554    ///
555    /// let c_string = CString::new("foo").expect("CString::new failed");
556    /// let bytes = c_string.into_bytes_with_nul();
557    /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
558    /// ```
559    pub fn into_bytes_with_nul(self) -> Vec<u8> {
560        self.into_inner().into_vec()
561    }
562
563    /// Returns the contents of this `CString` as a slice of bytes.
564    ///
565    /// The returned slice does **not** contain the trailing nul
566    /// terminator, and it is guaranteed to not have any interior nul
567    /// bytes. If you need the nul terminator, use
568    /// [`as_bytes_with_nul`] instead.
569    ///
570    /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
571    ///
572    /// # Examples
573    ///
574    /// ```
575    /// use cstr_core::CString;
576    ///
577    /// let c_string = CString::new("foo").expect("CString::new failed");
578    /// let bytes = c_string.as_bytes();
579    /// assert_eq!(bytes, &[b'f', b'o', b'o']);
580    /// ```
581    #[inline]
582    pub fn as_bytes(&self) -> &[u8] {
583        &self.inner[..self.inner.len() - 1]
584    }
585
586    /// Equivalent to the [`as_bytes`] function except that the returned slice
587    /// includes the trailing nul terminator.
588    ///
589    /// [`as_bytes`]: #method.as_bytes
590    ///
591    /// # Examples
592    ///
593    /// ```
594    /// use cstr_core::CString;
595    ///
596    /// let c_string = CString::new("foo").expect("CString::new failed");
597    /// let bytes = c_string.as_bytes_with_nul();
598    /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
599    /// ```
600    #[inline]
601    pub fn as_bytes_with_nul(&self) -> &[u8] {
602        &self.inner
603    }
604
605    /// Extracts a [`CStr`] slice containing the entire string.
606    ///
607    /// [`CStr`]: struct.CStr.html
608    ///
609    /// # Examples
610    ///
611    /// ```
612    /// use cstr_core::{CString, CStr};
613    ///
614    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
615    /// let cstr = c_string.as_c_str();
616    /// assert_eq!(cstr,
617    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
618    /// ```
619    #[inline]
620    pub fn as_c_str(&self) -> &CStr {
621        &*self
622    }
623
624    /// Converts this `CString` into a boxed [`CStr`].
625    ///
626    /// [`CStr`]: struct.CStr.html
627    ///
628    /// # Examples
629    ///
630    /// ```
631    /// use cstr_core::{CString, CStr};
632    ///
633    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
634    /// let boxed = c_string.into_boxed_c_str();
635    /// assert_eq!(&*boxed,
636    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
637    /// ```
638    pub fn into_boxed_c_str(self) -> Box<CStr> {
639        unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
640    }
641
642    /// Bypass "move out of struct which implements [`Drop`] trait" restriction.
643    fn into_inner(self) -> Box<[u8]> {
644        // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
645        // so we use `ManuallyDrop` to ensure `self` is not dropped.
646        // Then we can return the box directly without invalidating it.
647        // See https://github.com/rust-lang/rust/issues/62553.
648        let this = mem::ManuallyDrop::new(self);
649        unsafe { ptr::read(&this.inner) }
650    }
651}
652
653// Turns this `CString` into an empty string to prevent
654// memory unsafe code from working by accident. Inline
655// to prevent LLVM from optimizing it away in debug builds.
656#[cfg(feature = "alloc")]
657impl Drop for CString {
658    #[inline]
659    fn drop(&mut self) {
660        unsafe {
661            *self.inner.get_unchecked_mut(0) = 0;
662        }
663    }
664}
665
666#[cfg(feature = "alloc")]
667impl ops::Deref for CString {
668    type Target = CStr;
669
670    #[inline]
671    fn deref(&self) -> &CStr {
672        unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
673    }
674}
675
676#[cfg(feature = "alloc")]
677impl fmt::Debug for CString {
678    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
679        fmt::Debug::fmt(&**self, f)
680    }
681}
682
683#[cfg(feature = "alloc")]
684impl From<CString> for Vec<u8> {
685    /// Converts a [`CString`] into a [`Vec`]`<u8>`.
686    ///
687    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
688    #[inline]
689    fn from(s: CString) -> Vec<u8> {
690        s.into_bytes()
691    }
692}
693
694impl fmt::Debug for CStr {
695    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
696        write!(f, "\"")?;
697        for byte in self
698            .to_bytes()
699            .iter()
700            .flat_map(|&b| ascii::escape_default(b))
701        {
702            f.write_char(byte as char)?;
703        }
704        write!(f, "\"")
705    }
706}
707
708impl<'a> Default for &'a CStr {
709    fn default() -> &'a CStr {
710        const SLICE: &[c_char] = &[0];
711        unsafe { CStr::from_ptr(SLICE.as_ptr()) }
712    }
713}
714
715#[cfg(feature = "alloc")]
716impl Default for CString {
717    /// Creates an empty `CString`.
718    fn default() -> CString {
719        let a: &CStr = Default::default();
720        a.to_owned()
721    }
722}
723
724#[cfg(feature = "alloc")]
725impl Borrow<CStr> for CString {
726    #[inline]
727    fn borrow(&self) -> &CStr {
728        self
729    }
730}
731
732#[cfg(feature = "alloc")]
733impl<'a> From<Cow<'a, CStr>> for CString {
734    #[inline]
735    fn from(s: Cow<'a, CStr>) -> Self {
736        s.into_owned()
737    }
738}
739
740#[cfg(feature = "alloc")]
741impl From<&CStr> for Box<CStr> {
742    fn from(s: &CStr) -> Box<CStr> {
743        let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
744        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
745    }
746}
747
748#[cfg(feature = "alloc")]
749impl From<Box<CStr>> for CString {
750    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
751    #[inline]
752    fn from(s: Box<CStr>) -> CString {
753        s.into_c_string()
754    }
755}
756
757#[cfg(feature = "alloc")]
758impl Clone for Box<CStr> {
759    #[inline]
760    fn clone(&self) -> Self {
761        (**self).into()
762    }
763}
764
765#[cfg(feature = "alloc")]
766impl From<CString> for Box<CStr> {
767    /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
768    #[inline]
769    fn from(s: CString) -> Box<CStr> {
770        s.into_boxed_c_str()
771    }
772}
773
774#[cfg(feature = "alloc")]
775impl<'a> From<CString> for Cow<'a, CStr> {
776    #[inline]
777    fn from(s: CString) -> Cow<'a, CStr> {
778        Cow::Owned(s)
779    }
780}
781
782#[cfg(feature = "alloc")]
783impl<'a> From<&'a CStr> for Cow<'a, CStr> {
784    #[inline]
785    fn from(s: &'a CStr) -> Cow<'a, CStr> {
786        Cow::Borrowed(s)
787    }
788}
789
790#[cfg(feature = "alloc")]
791impl<'a> From<&'a CString> for Cow<'a, CStr> {
792    #[inline]
793    fn from(s: &'a CString) -> Cow<'a, CStr> {
794        Cow::Borrowed(s.as_c_str())
795    }
796}
797
798#[cfg(feature = "alloc")]
799#[cfg(feature = "arc")]
800impl From<CString> for Arc<CStr> {
801    #[inline]
802    fn from(s: CString) -> Arc<CStr> {
803        let arc: Arc<[u8]> = Arc::from(s.into_inner());
804        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
805    }
806}
807
808#[cfg(feature = "alloc")]
809#[cfg(feature = "arc")]
810impl<'a> From<&'a CStr> for Arc<CStr> {
811    #[inline]
812    fn from(s: &CStr) -> Arc<CStr> {
813        let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
814        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
815    }
816}
817
818#[cfg(feature = "alloc")]
819impl From<CString> for Rc<CStr> {
820    #[inline]
821    fn from(s: CString) -> Rc<CStr> {
822        let rc: Rc<[u8]> = Rc::from(s.into_inner());
823        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
824    }
825}
826
827#[cfg(feature = "alloc")]
828impl<'a> From<&'a CStr> for Rc<CStr> {
829    #[inline]
830    fn from(s: &CStr) -> Rc<CStr> {
831        let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
832        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
833    }
834}
835
836#[cfg(feature = "alloc")]
837impl Default for Box<CStr> {
838    fn default() -> Box<CStr> {
839        let boxed: Box<[u8]> = Box::from([0]);
840        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
841    }
842}
843
844#[cfg(feature = "std")]
845use std::ffi::{CStr as StdCStr, CString as StdCString};
846
847#[cfg(feature = "std")]
848impl From<CString> for StdCString {
849    #[inline]
850    fn from(s: CString) -> StdCString {
851        unsafe { StdCString::from_vec_unchecked(s.into_bytes()) }
852    }
853}
854
855#[cfg(feature = "std")]
856impl<'a> From<&'a CStr> for &'a StdCStr {
857    #[inline]
858    fn from(s: &'a CStr) -> &'a StdCStr {
859        s.as_ref()
860    }
861}
862
863#[cfg(feature = "std")]
864impl From<StdCString> for CString {
865    #[inline]
866    fn from(s: StdCString) -> CString {
867        unsafe { CString::from_vec_unchecked(s.into_bytes()) }
868    }
869}
870
871#[cfg(feature = "std")]
872impl<'a> From<&'a StdCStr> for &'a CStr {
873    #[inline]
874    fn from(s: &'a StdCStr) -> &'a CStr {
875        unsafe { CStr::from_bytes_with_nul_unchecked(s.to_bytes_with_nul()) }
876    }
877}
878
879#[cfg(feature = "std")]
880impl AsRef<StdCStr> for CString {
881    #[inline]
882    fn as_ref(&self) -> &StdCStr {
883        AsRef::<CStr>::as_ref(self).as_ref()
884    }
885}
886
887#[cfg(feature = "std")]
888impl Borrow<StdCStr> for CString {
889    #[inline]
890    fn borrow(&self) -> &StdCStr {
891        self.as_ref()
892    }
893}
894
895#[cfg(feature = "std")]
896impl AsRef<StdCStr> for CStr {
897    #[inline]
898    fn as_ref(&self) -> &StdCStr {
899        unsafe { StdCStr::from_bytes_with_nul_unchecked(self.to_bytes_with_nul()) }
900    }
901}
902
903#[cfg(feature = "alloc")]
904impl NulError {
905    /// Returns the position of the nul byte in the slice that was provided to
906    /// [`CString::new`].
907    ///
908    /// [`CString::new`]: struct.CString.html#method.new
909    ///
910    /// # Examples
911    ///
912    /// ```
913    /// use cstr_core::CString;
914    ///
915    /// let nul_error = CString::new("foo\0bar").unwrap_err();
916    /// assert_eq!(nul_error.nul_position(), 3);
917    ///
918    /// let nul_error = CString::new("foo bar\0").unwrap_err();
919    /// assert_eq!(nul_error.nul_position(), 7);
920    /// ```
921    pub fn nul_position(&self) -> usize {
922        self.0
923    }
924
925    /// Consumes this error, returning the underlying vector of bytes which
926    /// generated the error in the first place.
927    ///
928    /// # Examples
929    ///
930    /// ```
931    /// use cstr_core::CString;
932    ///
933    /// let nul_error = CString::new("foo\0bar").unwrap_err();
934    /// assert_eq!(nul_error.into_vec(), b"foo\0bar");
935    /// ```
936    pub fn into_vec(self) -> Vec<u8> {
937        self.1
938    }
939}
940
941#[cfg(feature = "alloc")]
942impl fmt::Display for NulError {
943    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
944        write!(f, "nul byte found in provided data at position: {}", self.0)
945    }
946}
947
948impl fmt::Display for FromBytesWithNulError {
949    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950        let description = match self.kind {
951            FromBytesWithNulErrorKind::InteriorNul(..) => {
952                "data provided contains an interior nul byte"
953            }
954            FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated",
955        };
956        f.write_str(description)?;
957        if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
958            write!(f, " at byte pos {}", pos)?;
959        }
960        Ok(())
961    }
962}
963
964#[cfg(feature = "alloc")]
965impl IntoStringError {
966    /// Consumes this error, returning original [`CString`] which generated the
967    /// error.
968    ///
969    /// [`CString`]: struct.CString.html
970    pub fn into_cstring(self) -> CString {
971        self.inner
972    }
973
974    /// Access the underlying UTF-8 error that was the cause of this error.
975    pub fn utf8_error(&self) -> Utf8Error {
976        self.error
977    }
978}
979
980#[cfg(feature = "alloc")]
981impl fmt::Display for IntoStringError {
982    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
983        "C string contained non-utf8 bytes".fmt(f)
984    }
985}
986
987impl CStr {
988    /// Wraps a raw C string with a safe C string wrapper.
989    ///
990    /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
991    /// allows inspection and interoperation of non-owned C strings. The total
992    /// size of the raw C string must be smaller than `isize::MAX` **bytes**
993    /// in memory due to calling the `slice::from_raw_parts` function.
994    /// This method is unsafe for a number of reasons:
995    ///
996    /// * There is no guarantee to the validity of `ptr`.
997    /// * The returned lifetime is not guaranteed to be the actual lifetime of
998    ///   `ptr`.
999    /// * There is no guarantee that the memory pointed to by `ptr` contains a
1000    ///   valid nul terminator byte at the end of the string.
1001    /// * It is not guaranteed that the memory pointed by `ptr` won't change
1002    ///   before the `CStr` has been destroyed.
1003    ///
1004    /// > **Note**: This operation is intended to be a 0-cost cast but it is
1005    /// > currently implemented with an up-front calculation of the length of
1006    /// > the string. This is not guaranteed to always be the case.
1007    ///
1008    /// # Examples
1009    ///
1010    /// ```ignore (extern-declaration)
1011    /// # fn main() {
1012    /// use cstr_core::CStr;
1013    /// use cstr_core::c_char;
1014    ///
1015    /// extern {
1016    ///     fn my_string() -> *const c_char;
1017    /// }
1018    ///
1019    /// unsafe {
1020    ///     let slice = CStr::from_ptr(my_string());
1021    ///     println!("string returned: {}", slice.to_str().unwrap());
1022    /// }
1023    /// # }
1024    /// ```
1025    pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
1026        let len = strlen(ptr);
1027        let ptr = ptr as *const u8;
1028        CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
1029    }
1030
1031    /// Creates a C string wrapper from a byte slice.
1032    ///
1033    /// This function will cast the provided `bytes` to a `CStr`
1034    /// wrapper after ensuring that the byte slice is nul-terminated
1035    /// and does not contain any interior nul bytes.
1036    ///
1037    /// # Examples
1038    ///
1039    /// ```
1040    /// use cstr_core::CStr;
1041    ///
1042    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
1043    /// assert!(cstr.is_ok());
1044    /// ```
1045    ///
1046    /// Creating a `CStr` without a trailing nul terminator is an error:
1047    ///
1048    /// ```
1049    /// use cstr_core::CStr;
1050    ///
1051    /// let cstr = CStr::from_bytes_with_nul(b"hello");
1052    /// assert!(cstr.is_err());
1053    /// ```
1054    ///
1055    /// Creating a `CStr` with an interior nul byte is an error:
1056    ///
1057    /// ```
1058    /// use cstr_core::CStr;
1059    ///
1060    /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
1061    /// assert!(cstr.is_err());
1062    /// ```
1063    #[cfg(feature = "nightly")]
1064    pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
1065        let nul_pos = memchr(0, bytes);
1066        if let Some(nul_pos) = nul_pos {
1067            if nul_pos + 1 != bytes.len() {
1068                return Err(FromBytesWithNulError::interior_nul(nul_pos));
1069            }
1070            Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) })
1071        } else {
1072            Err(FromBytesWithNulError::not_nul_terminated())
1073        }
1074    }
1075
1076    /// Creates a C string wrapper from a byte slice.
1077    ///
1078    /// This function will cast the provided `bytes` to a `CStr`
1079    /// wrapper after ensuring that the byte slice is nul-terminated
1080    /// and does not contain any interior nul bytes.
1081    ///
1082    /// # Examples
1083    ///
1084    /// ```
1085    /// use cstr_core::CStr;
1086    ///
1087    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
1088    /// assert!(cstr.is_ok());
1089    /// ```
1090    ///
1091    /// Creating a `CStr` without a trailing nul terminator is an error:
1092    ///
1093    /// ```
1094    /// use cstr_core::CStr;
1095    ///
1096    /// let cstr = CStr::from_bytes_with_nul(b"hello");
1097    /// assert!(cstr.is_err());
1098    /// ```
1099    ///
1100    /// Creating a `CStr` with an interior nul byte is an error:
1101    ///
1102    /// ```
1103    /// use cstr_core::CStr;
1104    ///
1105    /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
1106    /// assert!(cstr.is_err());
1107    /// ```
1108    #[cfg(not(feature = "nightly"))]
1109    pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
1110        let nul_pos = memchr(0, bytes);
1111        if let Some(nul_pos) = nul_pos {
1112            if nul_pos + 1 != bytes.len() {
1113                return Err(FromBytesWithNulError::interior_nul(nul_pos));
1114            }
1115            Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) })
1116        } else {
1117            Err(FromBytesWithNulError::not_nul_terminated())
1118        }
1119    }
1120
1121    /// Unsafely creates a C string wrapper from a byte slice.
1122    ///
1123    /// This function will cast the provided `bytes` to a `CStr` wrapper without
1124    /// performing any sanity checks. The provided slice **must** be nul-terminated
1125    /// and not contain any interior nul bytes.
1126    ///
1127    /// # Examples
1128    ///
1129    /// ```
1130    /// use cstr_core::{CStr, CString};
1131    ///
1132    /// unsafe {
1133    ///     let cstring = CString::new("hello").expect("CString::new failed");
1134    ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
1135    ///     assert_eq!(cstr, &*cstring);
1136    /// }
1137    /// ```
1138    #[cfg(feature = "nightly")]
1139    #[inline]
1140    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
1141        &*(bytes as *const [u8] as *const CStr)
1142    }
1143
1144    /// Unsafely creates a C string wrapper from a byte slice.
1145    ///
1146    /// This function will cast the provided `bytes` to a `CStr` wrapper without
1147    /// performing any sanity checks. The provided slice **must** be nul-terminated
1148    /// and not contain any interior nul bytes.
1149    ///
1150    /// # Examples
1151    ///
1152    /// ```
1153    /// use cstr_core::{CStr, CString};
1154    ///
1155    /// unsafe {
1156    ///     let cstring = CString::new("hello").expect("CString::new failed");
1157    ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
1158    ///     assert_eq!(cstr, &*cstring);
1159    /// }
1160    /// ```
1161    #[cfg(not(feature = "nightly"))]
1162    #[inline]
1163    pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
1164        &*(bytes as *const [u8] as *const CStr)
1165    }
1166
1167    /// Returns the inner pointer to this C string.
1168    ///
1169    /// The returned pointer will be valid for as long as `self` is, and points
1170    /// to a contiguous region of memory terminated with a 0 byte to represent
1171    /// the end of the string.
1172    ///
1173    /// **WARNING**
1174    ///
1175    /// The returned pointer is read-only; writing to it (including passing it
1176    /// to C code that writes to it) causes undefined behavior.
1177    ///
1178    /// It is your responsibility to make sure that the underlying memory is not
1179    /// freed too early. For example, the following code will cause undefined
1180    /// behavior when `ptr` is used inside the `unsafe` block:
1181    ///
1182    /// ```no_run
1183    /// # #![allow(unused_must_use)]
1184    /// use cstr_core::CString;
1185    ///
1186    /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
1187    /// unsafe {
1188    ///     // `ptr` is dangling
1189    ///     *ptr;
1190    /// }
1191    /// ```
1192    ///
1193    /// This happens because the pointer returned by `as_ptr` does not carry any
1194    /// lifetime information and the [`CString`] is deallocated immediately after
1195    /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated.
1196    /// To fix the problem, bind the `CString` to a local variable:
1197    ///
1198    /// ```no_run
1199    /// # #![allow(unused_must_use)]
1200    /// use cstr_core::CString;
1201    ///
1202    /// let hello = CString::new("Hello").expect("CString::new failed");
1203    /// let ptr = hello.as_ptr();
1204    /// unsafe {
1205    ///     // `ptr` is valid because `hello` is in scope
1206    ///     *ptr;
1207    /// }
1208    /// ```
1209    ///
1210    /// This way, the lifetime of the `CString` in `hello` encompasses
1211    /// the lifetime of `ptr` and the `unsafe` block.
1212    ///
1213    /// [`CString`]: struct.CString.html
1214    #[inline]
1215    pub const fn as_ptr(&self) -> *const c_char {
1216        self.inner.as_ptr()
1217    }
1218
1219    /// Converts this C string to a byte slice.
1220    ///
1221    /// The returned slice will **not** contain the trailing nul terminator that this C
1222    /// string has.
1223    ///
1224    /// > **Note**: This method is currently implemented as a constant-time
1225    /// > cast, but it is planned to alter its definition in the future to
1226    /// > perform the length calculation whenever this method is called.
1227    ///
1228    /// # Examples
1229    ///
1230    /// ```
1231    /// use cstr_core::CStr;
1232    ///
1233    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
1234    /// assert_eq!(cstr.to_bytes(), b"foo");
1235    /// ```
1236    #[inline]
1237    #[cfg(not(feature = "nightly"))]
1238    pub fn to_bytes(&self) -> &[u8] {
1239        let bytes = self.to_bytes_with_nul();
1240        &bytes[..bytes.len() - 1]
1241    }
1242
1243    /// Converts this C string to a byte slice.
1244    ///
1245    /// The returned slice will **not** contain the trailing nul terminator that this C
1246    /// string has.
1247    ///
1248    /// > **Note**: This method is currently implemented as a constant-time
1249    /// > cast, but it is planned to alter its definition in the future to
1250    /// > perform the length calculation whenever this method is called.
1251    ///
1252    /// # Examples
1253    ///
1254    /// ```
1255    /// use cstr_core::CStr;
1256    ///
1257    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
1258    /// assert_eq!(cstr.to_bytes(), b"foo");
1259    /// ```
1260    #[inline]
1261    #[cfg(feature = "nightly")]
1262    pub const fn to_bytes(&self) -> &[u8] {
1263        let bytes = self.to_bytes_with_nul();
1264        // unsafe: This is just like [:len - 1] (but const usable), and any underflow of the `- 1`
1265        // is avoided by the type's guarantee that there is a trailing nul byte.
1266        unsafe {
1267            slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1)
1268        }
1269    }
1270
1271    /// Converts this C string to a byte slice containing the trailing 0 byte.
1272    ///
1273    /// This function is the equivalent of [`to_bytes`] except that it will retain
1274    /// the trailing nul terminator instead of chopping it off.
1275    ///
1276    /// > **Note**: This method is currently implemented as a 0-cost cast, but
1277    /// > it is planned to alter its definition in the future to perform the
1278    /// > length calculation whenever this method is called.
1279    ///
1280    /// [`to_bytes`]: #method.to_bytes
1281    ///
1282    /// # Examples
1283    ///
1284    /// ```
1285    /// use cstr_core::CStr;
1286    ///
1287    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
1288    /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
1289    /// ```
1290    #[inline]
1291    #[cfg(feature = "nightly")]
1292    pub const fn to_bytes_with_nul(&self) -> &[u8] {
1293        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
1294    }
1295
1296    /// Converts this C string to a byte slice containing the trailing 0 byte.
1297    ///
1298    /// This function is the equivalent of [`to_bytes`] except that it will retain
1299    /// the trailing nul terminator instead of chopping it off.
1300    ///
1301    /// > **Note**: This method is currently implemented as a 0-cost cast, but
1302    /// > it is planned to alter its definition in the future to perform the
1303    /// > length calculation whenever this method is called.
1304    ///
1305    /// [`to_bytes`]: #method.to_bytes
1306    ///
1307    /// # Examples
1308    ///
1309    /// ```
1310    /// use cstr_core::CStr;
1311    ///
1312    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
1313    /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
1314    /// ```
1315    #[inline]
1316    #[cfg(not(feature = "nightly"))]
1317    pub fn to_bytes_with_nul(&self) -> &[u8] {
1318        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
1319    }
1320
1321    /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
1322    ///
1323    /// If the contents of the `CStr` are valid UTF-8 data, this
1324    /// function will return the corresponding [`&str`] slice. Otherwise,
1325    /// it will return an error with details of where UTF-8 validation failed.
1326    ///
1327    /// # Examples
1328    ///
1329    /// ```
1330    /// use cstr_core::CStr;
1331    ///
1332    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
1333    /// assert_eq!(cstr.to_str(), Ok("foo"));
1334    /// ```
1335    #[cfg(not(feature = "nightly"))]
1336    pub  fn to_str(&self) -> Result<&str, Utf8Error> {
1337        // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
1338        // instead of in `from_ptr()`, it may be worth considering if this should
1339        // be rewritten to do the UTF-8 check inline with the length calculation
1340        // instead of doing it afterwards.
1341        str::from_utf8(self.to_bytes())
1342    }
1343
1344    /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
1345    ///
1346    /// If the contents of the `CStr` are valid UTF-8 data, this
1347    /// function will return the corresponding [`&str`] slice. Otherwise,
1348    /// it will return an error with details of where UTF-8 validation failed.
1349    ///
1350    /// # Examples
1351    ///
1352    /// ```
1353    /// use cstr_core::CStr;
1354    ///
1355    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
1356    /// assert_eq!(cstr.to_str(), Ok("foo"));
1357    /// ```
1358    #[cfg(feature = "nightly")]
1359    pub const fn to_str(&self) -> Result<&str, Utf8Error> {
1360        // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
1361        // instead of in `from_ptr()`, it may be worth considering if this should
1362        // be rewritten to do the UTF-8 check inline with the length calculation
1363        // instead of doing it afterwards.
1364        str::from_utf8(self.to_bytes())
1365    }
1366
1367    /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
1368    ///
1369    /// If the contents of the `CStr` are valid UTF-8 data, this
1370    /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
1371    /// with the corresponding [`&str`] slice. Otherwise, it will
1372    /// replace any invalid UTF-8 sequences with
1373    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
1374    /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
1375    ///
1376    /// [`Borrowed`]: Cow::Borrowed
1377    /// [`Owned`]: Cow::Owned
1378    /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
1379    ///
1380    /// # Examples
1381    ///
1382    /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8:
1383    ///
1384    /// ```
1385    /// use std::borrow::Cow;
1386    /// use cstr_core::CStr;
1387    ///
1388    /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0")
1389    ///                  .expect("CStr::from_bytes_with_nul failed");
1390    /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World"));
1391    /// ```
1392    ///
1393    /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
1394    ///
1395    /// ```
1396    /// use std::borrow::Cow;
1397    /// use cstr_core::CStr;
1398    ///
1399    /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0")
1400    ///                  .expect("CStr::from_bytes_with_nul failed");
1401    /// assert_eq!(
1402    ///     cstr.to_string_lossy(),
1403    ///     Cow::Owned(String::from("Hello �World")) as Cow<'_, str>
1404    /// );
1405    /// ```
1406    #[cfg(feature = "alloc")]
1407    pub fn to_string_lossy(&self) -> Cow<'_, str> {
1408        String::from_utf8_lossy(self.to_bytes())
1409    }
1410
1411    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
1412    ///
1413    /// [`CString`]: struct.CString.html
1414    ///
1415    /// # Examples
1416    ///
1417    /// ```
1418    /// use cstr_core::CString;
1419    ///
1420    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
1421    /// let boxed = c_string.into_boxed_c_str();
1422    /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
1423    /// ```
1424    #[cfg(feature = "alloc")]
1425    pub fn into_c_string(self: Box<CStr>) -> CString {
1426        let raw = Box::into_raw(self) as *mut [u8];
1427        CString {
1428            inner: unsafe { Box::from_raw(raw) },
1429        }
1430    }
1431}
1432
1433impl PartialEq for CStr {
1434    fn eq(&self, other: &CStr) -> bool {
1435        self.to_bytes().eq(other.to_bytes())
1436    }
1437}
1438impl Eq for CStr {}
1439impl PartialOrd for CStr {
1440    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
1441        self.to_bytes().partial_cmp(&other.to_bytes())
1442    }
1443}
1444impl Ord for CStr {
1445    fn cmp(&self, other: &CStr) -> Ordering {
1446        self.to_bytes().cmp(&other.to_bytes())
1447    }
1448}
1449
1450#[cfg(feature = "alloc")]
1451impl ToOwned for CStr {
1452    type Owned = CString;
1453
1454    fn to_owned(&self) -> CString {
1455        CString {
1456            inner: self.to_bytes_with_nul().into(),
1457        }
1458    }
1459}
1460
1461#[cfg(feature = "alloc")]
1462impl From<&CStr> for CString {
1463    fn from(s: &CStr) -> CString {
1464        s.to_owned()
1465    }
1466}
1467
1468#[cfg(feature = "alloc")]
1469impl ops::Index<ops::RangeFull> for CString {
1470    type Output = CStr;
1471
1472    #[inline]
1473    fn index(&self, _index: ops::RangeFull) -> &CStr {
1474        self
1475    }
1476}
1477
1478impl AsRef<CStr> for CStr {
1479    #[inline]
1480    fn as_ref(&self) -> &CStr {
1481        self
1482    }
1483}
1484
1485#[cfg(feature = "alloc")]
1486impl AsRef<CStr> for CString {
1487    #[inline]
1488    fn as_ref(&self) -> &CStr {
1489        self
1490    }
1491}
1492
1493#[inline]
1494#[doc(hidden)]
1495pub const fn bytes_are_valid(bytes: &[u8]) -> bool {
1496    if bytes.len() == 0 || bytes[bytes.len() - 1] != 0 {
1497        return false;
1498    }
1499    let mut index = 0;
1500    // No for loops yet in const functions
1501    while index < bytes.len() - 1 {
1502        if bytes[index] == 0 {
1503            return false;
1504        }
1505        index += 1;
1506    }
1507    true
1508}
1509
1510/// Generate a [CStr] at compile time that is guaranteed to be correct. The given argument should be a string literal with no `\0` bytes.
1511///
1512/// This macro validates at compile time that the given string does not contain `\0` and automatically appends `\0`.
1513///
1514/// ```rust
1515/// let str: &cstr_core::CStr = cstr_core::cstr!("Hello world!");
1516/// assert_eq!("Hello world!", str.to_str().unwrap());
1517/// ```
1518///
1519/// **note**: if the string contains `\0` bytes, the error looks like:
1520/// ```bash
1521///  error[E0080]: evaluation of constant value failed
1522///  --> src/lib.rs:1358:29
1523///   |
1524/// 4 | let str: &cstr_core::CStr = cstr_core::cstr!("Hello \0world!");
1525///   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
1526///   |
1527///   = note: this error originates in the macro `cstr_core::cstr` (in Nightly builds, run with -Z macro-backtrace for more info)
1528/// ```
1529#[macro_export]
1530macro_rules! cstr {
1531    ($e:expr) => {{
1532        const STR: &[u8] = concat!($e, "\0").as_bytes();
1533        const STR_VALID: bool = $crate::bytes_are_valid(STR);
1534        let _ = [(); 0 - (!(STR_VALID) as usize)];
1535        unsafe {
1536            $crate::CStr::from_bytes_with_nul_unchecked(STR)
1537        }
1538    }}
1539}
1540
1541#[cfg(test)]
1542mod tests {
1543    use super::*;
1544    use std::borrow::Cow::{Borrowed, Owned};
1545    use std::collections::hash_map::DefaultHasher;
1546    use std::hash::{Hash, Hasher};
1547    use std::{format, vec};
1548
1549    #[test]
1550    fn c_to_rust() {
1551        let data = b"123\0";
1552        let ptr = data.as_ptr() as *const c_char;
1553        unsafe {
1554            assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
1555            assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
1556        }
1557    }
1558
1559    #[test]
1560    fn simple() {
1561        let s = CString::new("1234").unwrap();
1562        assert_eq!(s.as_bytes(), b"1234");
1563        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
1564    }
1565
1566    #[test]
1567    fn build_with_zero1() {
1568        assert!(CString::new(&b"\0"[..]).is_err());
1569    }
1570    #[test]
1571    fn build_with_zero2() {
1572        assert!(CString::new(vec![0]).is_err());
1573    }
1574
1575    #[test]
1576    fn build_with_zero3() {
1577        unsafe {
1578            let s = CString::from_vec_unchecked(vec![0]);
1579            assert_eq!(s.as_bytes(), b"\0");
1580        }
1581    }
1582
1583    #[test]
1584    fn formatted() {
1585        let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap();
1586        assert_eq!(format!("{:?}", s), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#);
1587    }
1588
1589    #[test]
1590    fn borrowed() {
1591        unsafe {
1592            let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
1593            assert_eq!(s.to_bytes(), b"12");
1594            assert_eq!(s.to_bytes_with_nul(), b"12\0");
1595        }
1596    }
1597
1598    #[test]
1599    fn to_str() {
1600        let data = b"123\xE2\x80\xA6\0";
1601        let ptr = data.as_ptr() as *const c_char;
1602        unsafe {
1603            assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…"));
1604            assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…"));
1605        }
1606        let data = b"123\xE2\0";
1607        let ptr = data.as_ptr() as *const c_char;
1608        unsafe {
1609            assert!(CStr::from_ptr(ptr).to_str().is_err());
1610            assert_eq!(
1611                CStr::from_ptr(ptr).to_string_lossy(),
1612                Owned::<str>(format!("123\u{FFFD}"))
1613            );
1614        }
1615    }
1616
1617    #[test]
1618    fn to_owned() {
1619        let data = b"123\0";
1620        let ptr = data.as_ptr() as *const c_char;
1621
1622        let owned = unsafe { CStr::from_ptr(ptr).to_owned() };
1623        assert_eq!(owned.as_bytes_with_nul(), data);
1624    }
1625
1626    #[test]
1627    fn equal_hash() {
1628        let data = b"123\xE2\xFA\xA6\0";
1629        let ptr = data.as_ptr() as *const c_char;
1630        let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) };
1631
1632        let mut s = DefaultHasher::new();
1633        cstr.hash(&mut s);
1634        let cstr_hash = s.finish();
1635        let mut s = DefaultHasher::new();
1636        CString::new(&data[..data.len() - 1]).unwrap().hash(&mut s);
1637        let cstring_hash = s.finish();
1638
1639        assert_eq!(cstr_hash, cstring_hash);
1640    }
1641
1642    #[test]
1643    fn from_bytes_with_nul() {
1644        let data = b"123\0";
1645        let cstr = CStr::from_bytes_with_nul(data);
1646        assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..]));
1647        let cstr = CStr::from_bytes_with_nul(data);
1648        assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..]));
1649
1650        unsafe {
1651            let cstr = CStr::from_bytes_with_nul(data);
1652            let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data);
1653            assert_eq!(cstr, Ok(cstr_unchecked));
1654        }
1655    }
1656
1657    #[test]
1658    fn from_bytes_with_nul_unterminated() {
1659        let data = b"123";
1660        let cstr = CStr::from_bytes_with_nul(data);
1661        assert!(cstr.is_err());
1662    }
1663
1664    #[test]
1665    fn from_bytes_with_nul_interior() {
1666        let data = b"1\023\0";
1667        let cstr = CStr::from_bytes_with_nul(data);
1668        assert!(cstr.is_err());
1669    }
1670
1671    #[test]
1672    fn into_boxed() {
1673        let orig: &[u8] = b"Hello, world!\0";
1674        let cstr = CStr::from_bytes_with_nul(orig).unwrap();
1675        let boxed: Box<CStr> = Box::from(cstr);
1676        let cstring = cstr.to_owned().into_boxed_c_str().into_c_string();
1677        assert_eq!(cstr, &*boxed);
1678        assert_eq!(&*boxed, &*cstring);
1679        assert_eq!(&*cstring, cstr);
1680    }
1681
1682    #[test]
1683    fn boxed_default() {
1684        let boxed = <Box<CStr>>::default();
1685        assert_eq!(boxed.to_bytes_with_nul(), &[0]);
1686    }
1687
1688    #[test]
1689    #[cfg(feature = "alloc")]
1690    #[cfg(feature = "arc")]
1691    fn into_rc() {
1692        let orig: &[u8] = b"Hello, world!\0";
1693        let cstr = CStr::from_bytes_with_nul(orig).unwrap();
1694        let rc: Rc<CStr> = Rc::from(cstr);
1695        let arc: Arc<CStr> = Arc::from(cstr);
1696
1697        assert_eq!(&*rc, cstr);
1698        assert_eq!(&*arc, cstr);
1699
1700        let rc2: Rc<CStr> = Rc::from(cstr.to_owned());
1701        let arc2: Arc<CStr> = Arc::from(cstr.to_owned());
1702
1703        assert_eq!(&*rc2, cstr);
1704        assert_eq!(&*arc2, cstr);
1705    }
1706
1707    #[test]
1708    #[cfg(feature = "nightly")]
1709    fn const_cstr() {
1710        const TESTING_CSTR: &CStr =
1711            unsafe { CStr::from_bytes_with_nul_unchecked(b"Hello world!\0") };
1712        let _ = TESTING_CSTR.as_ptr();
1713    }
1714}