diff --git a/examples/doc_get_line.rs b/examples/doc_get_line.rs index d2db141..433ef6e 100644 --- a/examples/doc_get_line.rs +++ b/examples/doc_get_line.rs @@ -2,14 +2,27 @@ use iof::{get_line, read}; fn main() { // Read a single string from input. + // + // v + // 42 + // abc let s: String = read!(); assert_eq!(s, "42"); // Read a line of string from input. + // Before reading, the cursor is at the end of the previous line. + // Therefore, it reads an empty string. + // + // v + // 42 + // abc let s: String = get_line(); assert_eq!(s, ""); // Read a line of string from input. + // + // v + // abc let s: String = get_line(); assert_eq!(s, "abc"); } diff --git a/examples/doc_get_line_some.rs b/examples/doc_get_line_some.rs index 2b608c6..0f5aa77 100644 --- a/examples/doc_get_line_some.rs +++ b/examples/doc_get_line_some.rs @@ -2,10 +2,20 @@ use iof::{get_line_some, read}; fn main() { // Read a single string from input. + // + // v + // 42 + // abc let s: String = read!(); assert_eq!(s, "42"); // Read a non-empty line of string from input. + // Before reading, the cursor is at the end of the previous line. + // However, as the function name implies, it will repeatedly read lines until a non-empty line is found. + // + // v + // 42 + // abc let s: String = get_line_some(); assert_eq!(s, "abc"); } diff --git a/examples/doc_read.rs b/examples/doc_read.rs index 4fa6aa8..e4a7e8b 100644 --- a/examples/doc_read.rs +++ b/examples/doc_read.rs @@ -1,37 +1,70 @@ use iof::{read, Mat}; +/// Some examples of reading from standard input. +/// +/// We use a `v` to indicate the cursor position. fn main() { // Read a single integer from input. + // + // v + // 42 abc def let n: u32 = read!(); assert_eq!(n, 42); // Read a single string from input. + // + // v + // 42 abc def let n: String = read!(); assert_eq!(n, "abc"); // Read a vector of characters from input. + // Spaces are ignored, and those characters need not be separated by spaces. + // + // v + // 42 abc def let v: Vec = read!(); assert_eq!(v, ['d', 'e', 'f']); - // Read a tuple from input. - // Equivalent to: + // Read a tuple from input. Equivalent to: + // + // ``` // let l: u32 = read!(); // let m: f64 = read!(); // let n: String = read!(); + // ``` + // + // v + // 0 0.3 lmn let (l, m, n): (u32, f64, String) = read!(); assert_eq!(l, 0); assert_eq!(m, 0.3); assert_eq!(n, "lmn"); // Read a vector of integers from input. + // They are separated by spaces. + // + // v + // 1 2 3 let v: Vec = read!(3); assert_eq!(v, [1, 2, 3]); // Read a matrix of integers from input. + // They are separated by spaces, and newlines are unnecessary but useful for readability. + // + // v + // 1 2 3 + // 4 5 6 let m: Mat = read!(2, 3); assert_eq!(m, [[1, 2, 3], [4, 5, 6]]); // Read a matrix of characters from input. + // Spaces are ignored and unnecessary, too. + // + // v + // .@/#$ + // !@#!@ + // *&@:, let m: Mat = read!(3, 5); assert_eq!( m, diff --git a/src/lib.rs b/src/lib.rs index ccce1c5..32e242c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -319,8 +319,8 @@ pub use { formatted::SepBy, mat::Mat, read::{ - error::ReadIntoError, - read_from::ReadFrom, + error::ReadError, + read_from::{ReadFrom, ReadFromError}, read_into::ReadInto, read_one_from::{ReadOneFrom, ReadOneFromError}, read_one_into::ReadOneInto, diff --git a/src/read/error.rs b/src/read/error.rs index ef7d21c..3894018 100644 --- a/src/read/error.rs +++ b/src/read/error.rs @@ -9,7 +9,7 @@ use crate::stream::{self, MSG_EOF, MSG_EOL}; /// [ReadInto]: crate::ReadInto /// [ReadOneFrom]: crate::ReadOneFrom #[derive(Debug)] -pub enum ReadIntoError { +pub enum ReadError { /// Error during reading from input. IOError(std::io::Error), /// Unexpected end of file. @@ -20,7 +20,7 @@ pub enum ReadIntoError { FromStrError(E, String, &'static str), } -impl Display for ReadIntoError +impl Display for ReadError where E: std::error::Error, { @@ -41,20 +41,20 @@ where } } -impl std::error::Error for ReadIntoError where E: std::error::Error {} +impl std::error::Error for ReadError where E: std::error::Error {} -impl From for ReadIntoError { +impl From for ReadError { fn from(error: std::io::Error) -> Self { Self::IOError(error) } } -impl From for ReadIntoError { +impl From for ReadError { fn from(error: stream::error::StreamError) -> Self { match error { stream::error::StreamError::IOError(e) => Self::IOError(e), - stream::error::StreamError::EOF => Self::EOF, - stream::error::StreamError::EOL => Self::EOL, + stream::error::StreamError::Eof => Self::EOF, + stream::error::StreamError::Eol => Self::EOL, } } } diff --git a/src/read/iter.rs b/src/read/iter.rs index 3f9e060..66975b2 100644 --- a/src/read/iter.rs +++ b/src/read/iter.rs @@ -1,7 +1,7 @@ use super::read_one_from::ReadOneFromError; use crate::{ stream::{error::StreamError, line_buf::LineBuf}, - BufReadExt, ReadIntoError, ReadOneFrom, + BufReadExt, ReadError, ReadOneFrom, }; use std::marker::PhantomData; @@ -24,7 +24,7 @@ impl<'s, S: BufReadExt + ?Sized, T: ReadOneFrom> Iterator for ReadAll<'s, S, T> fn next(&mut self) -> Option { match self.stream.try_get_string_some() { Ok(s) => Some(T::parse(s)), - Err(StreamError::EOF | StreamError::EOL) => None, + Err(StreamError::Eof | StreamError::Eol) => None, Err(e) => Some(Err(e.into())), } } @@ -50,7 +50,7 @@ impl<'s, T: ReadOneFrom> Iterator for ReadAllIn<'s, T> { fn next(&mut self) -> Option { match T::try_read_one_from(&mut self.stream) { Ok(t) => Some(Ok(t)), - Err(ReadIntoError::EOF | ReadIntoError::EOL) => None, + Err(ReadError::EOF | ReadError::EOL) => None, Err(e) => Some(Err(e)), } } diff --git a/src/read/macros.rs b/src/read/macros.rs index befb0da..0404ce2 100644 --- a/src/read/macros.rs +++ b/src/read/macros.rs @@ -38,7 +38,7 @@ macro_rules! impl_read_into_single { type ParseError = ::Err; fn parse(s: &str) -> Result> { - s.parse().map_err(|err| $crate::ReadIntoError::FromStrError(err, s.to_owned(), ::std::any::type_name::())) + s.parse().map_err(|err| $crate::ReadError::FromStrError(err, s.to_owned(), ::std::any::type_name::())) } fn try_read_one_from(stream: &mut S) -> Result> { @@ -52,7 +52,7 @@ macro_rules! impl_read_into_single { type ParseError = <$ty as ::std::str::FromStr>::Err; fn parse(s: &str) -> Result<$ty, $crate::ReadOneFromError> { - s.parse().map_err(|err| $crate::ReadIntoError::FromStrError(err, s.to_owned(), ::std::any::type_name::<$ty>())) + s.parse().map_err(|err| $crate::ReadError::FromStrError(err, s.to_owned(), ::std::any::type_name::<$ty>())) } } $crate::impl_read_into_single!($($tys)*); diff --git a/src/read/read_from.rs b/src/read/read_from.rs index 63ab607..552d493 100644 --- a/src/read/read_from.rs +++ b/src/read/read_from.rs @@ -1,21 +1,21 @@ use super::read_one_from::ReadOneFrom; -use crate::{array::array_try_from_fn, mat::Mat, BufReadExt, ReadIntoError}; +use crate::{array::array_try_from_fn, mat::Mat, BufReadExt, ReadError}; use std::fmt::{self, Display}; /// The error type for [ReadFrom]. -pub type ReadFromError = ReadIntoError<::ParseError>; +pub type ReadFromError = ReadError<::ParseError>; /// Read data from input stream. /// /// # Errors /// -/// - If the input cannot be parsed into `T`, [ReadIntoError::FromStrError] is returned. -/// - If the input is not valid UTF-8, [ReadIntoError::IOError] is returned. -/// - If an I/O error occurs, [ReadIntoError::IOError] is returned. +/// - If the input cannot be parsed into `T`, [ReadError::FromStrError] is returned. +/// - If the input is not valid UTF-8, [ReadError::IOError] is returned. +/// - If an I/O error occurs, [ReadError::IOError] is returned. /// -/// [ReadIntoError]: crate::ReadIntoError -/// [ReadIntoError::FromStrError]: crate::ReadIntoError::FromStrError -/// [ReadIntoError::IOError]: crate::ReadIntoError::IOError +/// [ReadError]: crate::ReadError +/// [ReadError::FromStrError]: crate::ReadError::FromStrError +/// [ReadError::IOError]: crate::ReadError::IOError pub trait ReadFrom: Sized { /// Errors that come from [ReadOneFrom]. type ParseError: std::error::Error; diff --git a/src/read/read_into.rs b/src/read/read_into.rs index 1f6db50..fa8dae1 100644 --- a/src/read/read_into.rs +++ b/src/read/read_into.rs @@ -6,10 +6,10 @@ use super::read_from::ReadFromError; pub trait ReadInto: BufReadExt { /// Errors that come from [ReadOneFrom]. /// - /// This is usually [ReadIntoError]. + /// This is usually [ReadError]. /// /// [ReadOneFrom]: crate::ReadOneFrom - /// [ReadIntoError]: crate::ReadIntoError + /// [ReadError]: crate::ReadError type Error: std::error::Error; /// Read from `self` and parse into `Self`. diff --git a/src/read/read_one_from.rs b/src/read/read_one_from.rs index 415a1d9..9ed4b0d 100644 --- a/src/read/read_one_from.rs +++ b/src/read/read_one_from.rs @@ -1,8 +1,8 @@ use super::iter::{ReadAll, ReadAllIn}; -use crate::{BufReadExt, ReadIntoError}; +use crate::{BufReadExt, ReadError}; /// The error type for [ReadOneFrom]. -pub type ReadOneFromError = ReadIntoError<::ParseError>; +pub type ReadOneFromError = ReadError<::ParseError>; /// Read a single data item from input stream. /// @@ -10,25 +10,25 @@ pub type ReadOneFromError = ReadIntoError<::ParseError>; /// /// # Errors /// -/// - If the input cannot be parsed into `T`, [ReadIntoError::FromStrError] is returned. -/// - If the input is not valid UTF-8, [ReadIntoError::IOError] is returned. -/// - If an I/O error occurs, [ReadIntoError::IOError] is returned. +/// - If the input cannot be parsed into `T`, [ReadError::FromStrError] is returned. +/// - If the input is not valid UTF-8, [ReadError::IOError] is returned. +/// - If an I/O error occurs, [ReadError::IOError] is returned. /// /// [ReadFrom]: crate::ReadFrom -/// [ReadIntoError]: crate::ReadIntoError -/// [ReadIntoError::FromStrError]: crate::ReadIntoError::FromStrError -/// [ReadIntoError::IOError]: crate::ReadIntoError::IOError +/// [ReadError]: crate::ReadError +/// [ReadError::FromStrError]: crate::ReadError::FromStrError +/// [ReadError::IOError]: crate::ReadError::IOError pub trait ReadOneFrom: Sized { /// Errors that come from parsing. type ParseError: std::error::Error; /// Parse a string into `Self`. - fn parse(s: &str) -> Result>; + fn parse(s: &str) -> Result>; /// Read from `stream` and parse into `Self`. fn try_read_one_from( stream: &mut S, - ) -> Result> { + ) -> Result> { let s = stream.try_get_string_some()?; Self::parse(s) } @@ -36,7 +36,7 @@ pub trait ReadOneFrom: Sized { /// Read an element in a single non-whitespace character from `stream`, parse into `Self`. fn try_read_in_char_from( stream: &mut S, - ) -> Result> { + ) -> Result> { let s = stream.try_get_non_ws()?; Self::parse(s.encode_utf8(&mut [0; 4])) } @@ -44,7 +44,7 @@ pub trait ReadOneFrom: Sized { /// Read an element in the remained line from `stream`, parse into `Self`. fn try_read_in_line_trimmed_from( stream: &mut S, - ) -> Result> { + ) -> Result> { let s = stream.try_get_line_trimmed()?.trim_start(); Self::parse(s) } @@ -52,7 +52,7 @@ pub trait ReadOneFrom: Sized { /// Read an element in a single trimmed line that is not empty from `stream`, parse into `Self`. fn try_read_in_line_some_trimmed_from( stream: &mut S, - ) -> Result> { + ) -> Result> { let s = stream.try_get_line_some_trimmed()?.trim_start(); Self::parse(s) } @@ -60,21 +60,21 @@ pub trait ReadOneFrom: Sized { /// Read all remaining elements from `stream` into a [Vec] of `Self`. fn try_read_all_from( stream: &mut S, - ) -> Result, ReadIntoError> { + ) -> Result, ReadError> { ReadAll::::new(stream).collect() } /// Read all elements in current line from `stream` into a [Vec] of `Self`. fn try_read_any_in_line_from( stream: &mut S, - ) -> Result, ReadIntoError> { + ) -> Result, ReadError> { ReadAllIn::::new(stream.try_get_line_trimmed()?).collect() } /// Read all elements in a non-empty line from `stream` into a [Vec] of `Self`. fn try_read_some_in_line_from( stream: &mut S, - ) -> Result, ReadIntoError> { + ) -> Result, ReadError> { ReadAllIn::::new(stream.try_get_line_some_trimmed()?).collect() } } diff --git a/src/read/read_one_into.rs b/src/read/read_one_into.rs index b8905e4..0b12be9 100644 --- a/src/read/read_one_into.rs +++ b/src/read/read_one_into.rs @@ -4,9 +4,9 @@ use crate::{stream, unwrap, BufReadExt, ReadOneFrom, ReadOneFromError}; pub trait ReadOneInto { /// Errors that come from [ReadOneFrom]. /// - /// This is usually [ReadIntoError]. + /// This is usually [ReadError]. /// - /// [ReadIntoError]: crate::ReadIntoError + /// [ReadError]: crate::ReadError type Error: std::error::Error + From; /// Read one from `self` and parse into `T`. diff --git a/src/stdio.rs b/src/stdio.rs index 745cd8d..6a12d39 100644 --- a/src/stdio.rs +++ b/src/stdio.rs @@ -17,12 +17,16 @@ pub(crate) mod stream; pub static STDIN: LazyLock>>> = LazyLock::new(|| Mutex::new(InputStream::new(BufReader::new(io::stdin())))); -/// Get a handle to the standard input stream. +/// Get an exclusive handle to the standard input stream. +/// +/// See [io::stdin] and [io::Stdin::lock] for more information. pub fn stdin() -> MutexGuard<'static, InputStream>> { STDIN.lock().unwrap() } -/// Get a handle to the standard output stream. +/// Get an exclusive handle to the standard output stream. +/// +/// See [io::stdout] and [io::Stdout::lock] for more information. pub fn stdout() -> io::StdoutLock<'static> { io::stdout().lock() } diff --git a/src/stdio/read_into.rs b/src/stdio/read_into.rs index bbe1c60..8e1bee8 100644 --- a/src/stdio/read_into.rs +++ b/src/stdio/read_into.rs @@ -10,24 +10,18 @@ pub use { // type StdinReader = InputStream>; macro_rules! expose_stdin { - ($try_fn:ident $str_try_fn:literal $fn:ident $str_fn:literal [$ty_arg:ident] [$trait:ident] [$($trait_arg:tt)*] ($($arg:ident: $arg_ty:ty), *) -> $ret:ty | $err:ty) => { - /// Call [` - #[doc = $str_try_fn] - /// `] on [std::io::StdinLock]. + ($try_fn:ident $fn:ident $trait_into:ident [$ty_arg:ident] [$trait:ident] [$($trait_arg:tt)*] ($($arg:ident: $arg_ty:ty), *) -> $ret:ty | $err:ty) => { + #[doc = concat!("Call [`", stringify!($trait_into), "::", stringify!($try_fn), "`] on [stdin].")] /// /// # Panics /// - /// If [` - #[doc = $str_try_fn] - /// `] panics. + #[doc = concat!("If [`", stringify!($trait_into), "::", stringify!($try_fn), "`] panics.")] /// /// # Errors /// /// If this function is called in multiple threads, the behavior is undefined, possibly causing a deadlock. /// - /// If [` - #[doc = $str_try_fn] - /// `] returns an error. + #[doc = concat!("If [`", stringify!($trait_into), "::", stringify!($try_fn), "`] returns an error.")] pub fn $try_fn<$ty_arg>($($arg: $arg_ty),*) -> Result<$ret, $err> where $ty_arg: $trait, @@ -35,10 +29,7 @@ macro_rules! expose_stdin { stdin().$try_fn($($arg),*) } - /// Unwrap the result of [` - #[doc = $str_try_fn] - /// `]. - #[track_caller] + #[doc = concat!("Unwrap the result of [`", stringify!($try_fn), "`].")] pub fn $fn<$ty_arg>($($arg: $arg_ty),*) -> $ret where $ty_arg: $trait, @@ -49,53 +40,43 @@ macro_rules! expose_stdin { } expose_stdin!( - try_read "ReadInto::try_read" - read "ReadInto::read" + try_read read ReadInto [T] [ReadFrom] [T] () -> T | ReadFromError ); expose_stdin!( - try_read_n "ReadInto::try_read_n" - read_n "ReadInto::read_n" + try_read_n read_n ReadInto [T] [ReadFrom] [T] (n: usize) -> Vec | ReadFromError ); expose_stdin!( - try_read_m_n "ReadInto::try_read_m_n" - read_m_n "ReadInto::read_m_n" + try_read_m_n read_m_n ReadInto [T] [ReadFrom] [T] (m: usize, n: usize) -> Mat | ReadFromError ); expose_stdin!( - try_read_one "ReadOneInto::try_read_one" - read_one "ReadOneInto::read_one" + try_read_one read_one ReadOneInto [T] [ReadOneFrom] [T] () -> T | ReadOneFromError ); expose_stdin!( - try_read_in_line_trimmed "ReadOneInto::try_read_in_line_trimmed" - read_in_line_trimmed "ReadOneInto::read_in_line_trimmed" + try_read_in_line_trimmed read_in_line_trimmed ReadOneInto [T] [ReadOneFrom] [T] () -> T | ReadOneFromError ); expose_stdin!( - try_read_in_line_some_trimmed "ReadOneInto::try_read_in_line_some_trimmed" - read_in_line_some_trimmed "ReadOneInto::read_in_line_some_trimmed" + try_read_in_line_some_trimmed read_in_line_some_trimmed ReadOneInto [T] [ReadOneFrom] [T] () -> T | ReadOneFromError ); expose_stdin!( - try_read_all "ReadOneInto::try_read_all" - read_all "ReadOneInto::read_all" + try_read_all read_all ReadOneInto [T] [ReadOneFrom] [T] () -> Vec | ReadOneFromError ); expose_stdin!( - try_read_any_in_line "ReadOneInto::try_read_any_in_line" - read_any_in_line "ReadOneInto::read_any_in_line" + try_read_any_in_line read_any_in_line ReadOneInto [T] [ReadOneFrom] [T] () -> Vec | ReadOneFromError ); expose_stdin!( - try_read_some_in_line "ReadOneInto::try_read_some_in_line" - read_some_in_line "ReadOneInto::read_all_in_line" + try_read_some_in_line read_some_in_line ReadOneInto [T] [ReadOneFrom] [T] () -> Vec | ReadOneFromError ); expose_stdin!( - try_read_in_char "ReadOneInto::try_read_in_char" - read_in_char "ReadOneInto::read_in_char" + try_read_in_char read_in_char ReadOneInto [T] [ReadOneFrom] [T] () -> T | ReadOneFromError ); diff --git a/src/stream/error.rs b/src/stream/error.rs index 1558e04..fcbcc3c 100644 --- a/src/stream/error.rs +++ b/src/stream/error.rs @@ -6,16 +6,16 @@ use super::{MSG_EOF, MSG_EOL}; #[derive(Debug)] pub enum StreamError { IOError(std::io::Error), - EOF, - EOL, + Eof, + Eol, } impl Display for StreamError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::IOError(e) => Display::fmt(e, f), - Self::EOF => f.write_str(MSG_EOF), - Self::EOL => f.write_str(MSG_EOL), + Self::Eof => f.write_str(MSG_EOF), + Self::Eol => f.write_str(MSG_EOL), } } } diff --git a/src/stream/input_stream.rs b/src/stream/input_stream.rs index e8c3f01..ca02dfd 100644 --- a/src/stream/input_stream.rs +++ b/src/stream/input_stream.rs @@ -92,7 +92,7 @@ impl InputStream { if self.is_eol() { continue; } - let remaining = unsafe { transmute(remaining_trimmed) }; + let remaining: &str = unsafe { transmute(remaining_trimmed) }; return Ok((remaining, len_skipped)); } } @@ -223,7 +223,7 @@ mod tests { assert_eq!(stream.try_get().unwrap(), 't'); assert_eq!(stream.try_get().unwrap(), '!'); assert!( - matches!(stream.try_get().unwrap_err(), StreamError::EOF), + matches!(stream.try_get().unwrap_err(), StreamError::Eof), "{:?}", stream.try_get_string_some(), ); @@ -238,7 +238,7 @@ mod tests { assert_eq!(stream.try_get_string_some().unwrap(), "Hello,"); assert_eq!(stream.try_get_string_some().unwrap(), "Rust!"); assert!( - matches!(stream.try_get_string_some().unwrap_err(), StreamError::EOF), + matches!(stream.try_get_string_some().unwrap_err(), StreamError::Eof), "{:?}", stream.try_get_string_some() ); diff --git a/src/stream/line_buf.rs b/src/stream/line_buf.rs index 091ea36..e11f26c 100644 --- a/src/stream/line_buf.rs +++ b/src/stream/line_buf.rs @@ -125,7 +125,7 @@ mod tests { assert_eq!(stream.try_get().unwrap(), 'l'); assert_eq!(stream.try_get().unwrap(), 'd'); assert_eq!(stream.try_get().unwrap(), '!'); - assert!(matches!(stream.try_get().unwrap_err(), StreamError::EOL)); + assert!(matches!(stream.try_get().unwrap_err(), StreamError::Eol)); } #[test] @@ -135,7 +135,7 @@ mod tests { assert_eq!(stream.try_get_string_some().unwrap(), "Hello,"); assert_eq!(stream.try_get_string_some().unwrap(), "world!"); assert!( - matches!(stream.try_get_string_some().unwrap_err(), StreamError::EOL), + matches!(stream.try_get_string_some().unwrap_err(), StreamError::Eol), "{:?}", stream.try_get_string_some() ); diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 85bae42..5a87dd4 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -15,11 +15,11 @@ const fn is_eol(c: char) -> bool { } fn err_eof() -> StreamError { - StreamError::EOF + StreamError::Eof } fn err_eol() -> StreamError { - StreamError::EOL + StreamError::Eol } #[inline] diff --git a/src/stream/traits.rs b/src/stream/traits.rs index 79d861e..6d31e5d 100644 --- a/src/stream/traits.rs +++ b/src/stream/traits.rs @@ -6,7 +6,7 @@ use std::mem::transmute; /// It provides a way to read: /// /// - A single non-ASCII-whitespace character ([BufReadExt::try_get_non_ws]), -/// - A single ASCII-white-space-separated string ([BufReadExt::try_get_string]), +/// - A single ASCII-white-space-separated string ([BufReadExt::try_get_string_some]), /// - A single non-empty line ([BufReadExt::try_get_line_some]), /// - Or just the remained line ([BufReadExt::try_get_line]). /// @@ -95,7 +95,7 @@ pub trait BufReadExt { /// Get a single not-empty line. The trailing newline will be consumed and trimmed. /// - /// Repeat reading a new line if current line is empty. + /// Repeatedly read a new line if current line is empty. #[inline] fn try_get_line_some(&mut self) -> Result<&str, StreamError> { loop { @@ -109,7 +109,7 @@ pub trait BufReadExt { /// Get a single not-empty line. The trailing white spaces will be consumed and trimmed. /// - /// Repeat reading a new line if current line is empty. + /// Repeatedly read a new line if current line is empty. #[inline] fn try_get_line_some_trimmed(&mut self) -> Result<&str, StreamError> { loop {