1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Prototype for `io::read_line`.
//!
//! This serves as a counterpart to
//! [`io::read_from_string`](https://github.com/rust-lang/rust/issues/80218) and
//! is inspired by proposals such as
//! [`std::io::input`](https://github.com/rust-lang/rust/pull/75435).
//!
//! This method makes it easier to read a line from a reader into a string, and leaves
//! more advances input proposals for later. For example [C++'s
//! text parsing
//! proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1729r1.html)
//! provides a coherent text parsing counterpart using `format!`-like syntax,
//! and would be interesting to explore porting to Rust.
//!
//! # Examples
//!
//! ```
//! # use io_read_line_prototype::read_line;
//! # use std::io;
//! # fn main() -> io::Result<()> {
//! // Before
//! let mut line = String::new();
//! io::stdin().read_line(&mut line)?;
//!
//! // After
//! let line = read_line(io::stdin())?;
//! # Ok(()) }
//! ```

#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
#![deny(missing_debug_implementations, nonstandard_style)]
#![warn(missing_docs, missing_doc_code_examples, unreachable_pub)]
#![feature(min_specialization)]

use std::io::{self, BufReader, Read};

/// Read a line from a [reader][Read] into a new [`String`].
///
/// This is a convenience function for [`BufRead::read_line`]. Using this
/// function avoids having to create a variable first and provides more type
/// safety since you can only get the buffer out if there were no errors. (If you
/// use [`BufRead::read_line`] you have to remember to check whether the read
/// succeeded because otherwise your buffer will be empty or only partially full.)
///
/// # Performance
///
/// The downside of this function's increased ease of use and type safety is
/// that it gives you less control over performance. For example, you can't
/// pre-allocate memory like you can using [`String::with_capacity`] and
/// [`Read::read_to_string`]. Also, you can't re-use the buffer if an error
/// occurs while reading.
///
/// In many cases, this function's performance will be adequate and the ease of use
/// and type safety tradeoffs will be worth it. However, there are cases where you
/// need more control over performance, and in those cases you should definitely use
/// [`BufRead::read_line`] directly.
///
/// # Errors
///
/// This function forces you to handle errors because the output (the `String`)
/// is wrapped in a [`Result`]. See [`BufRead::read_line`] for the errors
/// that can occur. If any error occurs, you will get an [`Err`], so you
/// don't have to worry about your buffer being empty or partially full.
///
/// [`BufRead::read_line`]: std::io::BufRead::read_line
///
/// # Examples
///
/// ```no_run
/// # use io_read_line_prototype::read_line;
/// # use std::io;
/// fn main() -> io::Result<()> {
///     let stdin = read_line(&mut io::stdin())?;
///     println!("Stdin was:");
///     println!("{}", stdin);
///     Ok(())
/// }
/// ```
pub fn read_line<R: Read>(reader: R) -> io::Result<String> {
    let mut buf = String::new();
    let mut reader = BufReader::new(reader);
    reader.read_to_string(&mut buf)?;
    Ok(buf)
}