summaryrefslogtreecommitdiffstats
path: root/tokio/src/io/util
diff options
context:
space:
mode:
authorGeoffry Song <goffrie@gmail.com>2020-04-21 10:41:41 -0700
committerGitHub <noreply@github.com>2020-04-21 19:41:41 +0200
commit2da15b5f246f25138edcddced725b71f1b2b7cc9 (patch)
tree4549083782ee6d115bd2e4a74a12566054a23cca /tokio/src/io/util
parent7e88b56be5fd70f53af6639c04546cf034a66d9e (diff)
io: remove unsafe from ReadToString (#2384)
Diffstat (limited to 'tokio/src/io/util')
-rw-r--r--tokio/src/io/util/read_to_string.rs36
1 files changed, 22 insertions, 14 deletions
diff --git a/tokio/src/io/util/read_to_string.rs b/tokio/src/io/util/read_to_string.rs
index e77d836d..cab0505a 100644
--- a/tokio/src/io/util/read_to_string.rs
+++ b/tokio/src/io/util/read_to_string.rs
@@ -4,7 +4,7 @@ use crate::io::AsyncRead;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
-use std::{io, mem, str};
+use std::{io, mem};
cfg_io_util! {
/// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method.
@@ -25,7 +25,7 @@ where
let start_len = buf.len();
ReadToString {
reader,
- bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
+ bytes: mem::replace(buf, String::new()).into_bytes(),
buf,
start_len,
}
@@ -38,19 +38,20 @@ fn read_to_string_internal<R: AsyncRead + ?Sized>(
bytes: &mut Vec<u8>,
start_len: usize,
) -> Poll<io::Result<usize>> {
- let ret = ready!(read_to_end_internal(reader, cx, bytes, start_len));
- if str::from_utf8(&bytes).is_err() {
- Poll::Ready(ret.and_then(|_| {
- Err(io::Error::new(
+ let ret = ready!(read_to_end_internal(reader, cx, bytes, start_len))?;
+ match String::from_utf8(mem::replace(bytes, Vec::new())) {
+ Ok(string) => {
+ debug_assert!(buf.is_empty());
+ *buf = string;
+ Poll::Ready(Ok(ret))
+ }
+ Err(e) => {
+ *bytes = e.into_bytes();
+ Poll::Ready(Err(io::Error::new(
io::ErrorKind::InvalidData,
"stream did not contain valid UTF-8",
- ))
- }))
- } else {
- debug_assert!(buf.is_empty());
- // Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`.
- mem::swap(unsafe { buf.as_mut_vec() }, bytes);
- Poll::Ready(ret)
+ )))
+ }
}
}
@@ -67,7 +68,14 @@ where
bytes,
start_len,
} = &mut *self;
- read_to_string_internal(Pin::new(reader), cx, buf, bytes, *start_len)
+ let ret = read_to_string_internal(Pin::new(reader), cx, buf, bytes, *start_len);
+ if let Poll::Ready(Err(_)) = ret {
+ // Put back the original string.
+ bytes.truncate(*start_len);
+ **buf = String::from_utf8(mem::replace(bytes, Vec::new()))
+ .expect("original string no longer utf-8");
+ }
+ ret
}
}