Skip to main content

use_stdin/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use std::io::{self, BufRead, Read};
5
6/// Commonly used stdin primitives.
7pub mod prelude {
8    pub use crate::{
9        StdinSource, read_line_from, read_stdin_line, read_stdin_to_string, read_to_string_from,
10    };
11}
12
13/// Marker type for the process standard input stream.
14#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
15pub struct StdinSource;
16
17impl StdinSource {
18    /// Creates a stdin source marker.
19    #[must_use]
20    pub const fn new() -> Self {
21        Self
22    }
23}
24
25/// Reads all process stdin into a string.
26///
27/// # Errors
28///
29/// Returns any I/O error reported while reading from stdin.
30pub fn read_stdin_to_string() -> io::Result<String> {
31    let stdin = io::stdin();
32    read_to_string_from(stdin.lock())
33}
34
35/// Reads one line from process stdin.
36///
37/// # Errors
38///
39/// Returns any I/O error reported while reading from stdin.
40pub fn read_stdin_line() -> io::Result<String> {
41    let stdin = io::stdin();
42    read_line_from(stdin.lock())
43}
44
45/// Reads all content from a generic reader into a string.
46///
47/// # Errors
48///
49/// Returns any I/O error reported by `reader`.
50pub fn read_to_string_from(mut reader: impl Read) -> io::Result<String> {
51    let mut input = String::new();
52    reader.read_to_string(&mut input)?;
53    Ok(input)
54}
55
56/// Reads one line from a buffered reader.
57///
58/// # Errors
59///
60/// Returns any I/O error reported by `reader`.
61pub fn read_line_from(mut reader: impl BufRead) -> io::Result<String> {
62    let mut input = String::new();
63    reader.read_line(&mut input)?;
64    Ok(input)
65}
66
67#[cfg(test)]
68mod tests {
69    use std::io::Cursor;
70
71    use super::{StdinSource, read_line_from, read_to_string_from};
72
73    #[test]
74    fn marker_is_copyable() {
75        let source = StdinSource::new();
76        let copied = source;
77
78        assert_eq!(source, copied);
79    }
80
81    #[test]
82    fn reads_from_generic_readers() -> Result<(), std::io::Error> {
83        assert_eq!(read_to_string_from(Cursor::new("hello"))?, "hello");
84        assert_eq!(read_line_from(Cursor::new("first\nsecond"))?, "first\n");
85        Ok(())
86    }
87}