@@ -234,15 +234,18 @@ pub struct NulError(usize, Vec<u8>);
234
234
235
235
/// An error indicating that a nul byte was not in the expected position.
236
236
///
237
- /// The slice used to create a [`CStr`] must have one and only one nul
238
- /// byte at the end of the slice .
237
+ /// The slice used to create a [`CStr`] or the vector used to create a
238
+ /// [`CString`] must have one and only one nul byte, positioned at the end .
239
239
///
240
240
/// This error is created by the
241
241
/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
242
- /// [`CStr`]. See its documentation for more.
242
+ /// [`CStr`] or the [`from_vec_with_nul`][`CString::from_vec_with_nul`] method
243
+ /// on [`CString`]. See their documentation for more.
243
244
///
244
245
/// [`CStr`]: struct.CStr.html
245
246
/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
247
+ /// [`CString`]: struct.CString.html
248
+ /// [`CString::from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
246
249
///
247
250
/// # Examples
248
251
///
@@ -632,6 +635,77 @@ impl CString {
632
635
let this = mem:: ManuallyDrop :: new ( self ) ;
633
636
unsafe { ptr:: read ( & this. inner ) }
634
637
}
638
+
639
+ /// Converts a `Vec` of `u8` to a `CString` without checking the invariants
640
+ /// on the given `Vec`.
641
+ ///
642
+ /// # Safety
643
+ ///
644
+ /// The given `Vec` **must** have one nul byte as its last element.
645
+ /// This means it cannot be empty nor have any other nul byte anywhere else.
646
+ ///
647
+ /// # Example
648
+ ///
649
+ /// ```
650
+ /// use std::ffi::CString;
651
+ /// assert_eq!(
652
+ /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
653
+ /// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
654
+ /// );
655
+ /// ```
656
+ #[ stable( feature = "cstring_from_vec_with_nul" , since = "1.46.0" ) ]
657
+ pub unsafe fn from_vec_with_nul_unchecked ( v : Vec < u8 > ) -> Self {
658
+ Self { inner : v. into_boxed_slice ( ) }
659
+ }
660
+
661
+ /// Attempts to converts a `Vec` of `u8` to a `CString`.
662
+ ///
663
+ /// Runtime checks are present to ensure there is only one nul byte in the
664
+ /// `Vec`, its last element.
665
+ ///
666
+ /// # Errors
667
+ ///
668
+ /// If a nul byte is present and not the last element or no nul bytes
669
+ /// is present, an error will be returned.
670
+ ///
671
+ /// # Examples
672
+ ///
673
+ /// A successful conversion will produce the same result as [`new`] when
674
+ /// called without the ending nul byte.
675
+ ///
676
+ /// ```
677
+ /// use std::ffi::CString;
678
+ /// assert_eq!(
679
+ /// CString::from_vec_with_nul(b"abc\0".to_vec())
680
+ /// .expect("CString::from_vec_with_nul failed"),
681
+ /// CString::new(b"abc".to_vec())
682
+ /// );
683
+ /// ```
684
+ ///
685
+ /// A incorrectly formatted vector will produce an error.
686
+ ///
687
+ /// ```
688
+ /// use std::ffi::{CString, FromBytesWithNulError};
689
+ /// // Interior nul byte
690
+ /// let _: FromBytesWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
691
+ /// // No nul byte
692
+ /// let _: FromBytesWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
693
+ /// ```
694
+ ///
695
+ /// [`new`]: #method.new
696
+ #[ stable( feature = "cstring_from_vec_with_nul" , since = "1.46.0" ) ]
697
+ pub fn from_vec_with_nul ( v : Vec < u8 > ) -> Result < Self , FromBytesWithNulError > {
698
+ let nul_pos = memchr:: memchr ( 0 , & v) ;
699
+ match nul_pos {
700
+ Some ( nul_pos) if nul_pos + 1 == v. len ( ) => {
701
+ // SAFETY: We know there is only one nul byte, at the end
702
+ // of the vec.
703
+ Ok ( unsafe { Self :: from_vec_with_nul_unchecked ( v) } )
704
+ }
705
+ Some ( nul_pos) => Err ( FromBytesWithNulError :: interior_nul ( nul_pos) ) ,
706
+ None => Err ( FromBytesWithNulError :: not_nul_terminated ( ) ) ,
707
+ }
708
+ }
635
709
}
636
710
637
711
// Turns this `CString` into an empty string to prevent
0 commit comments