io_read_line_prototype/lib.rs
1//! Prototype for `io::read_line`.
2//!
3//! This serves as a counterpart to
4//! [`io::read_to_string`](https://github.com/rust-lang/rust/issues/80218) and
5//! is inspired by proposals such as
6//! [`std::io::input`](https://github.com/rust-lang/rust/pull/75435).
7//!
8//! This method makes it easier to read a line from a reader into a string, and leaves
9//! more advances input proposals for later. For example [C++'s
10//! text parsing
11//! proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1729r1.html)
12//! provides a coherent text parsing counterpart using `format!`-like syntax,
13//! and would be interesting to explore porting to Rust.
14//!
15//! # Examples
16//!
17//! ```
18//! # use io_read_line_prototype::read_line;
19//! # use std::io;
20//! # fn main() -> io::Result<()> {
21//! // Before
22//! let mut line = String::new();
23//! io::stdin().read_line(&mut line)?;
24//!
25//! // After
26//! let line = read_line(io::stdin())?;
27//! # Ok(()) }
28//! ```
29
30#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
31#![deny(missing_debug_implementations, nonstandard_style)]
32#![warn(missing_docs, missing_doc_code_examples, unreachable_pub)]
33#![feature(min_specialization)]
34
35use std::io::{self, BufReader, Read};
36
37/// Read a line from a [reader][Read] into a new [`String`].
38///
39/// This is a convenience function for [`BufRead::read_line`]. Using this
40/// function avoids having to create a variable first and provides more type
41/// safety since you can only get the buffer out if there were no errors. (If you
42/// use [`BufRead::read_line`] you have to remember to check whether the read
43/// succeeded because otherwise your buffer will be empty or only partially full.)
44///
45/// # Performance
46///
47/// The downside of this function's increased ease of use and type safety is
48/// that it gives you less control over performance. For example, you can't
49/// pre-allocate memory like you can using [`String::with_capacity`] and
50/// [`Read::read_to_string`]. Also, you can't re-use the buffer if an error
51/// occurs while reading.
52///
53/// In many cases, this function's performance will be adequate and the ease of use
54/// and type safety tradeoffs will be worth it. However, there are cases where you
55/// need more control over performance, and in those cases you should definitely use
56/// [`BufRead::read_line`] directly.
57///
58/// # Errors
59///
60/// This function forces you to handle errors because the output (the `String`)
61/// is wrapped in a [`Result`]. See [`BufRead::read_line`] for the errors
62/// that can occur. If any error occurs, you will get an [`Err`], so you
63/// don't have to worry about your buffer being empty or partially full.
64///
65/// [`BufRead::read_line`]: std::io::BufRead::read_line
66///
67/// # Examples
68///
69/// ```no_run
70/// # use io_read_line_prototype::read_line;
71/// # use std::io;
72/// fn main() -> io::Result<()> {
73/// let stdin = read_line(&mut io::stdin())?;
74/// println!("Stdin was:");
75/// println!("{}", stdin);
76/// Ok(())
77/// }
78/// ```
79pub fn read_line<R: Read>(reader: R) -> io::Result<String> {
80 let mut buf = String::new();
81 let mut reader = BufReader::new(reader);
82 reader.read_to_string(&mut buf)?;
83 Ok(buf)
84}