use clap::{CommandFactory, Parser};
use qrcode::QrCode;
use qrsimple_cli::array::{Array, OCTANT_BLOCKS, SEXTANT_BLOCKS};
use qrsimple_cli::cli::{Cli, Render};
use qrsimple_cli::error::MyResult;
use qrsimple_cli::font;
use std::collections::HashSet;
use std::fs::File;
use std::io::{self, BufReader, Read};
fn main() {
let result = run();
if let Err(error) = result {
error.eprint();
}
}
fn run() -> MyResult<()> {
let cli = Cli::parse();
if let Some(shell) = cli.completion {
let name = env!("CARGO_BIN_NAME");
let mut command = Cli::command();
let mut stdout = io::stdout();
clap_complete::generate(shell, &mut command, name, &mut stdout);
} else {
let code = build_code(&cli.text)?;
let array = Array::new(code)?;
match cli.render.unwrap_or_else(test_fonts) {
Render::Large => array.print_large(),
Render::Medium => array.print_medium(),
Render::Small => array.print_small(),
}
}
Ok(())
}
fn test_fonts() -> Render {
let mut sextants = HashSet::from(SEXTANT_BLOCKS);
let mut octants = HashSet::from(OCTANT_BLOCKS);
font::test_fonts(&mut sextants, &mut octants);
if octants.is_empty() {
Render::Small
} else if sextants.is_empty() {
Render::Medium
} else {
Render::Large
}
}
fn build_code(text: &Option<String>) -> MyResult<QrCode> {
if let Some(text) = text {
if let Ok(mut reader) = File::open(text) {
let mut buffer = Vec::new();
reader.read_to_end(&mut buffer)?;
let code = QrCode::new(buffer)?;
Ok(code)
} else {
let code = QrCode::new(text.as_bytes())?;
Ok(code)
}
} else {
let stdin = io::stdin();
let mut reader = BufReader::new(stdin);
let mut buffer = Vec::new();
reader.read_to_end(&mut buffer)?;
let code = QrCode::new(buffer)?;
Ok(code)
}
}