diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index ad3f45bfadaf4..c403b82e04d24 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -355,6 +355,42 @@ impl CString { CString { inner: v.into_boxed_slice() } } + /// Creates a C-compatible string by reading from an object that implements ```Read```. + /// It reads all characters including the null character. + /// + /// Because bytes are checked on null characters during the reading process, + /// no extra checks are required to ensure that no null characters precede the + /// terminating null character. + /// + /// # Examples + /// + /// ``` + /// #![feature(cstring_from_reader)] + /// use std::ffi::CString; + /// + /// let test = "Example\0"; + /// let string = CString::from_reader(test.as_bytes()).unwrap(); + /// ``` + /// + #[unstable(feature = "cstring_from_reader", issue = "59229")] + pub fn from_reader(mut reader: impl io::Read) -> Result + { + let mut buffer = Vec::new(); + let mut character: u8 = 0; + + loop { + // Read a new character from reader and insert it into the buffer. + let slice = slice::from_mut(&mut character); + reader.read_exact(slice)?; + buffer.push(character); + + // Construct a CString if a null character has been found. + if character == 0 { + return Ok(CString { inner: buffer.into_boxed_slice() }); + } + } + } + /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`]. /// /// Additionally, the length of the string will be recalculated from the pointer.