acme_proxy_admin/admin/
prompt.rs1use std::io::{BufRead, Write};
7
8pub fn confirm(prompt: &str, assume_yes: bool, reader: &mut impl BufRead) -> bool {
10 if assume_yes {
11 return true;
12 }
13 print!("{prompt} [y/N] ");
14 let _ = std::io::stdout().flush();
15 let mut line = String::new();
16 if reader.read_line(&mut line).unwrap_or(0) == 0 {
17 return false;
18 }
19 matches!(line.trim().to_lowercase().as_str(), "y" | "yes")
20}
21
22#[cfg(test)]
23mod tests {
24 use super::*;
25
26 #[test]
27 fn confirm_accepts_y_variants() {
28 for input in ["y\n", "Y\n", "yes\n", "YES\n", " yes \n"] {
29 let mut reader = input.as_bytes();
30 assert!(
31 confirm("proceed?", false, &mut reader),
32 "expected {input:?} to confirm"
33 );
34 }
35 }
36
37 #[test]
38 fn confirm_rejects_everything_else() {
39 for input in ["n\n", "no\n", "\n", "garbage\n"] {
40 let mut reader = input.as_bytes();
41 assert!(
42 !confirm("proceed?", false, &mut reader),
43 "expected {input:?} to reject"
44 );
45 }
46 }
47
48 #[test]
49 fn confirm_rejects_eof() {
50 let mut reader: &[u8] = &[];
51 assert!(!confirm("proceed?", false, &mut reader));
52 }
53
54 #[test]
55 fn confirm_assume_yes_skips_reading() {
56 let mut reader: &[u8] = &[];
57 assert!(confirm("proceed?", true, &mut reader));
58 }
59}