From d346dfdf4687760e05ea63b0c78e81a189edf280 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 19 Nov 2021 19:08:42 +0000 Subject: [PATCH 1/2] str::lines and BufRead::lines: document trailing bare cr behaviour Apropos discussion here https://github.com/rust-lang/rust/pull/91047#issuecomment-974321038 Sadly, str::lines gets this wrong. I think it is probably too late to fix this, so document it instead. --- library/core/src/str/mod.rs | 13 +++++++++++++ library/std/src/io/mod.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index cd5ed35be79ba..542ff7d8bfb40 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -899,6 +899,19 @@ impl str { /// /// assert_eq!(None, lines.next()); /// ``` + /// + /// Handling of a trailing bare CR is, sadly, anomalous: + /// (`std::io::BufRead::lines` handles this case correctly.) + /// + /// ``` + /// let text = "foo\nbar\r"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); // should really return "bar\r" + /// + /// assert_eq!(None, lines.next()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn lines(&self) -> Lines<'_> { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8cc91566418dc..8191e420971b4 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2281,6 +2281,19 @@ pub trait BufRead: Read { /// assert_eq!(lines_iter.next(), None); /// ``` /// + /// Unlike [`str::lines`], trailing bare CR is handled correctly: + /// + /// ``` + /// use std::io::{self, BufRead}; + /// + /// let cursor = io::Cursor::new(b"lorem\nipsum\r"); + /// + /// let mut lines_iter = cursor.lines().map(|l| l.unwrap()); + /// assert_eq!(lines_iter.next(), Some(String::from("lorem"))); + /// assert_eq!(lines_iter.next(), Some(String::from("ipsum\r"))); // bare CR is not a newline + /// assert_eq!(lines_iter.next(), None); + /// ``` + /// /// # Errors /// /// Each line of the iterator has the same error semantics as [`BufRead::read_line`]. From 9b1f6c50c5204e50f6553ca4ed92974f7fa59e3a Mon Sep 17 00:00:00 2001 From: Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> Date: Mon, 11 Apr 2022 22:58:27 +0200 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: r00ster --- library/core/src/str/mod.rs | 5 ++--- library/std/src/io/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 542ff7d8bfb40..10276eb2ec9c6 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -900,15 +900,14 @@ impl str { /// assert_eq!(None, lines.next()); /// ``` /// - /// Handling of a trailing bare CR is, sadly, anomalous: - /// (`std::io::BufRead::lines` handles this case correctly.) + /// Unlike [`std::io::BufRead::lines`], trailing bare CR is handled as a newline: /// /// ``` /// let text = "foo\nbar\r"; /// let mut lines = text.lines(); /// /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); // should really return "bar\r" + /// assert_eq!(Some("bar"), lines.next()); // does not return "bar\r" /// /// assert_eq!(None, lines.next()); /// ``` diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8191e420971b4..e47d0a961141b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2281,7 +2281,7 @@ pub trait BufRead: Read { /// assert_eq!(lines_iter.next(), None); /// ``` /// - /// Unlike [`str::lines`], trailing bare CR is handled correctly: + /// Unlike [`str::lines`], trailing bare CR is not handled as a newline: /// /// ``` /// use std::io::{self, BufRead}; @@ -2290,7 +2290,7 @@ pub trait BufRead: Read { /// /// let mut lines_iter = cursor.lines().map(|l| l.unwrap()); /// assert_eq!(lines_iter.next(), Some(String::from("lorem"))); - /// assert_eq!(lines_iter.next(), Some(String::from("ipsum\r"))); // bare CR is not a newline + /// assert_eq!(lines_iter.next(), Some(String::from("ipsum\r"))); // does not return "ipsum" /// assert_eq!(lines_iter.next(), None); /// ``` ///