Skip to content

Commit 4c366ea

Browse files
ZenithsizThomas Bahn
authored and
Thomas Bahn
committed
Fixed issue regarding usage of subslice patterns.
Fixed usage of inexistant `AsMut<str>` impl for `String` (Only added in `1.43`). Extended test `ascii_str::tests::lines_iter_rev`.
1 parent 17cbbf0 commit 4c366ea

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

src/ascii_str.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ impl<'a> Iterator for Lines<'a> {
718718
None
719719
} else {
720720
let line = self.string;
721-
// SAFETY: Slicing `..0` is always valid and yields an empty slice
721+
// SAFETY: An empty string is a valid string.
722722
self.string = unsafe { AsciiStr::from_ascii_unchecked(b"") };
723723
Some(line)
724724
}
@@ -732,21 +732,37 @@ impl<'a> DoubleEndedIterator for Lines<'a> {
732732
}
733733

734734
// If we end with `LF` / `CR/LF`, remove them
735-
if let [slice @ .., AsciiChar::CarriageReturn, AsciiChar::LineFeed]
736-
| [slice @ .., AsciiChar::LineFeed] = self.string.as_slice()
737-
{
738-
self.string = slice.into();
735+
if let Some(AsciiChar::LineFeed) = self.string.last() {
736+
// SAFETY: `last()` returned `Some`, so our len is at least 1.
737+
self.string = unsafe {
738+
self.string
739+
.as_slice()
740+
.get_unchecked(..self.string.len() - 1)
741+
.into()
742+
};
743+
744+
if let Some(AsciiChar::CarriageReturn) = self.string.last() {
745+
// SAFETY: `last()` returned `Some`, so our len is at least 1.
746+
self.string = unsafe {
747+
self.string
748+
.as_slice()
749+
.get_unchecked(..self.string.len() - 1)
750+
.into()
751+
};
752+
}
739753
}
740754

741-
// SAFETY: This will never be `0`, as we remove any `LF` from the end, it is `1..len`
755+
// Get the position of the first `LF` from the end.
742756
let lf_rev_pos = self
743757
.string
744758
.chars()
745759
.rev()
746760
.position(|ch| ch == AsciiChar::LineFeed)
747761
.unwrap_or_else(|| self.string.len());
748762

749-
// SAFETY: As per above, `self.len() - lf_rev_pos` will be in range `0..len - 1`, so both indexes are correct.
763+
// SAFETY: `lf_rev_pos` will be in range `0..=len`, so `len - lf_rev_pos`
764+
// will be within `0..=len`, making it correct as a start and end
765+
// point for the strings.
750766
let line = unsafe {
751767
self.string
752768
.as_slice()
@@ -1171,7 +1187,7 @@ mod tests {
11711187
let mut_arr_mut_ref: &mut [AsciiChar] = &mut [AsciiChar::A];
11721188
let mut string = "A".to_string();
11731189
let mut string2 = "A".to_string();
1174-
let string_mut = string.as_mut();
1190+
let string_mut = string.as_mut_str();
11751191
let string_mut_bytes = unsafe { string2.as_bytes_mut() }; // SAFETY: We don't modify it
11761192

11771193
// Note: This is a trick because `rustfmt` doesn't support
@@ -1427,6 +1443,15 @@ mod tests {
14271443
assert_eq!(iter.next_back(), Some("baz".as_ascii_str().unwrap()));
14281444
assert_eq!(iter.next_back(), Some("".as_ascii_str().unwrap()));
14291445
assert_eq!(iter.next(), Some("bar".as_ascii_str().unwrap()));
1446+
1447+
let empty_lines = b"\n\r\n\n\r\n";
1448+
let mut iter_count = 0;
1449+
let ascii = AsciiStr::from_ascii(&empty_lines).unwrap();
1450+
for line in ascii.lines().rev() {
1451+
iter_count += 1;
1452+
assert!(line.is_empty());
1453+
}
1454+
assert_eq!(4, iter_count);
14301455
}
14311456

14321457
#[test]

0 commit comments

Comments
 (0)