-
Notifications
You must be signed in to change notification settings - Fork 0
/
tokio-flipcase.rs
79 lines (74 loc) · 3.04 KB
/
tokio-flipcase.rs
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
//! An example of using patharg with clap and tokio
//!
//! Run with `cargo run --example tokio-flipcase --features examples,tokio`
//!
//! Say you're using clap to write a command named "tokio-flipcase" that flips
//! the cases of all the letters in a file, changing uppercase to lowercase and
//! lowercase to uppercase, and you want this command to take a path to a file
//! to read input from and another path for the file to write the output to.
//! By using `patharg::InputArg` and `patharg::OutputArg` as the types of the
//! arguments in your `clap::Parser`, tokio-flipcase will treat a '-' argument
//! as referring to stdin/stdout, and you'll be able to use the types' methods
//! to read or write from any filepath or standard stream given on the command
//! line.
//!
//! tokio-flipcase can then be invoked in the following ways:
//!
//! - `tokio-flipcase` — Read input from stdin, write output to stdout
//! - `tokio-flipcase file.txt` — Read input from `file.txt`, write output to
//! stdout
//! - `tokio-flipcase -` — Read input from stdin, write output to stdout
//! - `tokio-flipcase -o out.txt` — Read input from stdin, write output to
//! `out.txt`
//! - `tokio-flipcase -o -` — Read input from stdin, write output to stdout
//! - `tokio-flipcase -o out.txt file.txt` — Read input from `file.txt`, write
//! output to `out.txt`
//! - `tokio-flipcase -o out.txt -` — Read input from stdin, write output to
//! `out.txt`
//! - `tokio-flipcase -o - file.txt` — Read input from `file.txt`, write output
//! to stdout
//! - `tokio-flipcase -o - -` — Read input from stdin, write output to stdout
use clap::Parser;
use patharg::{InputArg, OutputArg};
use tokio::io::AsyncWriteExt;
use tokio_stream::StreamExt;
/// Flip the cases of all the letters in a file.
#[derive(Parser)]
struct Arguments {
/// The file to write the case-flipped text to.
#[arg(short = 'o', long, default_value_t)]
// The `default_value_t` attribute causes the default value of the argument
// to be `OutputArg::default()`, which equals `OutputArg::Stdout`.
outfile: OutputArg,
/// The file to read the text to case-flip from.
#[arg(default_value_t)]
// The `default_value_t` attribute causes the default value of the argument
// to be `InputArg::default()`, which equals `InputArg::Stdin`.
infile: InputArg,
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let args = Arguments::parse();
let mut output = args.outfile.async_create().await?;
let mut stream = args.infile.async_lines().await?;
while let Some(r) = stream.next().await {
let line = r?;
let mut flipped = flipcase(line);
flipped.push('\n');
output.write_all(flipped.as_ref()).await?;
}
Ok(())
}
fn flipcase(s: String) -> String {
let mut out = String::with_capacity(s.len());
for c in s.chars() {
if c.is_uppercase() {
out.extend(c.to_lowercase());
} else if c.is_lowercase() {
out.extend(c.to_uppercase());
} else {
out.push(c);
}
}
out
}