1- use std:: { fs, mem:: swap, path:: PathBuf , str:: FromStr } ;
1+ use std:: { fs, io :: Write , mem:: swap, path:: PathBuf , str:: FromStr } ;
22
33use clap:: { IntoApp , Parser } ;
44use espflash:: {
55 cli:: {
66 board_info, connect, flash_elf_image, monitor:: monitor, save_elf_as_image, ConnectOpts ,
77 FlashConfigOpts , FlashOpts ,
88 } ,
9- Chip , Config , ImageFormatId ,
9+ Chip , Config , ImageFormatId , InvalidPartitionTable , PartitionTable ,
1010} ;
1111use miette:: { IntoDiagnostic , Result , WrapErr } ;
1212
@@ -34,6 +34,8 @@ pub enum SubCommand {
3434 BoardInfo ( ConnectOpts ) ,
3535 /// Save the image to disk instead of flashing to device
3636 SaveImage ( SaveImageOpts ) ,
37+ /// Operations for partitions tables
38+ PartitionTable ( PartitionTableOpts ) ,
3739}
3840
3941#[ derive( Parser ) ]
@@ -60,13 +62,34 @@ pub struct SaveImageOpts {
6062 pub partition_table : Option < PathBuf > ,
6163}
6264
65+ #[ derive( Parser ) ]
66+ pub struct PartitionTableOpts {
67+ /// Convert CSV parition table to binary representation
68+ #[ clap( long, required_unless_present_any = [ "info" , "to-csv" ] ) ]
69+ to_binary : bool ,
70+ /// Convert binary partition table to CSV representation
71+ #[ clap( long, required_unless_present_any = [ "info" , "to-binary" ] ) ]
72+ to_csv : bool ,
73+ /// Show information on partition table
74+ #[ clap( short, long, required_unless_present_any = [ "to-binary" , "to-csv" ] ) ]
75+ info : bool ,
76+ /// Input partition table
77+ partition_table : PathBuf ,
78+ /// Optional output file name, if unset will output to stdout
79+ #[ clap( short, long) ]
80+ output : Option < PathBuf > ,
81+ }
82+
6383fn main ( ) -> Result < ( ) > {
6484 miette:: set_panic_hook ( ) ;
6585
6686 let mut opts = Opts :: parse ( ) ;
6787 let config = Config :: load ( ) ?;
6888
69- if !matches ! ( opts. subcommand, Some ( SubCommand :: BoardInfo ( ..) ) ) {
89+ if !matches ! (
90+ opts. subcommand,
91+ Some ( SubCommand :: BoardInfo ( ..) | SubCommand :: PartitionTable ( ..) ) ,
92+ ) {
7093 // If neither the IMAGE nor SERIAL arguments have been provided, print the
7194 // help message and exit.
7295 if opts. image . is_none ( ) && opts. connect_opts . serial . is_none ( ) {
@@ -89,6 +112,7 @@ fn main() -> Result<()> {
89112 match subcommand {
90113 BoardInfo ( opts) => board_info ( opts, config) ,
91114 SaveImage ( opts) => save_image ( opts) ,
115+ PartitionTable ( opts) => partition_table ( opts) ,
92116 }
93117 } else {
94118 flash ( opts, config)
@@ -167,3 +191,50 @@ fn save_image(opts: SaveImageOpts) -> Result<()> {
167191
168192 Ok ( ( ) )
169193}
194+
195+ fn partition_table ( opts : PartitionTableOpts ) -> Result < ( ) > {
196+ if opts. to_binary {
197+ let input = fs:: read ( & opts. partition_table ) . into_diagnostic ( ) ?;
198+ let part_table = PartitionTable :: try_from_str ( String :: from_utf8 ( input) . into_diagnostic ( ) ?)
199+ . into_diagnostic ( ) ?;
200+
201+ // Use either stdout or a file if provided for the output.
202+ let mut writer: Box < dyn Write > = if let Some ( output) = opts. output {
203+ Box :: new ( fs:: File :: create ( output) . into_diagnostic ( ) ?)
204+ } else {
205+ Box :: new ( std:: io:: stdout ( ) )
206+ } ;
207+ part_table. save_bin ( & mut writer) . into_diagnostic ( ) ?;
208+ } else if opts. to_csv {
209+ let input = fs:: read ( & opts. partition_table ) . into_diagnostic ( ) ?;
210+ let part_table = PartitionTable :: try_from_bytes ( input) . into_diagnostic ( ) ?;
211+
212+ // Use either stdout or a file if provided for the output.
213+ let mut writer: Box < dyn Write > = if let Some ( output) = opts. output {
214+ Box :: new ( fs:: File :: create ( output) . into_diagnostic ( ) ?)
215+ } else {
216+ Box :: new ( std:: io:: stdout ( ) )
217+ } ;
218+ part_table. save_csv ( & mut writer) . into_diagnostic ( ) ?;
219+ } else if opts. info {
220+ let input = fs:: read ( & opts. partition_table ) . into_diagnostic ( ) ?;
221+
222+ // Try getting the partition table from either the csv or the binary representation and
223+ // fail otherwise.
224+ let part_table = if let Ok ( part_table) =
225+ PartitionTable :: try_from_bytes ( input. clone ( ) ) . into_diagnostic ( )
226+ {
227+ part_table
228+ } else if let Ok ( part_table) =
229+ PartitionTable :: try_from_str ( String :: from_utf8 ( input) . into_diagnostic ( ) ?)
230+ {
231+ part_table
232+ } else {
233+ return Err ( ( InvalidPartitionTable { } ) . into ( ) ) ;
234+ } ;
235+
236+ part_table. pretty_print ( ) ;
237+ }
238+
239+ Ok ( ( ) )
240+ }
0 commit comments