#![allow(missing_docs)]
use crate::{
color::Color,
probe::{Log, Probe},
utils::de_from_str,
};
use anyhow::Error;
use drone_config::parse_size;
use std::{
ffi::{OsStr, OsString},
os::unix::ffi::OsStrExt,
path::PathBuf,
};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct Cli {
#[structopt(long, short, parse(from_occurrences))]
pub verbosity: u64,
#[structopt(long, default_value = "auto", parse(try_from_str = de_from_str))]
pub color: Color,
#[structopt(subcommand)]
pub cmd: Cmd,
}
#[derive(Debug, StructOpt)]
pub enum Cmd {
Flash(FlashCmd),
Gdb(GdbCmd),
Heap(HeapCmd),
Log(LogCmd),
New(NewCmd),
Reset(ResetCmd),
Print(PrintCmd),
}
#[derive(Debug, StructOpt)]
pub struct NewCmd {
#[structopt(parse(from_os_str))]
pub path: PathBuf,
#[structopt(short, long)]
pub device: String,
#[structopt(short, long, parse(try_from_str = parse_size))]
pub flash_size: u32,
#[structopt(short, long, parse(try_from_str = parse_size))]
pub ram_size: u32,
#[structopt(short, long, parse(try_from_str = de_from_str))]
pub probe: Option<Probe>,
#[structopt(long, short, parse(try_from_str = de_from_str))]
pub log: Option<Log>,
#[structopt(long)]
pub name: Option<String>,
#[structopt(long, default_value = "nightly")]
pub toolchain: String,
}
#[derive(Debug, StructOpt)]
pub struct HeapCmd {
#[structopt(
short = "f",
long,
name = "heaptrace",
default_value = "heaptrace",
parse(from_os_str)
)]
pub trace_file: PathBuf,
#[structopt(short, long, default_value = "main")]
pub config: String,
#[structopt(short, long, parse(try_from_str = parse_size))]
pub size: Option<u32>,
#[structopt(subcommand)]
pub heap_sub_cmd: Option<HeapSubCmd>,
}
#[derive(Debug, StructOpt)]
pub enum HeapSubCmd {
Generate(HeapGenerateCmd),
}
#[derive(Debug, StructOpt)]
pub struct HeapGenerateCmd {
#[structopt(short, long, parse(try_from_str = parse_size))]
pub pools: u32,
}
#[derive(Debug, StructOpt)]
pub struct ResetCmd {}
#[derive(Debug, StructOpt)]
pub struct FlashCmd {
#[structopt(parse(from_os_str))]
pub firmware: PathBuf,
}
#[derive(Debug, StructOpt)]
pub struct GdbCmd {
#[structopt(parse(from_os_str))]
pub firmware: Option<PathBuf>,
#[structopt(short, long)]
pub reset: bool,
#[structopt(short, long)]
pub interpreter: Option<String>,
#[structopt(parse(from_os_str), last(true))]
pub gdb_args: Vec<OsString>,
}
#[derive(Debug, StructOpt)]
pub struct LogCmd {
#[structopt(short, long)]
pub reset: bool,
#[structopt(
name = "OUTPUT",
parse(try_from_os_str = parse_log_output)
)]
pub outputs: Vec<LogOutput>,
}
#[derive(Debug, Clone)]
pub struct LogOutput {
pub ports: Vec<u32>,
pub path: OsString,
}
#[derive(Debug, StructOpt)]
pub struct PrintCmd {
#[structopt(subcommand)]
pub print_sub_cmd: PrintSubCmd,
}
#[derive(Debug, StructOpt)]
pub enum PrintSubCmd {
Target,
SupportedDevices,
}
fn parse_log_output(src: &OsStr) -> Result<LogOutput, OsString> {
let mut chunks = src.as_bytes().split(|&b| b == b':');
let path = OsStr::from_bytes(chunks.next().unwrap()).into();
let ports = chunks
.map(|port| Ok(String::from_utf8(port.to_vec())?.parse()?))
.collect::<Result<_, Error>>()
.map_err(|err| err.to_string())?;
Ok(LogOutput { ports, path })
}