From ede7f5f17c8be0d0597fd526bd66430221509bf6 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 20 Mar 2019 15:24:12 +0100 Subject: [PATCH 1/6] Implement CString::from_reader. --- src/libstd/ffi/c_str.rs | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index ad3f45bfadaf4..ed545d46bbf83 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -355,6 +355,41 @@ 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 + /// + /// ``` + /// use std::ffi::CString; + /// + /// let test = "Example\0"; + /// let string = CString::from_reader(test.as_bytes()).unwrap(); + /// ``` + /// + #[stable(feature = "cstring_from_reader", since = "1.33.0")] + 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. @@ -1320,6 +1355,20 @@ mod tests { } } + #[test] + fn read_to_cstring1() { + let test = "Example\0"; + let string = CString::from_reader(test.as_bytes()).unwrap(); + assert_eq!(string.as_bytes(), b"Example"); + } + + #[test] + fn read_to_cstring2() { + let test = "Example"; + let result = CString::from_reader(test.as_bytes()); + assert_eq!(result.is_err(), true); + } + #[test] fn simple() { let s = CString::new("1234").unwrap(); From d8aeeb94f5aed1a452cc994009989b6af5021d96 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 20 Mar 2019 22:17:48 +0100 Subject: [PATCH 2/6] Replaced 'since' with 'issue' referencing issue #59229. --- src/libstd/ffi/c_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index ed545d46bbf83..45845cc812c57 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -371,7 +371,7 @@ impl CString { /// let string = CString::from_reader(test.as_bytes()).unwrap(); /// ``` /// - #[stable(feature = "cstring_from_reader", since = "1.33.0")] + #[stable(feature = "cstring_from_reader", issue = "59229")] pub fn from_reader(mut reader: impl io::Read) -> Result { let mut buffer = Vec::new(); From 52a98b62f25da1810aa2985c74b605e3a220b882 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 20 Mar 2019 22:56:02 +0100 Subject: [PATCH 3/6] Added a hashtag to the issue attribute. --- src/libstd/ffi/c_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 45845cc812c57..7c0e08e0917ff 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -371,7 +371,7 @@ impl CString { /// let string = CString::from_reader(test.as_bytes()).unwrap(); /// ``` /// - #[stable(feature = "cstring_from_reader", issue = "59229")] + #[stable(feature = "cstring_from_reader", issue = "#59229")] pub fn from_reader(mut reader: impl io::Read) -> Result { let mut buffer = Vec::new(); From 83c2327f1d6ae2e777102b1366fcf069fb346c3b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 20 Mar 2019 23:16:58 +0100 Subject: [PATCH 4/6] Update src/libstd/ffi/c_str.rs Changes stable to unstable and removed the hashtag. Co-Authored-By: DevQps <46896178+DevQps@users.noreply.github.com> --- src/libstd/ffi/c_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 7c0e08e0917ff..bf87c830f7a82 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -371,7 +371,7 @@ impl CString { /// let string = CString::from_reader(test.as_bytes()).unwrap(); /// ``` /// - #[stable(feature = "cstring_from_reader", issue = "#59229")] + #[unstable(feature = "cstring_from_reader", issue = "59229")] pub fn from_reader(mut reader: impl io::Read) -> Result { let mut buffer = Vec::new(); From 7a9c039b31fcb57102ca7e4f8a6dc8ea7903297b Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 21 Mar 2019 15:10:50 +0100 Subject: [PATCH 5/6] Removed the unit tests because they require the cstring_from_reader feature to be enabled. --- src/libstd/ffi/c_str.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 7c0e08e0917ff..acef580c8a310 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1355,20 +1355,6 @@ mod tests { } } - #[test] - fn read_to_cstring1() { - let test = "Example\0"; - let string = CString::from_reader(test.as_bytes()).unwrap(); - assert_eq!(string.as_bytes(), b"Example"); - } - - #[test] - fn read_to_cstring2() { - let test = "Example"; - let result = CString::from_reader(test.as_bytes()); - assert_eq!(result.is_err(), true); - } - #[test] fn simple() { let s = CString::new("1234").unwrap(); From 6e1766442693a6a07af3290869b8079eaae552bb Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 21 Mar 2019 22:55:17 +0100 Subject: [PATCH 6/6] Enabled the cstring_from_reader feature to enable the doc test. --- src/libstd/ffi/c_str.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 640f1afdeed1b..c403b82e04d24 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -365,6 +365,7 @@ impl CString { /// # Examples /// /// ``` + /// #![feature(cstring_from_reader)] /// use std::ffi::CString; /// /// let test = "Example\0";