Skip to content

Commit afb5cb1

Browse files
committed
Flash args
1 parent 4535b21 commit afb5cb1

File tree

2 files changed

+123
-69
lines changed

2 files changed

+123
-69
lines changed

cargo-idf/src/flash.rs

Lines changed: 4 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,6 @@
1-
use std::ffi::OsStr;
2-
use std::path::PathBuf;
3-
use std::str::FromStr;
1+
pub mod opts;
2+
pub use opts::FlashOpts;
43

5-
use anyhow::bail;
6-
use clap::{AppSettings, ArgEnum, Args};
7-
use strum::{Display, EnumString};
8-
9-
use crate::build;
10-
11-
#[derive(Args)]
12-
#[clap(global_setting = AppSettings::DisableVersionFlag)]
13-
pub struct FlashOpts {
14-
/// Which bootloader to flash [possible values: esp-idf, none, <file>]
15-
///
16-
/// - `esp-idf` will flash the bootloader compiled locally from the esp-idf.
17-
/// - `none` prevents flashing a bootloader.
18-
/// - `<file>` will flash the user provided binary file if it exists.
19-
#[clap(
20-
long,
21-
default_value_t = Bootloader::EspIdf,
22-
parse(try_from_os_str = Bootloader::try_from_os_str),
23-
verbatim_doc_comment
24-
)]
25-
bootloader: Bootloader,
26-
27-
/// How to flash the binary
28-
#[clap(long, arg_enum, default_value_t = Mode::Esptool)]
29-
mode: Mode,
30-
31-
#[clap(flatten)]
32-
build_opts: build::BuildOpts,
33-
}
34-
35-
#[derive(Debug, ArgEnum, Clone, Copy)]
36-
pub enum Mode {
37-
Esptool,
38-
Dfu,
39-
Uf2,
40-
}
41-
42-
#[derive(Debug, Clone, EnumString, Display)]
43-
#[strum(serialize_all = "kebab-case")]
44-
pub enum Bootloader {
45-
EspIdf,
46-
None,
47-
#[strum(default)]
48-
#[strum(to_string = "<file>")]
49-
File(PathBuf),
50-
}
51-
52-
impl Bootloader {
53-
pub fn try_from_os_str(arg: &OsStr) -> Result<Bootloader, anyhow::Error> {
54-
let val = if let Some(arg) = arg.to_str() {
55-
Bootloader::from_str(arg).unwrap()
56-
} else {
57-
Bootloader::File(arg.into())
58-
};
59-
60-
if let Bootloader::File(ref path) = val {
61-
if !path.is_file() {
62-
bail!("'{}' is not a file", path.display())
63-
}
64-
}
65-
Ok(val)
66-
}
67-
}
68-
69-
pub fn run(opts: FlashOpts) -> anyhow::Result<()> {
70-
Ok(())
4+
pub fn run(_opts: FlashOpts) -> anyhow::Result<()> {
5+
unimplemented!()
716
}

cargo-idf/src/flash/opts.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use std::ffi::{OsStr, OsString};
2+
use std::path::PathBuf;
3+
use std::str::FromStr;
4+
5+
use anyhow::bail;
6+
use clap::{AppSettings, ArgEnum, Args};
7+
use embuild::utils::OsStrExt;
8+
use strum::{Display, EnumDiscriminants, EnumString};
9+
10+
use crate::build;
11+
12+
#[derive(Args)]
13+
#[clap(global_setting = AppSettings::DisableVersionFlag)]
14+
pub struct FlashOpts {
15+
/// One or more images to flash [possible values: all, bootloader, partition-table,
16+
/// app, <partition name> <file>, <address> <file>]
17+
///
18+
/// - `all`: flash the whole project (bootloader, partition-table, app)
19+
/// - `bootloader`: flash bootloader (see `--bootloader` option)
20+
/// - `partition-table`: flash the partition table (see `--partition-table` option)
21+
/// - `app`: flash the app
22+
/// - `<partition name> <file>`: flash <file> at the address of <partition name>
23+
/// - `<address> <file>`: flash <file> at <address>
24+
#[clap(
25+
parse(from_os_str = ImageArg::from_os_str),
26+
validator_os = ImageArg::parse_validator(),
27+
verbatim_doc_comment,
28+
default_value = "all"
29+
)]
30+
images: Vec<ImageArg>,
31+
32+
/// The bootloader binary file to use instead of the default
33+
#[clap(long, parse(from_os_str), value_name = "file")]
34+
bootloader: Option<PathBuf>,
35+
36+
/// The partition table `.csv` file to use instead of the default
37+
#[clap(long, parse(from_os_str), value_name = "file")]
38+
partition_table: Option<PathBuf>,
39+
40+
#[clap(flatten)]
41+
build_opts: build::BuildOpts,
42+
}
43+
44+
#[derive(Debug, ArgEnum, Clone, Copy)]
45+
pub enum Mode {
46+
Esptool,
47+
Dfu,
48+
Uf2,
49+
}
50+
51+
#[derive(Debug, Clone, Display, EnumDiscriminants)]
52+
#[strum_discriminants(name(ImageArgKind))]
53+
pub enum ImageArg {
54+
#[strum(to_string = "<name>")]
55+
Name(ImageName),
56+
#[strum(to_string = "<address>")]
57+
Address(usize),
58+
#[strum(to_string = "<partition name or file>")]
59+
PartitionOrFile(OsString),
60+
Partition(String),
61+
File(PathBuf),
62+
}
63+
64+
impl Default for ImageArgKind {
65+
fn default() -> Self {
66+
ImageArgKind::Name
67+
}
68+
}
69+
70+
#[derive(Debug, EnumString, Display, Clone, Copy)]
71+
#[strum(serialize_all = "kebab-case")]
72+
pub enum ImageName {
73+
All,
74+
Bootloader,
75+
PartitionTable,
76+
App,
77+
}
78+
79+
impl ImageArg {
80+
fn from_os_str(arg: &OsStr) -> ImageArg {
81+
if let Some(arg) = arg.to_str() {
82+
if let Ok(name) = ImageName::from_str(arg) {
83+
return ImageArg::Name(name);
84+
} else if let Ok(address) = arg.parse::<usize>() {
85+
return ImageArg::Address(address);
86+
}
87+
}
88+
ImageArg::PartitionOrFile(arg.to_owned())
89+
}
90+
91+
fn parse_validator() -> impl FnMut(&OsStr) -> Result<(), anyhow::Error> {
92+
let mut previous = ImageArgKind::default();
93+
move |arg| {
94+
let next = Self::from_os_str(arg);
95+
previous = Self::parse(previous, next)?.into();
96+
Ok(())
97+
}
98+
}
99+
100+
/// Parses image arg with a given previous arg kind.
101+
///
102+
/// Never returns [`ImageArg::PartitionOrFile`].
103+
pub fn parse(last: ImageArgKind, next: ImageArg) -> Result<ImageArg, anyhow::Error> {
104+
use ImageArgKind::*;
105+
let result = match (last, next) {
106+
(Name | File, ImageArg::PartitionOrFile(file)) => {
107+
ImageArg::Partition(file.try_to_str()?.into())
108+
}
109+
(Partition | Address, ImageArg::PartitionOrFile(file)) => ImageArg::File(file.into()),
110+
(Name | File, val @ ImageArg::Name(_) | val @ ImageArg::Address(_)) => val,
111+
(Partition | Address, _) => bail!("expected <file>"),
112+
113+
(_, ImageArg::File(_) | ImageArg::Partition(_)) | (PartitionOrFile, _) => {
114+
unreachable!("invalid state")
115+
}
116+
};
117+
Ok(result)
118+
}
119+
}

0 commit comments

Comments
 (0)