dev_kit/command/qrcode/
mod.rs

1use crate::command::qrcode::generator::QrCodeImageVal;
2use crate::command::Command;
3use derive_more::{Deref, FromStr};
4use qrcode::Version;
5use std::ops::Deref;
6use std::path::PathBuf;
7use strum::Display;
8
9#[derive(clap::Subcommand)]
10pub enum QrCodeCommand {
11    #[clap(about = "Generate a QR code, alias 'gen'", alias("gen"))]
12    Generate {
13        #[arg(help = "QR code content", default_value = "")]
14        content: QrContent,
15        #[arg(short, long, help = r#"
16QR code error correction level, alias 'ecl'
17    7%: Low error correction level, alias 'l'
18    15%: Medium error correction level, alias 'm'
19    25%: Quartile error correction level, alias 'q'
20    30%: High error correction level, alias 'h'
21        "#, alias = "ecl", default_value = "q")]
22        ec_level: QrEcLevel,
23        #[arg(short, long, help = r#"
24QR code version,
25    In QR code terminology, Version means the size of the generated image. Larger version means the size of code is larger, and therefore can carry more information.
26    A normal QR code version. The parameter should be between 1 and 40.
27    QR size: version * 4 + 17
28"#, default_value = "auto")]
29        version: QrVersion,
30        #[arg(short, long, help = "QR code output type, alias 'type'", alias = "type", default_value = "text")]
31        output_type: OutputType,
32        #[arg(short, long, help = "QR code output file")]
33        file: Option<PathBuf>,
34        #[arg(short, long, help = "plain text output")]
35        plain: bool,
36    }
37}
38
39#[derive(Debug, Clone, Deref)]
40pub struct QrContent(String);
41
42#[derive(Debug, Copy, Clone, Deref)]
43pub struct QrEcLevel(qrcode::EcLevel);
44
45#[derive(Debug, Copy, Clone)]
46pub enum QrVersion {
47    Auto,
48    Version(Version),
49}
50
51#[derive(Debug, Copy, Clone, FromStr, Default, Display)]
52pub enum OutputType {
53    #[default]
54    Text,
55    Image,
56    Svg,
57}
58
59impl Command for QrCodeCommand {
60    fn run(&self) -> crate::Result<()> {
61        match self {
62            QrCodeCommand::Generate { content, ec_level, version, output_type, file, plain } => {
63                let result = generator::generate(content, ec_level, version, *output_type);
64                match result {
65                    Ok(result) => {
66                        let show_detail = !plain;
67                        if show_detail {
68                            print!(r#"
69Generate QR Code
70Error correction level: {}
71Version: {}
72Output Type: {}
73"#, result.ec_level, result.version, result.out_put_type());
74                        }
75                        match result.deref() {
76                            QrCodeImageVal::Text(text) => {
77                                if let Some(file) = file {
78                                    match std::fs::write(file, text) {
79                                        Ok(_) => {
80                                            if show_detail {
81                                                print!("Write QR Code to ")
82                                            }
83                                            println!("{}", file.display())
84                                        }
85                                        Err(err) => eprintln!("{}", err)
86                                    }
87                                } else {
88                                    println!("{}", text);
89                                }
90                                Ok(())
91                            }
92                            QrCodeImageVal::Image(path) | QrCodeImageVal::Svg(path) => {
93                                match if let Some(file_path) = file {
94                                    std::fs::copy(path, file_path).map(|_| file_path)
95                                } else {
96                                    Ok(path)
97                                } {
98                                    Ok(path) => {
99                                        if show_detail {
100                                            print!("Write QR Code to ")
101                                        }
102                                        println!("{}", path.display())
103                                    }
104                                    Err(err) => {
105                                        eprintln!("{}", err)
106                                    }
107                                }
108                                Ok(())
109                            }
110                        }
111                    }
112                    Err(err) => {
113                        eprintln!("Generate QR Code failed, {}", err);
114                        Ok(())
115                    }
116                }
117            }
118        }
119    }
120}
121
122pub mod generator;