From c6340b0fe50c7d8f8b9b60957aae8aaf6fc8e891 Mon Sep 17 00:00:00 2001 From: Sheldon Young Date: Fri, 29 Jul 2022 09:50:27 -0700 Subject: [PATCH 1/5] EscapeAscii no longer panics due to incorrect ExactSizeIterator --- library/core/src/slice/ascii.rs | 11 ++++++++--- library/core/tests/slice.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 63715a6b86b97..51dae5b7a16e3 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -67,7 +67,6 @@ impl [u8] { /// # Examples /// /// ``` - /// /// let s = b"0\t\r\n'\"\\\x9d"; /// let escaped = s.escape_ascii().to_string(); /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); @@ -76,7 +75,10 @@ impl [u8] { without modifying the original"] #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] pub fn escape_ascii(&self) -> EscapeAscii<'_> { - EscapeAscii { inner: self.iter().flat_map(EscapeByte) } + EscapeAscii { + inner: self.iter().flat_map(EscapeByte), + len: self.iter().map(|c| EscapeByte(c).len()).sum() + } } /// Returns a byte slice with leading ASCII whitespace bytes removed. @@ -174,6 +176,9 @@ impl_fn_for_zst! { #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct EscapeAscii<'a> { inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, + + /// Cached length of the iterator to implement `ExactSizeIterator`. + len: usize, } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] @@ -185,7 +190,7 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { } #[inline] fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() + (self.len, Some(self.len)) } #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 6d1516958f39b..b81fd36cf0862 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2245,6 +2245,7 @@ fn test_copy_within_panics_src_inverted() { // 2 is greater than 1, so this range is invalid. bytes.copy_within(2..1, 0); } + #[test] #[should_panic(expected = "attempted to index slice up to maximum usize")] fn test_copy_within_panics_src_out_of_bounds() { @@ -2574,3 +2575,11 @@ fn test_flatten_mut_size_overflow() { let x = &mut [[(); usize::MAX]; 2][..]; let _ = x.flatten_mut(); } + +#[test] +fn test_escape_ascii() { + assert_eq!([].escape_ascii().len(), 0); + assert_eq!([b'X'].escape_ascii().len(), 1); + assert_eq!([b'\t'].escape_ascii().to_string(), "\\t"); + assert_eq!([b'\t'].escape_ascii().size_hint(), (2, Some(2))); +} \ No newline at end of file From 603d0d62533c2ce84328eea8a57a59be4b15886d Mon Sep 17 00:00:00 2001 From: Sheldon Young Date: Fri, 29 Jul 2022 10:16:29 -0700 Subject: [PATCH 2/5] Add end of file newline for tidy --- library/core/tests/slice.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index b81fd36cf0862..ef3ecc14c74c8 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2582,4 +2582,4 @@ fn test_escape_ascii() { assert_eq!([b'X'].escape_ascii().len(), 1); assert_eq!([b'\t'].escape_ascii().to_string(), "\\t"); assert_eq!([b'\t'].escape_ascii().size_hint(), (2, Some(2))); -} \ No newline at end of file +} From e104c739d5d264b0eedc3bd2f9dcb6677828b873 Mon Sep 17 00:00:00 2001 From: Sheldon Young Date: Fri, 29 Jul 2022 10:32:13 -0700 Subject: [PATCH 3/5] Add comma for tidy --- library/core/src/slice/ascii.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 51dae5b7a16e3..bc606f753baed 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -77,7 +77,7 @@ impl [u8] { pub fn escape_ascii(&self) -> EscapeAscii<'_> { EscapeAscii { inner: self.iter().flat_map(EscapeByte), - len: self.iter().map(|c| EscapeByte(c).len()).sum() + len: self.iter().map(|c| EscapeByte(c).len()).sum(), } } From d925efc9fe78e19c20764547d5d135084d3dcdff Mon Sep 17 00:00:00 2001 From: Sheldon Young Date: Fri, 29 Jul 2022 11:38:24 -0700 Subject: [PATCH 4/5] Length of iterator is remaining --- library/core/src/slice/ascii.rs | 10 +++++----- library/core/tests/slice.rs | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index bc606f753baed..14d8212d5e2da 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -77,7 +77,7 @@ impl [u8] { pub fn escape_ascii(&self) -> EscapeAscii<'_> { EscapeAscii { inner: self.iter().flat_map(EscapeByte), - len: self.iter().map(|c| EscapeByte(c).len()).sum(), + remaining: self.iter().map(|c| EscapeByte(c).len()).sum(), } } @@ -176,9 +176,7 @@ impl_fn_for_zst! { #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct EscapeAscii<'a> { inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, - - /// Cached length of the iterator to implement `ExactSizeIterator`. - len: usize, + remaining: usize, } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] @@ -186,11 +184,12 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { type Item = u8; #[inline] fn next(&mut self) -> Option { + self.remaining -= 1; self.inner.next() } #[inline] fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) + (self.remaining, Some(self.remaining)) } #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R @@ -216,6 +215,7 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> { fn next_back(&mut self) -> Option { + self.remaining -= 1; self.inner.next_back() } } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index ef3ecc14c74c8..a7c4de9128829 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2575,11 +2575,17 @@ fn test_flatten_mut_size_overflow() { let x = &mut [[(); usize::MAX]; 2][..]; let _ = x.flatten_mut(); } - #[test] fn test_escape_ascii() { assert_eq!([].escape_ascii().len(), 0); assert_eq!([b'X'].escape_ascii().len(), 1); assert_eq!([b'\t'].escape_ascii().to_string(), "\\t"); assert_eq!([b'\t'].escape_ascii().size_hint(), (2, Some(2))); + + let mut esc = [b'A', b'B', b'C', b'D'].escape_ascii(); + assert_eq!(esc.len(), 4); + assert_eq!(esc.next(), Some(b'A')); + assert_eq!(esc.len(), 3); + assert_eq!(esc.next_back(), Some(b'D')); + assert_eq!(esc.len(), 2); } From 37a5ee9f4604c0f74bb91f1151a76fa0a6af77f0 Mon Sep 17 00:00:00 2001 From: Sheldon Young Date: Sat, 6 Aug 2022 10:01:01 -0700 Subject: [PATCH 5/5] EscapeAscii no longer implements ExactSizeIterator --- library/core/src/slice/ascii.rs | 14 +------------- library/core/tests/slice.rs | 14 -------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 14d8212d5e2da..bb91cb3b6b833 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -75,10 +75,7 @@ impl [u8] { without modifying the original"] #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] pub fn escape_ascii(&self) -> EscapeAscii<'_> { - EscapeAscii { - inner: self.iter().flat_map(EscapeByte), - remaining: self.iter().map(|c| EscapeByte(c).len()).sum(), - } + EscapeAscii { inner: self.iter().flat_map(EscapeByte) } } /// Returns a byte slice with leading ASCII whitespace bytes removed. @@ -176,7 +173,6 @@ impl_fn_for_zst! { #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct EscapeAscii<'a> { inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, - remaining: usize, } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] @@ -184,14 +180,9 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { type Item = u8; #[inline] fn next(&mut self) -> Option { - self.remaining -= 1; self.inner.next() } #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.remaining, Some(self.remaining)) - } - #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Fold: FnMut(Acc, Self::Item) -> R, @@ -215,13 +206,10 @@ impl<'a> iter::Iterator for EscapeAscii<'a> { #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> { fn next_back(&mut self) -> Option { - self.remaining -= 1; self.inner.next_back() } } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] -impl<'a> iter::ExactSizeIterator for EscapeAscii<'a> {} -#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> iter::FusedIterator for EscapeAscii<'a> {} #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> fmt::Display for EscapeAscii<'a> { diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 49d96506f916a..ab01d46959235 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2596,17 +2596,3 @@ fn test_flatten_mut_size_overflow() { let x = &mut [[(); usize::MAX]; 2][..]; let _ = x.flatten_mut(); } -#[test] -fn test_escape_ascii() { - assert_eq!([].escape_ascii().len(), 0); - assert_eq!([b'X'].escape_ascii().len(), 1); - assert_eq!([b'\t'].escape_ascii().to_string(), "\\t"); - assert_eq!([b'\t'].escape_ascii().size_hint(), (2, Some(2))); - - let mut esc = [b'A', b'B', b'C', b'D'].escape_ascii(); - assert_eq!(esc.len(), 4); - assert_eq!(esc.next(), Some(b'A')); - assert_eq!(esc.len(), 3); - assert_eq!(esc.next_back(), Some(b'D')); - assert_eq!(esc.len(), 2); -}