1use std::io::{self, Write};
4
5const TARGET_ARCH: &str = std::env::consts::ARCH;
7const TARGET_OS: &str = std::env::consts::OS;
9
10fn build_profile() -> &'static str {
12 if cfg!(debug_assertions) {
13 "debug"
14 } else {
15 "release"
16 }
17}
18
19fn binary_path() -> Option<String> {
21 std::env::current_exe()
22 .ok()
23 .map(|p| p.display().to_string())
24}
25
26pub fn run() -> io::Result<()> {
33 let stdout = io::stdout();
34 let mut out = stdout.lock();
35 write_report(&mut out)
36}
37
38fn write_report<W: Write>(out: &mut W) -> io::Result<()> {
40 writeln!(out, "mnemo {}", env!("CARGO_PKG_VERSION"))?;
41 writeln!(out, " cible : {TARGET_OS}/{TARGET_ARCH}")?;
42 writeln!(out, " profil : {}", build_profile())?;
43 match binary_path() {
44 Some(p) => writeln!(out, " binaire : {p}")?,
45 None => writeln!(out, " binaire : (indisponible)")?,
46 }
47 Ok(())
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 struct BrokenPipeWriter;
57
58 impl Write for BrokenPipeWriter {
59 fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
60 Err(io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe"))
61 }
62
63 fn flush(&mut self) -> io::Result<()> {
64 Ok(())
65 }
66 }
67
68 #[test]
69 fn write_report_ecrit_la_version() {
70 let mut buf: Vec<u8> = Vec::new();
71 write_report(&mut buf).expect("écriture en mémoire");
72 let rendu = String::from_utf8(buf).expect("utf8");
73 assert!(rendu.starts_with("mnemo "));
74 assert!(rendu.contains("cible"));
75 }
76
77 #[test]
78 fn write_report_remonte_broken_pipe_sans_paniquer() {
79 let mut writer = BrokenPipeWriter;
80 let err = write_report(&mut writer).expect_err("doit retourner une erreur");
81 assert_eq!(err.kind(), io::ErrorKind::BrokenPipe);
82 }
83}