1#![doc = include_str!("../README.md")]
2
3use std::io::{self, Read};
4use std::str::FromStr;
5use std::sync::atomic::AtomicBool;
6
7mod maybe_stdin;
8pub use maybe_stdin::MaybeStdin;
9mod file_or_stdin;
10pub use file_or_stdin::FileOrStdin;
11
12static STDIN_HAS_BEEN_READ: AtomicBool = AtomicBool::new(false);
13
14#[derive(Debug, thiserror::Error)]
15pub enum StdinError {
16 #[error("stdin read from more than once")]
17 StdInRepeatedUse,
18 #[error(transparent)]
19 StdIn(#[from] io::Error),
20 #[error("unable to parse from_str: {0}")]
21 FromStr(String),
22}
23
24#[derive(Clone)]
26pub(crate) enum Source {
27 Stdin,
28 Arg(String),
29}
30
31impl Source {
32 pub(crate) fn into_reader(self) -> Result<impl std::io::Read, StdinError> {
33 let input: Box<dyn std::io::Read + 'static> = match self {
34 Source::Stdin => {
35 if STDIN_HAS_BEEN_READ.load(std::sync::atomic::Ordering::Acquire) {
36 return Err(StdinError::StdInRepeatedUse);
37 }
38 STDIN_HAS_BEEN_READ.store(true, std::sync::atomic::Ordering::SeqCst);
39 Box::new(std::io::stdin())
40 }
41 Source::Arg(filepath) => {
42 let f = std::fs::File::open(filepath)?;
43 Box::new(f)
44 }
45 };
46 Ok(input)
47 }
48
49 pub(crate) fn get_value(self) -> Result<String, StdinError> {
50 match self {
51 Source::Stdin => {
52 if STDIN_HAS_BEEN_READ.load(std::sync::atomic::Ordering::Acquire) {
53 return Err(StdinError::StdInRepeatedUse);
54 }
55 STDIN_HAS_BEEN_READ.store(true, std::sync::atomic::Ordering::SeqCst);
56 let stdin = io::stdin();
57 let mut input = String::new();
58 stdin.lock().read_to_string(&mut input)?;
59 Ok(input)
60 }
61 Source::Arg(value) => Ok(value),
62 }
63 }
64}
65
66impl FromStr for Source {
67 type Err = StdinError;
68
69 fn from_str(s: &str) -> Result<Self, Self::Err> {
70 match s {
71 "-" => Ok(Self::Stdin),
72 arg => Ok(Self::Arg(arg.to_owned())),
73 }
74 }
75}
76
77impl std::fmt::Debug for Source {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 match self {
80 Source::Stdin => write!(f, "stdin"),
81 Source::Arg(v) => v.fmt(f),
82 }
83 }
84}