@@ -214,6 +214,36 @@ impl FromVecWithNulError {
214
214
}
215
215
}
216
216
217
+ /// An error indicating that a nul byte was not found.
218
+ ///
219
+ /// The vector passed to [`CString::from_vec_until_nul`] must have at
220
+ /// least one nul byte present.
221
+ ///
222
+ #[ derive( Clone , PartialEq , Eq , Debug ) ]
223
+ #[ unstable( feature = "cstr_from_bytes_until_nul" , issue = "95027" ) ]
224
+ pub struct FromVecUntilNulError {
225
+ bytes : Vec < u8 > ,
226
+ }
227
+
228
+ #[ unstable( feature = "cstr_from_bytes_until_nul" , issue = "95027" ) ]
229
+ impl FromVecUntilNulError {
230
+ /// Returns a `u8` slice containing the bytes that were attempted to convert
231
+ /// to a [`CString`].
232
+ #[ must_use]
233
+ #[ unstable( feature = "cstr_from_bytes_until_nul" , issue = "95027" ) ]
234
+ pub fn as_bytes ( & self ) -> & [ u8 ] {
235
+ & self . bytes [ ..]
236
+ }
237
+
238
+ /// Returns ownership of the bytes that were attempted to convert
239
+ /// to a [`CString`].
240
+ #[ must_use = "`self` will be dropped if the result is not used" ]
241
+ #[ unstable( feature = "cstr_from_bytes_until_nul" , issue = "95027" ) ]
242
+ pub fn into_bytes ( self ) -> Vec < u8 > {
243
+ self . bytes
244
+ }
245
+ }
246
+
217
247
/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
218
248
///
219
249
/// `CString` is just a wrapper over a buffer of bytes with a nul terminator;
@@ -690,6 +720,50 @@ impl CString {
690
720
} ) ,
691
721
}
692
722
}
723
+
724
+ /// Attempts to convert a <code>[Vec]<[u8]></code> to a [`CString`].
725
+ ///
726
+ /// The input [`Vec`] must contain at least one nul byte.
727
+ ///
728
+ /// If the nul byte is not at the end of the input `Vec`, then the `Vec`
729
+ /// will be truncated so that there is only one nul byte, and that byte
730
+ /// is at the end.
731
+ ///
732
+ /// # Errors
733
+ ///
734
+ /// If no nul byte is present, an error will be returned.
735
+ ///
736
+ /// # Examples
737
+ /// ```
738
+ /// #![feature(cstr_from_bytes_until_nul)]
739
+ ///
740
+ /// use std::ffi::CString;
741
+ ///
742
+ /// let mut buffer = vec![0u8; 16];
743
+ /// unsafe {
744
+ /// // Here we might call an unsafe C function that writes a string
745
+ /// // into the buffer.
746
+ /// let buf_ptr = buffer.as_mut_ptr();
747
+ /// buf_ptr.write_bytes(b'A', 8);
748
+ /// }
749
+ /// // Attempt to extract a C nul-terminated string from the buffer.
750
+ /// let c_str = CString::from_vec_until_nul(buffer).unwrap();
751
+ /// assert_eq!(c_str.into_string().unwrap(), "AAAAAAAA");
752
+ /// ```
753
+ ///
754
+ #[ unstable( feature = "cstr_from_bytes_until_nul" , issue = "95027" ) ]
755
+ pub fn from_vec_until_nul ( mut v : Vec < u8 > ) -> Result < Self , FromVecUntilNulError > {
756
+ let nul_pos = memchr:: memchr ( 0 , & v) ;
757
+ match nul_pos {
758
+ Some ( nul_pos) => {
759
+ v. truncate ( nul_pos + 1 ) ;
760
+ // SAFETY: We know there is a nul byte at nul_pos, so this slice
761
+ // (ending at the nul byte) is a well-formed C string.
762
+ Ok ( unsafe { Self :: _from_vec_with_nul_unchecked ( v) } )
763
+ }
764
+ None => Err ( FromVecUntilNulError { bytes : v } ) ,
765
+ }
766
+ }
693
767
}
694
768
695
769
// Turns this `CString` into an empty string to prevent
0 commit comments