Skip to content

Commit da3676e

Browse files
author
Mat Wood
committed
Add Source enum for capturing the source of the user-provided value
1 parent 59767fd commit da3676e

File tree

4 files changed

+53
-35
lines changed

4 files changed

+53
-35
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clap-stdin"
3-
version = "0.2.1"
3+
version = "0.2.2"
44
edition = "2021"
55
authors = ["Mat Wood <[email protected]>"]
66
description = "Provides a type for easily accepting Clap arguments from stdin"

src/file_or_stdin.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::fs;
22
use std::io::{self, Read};
33
use std::str::FromStr;
4-
use std::sync::atomic::Ordering;
54

6-
use super::{StdinError, STDIN_HAS_BEEN_USED};
5+
use super::{Source, StdinError};
76

87
/// Wrapper struct to either read in a file or contents from `stdin`
98
///
@@ -34,15 +33,11 @@ use super::{StdinError, STDIN_HAS_BEEN_USED};
3433
/// ```
3534
#[derive(Clone)]
3635
pub struct FileOrStdin<T = String> {
36+
/// Source of the contents
37+
pub source: Source,
3738
inner: T,
3839
}
3940

40-
impl<T> FileOrStdin<T> {
41-
fn new(s: T) -> Self {
42-
Self { inner: s }
43-
}
44-
}
45-
4641
impl<T> FromStr for FileOrStdin<T>
4742
where
4843
T: FromStr,
@@ -51,22 +46,19 @@ where
5146
type Err = StdinError;
5247

5348
fn from_str(s: &str) -> Result<Self, Self::Err> {
54-
match s {
55-
"-" => {
56-
if STDIN_HAS_BEEN_USED.load(std::sync::atomic::Ordering::Acquire) {
57-
return Err(StdinError::StdInRepeatedUse);
58-
}
59-
STDIN_HAS_BEEN_USED.store(true, Ordering::SeqCst);
49+
let source = Source::from_str(s)?;
50+
match &source {
51+
Source::Stdin => {
6052
let stdin = io::stdin();
6153
let mut input = String::new();
6254
stdin.lock().read_to_string(&mut input)?;
6355
Ok(T::from_str(input.trim_end())
6456
.map_err(|e| StdinError::FromStr(format!("{e}")))
65-
.map(|val| FileOrStdin::new(val))?)
57+
.map(|val| Self { source, inner: val })?)
6658
}
67-
filepath => Ok(T::from_str(&fs::read_to_string(filepath)?)
59+
Source::Arg(filepath) => Ok(T::from_str(&fs::read_to_string(filepath)?)
6860
.map_err(|e| StdinError::FromStr(format!("{e}")))
69-
.map(|val| FileOrStdin::new(val))?),
61+
.map(|val| FileOrStdin { source, inner: val })?),
7062
}
7163
}
7264
}

src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![doc = include_str!("../README.md")]
22

33
use std::io;
4+
use std::str::FromStr;
45
use std::sync::atomic::AtomicBool;
56

67
mod maybe_stdin;
@@ -19,3 +20,36 @@ pub enum StdinError {
1920
#[error("unable to parse from_str: {0}")]
2021
FromStr(String),
2122
}
23+
24+
/// Source of the value contents will be either from `stdin` or a CLI arg provided value
25+
#[derive(Clone)]
26+
pub enum Source {
27+
Stdin,
28+
Arg(String),
29+
}
30+
31+
impl FromStr for Source {
32+
type Err = StdinError;
33+
34+
fn from_str(s: &str) -> Result<Self, Self::Err> {
35+
match s {
36+
"-" => {
37+
if STDIN_HAS_BEEN_USED.load(std::sync::atomic::Ordering::Acquire) {
38+
return Err(StdinError::StdInRepeatedUse);
39+
}
40+
STDIN_HAS_BEEN_USED.store(true, std::sync::atomic::Ordering::SeqCst);
41+
Ok(Self::Stdin)
42+
}
43+
arg => Ok(Self::Arg(arg.to_owned())),
44+
}
45+
}
46+
}
47+
48+
impl std::fmt::Debug for Source {
49+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50+
match self {
51+
Source::Stdin => write!(f, "stdin"),
52+
Source::Arg(v) => v.fmt(f),
53+
}
54+
}
55+
}

src/maybe_stdin.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use std::io::{self, Read};
22
use std::str::FromStr;
3-
use std::sync::atomic::Ordering;
43

5-
use super::{StdinError, STDIN_HAS_BEEN_USED};
4+
use super::{Source, StdinError};
65

76
/// Wrapper struct to parse arg values from `stdin`
87
///
@@ -28,15 +27,11 @@ use super::{StdinError, STDIN_HAS_BEEN_USED};
2827
/// ```
2928
#[derive(Clone)]
3029
pub struct MaybeStdin<T> {
30+
/// Source of the contents
31+
pub source: Source,
3132
inner: T,
3233
}
3334

34-
impl<T> MaybeStdin<T> {
35-
fn new(inner: T) -> Self {
36-
Self { inner }
37-
}
38-
}
39-
4035
impl<T> FromStr for MaybeStdin<T>
4136
where
4237
T: FromStr,
@@ -45,22 +40,19 @@ where
4540
type Err = StdinError;
4641

4742
fn from_str(s: &str) -> Result<Self, Self::Err> {
48-
match s {
49-
"-" => {
50-
if STDIN_HAS_BEEN_USED.load(std::sync::atomic::Ordering::Acquire) {
51-
return Err(StdinError::StdInRepeatedUse);
52-
}
53-
STDIN_HAS_BEEN_USED.store(true, Ordering::SeqCst);
43+
let source = Source::from_str(s)?;
44+
match &source {
45+
Source::Stdin => {
5446
let stdin = io::stdin();
5547
let mut input = String::new();
5648
stdin.lock().read_to_string(&mut input)?;
5749
Ok(T::from_str(input.trim_end())
5850
.map_err(|e| StdinError::FromStr(format!("{e}")))
59-
.map(|val| MaybeStdin::new(val))?)
51+
.map(|val| Self { source, inner: val })?)
6052
}
61-
other => Ok(T::from_str(other)
53+
Source::Arg(value) => Ok(T::from_str(value)
6254
.map_err(|e| StdinError::FromStr(format!("{e}")))
63-
.map(|val| MaybeStdin::new(val))?),
55+
.map(|val| Self { source, inner: val })?),
6456
}
6557
}
6658
}

0 commit comments

Comments
 (0)