From 0f09eeea5fe07494b1f3cdb01f1ebfd31cba0166 Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Thu, 7 May 2026 14:17:56 -0400 Subject: [PATCH 1/9] Make idol_result return a Loadable type --- cmd/sbrmi/src/lib.rs | 74 +++++++++++++++++---------------------- cmd/vpd/src/lib.rs | 44 +++++++---------------- humility-hiffy/src/lib.rs | 13 +++---- 3 files changed, 52 insertions(+), 79 deletions(-) diff --git a/cmd/sbrmi/src/lib.rs b/cmd/sbrmi/src/lib.rs index 11b3c6ba2..f147ab360 100644 --- a/cmd/sbrmi/src/lib.rs +++ b/cmd/sbrmi/src/lib.rs @@ -89,7 +89,7 @@ //! desired target thread; full MCA information can similarly be retrieved //! using the `--mca` option and specifyin a desired thread. -use anyhow::{Result, anyhow}; +use anyhow::Result; use clap::{ArgGroup, CommandFactory, Parser}; use colored::Colorize; use hif::*; @@ -155,21 +155,14 @@ fn call_cpuid( ops.push(Op::Done); let results = context.run(core, ops.as_slice(), None)?; - let result = context.idol_result(&op, &results[0])?; - let registers = result.as_struct()?["value"].as_array()?; - - let register = |ndx| { - let b: &reflect::Value = ®isters[ndx]; - b.as_base()? - .as_u32() - .ok_or_else(|| anyhow!("couldn't decode index {ndx} as u32")) - }; + let result = context.idol_result::(&op, &results[0])?; + let registers = result.field::<[u32; 4]>("value")?; Ok(CpuIdResult { - eax: register(0)?, - ebx: register(1)?, - ecx: register(2)?, - edx: register(3)?, + eax: registers[0], + ebx: registers[1], + ecx: registers[2], + edx: registers[3], }) } @@ -234,12 +227,10 @@ fn cpuid( Ok(()) } -fn threadmap(arr: &reflect::Array) -> Result> { +fn threadmap(arr: &[u8]) -> Result> { let mut rval = HashSet::new(); - for (base, elem) in arr.iter().enumerate() { - let val = elem.as_base()?.as_u8().unwrap(); - + for (base, val) in arr.iter().enumerate() { for bit in 0..8 { if val & (1 << bit) != 0 { rval.insert(((base * 8) + bit) as u8); @@ -405,12 +396,8 @@ fn mca( let ipid_results = &results[nbanks as usize..]; for (bank, r) in results[..nbanks as usize].iter().enumerate() { - let status = context.idol_result(&op, r)?.as_base()?.as_u64().unwrap(); - let ipid = context - .idol_result(&op, &ipid_results[bank])? - .as_base()? - .as_u64() - .unwrap(); + let status = context.idol_result::(&op, r)?; + let ipid = context.idol_result::(&op, &ipid_results[bank])?; if !all_mca { if status == 0 { @@ -457,7 +444,7 @@ fn mca( let mut values = HashMap::new(); for (ndx, reg) in reg_results.iter().enumerate() { - let v = context.idol_result(&op, reg)?.as_base()?.as_u64().unwrap(); + let v = context.idol_result::(&op, reg)?; values.insert(allregs[ndx], v); } @@ -552,23 +539,26 @@ fn sbrmi(context: &mut ExecutionContext) -> Result<()> { let results = context.run(core, ops.as_slice(), None)?; - let nthreads = context - .idol_result(&nthreads, &results[0])? - .as_base()? - .as_u8() - .unwrap(); - - let result = context.idol_result(&enabled, &results[1])?; - let enabled = threadmap(result.as_struct()?["value"].as_array()?)?; - - let result = context.idol_result(&alert, &results[2])?; - let alert = threadmap(result.as_struct()?["value"].as_array()?)?; - - let mcg_cap = context - .idol_result(&mcg_cap, &results[3])? - .as_base()? - .as_u64() - .unwrap(); + println!( + "{:#x?}", + context + .idol_result::(&nthreads, &results[0])? + ); + let nthreads = context.idol_result::(&nthreads, &results[0])?; + + println!( + "{:#x?}", + context + .idol_result::(&enabled, &results[1])? + ); + let result = + context.idol_result::(&enabled, &results[1])?; + let enabled = threadmap(&result.field::>("value")?)?; + + let result = context.idol_result::(&alert, &results[2])?; + let alert = threadmap(&result.field::>("value")?)?; + + let mcg_cap = context.idol_result::(&mcg_cap, &results[3])?; if subargs.mca { let thread = subargs.thread.unwrap(); diff --git a/cmd/vpd/src/lib.rs b/cmd/vpd/src/lib.rs index fe22ba0db..a37cda2e7 100644 --- a/cmd/vpd/src/lib.rs +++ b/cmd/vpd/src/lib.rs @@ -419,13 +419,9 @@ fn vpd_write( let results = context.run(core, ops.as_slice(), None)?; for (o, result) in results.iter().enumerate() { - if let Err(err) = context.idol_result(&op, result) { - bail!( - "failed to write VPD at offset {}: {:?}", - offset + o, - err - ); - } + context.idol_result::<()>(&op, result).with_context(|| { + format!("failed to write VPD at offset {}", offset + o) + })?; } offset += results.len(); @@ -474,20 +470,9 @@ fn vpd_read_at( let results = context.run(core, ops.as_slice(), None)?; let r = context - .idol_result(op, &results[0]) + .idol_result::(op, &results[0]) .with_context(|| format!("failed to read at offset {offset}"))?; - let contents = r.as_struct()?["value"].as_array()?; - let mut rval = vec![]; - - for b in contents.iter() { - if let reflect::Base::U8(val) = b.as_base()? { - rval.push(*val); - } else { - bail!("expected array of U8; found {:?}", contents); - } - } - - Ok(rval) + r.field::>("value") } fn vpd_slurp( @@ -596,9 +581,7 @@ fn vpd_lock( } }; - if let Err(err) = vpd_read(hubris, core, subargs) { - bail!("can't lock VPD: {err}"); - } + vpd_read(hubris, core, subargs).context("can't lock VPD")?; let payload = op.payload(&[("index", idol::IdolArgument::Scalar(index as u64))])?; @@ -610,9 +593,9 @@ fn vpd_lock( let results = context.run(core, ops.as_slice(), None)?; - if let Err(err) = context.idol_result(&op, &results[0]) { - bail!("failed to lock {index}: {err:?}"); - } + context + .idol_result::<()>(&op, &results[0]) + .with_context(|| format!("failed to lock {index}"))?; humility::msg!("successfully locked VPD"); @@ -715,11 +698,10 @@ fn vpd_lock_all( let mut success = 0; for (ndx, r) in locking.iter().zip(results.iter()) { - if let Err(err) = context.idol_result(&lock_op, r) { - humility::warn!("failed to lock VPD {ndx}: {err:?}"); - } else { - success += 1; - } + context + .idol_result::<()>(&lock_op, r) + .with_context(|| format!("failed to lock VPD {ndx}"))?; + success += 1; } if success != locking.len() { diff --git a/humility-hiffy/src/lib.rs b/humility-hiffy/src/lib.rs index 44ba00cfa..d3589aad2 100644 --- a/humility-hiffy/src/lib.rs +++ b/humility-hiffy/src/lib.rs @@ -991,17 +991,17 @@ impl<'a> HiffyContext<'a> { } /// Convenience routine to pull out the result of an Idol call - pub fn idol_result( + pub fn idol_result( &mut self, op: &idol::IdolOperation, result: &Result, IpcError>, - ) -> Result { + ) -> Result { use humility::reflect::{deserialize_value, load_value}; - match result { + let value = match result { Ok(val) => { let ty = self.hubris.lookup_type(op.ok).unwrap(); - Ok(match op.operation.encoding { + match op.operation.encoding { ::idol::syntax::Encoding::Zerocopy => { load_value(self.hubris, val, ty, 0)? } @@ -1009,10 +1009,11 @@ impl<'a> HiffyContext<'a> { | ::idol::syntax::Encoding::Hubpack => { deserialize_value(self.hubris, val, ty)?.0 } - }) + } } Err(e) => bail!("{}", op.strerror(*e)), - } + }; + T::from_value(&value) } /// Begins HIF execution. This is potentially non-blocking with respect to From 5171b498f5d80654f5777a2fc13459878ab89793 Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Mon, 18 May 2026 16:38:17 -0400 Subject: [PATCH 2/9] Automatically unpack `value` member of REPLY --- cmd/sbrmi/src/lib.rs | 26 +++++--------------------- cmd/vpd/src/lib.rs | 8 +++----- humility-idol/src/lib.rs | 15 ++++++++++++--- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/cmd/sbrmi/src/lib.rs b/cmd/sbrmi/src/lib.rs index f147ab360..2a33b36a0 100644 --- a/cmd/sbrmi/src/lib.rs +++ b/cmd/sbrmi/src/lib.rs @@ -95,7 +95,6 @@ use colored::Colorize; use hif::*; use humility::core::Core; use humility::hubris::*; -use humility::reflect; use humility_cli::ExecutionContext; use humility_cmd::Command; use humility_hiffy::*; @@ -155,8 +154,7 @@ fn call_cpuid( ops.push(Op::Done); let results = context.run(core, ops.as_slice(), None)?; - let result = context.idol_result::(&op, &results[0])?; - let registers = result.field::<[u32; 4]>("value")?; + let registers = context.idol_result::<[u32; 4]>(&op, &results[0])?; Ok(CpuIdResult { eax: registers[0], @@ -539,25 +537,11 @@ fn sbrmi(context: &mut ExecutionContext) -> Result<()> { let results = context.run(core, ops.as_slice(), None)?; - println!( - "{:#x?}", - context - .idol_result::(&nthreads, &results[0])? - ); let nthreads = context.idol_result::(&nthreads, &results[0])?; - - println!( - "{:#x?}", - context - .idol_result::(&enabled, &results[1])? - ); - let result = - context.idol_result::(&enabled, &results[1])?; - let enabled = threadmap(&result.field::>("value")?)?; - - let result = context.idol_result::(&alert, &results[2])?; - let alert = threadmap(&result.field::>("value")?)?; - + let enabled = + threadmap(&context.idol_result::>(&enabled, &results[1])?)?; + let alert = + threadmap(&context.idol_result::>(&alert, &results[2])?)?; let mcg_cap = context.idol_result::(&mcg_cap, &results[3])?; if subargs.mca { diff --git a/cmd/vpd/src/lib.rs b/cmd/vpd/src/lib.rs index a37cda2e7..6f7334fcb 100644 --- a/cmd/vpd/src/lib.rs +++ b/cmd/vpd/src/lib.rs @@ -107,7 +107,6 @@ use clap::{ArgGroup, CommandFactory, Parser}; use hif::*; use humility::core::Core; use humility::hubris::*; -use humility::reflect; use humility_cli::ExecutionContext; use humility_cmd::{Command, Dumper}; use humility_hiffy::*; @@ -469,10 +468,9 @@ fn vpd_read_at( let results = context.run(core, ops.as_slice(), None)?; - let r = context - .idol_result::(op, &results[0]) - .with_context(|| format!("failed to read at offset {offset}"))?; - r.field::>("value") + context + .idol_result::>(op, &results[0]) + .with_context(|| format!("failed to read at offset {offset}")) } fn vpd_slurp( diff --git a/humility-idol/src/lib.rs b/humility-idol/src/lib.rs index 78149d163..ad8e54df8 100644 --- a/humility-idol/src/lib.rs +++ b/humility-idol/src/lib.rs @@ -819,15 +819,24 @@ pub fn lookup_reply<'a>( _ => match m.lookup_struct_byname(hubris, ok) { Ok(Some(s)) => Ok(s.goff), _ => { - // // As a last ditch, we look up the REPLY type. This is // a last effort because it might not be there: if no // task calls the function, the type will be absent. - // let t = format!("{}_{}_REPLY", iface.name, op); + // The generated REPLY type contains a single member + // named "value", which we'll use here if possible + // (instead of the outer wrapper type) match hubris.lookup_struct_byname(&t) { - Ok(s) => Ok(s.goff), + Ok(s) => { + if s.members.len() == 1 + && let Ok(m) = s.lookup_member("value") + { + Ok(m.goff) + } else { + Ok(s.goff) + } + } Err(_) => lookup_ok_err(ok), } } From f1b8bcc5f9206e5d06fa018b4c9236e05316a07f Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Thu, 7 May 2026 14:33:57 -0400 Subject: [PATCH 3/9] Make hiffy_decode return a non-nested error --- cmd/hiffy/src/lib.rs | 4 +- cmd/host/src/lib.rs | 10 ++--- cmd/monorail/src/lib.rs | 76 ++++++++++++++---------------------- cmd/net/src/lib.rs | 2 +- cmd/powershelf/src/lib.rs | 10 ++++- cmd/rendmp/src/lib.rs | 20 +++++----- humility-auxflash/src/lib.rs | 6 +-- humility-hiffy/src/lib.rs | 19 +++++---- 8 files changed, 67 insertions(+), 80 deletions(-) diff --git a/cmd/hiffy/src/lib.rs b/cmd/hiffy/src/lib.rs index eb5bbb3c3..238dfa92c 100644 --- a/cmd/hiffy/src/lib.rs +++ b/cmd/hiffy/src/lib.rs @@ -322,8 +322,8 @@ fn hiffy(context: &mut ExecutionContext) -> Result<()> { output.as_deref_mut(), ) { Ok(s) => Ok(s), - Err(HiffyCallError::Hiffy(s)) => Err(s), - Err(HiffyCallError::Other(e)) => return Err(e), + Err(HiffyError::Hiffy(s)) => Err(s), + Err(HiffyError::Other(e)) => return Err(e), }, output, ) diff --git a/cmd/host/src/lib.rs b/cmd/host/src/lib.rs index e953ef2bc..adff82210 100644 --- a/cmd/host/src/lib.rs +++ b/cmd/host/src/lib.rs @@ -100,7 +100,7 @@ //! # etc... //! ``` -use anyhow::{Result, anyhow, bail}; +use anyhow::{Result, anyhow}; use chrono::DateTime; use clap::{CommandFactory, Parser}; @@ -369,9 +369,6 @@ fn host_post_codes( let op = hubris.get_idol_command("Sequencer.get_post_code")?; let handle_value = |v| { - let Ok(reflect::Value::Base(reflect::Base::U32(v))) = v else { - bail!("Got bad value from get_post_code: expected U32, got {v:?}"); - }; if raw { println!("{v:08x}"); } else { @@ -379,7 +376,6 @@ fn host_post_codes( let detail = decoded.lines().join("\n"); println!("{detail}"); } - Ok(()) }; let send = context.get_function("Send", 4)?; @@ -422,8 +418,8 @@ fn host_post_codes( ops.push(Op::Done); // Finish for r in context.run(core, ops.as_slice(), None)? { - let v = humility_hiffy::hiffy_decode(hubris, &op, r)?; - handle_value(v)?; + let v = humility_hiffy::hiffy_decode::(hubris, &op, r)?; + handle_value(v); } } Ok(()) diff --git a/cmd/monorail/src/lib.rs b/cmd/monorail/src/lib.rs index 01283642d..c859ad80b 100644 --- a/cmd/monorail/src/lib.rs +++ b/cmd/monorail/src/lib.rs @@ -172,10 +172,10 @@ use humility::core::Core; use humility::hubris::*; use humility::reflect::*; use humility_cli::ExecutionContext; -use humility_hiffy::HiffyContext; +use humility_hiffy::{HiffyContext, HiffyError}; use humility_idol::{HubrisIdol, IdolArgument}; -use anyhow::{Result, anyhow, bail}; +use anyhow::{Result, anyhow}; use clap::{CommandFactory, Parser}; use colored::Colorize; @@ -600,14 +600,9 @@ fn monorail_dump( results .into_iter() .map(move |r| humility_hiffy::hiffy_decode(hubris, &op_read, r)) - .collect::>>>()? + .collect::, _>>()? }; - for (i, v) in results.iter().enumerate() { - let value = if let Ok(Value::Base(Base::U32(v))) = v { - v - } else { - bail!("Got bad reflected value: expected U32, got {v:?}"); - }; + for (i, value) in results.iter().enumerate() { let addr = format!("{}", start_address as usize + i * 4); // XXX this is inefficient match parse_reg_or_addr(&addr) { @@ -684,7 +679,7 @@ fn monorail_status( hubris, &op_port, r, ) }) - .collect::>>>()?; + .collect::>(); let phy_results = phy_results .into_iter() .map(move |r| { @@ -692,7 +687,7 @@ fn monorail_status( hubris, &op_phy, r, ) }) - .collect::>>>()?; + .collect::>(); // Decode the port and phy status values into reflect::Value port_results.into_iter().zip(phy_results).collect::>() @@ -717,19 +712,10 @@ fn monorail_status( v => panic!("Expected enum, got {:?}", v), }; // Extracts a device name from a reflected value, e.g. "DEV1G_0" - let decode_dev = |value: &Value| match value { - Value::Tuple(dev) => { - let d = match &dev[0] { - Value::Enum(d) => d.disc(), - d => panic!("Could not get enum from {:?}", d), - }; - let n = match &dev[1] { - Value::Base(Base::U8(n)) => n, - d => panic!("Could not get U8 from {:?}", d), - }; - format!("{}_{}", d.to_uppercase(), n) - } - dev => panic!("Expected tuple, got {:?}", dev), + let decode_dev = |dev: &Tuple| -> Result<_> { + let d = dev.field::(0)?; + let n = dev.field::(1)?; + Ok(format!("{}_{}", d.disc().to_uppercase(), n)) }; let fmt_link = |v: &Value| match v { @@ -759,20 +745,18 @@ fn monorail_status( match port_value { Ok(s) => { assert_eq!(s.name(), "PortStatus"); - let (dev, serdes, mode, speed) = match &s["cfg"] { - Value::Struct(cfg) => { - assert_eq!(cfg.name(), "PortConfig"); - let dev = decode_dev(&cfg["dev"]); - let serdes = decode_dev(&cfg["serdes"]); - let (mode, speed) = decode_mode(&cfg["mode"]); - ( - dev.replace("DEV", ""), - serdes.replace("SERDES", ""), - mode, - speed, - ) - } - v => panic!("Expected Struct, got {:?}", v), + let (dev, serdes, mode, speed) = { + let cfg = s.field::("cfg")?; + assert_eq!(cfg.name(), "PortConfig"); + let dev = decode_dev(&cfg.field("dev")?)?; + let serdes = decode_dev(&cfg.field("serdes")?)?; + let (mode, speed) = decode_mode(&cfg["mode"]); + ( + dev.replace("DEV", ""), + serdes.replace("SERDES", ""), + mode, + speed, + ) }; let fmt_mode = match mode.as_str() { "SGMII" => mode.cyan(), @@ -791,7 +775,9 @@ fn monorail_status( ) } Err(e) => { - if e == "UnconfiguredPort" { + if let HiffyError::Hiffy(e) = &e + && e == "UnconfiguredPort" + { print!( "{}", "-- -- -- -- -- ".dimmed() @@ -805,19 +791,17 @@ fn monorail_status( match phy_value { Ok(s) => { assert_eq!(s.name(), "PhyStatus"); - let phy_ty = match &s["ty"] { - Value::Enum(e) => e.disc().to_uppercase(), - v => panic!("Expected struct, got {:?}", v), - }; println!( "{:<6} {:<8} {:<10}", - phy_ty, + s.field::("ty")?.disc().to_uppercase(), fmt_link(&s["mac_link_up"]), fmt_link(&s["media_link_up"]), ) } Err(e) => { - if e == "UnconfiguredPort" || e == "NoPhy" { + if let HiffyError::Hiffy(e) = &e + && (e == "UnconfiguredPort" || e == "NoPhy") + { println!("{}", "-- -- --".dimmed()); } else { println!("Got unexpected error {e}"); @@ -885,7 +869,7 @@ fn monorail_mac_table( hubris, &op, r, ) }) - .collect::>>>()?; + .collect::>>(); let mut mac_table: BTreeMap> = BTreeMap::new(); for r in results { diff --git a/cmd/net/src/lib.rs b/cmd/net/src/lib.rs index 7e74c5d97..64cf47e4e 100644 --- a/cmd/net/src/lib.rs +++ b/cmd/net/src/lib.rs @@ -204,7 +204,7 @@ fn net_mac_table( hubris, &op, r, ) }) - .collect::>>>()?; + .collect::>(); let mut mac_table: BTreeMap> = BTreeMap::new(); for r in results { diff --git a/cmd/powershelf/src/lib.rs b/cmd/powershelf/src/lib.rs index 0d64a39c4..0ebf15206 100644 --- a/cmd/powershelf/src/lib.rs +++ b/cmd/powershelf/src/lib.rs @@ -164,7 +164,15 @@ fn powershelf_run(context: &mut ExecutionContext) -> Result<()> { let results = context.run(core, ops.as_slice(), None)?; for (ndx, variant) in operation.variants.iter().enumerate() { - let result = hiffy_decode(hubris, &idol_cmd, results[ndx].clone())?; + let result = match hiffy_decode::( + hubris, + &idol_cmd, + results[ndx].clone(), + ) { + Ok(s) => Ok(s), + Err(HiffyError::Hiffy(s)) => Err(s), + Err(HiffyError::Other(e)) => return Err(e), + }; println!( "{:<20} => {}", diff --git a/cmd/rendmp/src/lib.rs b/cmd/rendmp/src/lib.rs index ad3cde1aa..af8846498 100644 --- a/cmd/rendmp/src/lib.rs +++ b/cmd/rendmp/src/lib.rs @@ -1208,11 +1208,7 @@ fn get_pin_states( // Decode Hiffy results let mut values = vec![]; for r in results { - match hiffy_decode(hubris, &op, r)? { - Err(e) => bail!("hiffy error: {e}"), - Ok(Value::Base(Base::U32(b))) => values.push(b), - v => bail!("unexpected type in result: {v:?}"), - } + values.push(hiffy_decode::(hubris, &op, r)?); } let phases = dev.phases(); @@ -1617,8 +1613,7 @@ impl<'a, 'b> HifWorker<'a, 'b> { Call::WriteByte => &self.write_byte, Call::WriteWord32 => &self.write_word32, }; - let v = hiffy_decode::(self.hubris, op, value) - .with_context(|| format!("failed to decode {call:?} result"))?; + let v = hiffy_decode::(self.hubris, op, value); match v { Ok(v) => match (v, call) { (Base::U32(v), Call::ReadDma(..)) => { @@ -1647,7 +1642,12 @@ impl<'a, 'b> HifWorker<'a, 'b> { bail!("got unexpected result {base} for {op:?}") } }, - Err(e) => out.push(Err(e)), + Err(HiffyError::Hiffy(e)) => out.push(Err(e)), + Err(HiffyError::Other(e)) => { + return Err(e).with_context(|| { + format!("failed to decode {call:?} result") + }); + } } } Ok(out) @@ -1669,8 +1669,8 @@ fn rendmp_phase_check<'a>( let r = hiffy_call(hubris, core, context, &power_state_op, &[], None, None); let v = match r { Ok(r) => Ok(r), - Err(HiffyCallError::Hiffy(s)) => Err(s), - Err(HiffyCallError::Other(e)) => { + Err(HiffyError::Hiffy(s)) => Err(s), + Err(HiffyError::Other(e)) => { return Err(e.context("power state check")); } }; diff --git a/humility-auxflash/src/lib.rs b/humility-auxflash/src/lib.rs index 2fb340148..94529eef0 100644 --- a/humility-auxflash/src/lib.rs +++ b/humility-auxflash/src/lib.rs @@ -6,7 +6,7 @@ use indicatif::{ProgressBar, ProgressStyle}; use humility::core::Core; use humility::hubris::*; -use humility_hiffy::{HiffyCallError, HiffyContext}; +use humility_hiffy::{HiffyContext, HiffyError}; use humility_idol::{HubrisIdol, IdolArgument}; use std::time::Duration; @@ -72,7 +72,7 @@ impl<'a> AuxFlashHandler<'a> { ); match value { Ok(v) => Ok(Some(v)), - Err(HiffyCallError::Hiffy(s)) if s == "NoActiveSlot" => Ok(None), + Err(HiffyError::Hiffy(s)) if s == "NoActiveSlot" => Ok(None), Err(e) => Err(e.into()), } } @@ -109,7 +109,7 @@ impl<'a> AuxFlashHandler<'a> { ); match value { Ok(v) => Ok(Some(v.0)), - Err(HiffyCallError::Hiffy(e)) if e == "MissingChck" => Ok(None), + Err(HiffyError::Hiffy(e)) if e == "MissingChck" => Ok(None), Err(e) => Err(e.into()), } } diff --git a/humility-hiffy/src/lib.rs b/humility-hiffy/src/lib.rs index d3589aad2..ac716dbf2 100644 --- a/humility-hiffy/src/lib.rs +++ b/humility-hiffy/src/lib.rs @@ -1440,7 +1440,7 @@ fn has_task_started( /// Error returned from [`hiffy_call`] #[derive(thiserror::Error, Debug)] -pub enum HiffyCallError { +pub enum HiffyError { /// A function called in the HIF program returned an error #[error("hiffy error: {0}")] Hiffy(String), @@ -1458,7 +1458,7 @@ pub fn hiffy_call( args: &[(&str, idol::IdolArgument)], lease_write: Option<&[u8]>, lease_read: Option<&mut [u8]>, -) -> Result { +) -> Result { check_op(op)?; check_leases(op, lease_write, lease_read.as_deref())?; @@ -1496,7 +1496,7 @@ pub fn hiffy_call( let mut results = context.run(core, ops.as_slice(), lease_write)?; if results.len() != 1 { - return Err(HiffyCallError::Other(anyhow!( + return Err(HiffyError::Other(anyhow!( "unexpected results length: {:?}", results ))); @@ -1506,7 +1506,7 @@ pub fn hiffy_call( // If this is a Read operation, steal extra data from the returned stack // and copy it into the incoming 'read' argument - let out = match lease_read { + match lease_read { Some(data) => { let ok_size = op.reply_size()?; if let Ok(v) = v.as_mut() { @@ -1514,11 +1514,10 @@ pub fn hiffy_call( data.copy_from_slice(&extra_data); } // Shoehorn that extra data in, assuming decoding worked. - hiffy_decode(hubris, op, v)? + hiffy_decode(hubris, op, v) } - _ => hiffy_decode(hubris, op, v)?, - }; - out.map_err(HiffyCallError::Hiffy) + _ => hiffy_decode(hubris, op, v), + } } /// Decodes a value returned from [hiffy_call] or equivalent. @@ -1529,7 +1528,7 @@ pub fn hiffy_decode( hubris: &HubrisArchive, op: &idol::IdolOperation, val: Result, impl Into>, -) -> Result> { +) -> Result { let r = match val.map_err(Into::into) { Ok(val) => { let ty = hubris.lookup_type(op.ok).unwrap(); @@ -1565,7 +1564,7 @@ pub fn hiffy_decode( }, Err(dead @ IpcError::ServerDied(_)) => Err(format!("<{dead}>")), }; - Ok(r) + r.map_err(HiffyError::Hiffy) } pub fn hiffy_format_result( From bccc5309133d80362bdea22d46ccc71f526134ee Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Wed, 13 May 2026 11:15:31 -0700 Subject: [PATCH 4/9] Dispatch on an `enum Subcommand` --- Cargo.lock | 50 +------------- Cargo.toml | 1 + cmd/auxflash/Cargo.toml | 1 - cmd/auxflash/src/lib.rs | 20 +++--- cmd/console-proxy/Cargo.toml | 1 - cmd/console-proxy/src/lib.rs | 18 +++-- cmd/console-proxy/src/posix.rs | 7 +- cmd/counters/Cargo.toml | 1 - cmd/counters/src/lib.rs | 20 +++--- cmd/dashboard/Cargo.toml | 1 - cmd/dashboard/src/lib.rs | 24 ++++--- cmd/debugmailbox/Cargo.toml | 1 - cmd/debugmailbox/src/lib.rs | 23 ++++--- cmd/diagnose/Cargo.toml | 1 - cmd/diagnose/src/lib.rs | 25 +++---- cmd/discover/Cargo.toml | 1 - cmd/discover/src/lib.rs | 22 +++---- cmd/doc/Cargo.toml | 1 - cmd/doc/src/lib.rs | 18 ++--- cmd/dump/Cargo.toml | 1 - cmd/dump/src/lib.rs | 17 ++--- cmd/ereport/Cargo.toml | 1 - cmd/ereport/src/lib.rs | 17 ++--- cmd/exec/Cargo.toml | 1 - cmd/exec/src/lib.rs | 17 ++--- cmd/extract/Cargo.toml | 1 - cmd/extract/src/lib.rs | 17 ++--- cmd/flash/Cargo.toml | 1 - cmd/flash/src/lib.rs | 21 +++--- cmd/gimlet/src/lib.rs | 17 ++--- cmd/gpio/Cargo.toml | 1 - cmd/gpio/src/lib.rs | 17 ++--- cmd/hash/Cargo.toml | 1 - cmd/hash/src/lib.rs | 17 ++--- cmd/hiffy/src/lib.rs | 18 ++--- cmd/host/Cargo.toml | 3 +- cmd/host/src/lib.rs | 17 ++--- cmd/hydrate/Cargo.toml | 1 - cmd/hydrate/src/lib.rs | 16 ++--- cmd/i2c/src/lib.rs | 16 +++-- cmd/ibc/src/lib.rs | 17 ++--- cmd/jefe/Cargo.toml | 1 - cmd/jefe/src/lib.rs | 17 ++--- cmd/lpc55gpio/src/lib.rs | 17 ++--- cmd/lsusb/Cargo.toml | 1 - cmd/lsusb/src/lib.rs | 16 ++--- cmd/manifest/Cargo.toml | 1 - cmd/manifest/src/lib.rs | 21 +++--- cmd/map/Cargo.toml | 1 - cmd/map/src/lib.rs | 16 +++-- cmd/monorail/Cargo.toml | 1 - cmd/monorail/src/lib.rs | 22 +++---- cmd/mwocp/Cargo.toml | 1 - cmd/mwocp/src/lib.rs | 17 ++--- cmd/net/Cargo.toml | 1 - cmd/net/src/lib.rs | 20 +++--- cmd/pmbus/Cargo.toml | 1 - cmd/pmbus/src/lib.rs | 17 ++--- cmd/power/Cargo.toml | 1 - cmd/power/src/lib.rs | 17 ++--- cmd/powershelf/Cargo.toml | 1 - cmd/powershelf/src/lib.rs | 22 +++---- cmd/probe/Cargo.toml | 1 - cmd/probe/src/lib.rs | 17 ++--- cmd/qspi/src/lib.rs | 18 ++--- cmd/readmem/src/lib.rs | 18 ++--- cmd/readvar/Cargo.toml | 1 - cmd/readvar/src/lib.rs | 17 ++--- cmd/rebootleby/Cargo.toml | 1 - cmd/rebootleby/src/lib.rs | 21 +++--- cmd/registers/Cargo.toml | 1 - cmd/registers/src/lib.rs | 20 +++--- cmd/rencm/src/lib.rs | 18 ++--- cmd/rendmp/Cargo.toml | 1 - cmd/rendmp/src/lib.rs | 17 ++--- cmd/reset/Cargo.toml | 1 - cmd/reset/src/lib.rs | 17 ++--- cmd/ringbuf/Cargo.toml | 1 - cmd/ringbuf/src/lib.rs | 17 ++--- cmd/sbrmi/Cargo.toml | 1 - cmd/sbrmi/src/lib.rs | 17 ++--- cmd/sensors/Cargo.toml | 1 - cmd/sensors/src/lib.rs | 17 ++--- cmd/spctrl/src/lib.rs | 18 ++--- cmd/spd/Cargo.toml | 1 - cmd/spd/src/lib.rs | 17 ++--- cmd/spi/src/lib.rs | 18 ++--- cmd/stackmargin/src/lib.rs | 22 +++---- cmd/stmsecure/Cargo.toml | 1 - cmd/stmsecure/src/lib.rs | 46 ++++++++----- cmd/tasks/Cargo.toml | 1 - cmd/tasks/src/lib.rs | 17 ++--- cmd/test/Cargo.toml | 1 - cmd/test/src/lib.rs | 17 ++--- cmd/tofino-eeprom/Cargo.toml | 1 - cmd/tofino-eeprom/src/lib.rs | 17 ++--- cmd/validate/Cargo.toml | 1 - cmd/validate/src/lib.rs | 20 +++--- cmd/vpd/src/lib.rs | 18 ++--- cmd/writeword/Cargo.toml | 1 - cmd/writeword/src/lib.rs | 20 +++--- humility-bin/Cargo.toml | 4 +- humility-bin/build.rs | 82 ++++++++++++++++------- humility-bin/src/cmd.rs | 47 +------------ humility-bin/src/main.rs | 116 +++++++++++++++------------------ humility-cli/src/lib.rs | 21 ++---- humility-cmd/Cargo.toml | 7 -- humility-cmd/src/lib.rs | 15 ----- 108 files changed, 689 insertions(+), 746 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c31baa86f..b65aa0219 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1636,6 +1636,7 @@ dependencies = [ "colored", "csv", "env_logger", + "heck", "hif", "humility-cli", "humility-cmd", @@ -1731,12 +1732,6 @@ dependencies = [ [[package]] name = "humility-cmd" version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "humility-cli", - "humility-core", -] [[package]] name = "humility-cmd-auxflash" @@ -1748,7 +1743,6 @@ dependencies = [ "hif", "humility-auxflash", "humility-cli", - "humility-cmd", "humility-core", "idol", "log", @@ -1764,7 +1758,6 @@ dependencies = [ "clap", "crossbeam-channel", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -1780,7 +1773,6 @@ dependencies = [ "clap", "colored", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", "indexmap 2.14.0", @@ -1797,7 +1789,6 @@ dependencies = [ "crossterm 0.29.0", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -1814,7 +1805,6 @@ dependencies = [ "byteorder", "clap", "humility-cli", - "humility-cmd", "humility-cortex", "parse_int", "probe-rs", @@ -1827,7 +1817,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", "humility-jefe", @@ -1843,7 +1832,6 @@ dependencies = [ "colored", "hubpack", "humility-cli", - "humility-cmd", "humility-core", "parse_int", "serde", @@ -1858,7 +1846,6 @@ dependencies = [ "cargo_metadata", "clap", "humility-cli", - "humility-cmd", "termimad 0.34.1", ] @@ -1872,7 +1859,6 @@ dependencies = [ "hubpack", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "humility-dump-agent", "humpty", @@ -1895,7 +1881,6 @@ dependencies = [ "clap", "hex", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", "serde", @@ -1910,7 +1895,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-log", "serde_json", "splitty", @@ -1923,7 +1907,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-log", "zip", ] @@ -1937,7 +1920,6 @@ dependencies = [ "goblin", "humility-auxflash", "humility-cli", - "humility-cmd", "humility-core", "humility-cortex", "humility-probes-core", @@ -1976,7 +1958,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-hiffy", "parse_int", ] @@ -1989,7 +1970,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "indicatif", @@ -2023,7 +2003,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", "humility-hiffy", @@ -2043,7 +2022,6 @@ dependencies = [ "hubpack", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "humility-log", "humpty", @@ -2097,7 +2075,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "humility-jefe", "parse_int", @@ -2123,7 +2100,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "rusb", ] @@ -2135,7 +2111,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "serde_json", ] @@ -2147,7 +2122,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", ] @@ -2160,7 +2134,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -2181,7 +2154,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-i2c", @@ -2204,7 +2176,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -2220,7 +2191,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-i2c", @@ -2239,7 +2209,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -2257,7 +2226,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -2276,7 +2244,6 @@ dependencies = [ "clap", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "humility-cortex", "num-traits", @@ -2321,7 +2288,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", ] @@ -2333,7 +2299,6 @@ dependencies = [ "clap", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "humility-cortex", "ihex", @@ -2352,7 +2317,6 @@ dependencies = [ "clap", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "humility-cortex", "humility-stack", @@ -2388,7 +2352,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-i2c", @@ -2412,7 +2375,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "humility-probes-core", ] @@ -2424,7 +2386,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", ] @@ -2438,7 +2399,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -2456,7 +2416,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", "humility-hiffy", @@ -2487,7 +2446,6 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-i2c", @@ -2531,7 +2489,6 @@ dependencies = [ "clap", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "parse_int", ] @@ -2544,7 +2501,6 @@ dependencies = [ "clap", "humility-arch-arm", "humility-cli", - "humility-cmd", "humility-core", "humility-doppel", "humility-stack", @@ -2562,7 +2518,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-cmd-tasks", "humility-core", "humility-cortex", @@ -2577,7 +2532,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-idol", @@ -2594,7 +2548,6 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", "humility-hiffy", "humility-i2c", @@ -2633,7 +2586,6 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", "parse-size", "parse_int", diff --git a/Cargo.toml b/Cargo.toml index 5ce4297f9..b82bac501 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -205,6 +205,7 @@ ctrlc = "3.1.5" env_logger = "0.11.10" gimli = "0.33.0" goblin = "0.10" +heck = "0.5" hex = "0.4.3" hubpack = "0.1.1" ihex = "3.0" diff --git a/cmd/auxflash/Cargo.toml b/cmd/auxflash/Cargo.toml index 90738c23f..bd7cec17f 100644 --- a/cmd/auxflash/Cargo.toml +++ b/cmd/auxflash/Cargo.toml @@ -17,5 +17,4 @@ parse_int.workspace = true humility.workspace = true humility-auxflash.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true diff --git a/cmd/auxflash/src/lib.rs b/cmd/auxflash/src/lib.rs index b17fa824e..54f7c8c89 100644 --- a/cmd/auxflash/src/lib.rs +++ b/cmd/auxflash/src/lib.rs @@ -10,16 +10,15 @@ //! program auxiliary flash when needed. use anyhow::Result; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; -use humility_cli::ExecutionContext; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_auxflash::AuxFlashHandler; -use humility_cmd::Command; #[derive(Parser, Debug)] #[clap(name = "auxflash", about = env!("CARGO_PKG_DESCRIPTION"))] -struct AuxFlashArgs { +pub struct AuxFlashArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 15000, value_name = "timeout_ms", @@ -97,8 +96,10 @@ fn auxflash_status(mut worker: AuxFlashHandler, verbose: bool) -> Result<()> { Ok(()) } -fn auxflash(context: &mut ExecutionContext) -> Result<()> { - let subargs = AuxFlashArgs::try_parse_from(&context.cli.cmd)?; +fn auxflash( + subargs: AuxFlashArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let timeout = std::time::Duration::from_millis(subargs.timeout); @@ -131,6 +132,9 @@ fn auxflash(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: AuxFlashArgs::command(), name: "auxflash", run: auxflash } +pub type Args = AuxFlashArgs; +impl HumilitySubcommand for AuxFlashArgs { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + auxflash(args, context) + } } diff --git a/cmd/console-proxy/Cargo.toml b/cmd/console-proxy/Cargo.toml index cc9e6f0f1..4d039897a 100644 --- a/cmd/console-proxy/Cargo.toml +++ b/cmd/console-proxy/Cargo.toml @@ -11,7 +11,6 @@ crossbeam-channel.workspace = true parse_int.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/console-proxy/src/lib.rs b/cmd/console-proxy/src/lib.rs index 3ed4e3cf6..4fbc2d975 100644 --- a/cmd/console-proxy/src/lib.rs +++ b/cmd/console-proxy/src/lib.rs @@ -6,12 +6,10 @@ //! //! Act as a proxy for the host serial console when it is jumpered to the SP. +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use std::path::PathBuf; -use clap::{CommandFactory, Parser}; - -use humility_cmd::Command; - #[cfg(not(windows))] mod posix; @@ -20,6 +18,7 @@ use posix::console_proxy; #[cfg(windows)] fn console_proxy( + _args: UartConsoleArgs, _context: &mut humility_cli::ExecutionContext, ) -> anyhow::Result<()> { anyhow::bail!("the console-proxy subcommand is not available on Windows") @@ -27,7 +26,7 @@ fn console_proxy( #[derive(Parser, Debug)] #[clap(name = "console-proxy", about = env!("CARGO_PKG_DESCRIPTION"))] -struct UartConsoleArgs { +pub struct UartConsoleArgs { #[clap( long, short = 'T', @@ -108,10 +107,9 @@ enum UartConsoleCommand { Client, } -pub fn init() -> Command { - Command { - app: UartConsoleArgs::command(), - name: "console-proxy", - run: console_proxy, +pub type Args = UartConsoleArgs; +impl HumilitySubcommand for UartConsoleArgs { + fn run(args: Args, context: &mut ExecutionContext) -> anyhow::Result<()> { + console_proxy(args, context) } } diff --git a/cmd/console-proxy/src/posix.rs b/cmd/console-proxy/src/posix.rs index 2f8322569..9ccd76e0e 100644 --- a/cmd/console-proxy/src/posix.rs +++ b/cmd/console-proxy/src/posix.rs @@ -11,7 +11,6 @@ use std::time::Duration; use std::{io, thread}; use anyhow::{Context, Result}; -use clap::Parser; use crossbeam_channel::{Sender, select}; use picocom_map::RemapRules; use termios::Termios; @@ -279,8 +278,10 @@ impl UnrawTermiosGuard { } } -pub(super) fn console_proxy(context: &mut ExecutionContext) -> Result<()> { - let subargs = UartConsoleArgs::try_parse_from(&context.cli.cmd)?; +pub(super) fn console_proxy( + subargs: UartConsoleArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let hiffy_timeout = Duration::from_millis(subargs.hiffy_timeout); diff --git a/cmd/counters/Cargo.toml b/cmd/counters/Cargo.toml index be71743cb..f2d6b31bc 100644 --- a/cmd/counters/Cargo.toml +++ b/cmd/counters/Cargo.toml @@ -14,5 +14,4 @@ serde_json = { workspace = true } humility = { workspace = true } humility-doppel = { workspace = true, features = ["serde"] } -humility-cmd = { workspace = true } humility-cli = { workspace = true } diff --git a/cmd/counters/src/lib.rs b/cmd/counters/src/lib.rs index 55f6c1554..e6f9e899a 100644 --- a/cmd/counters/src/lib.rs +++ b/cmd/counters/src/lib.rs @@ -200,13 +200,12 @@ //! show only the calls to specific IPC interfaces from specific tasks. use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser, ValueEnum}; +use clap::{Parser, ValueEnum}; use colored::Colorize; use humility::core::Core; use humility::hubris::*; use humility::reflect::{self, Load, Value}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_doppel::{CountedRingbuf, CounterVariant, Counters}; use indexmap::IndexMap; use std::collections::BTreeMap; @@ -218,7 +217,7 @@ mod ipc; // This attribute means that any the args defined in `Options` will conflict // with the `list` subcommand. #[clap(args_conflicts_with_subcommands = true)] -struct CountersArgs { +pub struct CountersArgs { #[clap(subcommand)] command: Option, @@ -323,9 +322,11 @@ enum Output { const LIST_HINT: &str = "use `humility counters list` to list all \ available counters"; -fn counters(context: &mut ExecutionContext) -> Result<()> { +fn counters( + subargs: CountersArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; - let subargs = CountersArgs::try_parse_from(&context.cli.cmd)?; if let Some(Subcmd::Ipc(ipc)) = subargs.command { let core = &mut *context.cli.attach_live_or_dump_match(hubris)?; @@ -622,6 +623,9 @@ fn hint() -> impl std::fmt::Display { "hint:".bold() } -pub fn init() -> Command { - Command { app: CountersArgs::command(), name: "counters", run: counters } +pub type Args = CountersArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + counters(args, context) + } } diff --git a/cmd/dashboard/Cargo.toml b/cmd/dashboard/Cargo.toml index 5970dd82d..a807cb4fd 100644 --- a/cmd/dashboard/Cargo.toml +++ b/cmd/dashboard/Cargo.toml @@ -14,7 +14,6 @@ crossterm.workspace = true ratatui.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/dashboard/src/lib.rs b/cmd/dashboard/src/lib.rs index 97fbe5457..5e24e1aea 100644 --- a/cmd/dashboard/src/lib.rs +++ b/cmd/dashboard/src/lib.rs @@ -13,7 +13,7 @@ //! use anyhow::{Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use crossterm::{ event::{ self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, @@ -28,8 +28,7 @@ use crossterm::{ use hif::*; use humility::core::Core; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; use ratatui::{ @@ -51,7 +50,7 @@ use std::time::{Duration, Instant}; #[derive(Parser, Debug)] #[clap(name = "dashboard", about = env!("CARGO_PKG_DESCRIPTION"))] -struct DashboardArgs { +pub struct DashboardArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -736,8 +735,10 @@ where } } -fn dashboard(context: &mut ExecutionContext) -> Result<()> { - let subargs = DashboardArgs::try_parse_from(&context.cli.cmd)?; +fn dashboard( + subargs: DashboardArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -766,10 +767,6 @@ fn dashboard(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: DashboardArgs::command(), name: "dashboard", run: dashboard } -} - fn sensor_ops( hubris: &HubrisArchive, context: &mut HiffyContext, @@ -1086,3 +1083,10 @@ fn draw(f: &mut Frame, dashboard: &mut Dashboard) { draw_graphs(f, screen[0], dashboard); draw_status(f, screen[1], &dashboard.status()); } + +pub type Args = DashboardArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + dashboard(args, context) + } +} diff --git a/cmd/debugmailbox/Cargo.toml b/cmd/debugmailbox/Cargo.toml index a485a477c..2fd66f775 100644 --- a/cmd/debugmailbox/Cargo.toml +++ b/cmd/debugmailbox/Cargo.toml @@ -12,5 +12,4 @@ parse_int.workspace = true probe-rs.workspace = true humility-cortex.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true diff --git a/cmd/debugmailbox/src/lib.rs b/cmd/debugmailbox/src/lib.rs index 6de6a9011..3533efa9f 100644 --- a/cmd/debugmailbox/src/lib.rs +++ b/cmd/debugmailbox/src/lib.rs @@ -30,9 +30,8 @@ use std::{ use anyhow::{Context, Result, bail}; use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use probe_rs::{ DebugProbeError, DebugProbeSelector, Probe, architecture::arm::{ApAddress, ArmProbeInterface, DapError, DpAddress}, @@ -265,9 +264,10 @@ fn read_return<'a>( .context("Reading debugmailbox RETURN register") } -fn debugmailboxcmd(context: &mut ExecutionContext) -> Result<()> { - let subargs = DebugMailboxArgs::try_parse_from(&context.cli.cmd)?; - +fn debugmailboxcmd( + subargs: DebugMailboxArgs, + context: &mut ExecutionContext, +) -> Result<()> { // Get a list of all available debug probes. let probes = Probe::list_all(); @@ -454,15 +454,14 @@ fn debugmailboxcmd(context: &mut ExecutionContext) -> Result<()> { } #[derive(Parser, Debug)] #[clap(name = "debugmailbox", about = env!("CARGO_PKG_DESCRIPTION"))] -struct DebugMailboxArgs { +pub struct DebugMailboxArgs { #[clap(subcommand)] cmd: DebugMailboxCmd, } -pub fn init() -> Command { - Command { - app: DebugMailboxArgs::command(), - name: "debugmailbox", - run: debugmailboxcmd, +pub type Args = DebugMailboxArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + debugmailboxcmd(args, context) } } diff --git a/cmd/diagnose/Cargo.toml b/cmd/diagnose/Cargo.toml index 734262d11..bb666c421 100644 --- a/cmd/diagnose/Cargo.toml +++ b/cmd/diagnose/Cargo.toml @@ -10,7 +10,6 @@ anyhow.workspace = true parse_int.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-doppel.workspace = true humility-jefe.workspace = true diff --git a/cmd/diagnose/src/lib.rs b/cmd/diagnose/src/lib.rs index fc2f7ccfa..7a090391a 100644 --- a/cmd/diagnose/src/lib.rs +++ b/cmd/diagnose/src/lib.rs @@ -15,23 +15,17 @@ //! at the OS level, like faults. use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::core::Core; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_doppel::{GenOrRestartCount, Task, TaskDesc, TaskState}; use std::num::NonZeroU32; use std::time::Duration; -/// Command registration. -pub fn init() -> Command { - Command { app: DiagnoseArgs::command(), name: "diagnose", run: diagnose } -} - #[derive(Parser, Debug)] #[clap(name = "diagnose", about = env!("CARGO_PKG_DESCRIPTION"))] -struct DiagnoseArgs { +pub struct DiagnoseArgs { /// timeout to wait for interactions with the supervisor task to complete #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -72,8 +66,10 @@ fn section(title: &str) { println!("\n--- {} ---\n", title); } -fn diagnose(context: &mut ExecutionContext) -> Result<()> { - let subargs = DiagnoseArgs::try_parse_from(&context.cli.cmd)?; +fn diagnose( + subargs: DiagnoseArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_or_dump_booted(hubris)?; @@ -381,3 +377,10 @@ fn find_task_names<'a>( }) .collect()) } + +pub type Args = DiagnoseArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + diagnose(args, context) + } +} diff --git a/cmd/discover/Cargo.toml b/cmd/discover/Cargo.toml index ee7b54bc1..38fb4134d 100644 --- a/cmd/discover/Cargo.toml +++ b/cmd/discover/Cargo.toml @@ -6,7 +6,6 @@ description = "listen for compatible SPs on a network" [dependencies] humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true hubpack.workspace = true diff --git a/cmd/discover/src/lib.rs b/cmd/discover/src/lib.rs index 8d981ba51..e1f116d1b 100644 --- a/cmd/discover/src/lib.rs +++ b/cmd/discover/src/lib.rs @@ -40,12 +40,11 @@ use std::net::{IpAddr, Ipv6Addr, UdpSocket}; use std::time::{Duration, Instant}; use anyhow::{Result, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use colored::Colorize; use hubpack::SerializedSize; use humility::net::decode_iface; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use serde::{Deserialize, Serialize}; #[derive(Parser, Debug)] @@ -53,7 +52,7 @@ use serde::{Deserialize, Serialize}; name = "discover", about = env!("CARGO_PKG_DESCRIPTION"), group = ArgGroup::new("target").multiple(false) )] -struct DiscoverArgs { +pub struct DiscoverArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 2000, value_name = "timeout_ms", @@ -311,8 +310,10 @@ fn discover_dump(seen: BTreeSet, image_id: Option<&[u8]>) { } } -fn discover_run(context: &mut ExecutionContext) -> Result<()> { - let subargs = DiscoverArgs::try_parse_from(&context.cli.cmd)?; +fn discover_run( + subargs: DiscoverArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.try_archive()?; let image_id = hubris.as_ref().map(|h| h.image_id()); @@ -325,10 +326,9 @@ fn discover_run(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { - app: DiscoverArgs::command(), - name: "discover", - run: discover_run, +pub type Args = DiscoverArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + discover_run(args, context) } } diff --git a/cmd/doc/Cargo.toml b/cmd/doc/Cargo.toml index 341ec551a..a7a29d1d6 100644 --- a/cmd/doc/Cargo.toml +++ b/cmd/doc/Cargo.toml @@ -10,7 +10,6 @@ cargo-readme = { workspace = true } anyhow = { workspace = true } [dependencies] -humility-cmd = { workspace = true } humility-cli = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/doc/src/lib.rs b/cmd/doc/src/lib.rs index 7a5982d61..0e23f51ca 100644 --- a/cmd/doc/src/lib.rs +++ b/cmd/doc/src/lib.rs @@ -11,9 +11,8 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use std::collections::HashMap; use termimad::*; @@ -21,15 +20,13 @@ include!(concat!(env!("OUT_DIR"), "/docs.rs")); #[derive(Parser, Debug)] #[clap(name = "doc", about = env!("CARGO_PKG_DESCRIPTION"))] -struct DocArgs { +pub struct DocArgs { /// Humility command for which to get documentation #[clap(value_name = "command")] command: Option, } -fn doc(context: &mut ExecutionContext) -> Result<()> { - let subargs = DocArgs::try_parse_from(&context.cli.cmd)?; - +fn doc(subargs: DocArgs, _context: &mut ExecutionContext) -> Result<()> { let text = match subargs.command { Some(ref cmd) => match cmd_docs(cmd) { Some(text) => text, @@ -63,6 +60,9 @@ fn doc(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: DocArgs::command(), name: "doc", run: doc } +pub type Args = DocArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + doc(args, context) + } } diff --git a/cmd/dump/Cargo.toml b/cmd/dump/Cargo.toml index 3e601dcd2..a99a6a2e7 100644 --- a/cmd/dump/Cargo.toml +++ b/cmd/dump/Cargo.toml @@ -20,7 +20,6 @@ zerocopy.workspace = true zip.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-dump-agent.workspace = true humility-arch-arm.workspace = true diff --git a/cmd/dump/src/lib.rs b/cmd/dump/src/lib.rs index 20d876548..1704d5e3e 100644 --- a/cmd/dump/src/lib.rs +++ b/cmd/dump/src/lib.rs @@ -66,12 +66,11 @@ //! use anyhow::{Result, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use humility::core::Core; use humility::hubris::*; use humility_arch_arm::ARMRegister; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_dump_agent::{ DumpAgent, DumpAgentCore, DumpAgentExt, DumpArea, DumpBreakdown, HiffyDumpAgent, UdpDumpAgent, task_areas, @@ -89,7 +88,7 @@ use std::time::Instant; group = ArgGroup::new("simulation").multiple(false) .required(false).requires("force_dump_agent") )] -struct DumpArgs { +pub struct DumpArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 20000, value_name = "timeout_ms", @@ -851,8 +850,7 @@ fn dump_agent_status( Ok(()) } -fn dumpcmd(context: &mut ExecutionContext) -> Result<()> { - let subargs = DumpArgs::try_parse_from(&context.cli.cmd)?; +fn dumpcmd(subargs: DumpArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_match(hubris)?; @@ -898,6 +896,9 @@ fn dumpcmd(context: &mut ExecutionContext) -> Result<()> { } } -pub fn init() -> Command { - Command { app: DumpArgs::command(), name: "dump", run: dumpcmd } +pub type Args = DumpArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + dumpcmd(args, context) + } } diff --git a/cmd/ereport/Cargo.toml b/cmd/ereport/Cargo.toml index 5039d9d03..9cea9069f 100644 --- a/cmd/ereport/Cargo.toml +++ b/cmd/ereport/Cargo.toml @@ -14,6 +14,5 @@ serde_json.workspace = true zerocopy.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-doppel.workspace = true diff --git a/cmd/ereport/src/lib.rs b/cmd/ereport/src/lib.rs index fa145d074..96e70de0e 100644 --- a/cmd/ereport/src/lib.rs +++ b/cmd/ereport/src/lib.rs @@ -10,18 +10,17 @@ use humility::{ core::Core, hubris::{HubrisArchive, HubrisTask}, }; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use anyhow::{Context, Result, anyhow}; use std::collections::VecDeque; use zerocopy::{FromBytes, Immutable, KnownLayout}; -use clap::{CommandFactory, Parser}; +use clap::Parser; #[derive(Parser, Debug)] #[clap(name = "ereport", about = env!("CARGO_PKG_DESCRIPTION"))] -struct EreportArgs { +pub struct EreportArgs { #[clap(subcommand)] cmd: EreportCmd, } @@ -336,8 +335,7 @@ fn pretty_print_value(value: &ciborium::Value, indent: usize, is_key: bool) { } } -fn ereport(context: &mut ExecutionContext) -> Result<()> { - let subargs = EreportArgs::try_parse_from(&context.cli.cmd)?; +fn ereport(subargs: EreportArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_or_dump_booted(hubris)?; @@ -346,6 +344,9 @@ fn ereport(context: &mut ExecutionContext) -> Result<()> { } } -pub fn init() -> Command { - Command { app: EreportArgs::command(), name: "ereport", run: ereport } +pub type Args = EreportArgs; +impl HumilitySubcommand for Args { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()> { + ereport(args, context) + } } diff --git a/cmd/exec/Cargo.toml b/cmd/exec/Cargo.toml index d826660b0..b7d4ad1eb 100644 --- a/cmd/exec/Cargo.toml +++ b/cmd/exec/Cargo.toml @@ -11,5 +11,4 @@ splitty.workspace = true serde_json.workspace = true humility-log.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true diff --git a/cmd/exec/src/lib.rs b/cmd/exec/src/lib.rs index a237a50b9..cf8176f82 100644 --- a/cmd/exec/src/lib.rs +++ b/cmd/exec/src/lib.rs @@ -22,16 +22,15 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_log::msg; use serde_json::Value; use std::collections::BTreeMap; #[derive(Parser, Debug)] #[clap(name = "exec", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ExecArgs { +pub struct ExecArgs { /// list possible commands #[clap(long, short)] list: bool, @@ -71,8 +70,7 @@ fn load_cmds<'a>( Ok(()) } -fn exec(context: &mut ExecutionContext) -> Result<()> { - let subargs = ExecArgs::try_parse_from(&context.cli.cmd)?; +fn exec(subargs: ExecArgs, context: &mut ExecutionContext) -> Result<()> { let env = context.environment.as_ref(); let env = match env { @@ -142,6 +140,9 @@ fn exec(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ExecArgs::command(), name: "exec", run: exec } +pub type Args = ExecArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + exec(args, context) + } } diff --git a/cmd/extract/Cargo.toml b/cmd/extract/Cargo.toml index 9cf92747e..5fb9c1c93 100644 --- a/cmd/extract/Cargo.toml +++ b/cmd/extract/Cargo.toml @@ -10,5 +10,4 @@ clap.workspace = true zip.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-log.workspace = true diff --git a/cmd/extract/src/lib.rs b/cmd/extract/src/lib.rs index 96ca5a990..7b3bf49ba 100644 --- a/cmd/extract/src/lib.rs +++ b/cmd/extract/src/lib.rs @@ -130,9 +130,8 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_log::msg; use std::fs::File; use std::io::Cursor; @@ -140,7 +139,7 @@ use std::io::{self, Read, Write}; #[derive(Parser, Debug)] #[clap(name = "extract", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ExtractArgs { +pub struct ExtractArgs { /// list contents #[clap(long, short)] list: bool, @@ -153,8 +152,7 @@ struct ExtractArgs { file: Option, } -fn extract(context: &mut ExecutionContext) -> Result<()> { - let subargs = ExtractArgs::try_parse_from(&context.cli.cmd)?; +fn extract(subargs: ExtractArgs, context: &mut ExecutionContext) -> Result<()> { let archive = context.cli.raw_archive()?; if subargs.list { @@ -235,6 +233,9 @@ fn extract(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ExtractArgs::command(), name: "extract", run: extract } +pub type Args = ExtractArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + extract(args, context) + } } diff --git a/cmd/flash/Cargo.toml b/cmd/flash/Cargo.toml index 5be8ddc1e..1163fb1cf 100644 --- a/cmd/flash/Cargo.toml +++ b/cmd/flash/Cargo.toml @@ -7,7 +7,6 @@ description = "flash archive onto attached device" [dependencies] humility = { workspace = true } humility-cortex = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } humility-probes-core = { workspace = true } humility-auxflash = { workspace = true } diff --git a/cmd/flash/src/lib.rs b/cmd/flash/src/lib.rs index 125eabd16..eae522f39 100644 --- a/cmd/flash/src/lib.rs +++ b/cmd/flash/src/lib.rs @@ -20,15 +20,14 @@ //! information about auxiliary flash management. use anyhow::{Context, Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::{core::Core, hubris::*}; use humility_auxflash::AuxFlashHandler; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; #[derive(Parser, Debug)] #[clap(name = "flash", about = env!("CARGO_PKG_DESCRIPTION"))] -struct FlashArgs { +pub struct FlashArgs { /// force re-flashing if archive matches #[clap(long, short = 'F')] force: bool, @@ -192,9 +191,8 @@ fn get_image_state( } } -fn flashcmd(context: &mut ExecutionContext) -> Result<()> { +fn flashcmd(subargs: FlashArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; - let subargs = FlashArgs::try_parse_from(&context.cli.cmd)?; let config = hubris.load_flash_config()?; @@ -352,10 +350,6 @@ fn program_auxflash( } } -pub fn init() -> Command { - Command { app: FlashArgs::command(), name: "flash", run: flashcmd } -} - /// While it may sound like the impetus for an OSHA investigation at the North /// Pole, this function is _actually_ designed to generate small (32-byte) /// chunks describing the data in the PHDRs of an ELF file. Unless the file is @@ -421,3 +415,10 @@ fn generate_ihex_from_elf(data: &[u8]) -> Result { Ok(ihex::create_object_file_representation(&records)?) } + +pub type Args = FlashArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + flashcmd(args, context) + } +} diff --git a/cmd/gimlet/src/lib.rs b/cmd/gimlet/src/lib.rs index 16ace5f58..940ac577e 100644 --- a/cmd/gimlet/src/lib.rs +++ b/cmd/gimlet/src/lib.rs @@ -17,10 +17,10 @@ use std::net::{SocketAddrV6, UdpSocket}; use std::time::Duration; use anyhow::{Context, Result, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use humility::net::ScopedV6Addr; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; /// This is defined in the gimlet TOML. const HARDCODED_PORT: u16 = 23547; @@ -30,7 +30,7 @@ const HARDCODED_PORT: u16 = 23547; name = "gimlet", about = env!("CARGO_PKG_DESCRIPTION"), group = ArgGroup::new("target").multiple(false) )] -struct Args { +pub struct Args { /// How long to wait for a response from the target, in milliseconds. #[clap( long, short = 'T', default_value_t = 2000, value_name = "ms", @@ -101,7 +101,7 @@ impl Client { } } -fn run(context: &mut ExecutionContext) -> Result<()> { +fn run(subargs: Args, context: &mut ExecutionContext) -> Result<()> { let ip = context .cli .ip @@ -113,7 +113,6 @@ fn run(context: &mut ExecutionContext) -> Result<()> { "the `--ip ` argument is required with `humility gimlet`" ) })?; - let subargs = Args::try_parse_from(&context.cli.cmd)?; let mut client = Client::new(ip, subargs.port, Duration::from_millis(subargs.timeout))?; @@ -132,6 +131,8 @@ fn run(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: Args::command(), name: "gimlet", run } +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + run(args, context) + } } diff --git a/cmd/gpio/Cargo.toml b/cmd/gpio/Cargo.toml index 24a585095..0e4ddd660 100644 --- a/cmd/gpio/Cargo.toml +++ b/cmd/gpio/Cargo.toml @@ -11,5 +11,4 @@ anyhow.workspace = true parse_int.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-hiffy.workspace = true diff --git a/cmd/gpio/src/lib.rs b/cmd/gpio/src/lib.rs index 0d25cd02a..6b0c97518 100644 --- a/cmd/gpio/src/lib.rs +++ b/cmd/gpio/src/lib.rs @@ -92,20 +92,19 @@ //! ``` //! -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::HiffyContext; use std::str; use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use std::convert::TryInto; #[derive(Parser, Debug)] #[clap(name = "gpio", about = env!("CARGO_PKG_DESCRIPTION"))] -struct GpioArgs { +pub struct GpioArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -149,8 +148,7 @@ struct GpioArgs { pins: Option>, } -fn gpio(context: &mut ExecutionContext) -> Result<()> { - let subargs = GpioArgs::try_parse_from(&context.cli.cmd)?; +fn gpio(subargs: GpioArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let timeout = std::time::Duration::from_millis(subargs.timeout); @@ -327,6 +325,9 @@ fn gpio(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: GpioArgs::command(), name: "gpio", run: gpio } +pub type Args = GpioArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + gpio(args, context) + } } diff --git a/cmd/hash/Cargo.toml b/cmd/hash/Cargo.toml index b556d3a5b..bebdcb2dd 100644 --- a/cmd/hash/Cargo.toml +++ b/cmd/hash/Cargo.toml @@ -13,6 +13,5 @@ parse_int.workspace = true indicatif.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true diff --git a/cmd/hash/src/lib.rs b/cmd/hash/src/lib.rs index 4ae39251f..edf6474aa 100644 --- a/cmd/hash/src/lib.rs +++ b/cmd/hash/src/lib.rs @@ -17,10 +17,9 @@ //! use anyhow::{Context, Result, anyhow, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use sha2::{Digest, Sha256}; use std::fs::File; @@ -36,7 +35,7 @@ use indicatif::{ProgressBar, ProgressStyle}; group = ArgGroup::new("command").multiple(false), group = ArgGroup::new("data").multiple(false) )] -struct HashArgs { +pub struct HashArgs { /// Initialize the hash block and optionally provide a length. #[clap(long, short)] // not in group "command" to allow -i update init: bool, @@ -92,8 +91,7 @@ struct HashArgs { long: bool, } -fn hash(context: &mut ExecutionContext) -> Result<()> { - let subargs = HashArgs::try_parse_from(&context.cli.cmd)?; +fn hash(subargs: HashArgs, context: &mut ExecutionContext) -> Result<()> { let archive = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(archive)?; @@ -474,6 +472,9 @@ fn print_hash(buf: &[u8]) { } } -pub fn init() -> Command { - Command { app: HashArgs::command(), name: "hash", run: hash } +pub type Args = HashArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + hash(args, context) + } } diff --git a/cmd/hiffy/src/lib.rs b/cmd/hiffy/src/lib.rs index 238dfa92c..0ee677674 100644 --- a/cmd/hiffy/src/lib.rs +++ b/cmd/hiffy/src/lib.rs @@ -47,11 +47,11 @@ use ::idol::syntax::send::{Operation, Reply}; use anyhow::{Context, Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::*; use humility::warn; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use humility_idol as idol; use std::io::IsTerminal; @@ -59,7 +59,7 @@ use std::io::Read; #[derive(Parser, Debug)] #[clap(name = "hiffy", about = env!("CARGO_PKG_DESCRIPTION"))] -struct HiffyArgs { +pub struct HiffyArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -199,8 +199,7 @@ pub fn hiffy_list(hubris: &HubrisArchive, filter: Vec) -> Result<()> { Ok(()) } -fn hiffy(context: &mut ExecutionContext) -> Result<()> { - let subargs = HiffyArgs::try_parse_from(&context.cli.cmd)?; +fn hiffy(subargs: HiffyArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; if subargs.list { @@ -348,6 +347,9 @@ fn hiffy(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: HiffyArgs::command(), name: "hiffy", run: hiffy } +pub type Args = HiffyArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + hiffy(args, context) + } } diff --git a/cmd/host/Cargo.toml b/cmd/host/Cargo.toml index 5f8069ccb..b688bcb2d 100644 --- a/cmd/host/Cargo.toml +++ b/cmd/host/Cargo.toml @@ -10,13 +10,12 @@ description = "Pretty-printing of host state" anyhow.workspace = true chrono.workspace = true clap.workspace = true +turin-post-decoder.workspace = true hif.workspace = true ipcc-data.workspace = true -turin-post-decoder.workspace = true humility.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-doppel.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/host/src/lib.rs b/cmd/host/src/lib.rs index adff82210..b30d7c6f6 100644 --- a/cmd/host/src/lib.rs +++ b/cmd/host/src/lib.rs @@ -102,11 +102,10 @@ use anyhow::{Result, anyhow}; use chrono::DateTime; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::{core::Core, hubris::HubrisArchive, reflect, reflect::Load}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_doppel as doppel; use humility_hiffy::HiffyContext; use humility_idol::HubrisIdol; @@ -141,7 +140,7 @@ enum CosmoHostCommand { #[derive(Parser, Debug)] #[clap(name = "host", about = env!("CARGO_PKG_DESCRIPTION"))] -struct HostArgs { +pub struct HostArgs { #[clap(subcommand)] cmd: HostCommand, } @@ -457,8 +456,7 @@ fn host_last_post_code( Ok(()) } -fn host(context: &mut ExecutionContext) -> Result<()> { - let subargs = HostArgs::try_parse_from(&context.cli.cmd)?; +fn host(subargs: HostArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; match subargs.cmd { @@ -487,6 +485,9 @@ fn host(context: &mut ExecutionContext) -> Result<()> { } } -pub fn init() -> Command { - Command { app: HostArgs::command(), name: "host", run: host } +pub type Args = HostArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + host(args, context) + } } diff --git a/cmd/hydrate/Cargo.toml b/cmd/hydrate/Cargo.toml index b2d3b17de..948a4ab8f 100644 --- a/cmd/hydrate/Cargo.toml +++ b/cmd/hydrate/Cargo.toml @@ -8,7 +8,6 @@ description = "Rehydrate a bare memory dump" humility.workspace = true humility-arch-arm.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-log.workspace = true hubpack.workspace = true diff --git a/cmd/hydrate/src/lib.rs b/cmd/hydrate/src/lib.rs index ccf4804b3..2bb1998bf 100644 --- a/cmd/hydrate/src/lib.rs +++ b/cmd/hydrate/src/lib.rs @@ -18,11 +18,10 @@ //! lowest available value); use `--out` to specify a different path name. use anyhow::{Context, Result, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use humility::hubris::HubrisFlashMap; use humility_arch_arm::ARMRegister; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_log::msg; use std::{collections::BTreeMap, io::Read, path::PathBuf}; @@ -31,7 +30,7 @@ use std::{collections::BTreeMap, io::Read, path::PathBuf}; name = "hydrate", about = env!("CARGO_PKG_DESCRIPTION"), group = ArgGroup::new("target").multiple(false) )] -struct Args { +pub struct Args { /// Path to write the resulting dump #[clap(short, long)] out: Option, @@ -108,8 +107,7 @@ impl humility::core::Core for DryCore { } } -fn run(context: &mut ExecutionContext) -> Result<()> { - let subargs = Args::try_parse_from(&context.cli.cmd)?; +fn run(subargs: Args, context: &mut ExecutionContext) -> Result<()> { let f = std::fs::File::open(&subargs.file)?; let mut z = zip::ZipArchive::new(f)?; @@ -195,6 +193,8 @@ fn run(context: &mut ExecutionContext) -> Result<()> { ) } -pub fn init() -> Command { - Command { app: Args::command(), name: "hydrate", run } +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + run(args, context) + } } diff --git a/cmd/i2c/src/lib.rs b/cmd/i2c/src/lib.rs index c91be5081..1c335d2a5 100644 --- a/cmd/i2c/src/lib.rs +++ b/cmd/i2c/src/lib.rs @@ -91,10 +91,10 @@ //! ``` use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use humility_log::msg; @@ -423,8 +423,7 @@ fn i2c_done( Ok(()) } -fn i2c(context: &mut ExecutionContext) -> Result<()> { - let subargs = I2cArgs::try_parse_from(&context.cli.cmd)?; +fn i2c(subargs: I2cArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; if !subargs.scan @@ -710,6 +709,9 @@ fn i2c(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: I2cArgs::command(), name: "i2c", run: i2c } +pub type Args = I2cArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + i2c(args, context) + } } diff --git a/cmd/ibc/src/lib.rs b/cmd/ibc/src/lib.rs index 207cc392f..6175f4e8e 100644 --- a/cmd/ibc/src/lib.rs +++ b/cmd/ibc/src/lib.rs @@ -101,9 +101,9 @@ //! use anyhow::{Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; -use humility_cli::ExecutionContext; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_idol::{self as idol, HubrisIdol}; use zerocopy::{ FromBytes, Immutable, IntoBytes, KnownLayout, @@ -114,12 +114,11 @@ use hif::*; use humility::core::Core; use humility::hubris::*; -use humility_cmd::Command; use humility_hiffy::HiffyContext; #[derive(Parser, Debug)] #[clap(name = "ibc", about = env!("CARGO_PKG_DESCRIPTION"))] -struct IbcArgs { +pub struct IbcArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 15000, value_name = "timeout_ms", @@ -514,8 +513,7 @@ struct IbcEvent { //////////////////////////////////////////////////////////////////////////////// -fn ibc(context: &mut ExecutionContext) -> Result<()> { - let subargs = IbcArgs::try_parse_from(&context.cli.cmd)?; +fn ibc(subargs: IbcArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let mut worker = IbcHandler::new(hubris, core, subargs.timeout)?; @@ -528,6 +526,9 @@ fn ibc(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: IbcArgs::command(), name: "ibc", run: ibc } +pub type Args = IbcArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + ibc(args, context) + } } diff --git a/cmd/jefe/Cargo.toml b/cmd/jefe/Cargo.toml index 3c598dd5c..9ea82211f 100644 --- a/cmd/jefe/Cargo.toml +++ b/cmd/jefe/Cargo.toml @@ -10,6 +10,5 @@ clap.workspace = true parse_int.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-jefe.workspace = true diff --git a/cmd/jefe/src/lib.rs b/cmd/jefe/src/lib.rs index 503cf5798..31ef5acd5 100644 --- a/cmd/jefe/src/lib.rs +++ b/cmd/jefe/src/lib.rs @@ -95,16 +95,15 @@ //! normal, or `--start`/`-s` to run it once but catch the next fault. use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_jefe::{JefeRequest, send_request}; use std::num::NonZeroU32; #[derive(Parser, Debug)] #[clap(name = "jefe", about = env!("CARGO_PKG_DESCRIPTION"))] -struct JefeArgs { +pub struct JefeArgs { /// sets timeout #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -131,8 +130,7 @@ struct JefeArgs { task: String, } -fn jefe(context: &mut ExecutionContext) -> Result<()> { - let subargs = JefeArgs::try_parse_from(&context.cli.cmd)?; +fn jefe(subargs: JefeArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -170,6 +168,9 @@ fn jefe(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: JefeArgs::command(), name: "jefe", run: jefe } +pub type Args = JefeArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + jefe(args, context) + } } diff --git a/cmd/lpc55gpio/src/lib.rs b/cmd/lpc55gpio/src/lib.rs index 9f5a3ddee..653ce4e65 100644 --- a/cmd/lpc55gpio/src/lib.rs +++ b/cmd/lpc55gpio/src/lib.rs @@ -102,20 +102,19 @@ //! ``` //! -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use std::str; use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use std::convert::TryInto; #[derive(Parser, Debug)] #[clap(name = "lpc55gpio", about = "GPIO pin manipulation (lpc55 variant)")] -struct GpioArgs { +pub struct GpioArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -163,8 +162,7 @@ struct GpioArgs { pins: Option>, } -fn gpio(context: &mut ExecutionContext) -> Result<()> { - let subargs = GpioArgs::try_parse_from(&context.cli.cmd)?; +fn gpio(subargs: GpioArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let timeout = std::time::Duration::from_millis(subargs.timeout); @@ -311,6 +309,9 @@ fn gpio(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: GpioArgs::command(), name: "lpc55gpio", run: gpio } +pub type Args = GpioArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + gpio(args, context) + } } diff --git a/cmd/lsusb/Cargo.toml b/cmd/lsusb/Cargo.toml index 6117765df..b7c3e4957 100644 --- a/cmd/lsusb/Cargo.toml +++ b/cmd/lsusb/Cargo.toml @@ -6,7 +6,6 @@ description = "List all USB devices visible to Humility" [dependencies] humility = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/lsusb/src/lib.rs b/cmd/lsusb/src/lib.rs index 4a52c7283..321061144 100644 --- a/cmd/lsusb/src/lib.rs +++ b/cmd/lsusb/src/lib.rs @@ -8,20 +8,18 @@ //! on the system, to help you choose probes and/or diagnose permissions issues. use anyhow::{Context, Result, anyhow}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use std::collections::HashMap; use std::time::Duration; #[derive(Parser, Debug)] #[clap(name = "lsusb", about = env!("CARGO_PKG_DESCRIPTION"))] -struct Args { +pub struct Args { // None as yet } -fn lsusb(context: &mut ExecutionContext) -> Result<()> { - let _subargs = Args::try_parse_from(&context.cli.cmd)?; +fn lsusb(_args: Args, context: &mut ExecutionContext) -> Result<()> { let mut targets = if let Some(ref env) = context.cli.environment { humility_cli::env::Environment::read(env) .with_context(|| { @@ -140,6 +138,8 @@ fn list1( Ok((format!("{vid:04x}:{pid:04x}:{serial}"), format!("{man}\t{prod}"))) } -pub fn init() -> Command { - Command { app: Args::command(), name: "lsusb", run: lsusb } +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + lsusb(args, context) + } } diff --git a/cmd/manifest/Cargo.toml b/cmd/manifest/Cargo.toml index 49b272c33..0b7039e4d 100644 --- a/cmd/manifest/Cargo.toml +++ b/cmd/manifest/Cargo.toml @@ -6,7 +6,6 @@ description = "print archive manifest" [dependencies] humility = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/manifest/src/lib.rs b/cmd/manifest/src/lib.rs index 4178ab759..b8891f4cd 100644 --- a/cmd/manifest/src/lib.rs +++ b/cmd/manifest/src/lib.rs @@ -42,27 +42,27 @@ //! `humility manifest` can operate on either an archive or on a dump. use anyhow::Result; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use std::collections::HashSet; #[derive(Parser, Debug)] #[clap(name = "manifest", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ManifestArgs { +pub struct ManifestArgs { /// generate JSON output #[clap(short, long)] json: bool, } #[allow(clippy::print_literal)] -fn manifestcmd(context: &mut ExecutionContext) -> Result<()> { +fn manifestcmd( + subargs: ManifestArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = context.cli.archive()?; let manifest = &hubris.manifest; - let subargs = ManifestArgs::try_parse_from(&context.cli.cmd)?; - if subargs.json { println!("{}", serde_json::to_string(manifest)?); return Ok(()); @@ -261,6 +261,9 @@ fn manifestcmd(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ManifestArgs::command(), name: "manifest", run: manifestcmd } +pub type Args = ManifestArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + manifestcmd(args, context) + } } diff --git a/cmd/map/Cargo.toml b/cmd/map/Cargo.toml index de4ea59af..dacbe78fa 100644 --- a/cmd/map/Cargo.toml +++ b/cmd/map/Cargo.toml @@ -6,7 +6,6 @@ description = "print memory map, with association of regions to tasks" [dependencies] humility = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/map/src/lib.rs b/cmd/map/src/lib.rs index 3ef6ae8fd..dc77fb7f7 100644 --- a/cmd/map/src/lib.rs +++ b/cmd/map/src/lib.rs @@ -62,15 +62,14 @@ //! we can see from the `map` output has been sized to only 256 bytes.) use anyhow::Result; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; #[derive(Parser, Debug)] #[clap(name = "map", about = env!("CARGO_PKG_DESCRIPTION"))] -struct MapArgs {} +pub struct MapArgs {} -fn mapcmd(context: &mut ExecutionContext) -> Result<()> { +fn mapcmd(_args: MapArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; // Use an archive core to easily read from flash @@ -135,6 +134,9 @@ fn mapcmd(context: &mut ExecutionContext) -> Result<()> { } /// This is some init right here -pub fn init() -> Command { - Command { app: MapArgs::command(), name: "map", run: mapcmd } +pub type Args = MapArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + mapcmd(args, context) + } } diff --git a/cmd/monorail/Cargo.toml b/cmd/monorail/Cargo.toml index e78d24651..8f62eaad0 100644 --- a/cmd/monorail/Cargo.toml +++ b/cmd/monorail/Cargo.toml @@ -18,7 +18,6 @@ parse_int.workspace = true regex.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/monorail/src/lib.rs b/cmd/monorail/src/lib.rs index c859ad80b..859d08845 100644 --- a/cmd/monorail/src/lib.rs +++ b/cmd/monorail/src/lib.rs @@ -171,20 +171,20 @@ use std::convert::TryInto; use humility::core::Core; use humility::hubris::*; use humility::reflect::*; -use humility_cli::ExecutionContext; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::{HiffyContext, HiffyError}; use humility_idol::{HubrisIdol, IdolArgument}; use anyhow::{Result, anyhow}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; use vsc7448_info::parse::{PhyRegister, TargetRegister}; use vsc7448_types::Field; #[derive(Parser, Debug)] #[clap(name = "monorail", about = env!("CARGO_PKG_DESCRIPTION"))] -struct MonorailArgs { +pub struct MonorailArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -965,9 +965,10 @@ fn monorail_counters( Ok(()) } -fn monorail(context: &mut ExecutionContext) -> Result<()> { - let subargs = MonorailArgs::try_parse_from(&context.cli.cmd)?; - +fn monorail( + subargs: MonorailArgs, + context: &mut ExecutionContext, +) -> Result<()> { // Early exit for subcommands which don't require an archive or Core match &subargs.cmd { Command::Info { reg, value } => { @@ -1079,10 +1080,9 @@ fn monorail(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> humility_cmd::Command { - humility_cmd::Command { - app: MonorailArgs::command(), - name: "monorail", - run: monorail, +pub type Args = MonorailArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + monorail(args, context) } } diff --git a/cmd/mwocp/Cargo.toml b/cmd/mwocp/Cargo.toml index 4cb2fa7f7..31d4157df 100644 --- a/cmd/mwocp/Cargo.toml +++ b/cmd/mwocp/Cargo.toml @@ -17,7 +17,6 @@ pmbus.workspace = true zerocopy.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-hiffy.workspace = true humility-i2c.workspace = true humility-idol.workspace = true diff --git a/cmd/mwocp/src/lib.rs b/cmd/mwocp/src/lib.rs index c0bc1e58b..7c3dd5ea9 100644 --- a/cmd/mwocp/src/lib.rs +++ b/cmd/mwocp/src/lib.rs @@ -34,13 +34,12 @@ use humility::hubris::*; use humility::msg; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_i2c::I2cArgs; use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use indicatif::{HumanBytes, HumanDuration}; use indicatif::{ProgressBar, ProgressStyle}; @@ -53,7 +52,7 @@ use std::time::Instant; #[clap(name = "mwocp", about = env!("CARGO_PKG_DESCRIPTION"), group = clap::ArgGroup::new("subcommand").multiple(false) )] -struct MwocpArgs { +pub struct MwocpArgs { /// sets timeout #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -116,8 +115,7 @@ const MWOCP68_BLOCK_DELAY_MS: u8 = 100; const MWOCP68_CHECKSUM_DELAY: u64 = 2; const MWOCP68_REBOOT_DELAY: u64 = 5; -fn mwocp(context: &mut ExecutionContext) -> Result<()> { - let subargs = MwocpArgs::try_parse_from(&context.cli.cmd)?; +fn mwocp(subargs: MwocpArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -577,6 +575,9 @@ fn mwocp(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: MwocpArgs::command(), name: "mwocp", run: mwocp } +pub type Args = MwocpArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + mwocp(args, context) + } } diff --git a/cmd/net/Cargo.toml b/cmd/net/Cargo.toml index 47a04aee5..8e0bc27bc 100644 --- a/cmd/net/Cargo.toml +++ b/cmd/net/Cargo.toml @@ -15,7 +15,6 @@ parse_int.workspace = true colored.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/net/src/lib.rs b/cmd/net/src/lib.rs index 64cf47e4e..efb658c92 100644 --- a/cmd/net/src/lib.rs +++ b/cmd/net/src/lib.rs @@ -40,14 +40,13 @@ use std::collections::BTreeMap; use anyhow::Result; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; use humility::core::Core; use humility::hubris::HubrisArchive; use humility::reflect::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::HiffyContext; use humility_idol::HubrisIdol; @@ -61,7 +60,7 @@ enum NetCommand { Status, /// Print the counters /// - /// This is a destructive operation that clears counter values, resetting + /// This is a depub structive operation that clears counter values, resetting /// them to zero. /// /// If no flags are provided, both the table and diagram are shown. @@ -77,7 +76,7 @@ enum NetCommand { #[derive(Parser, Debug)] #[clap(name = "net", about = env!("CARGO_PKG_DESCRIPTION"))] -struct NetArgs { +pub struct NetArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -522,9 +521,7 @@ fn net_counters_diagram(s: &Struct) -> Result<()> { Ok(()) } -fn net(context: &mut ExecutionContext) -> Result<()> { - let subargs = NetArgs::try_parse_from(&context.cli.cmd)?; - +fn net(subargs: NetArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let timeout = std::time::Duration::from_millis(subargs.timeout); @@ -541,6 +538,9 @@ fn net(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: NetArgs::command(), name: "net", run: net } +pub type Args = NetArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + net(args, context) + } } diff --git a/cmd/pmbus/Cargo.toml b/cmd/pmbus/Cargo.toml index ac6d5d429..35e529d2e 100644 --- a/cmd/pmbus/Cargo.toml +++ b/cmd/pmbus/Cargo.toml @@ -15,7 +15,6 @@ parse_int.workspace = true humility.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-hiffy.workspace = true humility-i2c.workspace = true humility-idol.workspace = true diff --git a/cmd/pmbus/src/lib.rs b/cmd/pmbus/src/lib.rs index 8ad271f2f..71115faa7 100644 --- a/cmd/pmbus/src/lib.rs +++ b/cmd/pmbus/src/lib.rs @@ -190,14 +190,13 @@ use colored::Colorize; use humility::hubris::*; use humility::{core::Core, warn}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_i2c::I2cArgs; use humility_idol::{HubrisIdol, IdolArgument, IdolOperation}; use anyhow::{Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use indexmap::IndexMap; use pmbus::commands::*; @@ -207,7 +206,7 @@ use std::fmt::Write; #[derive(Parser, Debug)] #[clap(name = "pmbus", about = env!("CARGO_PKG_DESCRIPTION"))] -struct PmbusArgs { +pub struct PmbusArgs { /// sets timeout #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -1904,8 +1903,7 @@ impl PmbusWorker for IdolWorker<'_> { } #[allow(clippy::print_literal)] -fn pmbus(context: &mut ExecutionContext) -> Result<()> { - let subargs = PmbusArgs::try_parse_from(&context.cli.cmd)?; +fn pmbus(subargs: PmbusArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; if subargs.list { @@ -2244,6 +2242,9 @@ fn pmbus_main( Ok(()) } -pub fn init() -> Command { - Command { app: PmbusArgs::command(), name: "pmbus", run: pmbus } +pub type Args = PmbusArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + pmbus(args, context) + } } diff --git a/cmd/power/Cargo.toml b/cmd/power/Cargo.toml index 612251608..416df1000 100644 --- a/cmd/power/Cargo.toml +++ b/cmd/power/Cargo.toml @@ -14,7 +14,6 @@ idol = { workspace = true } log = { workspace = true } humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/power/src/lib.rs b/cmd/power/src/lib.rs index 8c5556933..376ca358d 100644 --- a/cmd/power/src/lib.rs +++ b/cmd/power/src/lib.rs @@ -16,19 +16,18 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use humility::core::Core; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; use std::collections::{BTreeMap, HashSet}; #[derive(Parser, Debug)] #[clap(name = "power", about = env!("CARGO_PKG_DESCRIPTION"))] -struct PowerArgs { +pub struct PowerArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -115,8 +114,7 @@ fn phase_currents( Ok(()) } -fn power(context: &mut ExecutionContext) -> Result<()> { - let subargs = PowerArgs::try_parse_from(&context.cli.cmd)?; +fn power(subargs: PowerArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -308,6 +306,9 @@ fn power(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: PowerArgs::command(), name: "power", run: power } +pub type Args = PowerArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + power(args, context) + } } diff --git a/cmd/powershelf/Cargo.toml b/cmd/powershelf/Cargo.toml index fe0e998de..1e1daa5e0 100644 --- a/cmd/powershelf/Cargo.toml +++ b/cmd/powershelf/Cargo.toml @@ -6,7 +6,6 @@ description = "inspect powershelf over the management network" [dependencies] humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/powershelf/src/lib.rs b/cmd/powershelf/src/lib.rs index 0ebf15206..5f4171d30 100644 --- a/cmd/powershelf/src/lib.rs +++ b/cmd/powershelf/src/lib.rs @@ -14,18 +14,17 @@ //! indices 0 through 5). use anyhow::{Context, Result, anyhow}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use humility::hubris::HubrisArchive; use humility::hubris::HubrisEnum; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; #[derive(Parser, Debug)] #[clap(name = "powershelf", about = env!("CARGO_PKG_DESCRIPTION"))] -struct PowershelfArgs { +pub struct PowershelfArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -129,8 +128,10 @@ fn interpret_raw_variant(variant: &str, payload: &[u8]) { } } -fn powershelf_run(context: &mut ExecutionContext) -> Result<()> { - let subargs = PowershelfArgs::try_parse_from(&context.cli.cmd)?; +fn powershelf_run( + subargs: PowershelfArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -218,10 +219,9 @@ fn powershelf_run(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { - app: PowershelfArgs::command(), - name: "powershelf", - run: powershelf_run, +pub type Args = PowershelfArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + powershelf_run(args, context) } } diff --git a/cmd/probe/Cargo.toml b/cmd/probe/Cargo.toml index f1ceb92d7..655b960f2 100644 --- a/cmd/probe/Cargo.toml +++ b/cmd/probe/Cargo.toml @@ -12,5 +12,4 @@ num-traits.workspace = true humility.workspace = true humility-arch-arm.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-cortex.workspace = true diff --git a/cmd/probe/src/lib.rs b/cmd/probe/src/lib.rs index 089fdfd6e..415503c9b 100644 --- a/cmd/probe/src/lib.rs +++ b/cmd/probe/src/lib.rs @@ -87,25 +87,23 @@ //! ``` use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::HubrisValidate; use humility_arch_arm::ARMRegister; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_cortex::debug::*; use humility_cortex::scs::*; #[derive(Parser, Debug)] #[clap(name = "probe", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ProbeArgs { +pub struct ProbeArgs { /// display environment variable for this probe #[clap(long, short)] environment: bool, } #[rustfmt::skip::macros(format)] -fn probecmd(context: &mut ExecutionContext) -> Result<()> { - let subargs = ProbeArgs::try_parse_from(&context.cli.cmd)?; +fn probecmd(subargs: ProbeArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = context.cli.try_archive()?; let core = &mut *context.cli.attach_probe(hubris.as_ref())?; @@ -411,6 +409,9 @@ fn probecmd(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ProbeArgs::command(), name: "probe", run: probecmd } +pub type Args = ProbeArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + probecmd(args, context) + } } diff --git a/cmd/qspi/src/lib.rs b/cmd/qspi/src/lib.rs index e13276427..e2218fc55 100644 --- a/cmd/qspi/src/lib.rs +++ b/cmd/qspi/src/lib.rs @@ -83,8 +83,8 @@ //! as well as bulk erase. use humility::core::Core; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use humility_idol::{HubrisIdol, IdolArgument}; use sha2::{Digest, Sha256}; @@ -96,7 +96,7 @@ use std::mem; use std::time::Instant; use anyhow::{Result, anyhow, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use hif::*; use indicatif::{HumanBytes, HumanDuration}; @@ -107,7 +107,7 @@ use indicatif::{ProgressBar, ProgressStyle}; name = "qspi", about = env!("CARGO_PKG_DESCRIPTION"), group = ArgGroup::new("command").multiple(false) )] -struct QspiArgs { +pub struct QspiArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 30000, value_name = "timeout_ms", @@ -481,8 +481,7 @@ fn write( } } -fn qspi(context: &mut ExecutionContext) -> Result<()> { - let subargs = QspiArgs::try_parse_from(&context.cli.cmd)?; +fn qspi(subargs: QspiArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -1183,6 +1182,9 @@ impl fmt::Display for DeviceIdData { } } -pub fn init() -> Command { - Command { app: QspiArgs::command(), name: "qspi", run: qspi } +pub type Args = QspiArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + qspi(args, context) + } } diff --git a/cmd/readmem/src/lib.rs b/cmd/readmem/src/lib.rs index 0de3e903c..948b5d462 100644 --- a/cmd/readmem/src/lib.rs +++ b/cmd/readmem/src/lib.rs @@ -116,10 +116,10 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use std::convert::TryInto; use std::io::Write; use std::path::PathBuf; @@ -141,7 +141,7 @@ fn parse_size(src: &str) -> Result { #[derive(Parser, Debug)] #[clap(name = "readmem", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ReadmemArgs { +pub struct ReadmemArgs { /// print out as halfwords instead of as bytes #[clap(long, short = 'H', conflicts_with_all = &["word", "symbol", "file"])] halfword: bool, @@ -166,8 +166,7 @@ struct ReadmemArgs { length: Option, } -fn readmem(context: &mut ExecutionContext) -> Result<()> { - let subargs = ReadmemArgs::try_parse_from(&context.cli.cmd)?; +fn readmem(subargs: ReadmemArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = context.cli.try_archive()?; let core = &mut *context.cli.attach_live_or_dump(hubris.as_ref(), None)?; @@ -268,6 +267,9 @@ fn readmem(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ReadmemArgs::command(), name: "readmem", run: readmem } +pub type Args = ReadmemArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + readmem(args, context) + } } diff --git a/cmd/readvar/Cargo.toml b/cmd/readvar/Cargo.toml index 328c26433..3a51dc3d3 100644 --- a/cmd/readvar/Cargo.toml +++ b/cmd/readvar/Cargo.toml @@ -9,5 +9,4 @@ clap.workspace = true anyhow.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true diff --git a/cmd/readvar/src/lib.rs b/cmd/readvar/src/lib.rs index ec8050f09..5fdfe3892 100644 --- a/cmd/readvar/src/lib.rs +++ b/cmd/readvar/src/lib.rs @@ -37,15 +37,14 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::core::{Core, ProbeError}; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; #[derive(Parser, Debug)] #[clap(name = "readvar", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ReadvarArgs { +pub struct ReadvarArgs { /// values in decimal instead of hex #[clap(long, short)] decimal: bool, @@ -99,8 +98,7 @@ fn readvar_dump( Ok(()) } -fn readvar(context: &mut ExecutionContext) -> Result<()> { - let subargs = ReadvarArgs::try_parse_from(&context.cli.cmd)?; +fn readvar(subargs: ReadvarArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; if subargs.list { @@ -179,6 +177,9 @@ fn readvar(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ReadvarArgs::command(), name: "readvar", run: readvar } +pub type Args = ReadvarArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + readvar(args, context) + } } diff --git a/cmd/rebootleby/Cargo.toml b/cmd/rebootleby/Cargo.toml index d36c0452f..5fe3c670d 100644 --- a/cmd/rebootleby/Cargo.toml +++ b/cmd/rebootleby/Cargo.toml @@ -8,7 +8,6 @@ description = "Do something kind of like embootleby to recover a device with bad humility = { workspace = true } humility-arch-arm = { workspace = true } humility-cortex = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/rebootleby/src/lib.rs b/cmd/rebootleby/src/lib.rs index b1b252213..08831123c 100644 --- a/cmd/rebootleby/src/lib.rs +++ b/cmd/rebootleby/src/lib.rs @@ -11,11 +11,10 @@ //! !!! Using this can be dangerous and should be undertaken with caution use anyhow::{Context, Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::core::Core; use humility_arch_arm::ARMRegister; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use std::io::Read; use std::ops::RangeInclusive; use std::path::PathBuf; @@ -24,7 +23,7 @@ use zip::ZipArchive; #[derive(Parser, Debug)] #[clap(about = env!("CARGO_PKG_DESCRIPTION"))] -struct Rebootleby { +pub struct Rebootleby { /// Path to a Bootleby Bundle file. path: PathBuf, /// Flag to ensure you _really_ mean to run this command @@ -32,9 +31,10 @@ struct Rebootleby { yes_really: bool, } -fn rebootleby(context: &mut ExecutionContext) -> Result<()> { - let subargs = Rebootleby::try_parse_from(&context.cli.cmd)?; - +fn rebootleby( + subargs: Rebootleby, + context: &mut ExecutionContext, +) -> Result<()> { // Load bundle let bundle_reader = std::fs::File::open(&subargs.path) .with_context(|| format!("loading {}", subargs.path.display()))?; @@ -138,8 +138,11 @@ fn rebootleby(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: Rebootleby::command(), name: "rebootleby", run: rebootleby } +pub type Args = Rebootleby; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + rebootleby(args, context) + } } // The undocumented registers. These look remarkably similar to the diff --git a/cmd/registers/Cargo.toml b/cmd/registers/Cargo.toml index addc7953c..ef20ec58e 100644 --- a/cmd/registers/Cargo.toml +++ b/cmd/registers/Cargo.toml @@ -12,6 +12,5 @@ num-traits.workspace = true humility.workspace = true humility-arch-arm.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-cortex.workspace = true humility-stack.workspace = true diff --git a/cmd/registers/src/lib.rs b/cmd/registers/src/lib.rs index 7136086e4..d02fb74f0 100644 --- a/cmd/registers/src/lib.rs +++ b/cmd/registers/src/lib.rs @@ -130,18 +130,17 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::*; use humility_arch_arm::{ARMRegister, ARMRegisterField}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_cortex::debug::*; use num_traits::FromPrimitive; use std::collections::BTreeMap; #[derive(Parser, Debug)] #[clap(name = "registers", about = env!("CARGO_PKG_DESCRIPTION"))] -struct RegistersArgs { +pub struct RegistersArgs { /// show stack backtrace #[clap(long, short)] stack: bool, @@ -232,8 +231,10 @@ fn print_reg(reg: ARMRegister, val: u32, fields: &[ARMRegisterField]) { println!(); } -fn registers(context: &mut ExecutionContext) -> Result<()> { - let subargs = RegistersArgs::try_parse_from(&context.cli.cmd)?; +fn registers( + subargs: RegistersArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.try_archive()?; let core = &mut *context.cli.attach_live_or_dump(hubris.as_ref(), None)?; let mut regs = BTreeMap::new(); @@ -362,6 +363,9 @@ fn registers(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: RegistersArgs::command(), name: "registers", run: registers } +pub type Args = RegistersArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + registers(args, context) + } } diff --git a/cmd/rencm/src/lib.rs b/cmd/rencm/src/lib.rs index fa19052d6..c91034175 100644 --- a/cmd/rencm/src/lib.rs +++ b/cmd/rencm/src/lib.rs @@ -10,15 +10,15 @@ use humility::core::Core; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use humility_i2c::I2cArgs; use itertools::Itertools; use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use idt8a3xxxx::*; use std::collections::BTreeMap; @@ -30,7 +30,7 @@ use serde_xml_rs::from_str; #[derive(Parser, Debug)] #[clap(name = "rencm", about = env!("CARGO_PKG_DESCRIPTION"))] -struct RencmArgs { +pub struct RencmArgs { /// sets timeout #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -792,8 +792,7 @@ fn rencm_ingest(subargs: &RencmArgs, modules: &[Module]) -> Result<()> { Ok(()) } -fn rencm(context: &mut ExecutionContext) -> Result<()> { - let subargs = RencmArgs::try_parse_from(&context.cli.cmd)?; +fn rencm(subargs: RencmArgs, context: &mut ExecutionContext) -> Result<()> { let modules = modules(); if subargs.ingest.is_some() { @@ -805,6 +804,9 @@ fn rencm(context: &mut ExecutionContext) -> Result<()> { rencm_attached(hubris, core, &subargs, modules) } -pub fn init() -> Command { - Command { app: RencmArgs::command(), name: "rencm", run: rencm } +pub type Args = RencmArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + rencm(args, context) + } } diff --git a/cmd/rendmp/Cargo.toml b/cmd/rendmp/Cargo.toml index 81dbda71e..d795b6760 100644 --- a/cmd/rendmp/Cargo.toml +++ b/cmd/rendmp/Cargo.toml @@ -19,7 +19,6 @@ strum_macros.workspace = true zerocopy.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-hiffy.workspace = true humility-i2c.workspace = true humility-idol.workspace = true diff --git a/cmd/rendmp/src/lib.rs b/cmd/rendmp/src/lib.rs index af8846498..7ae596dd7 100644 --- a/cmd/rendmp/src/lib.rs +++ b/cmd/rendmp/src/lib.rs @@ -145,14 +145,13 @@ use humility::hubris::*; use humility::reflect::{Base, Value}; use humility::warn; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_i2c::I2cArgs; use humility_idol::{HubrisIdol, IdolOperation}; use anyhow::{Context, Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; use hif::*; use indicatif::{HumanBytes, HumanDuration}; @@ -176,7 +175,7 @@ mod blackbox; #[clap(name = "rendmp", about = env!("CARGO_PKG_DESCRIPTION"), group = clap::ArgGroup::new("subcommand").multiple(false) )] -struct RendmpArgs { +pub struct RendmpArgs { /// sets timeout #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -2296,8 +2295,7 @@ fn restore_default_config<'a>( Ok(()) } -fn rendmp(context: &mut ExecutionContext) -> Result<()> { - let subargs = RendmpArgs::try_parse_from(&context.cli.cmd)?; +fn rendmp(subargs: RendmpArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -2886,6 +2884,9 @@ fn rendmp(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: RendmpArgs::command(), name: "rendmp", run: rendmp } +pub type Args = RendmpArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + rendmp(args, context) + } } diff --git a/cmd/reset/Cargo.toml b/cmd/reset/Cargo.toml index 19f3ea096..be4f678fb 100644 --- a/cmd/reset/Cargo.toml +++ b/cmd/reset/Cargo.toml @@ -6,7 +6,6 @@ description = "Reset the chip using external pins" [dependencies] humility = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } humility-probes-core = { workspace = true } clap = { workspace = true } diff --git a/cmd/reset/src/lib.rs b/cmd/reset/src/lib.rs index 6484b59c4..a80c12234 100644 --- a/cmd/reset/src/lib.rs +++ b/cmd/reset/src/lib.rs @@ -8,13 +8,12 @@ //! or using software reset with the appropriate flag use anyhow::Result; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; #[derive(Parser, Debug)] #[clap(name = "reset", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ResetArgs { +pub struct ResetArgs { /// Use a software reset instead of pin reset #[clap(long, conflicts_with_all = &["halt"])] soft_reset: bool, @@ -26,8 +25,7 @@ struct ResetArgs { use_token: Option, } -fn reset(context: &mut ExecutionContext) -> Result<()> { - let subargs = ResetArgs::try_parse_from(&context.cli.cmd)?; +fn reset(subargs: ResetArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = context.cli.try_archive()?; let probe = match &context.cli.probe { @@ -111,6 +109,9 @@ fn reset(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ResetArgs::command(), name: "reset", run: reset } +pub type Args = ResetArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + reset(args, context) + } } diff --git a/cmd/ringbuf/Cargo.toml b/cmd/ringbuf/Cargo.toml index 435b48608..2934d67d0 100644 --- a/cmd/ringbuf/Cargo.toml +++ b/cmd/ringbuf/Cargo.toml @@ -9,6 +9,5 @@ clap.workspace = true anyhow.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-doppel.workspace = true diff --git a/cmd/ringbuf/src/lib.rs b/cmd/ringbuf/src/lib.rs index 212056762..f18a025f7 100644 --- a/cmd/ringbuf/src/lib.rs +++ b/cmd/ringbuf/src/lib.rs @@ -63,17 +63,16 @@ //! documentation](https://github.com/oxidecomputer/hubris/blob/master/lib/ringbuf/src/lib.rs) for more details. use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::core::Core; use humility::hubris::*; use humility::reflect::{self, Format, Load, Value}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_doppel::{CountedRingbuf, CounterVariant, Ringbuf, StaticCell}; #[derive(Parser, Debug)] #[clap(name = "ringbuf", about = env!("CARGO_PKG_DESCRIPTION"))] -struct RingbufArgs { +pub struct RingbufArgs { /// list variables #[clap(long, short)] list: bool, @@ -232,8 +231,7 @@ fn taskname<'a>( // this allow is meant for the header println! in the body but you cannot apply // an attribute to a macro invoction, so we have to put it here instead. #[allow(clippy::print_literal)] -fn ringbuf(context: &mut ExecutionContext) -> Result<()> { - let subargs = RingbufArgs::try_parse_from(&context.cli.cmd)?; +fn ringbuf(subargs: RingbufArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let mut ringbufs = vec![]; @@ -315,6 +313,9 @@ fn ringbuf(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: RingbufArgs::command(), name: "ringbuf", run: ringbuf } +pub type Args = RingbufArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + ringbuf(args, context) + } } diff --git a/cmd/sbrmi/Cargo.toml b/cmd/sbrmi/Cargo.toml index 6747bc4c1..6d37b525e 100644 --- a/cmd/sbrmi/Cargo.toml +++ b/cmd/sbrmi/Cargo.toml @@ -15,7 +15,6 @@ termimad.workspace = true zerocopy.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/sbrmi/src/lib.rs b/cmd/sbrmi/src/lib.rs index 2a33b36a0..5e9d00fb5 100644 --- a/cmd/sbrmi/src/lib.rs +++ b/cmd/sbrmi/src/lib.rs @@ -90,13 +90,12 @@ //! using the `--mca` option and specifyin a desired thread. use anyhow::Result; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use colored::Colorize; use hif::*; use humility::core::Core; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; use raw_cpuid::{CpuId, CpuIdResult}; @@ -109,7 +108,7 @@ use std::rc::Rc; name = "sbrmi", about = env!("CARGO_PKG_DESCRIPTION"), group = ArgGroup::new("command").multiple(false).required(false) )] -struct SbrmiArgs { +pub struct SbrmiArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -502,8 +501,7 @@ fn mca( Ok(()) } -fn sbrmi(context: &mut ExecutionContext) -> Result<()> { - let subargs = SbrmiArgs::try_parse_from(&context.cli.cmd)?; +fn sbrmi(subargs: SbrmiArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let timeout = std::time::Duration::from_millis(subargs.timeout); @@ -589,6 +587,9 @@ fn sbrmi(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: SbrmiArgs::command(), name: "sbrmi", run: sbrmi } +pub type Args = SbrmiArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + sbrmi(args, context) + } } diff --git a/cmd/sensors/Cargo.toml b/cmd/sensors/Cargo.toml index 9c7e5b4e9..1bc568096 100644 --- a/cmd/sensors/Cargo.toml +++ b/cmd/sensors/Cargo.toml @@ -13,7 +13,6 @@ indexmap.workspace = true itertools.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-doppel.workspace = true humility-hiffy.workspace = true diff --git a/cmd/sensors/src/lib.rs b/cmd/sensors/src/lib.rs index bbbcdcd28..40de5053a 100644 --- a/cmd/sensors/src/lib.rs +++ b/cmd/sensors/src/lib.rs @@ -25,13 +25,12 @@ //! counts are also displayed. use anyhow::{Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; use humility::core::Core; use humility::hubris::*; use humility::reflect::{self, Load}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_doppel as doppel; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; @@ -42,7 +41,7 @@ use std::time::{Duration, Instant}; #[derive(Parser, Debug)] #[clap(name = "sensors", about = env!("CARGO_PKG_DESCRIPTION"))] -struct SensorsArgs { +pub struct SensorsArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -531,8 +530,7 @@ fn print( Ok(()) } -fn sensors(context: &mut ExecutionContext) -> Result<()> { - let subargs = SensorsArgs::try_parse_from(&context.cli.cmd)?; +fn sensors(subargs: SensorsArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let types = if let Some(ref types) = subargs.types { @@ -648,6 +646,9 @@ fn sensors(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: SensorsArgs::command(), name: "sensors", run: sensors } +pub type Args = SensorsArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + sensors(args, context) + } } diff --git a/cmd/spctrl/src/lib.rs b/cmd/spctrl/src/lib.rs index e77cadb80..68d8973e4 100644 --- a/cmd/spctrl/src/lib.rs +++ b/cmd/spctrl/src/lib.rs @@ -44,14 +44,14 @@ //! 0x00000030 | f739ba6f 20067a60 310c4e08 e42eca28 | o.9.`z. .N.1(... //! ``` -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use std::str; use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; #[derive(Parser, Debug)] @@ -72,7 +72,7 @@ enum SpCtrlCmd { #[derive(Parser, Debug)] #[clap(name = "spctrl", about = env!("CARGO_PKG_DESCRIPTION"))] -struct SpCtrlArgs { +pub struct SpCtrlArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -88,8 +88,7 @@ struct SpCtrlArgs { word: bool, } -fn spctrl(context: &mut ExecutionContext) -> Result<()> { - let subargs = SpCtrlArgs::try_parse_from(&context.cli.cmd)?; +fn spctrl(subargs: SpCtrlArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let timeout = std::time::Duration::from_millis(subargs.timeout); @@ -151,6 +150,9 @@ fn spctrl(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: SpCtrlArgs::command(), name: "spctrl", run: spctrl } +pub type Args = SpCtrlArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + spctrl(args, context) + } } diff --git a/cmd/spd/Cargo.toml b/cmd/spd/Cargo.toml index 6bcb4bc0d..023d30b99 100644 --- a/cmd/spd/Cargo.toml +++ b/cmd/spd/Cargo.toml @@ -13,7 +13,6 @@ jep106.workspace = true parse_int.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true humility-hiffy.workspace = true humility-i2c.workspace = true humility-log.workspace = true diff --git a/cmd/spd/src/lib.rs b/cmd/spd/src/lib.rs index 0059f5854..6260b1d02 100644 --- a/cmd/spd/src/lib.rs +++ b/cmd/spd/src/lib.rs @@ -107,8 +107,7 @@ //! use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use humility_i2c::I2cArgs; use humility_log::msg; @@ -118,12 +117,12 @@ use std::io::Write; use std::str; use anyhow::{Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; #[derive(Parser, Debug)] #[clap(name = "spd", about = env!("CARGO_PKG_DESCRIPTION"))] -struct SpdArgs { +pub struct SpdArgs { /// sets timeout #[clap( long, short, default_value_t = 5000, value_name = "timeout_ms", @@ -330,8 +329,7 @@ fn set_page( ops.push(Op::DropN(4)); } -fn spd(context: &mut ExecutionContext) -> Result<()> { - let subargs = SpdArgs::try_parse_from(&context.cli.cmd)?; +fn spd(subargs: SpdArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_or_dump_booted(hubris)?; @@ -519,6 +517,9 @@ fn dump_ddr4_over_i2c( Ok(()) } -pub fn init() -> Command { - Command { app: SpdArgs::command(), name: "spd", run: spd } +pub type Args = SpdArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + spd(args, context) + } } diff --git a/cmd/spi/src/lib.rs b/cmd/spi/src/lib.rs index 632b28318..1d842afe1 100644 --- a/cmd/spi/src/lib.rs +++ b/cmd/spi/src/lib.rs @@ -33,20 +33,20 @@ //! use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use std::convert::TryInto; use std::str; use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use hif::*; #[derive(Parser, Debug)] #[clap(name = "spi", about = env!("CARGO_PKG_DESCRIPTION"))] -struct SpiArgs { +pub struct SpiArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -170,8 +170,7 @@ pub fn spi_task( Ok(task) } -fn spi(context: &mut ExecutionContext) -> Result<()> { - let subargs = SpiArgs::try_parse_from(&context.cli.cmd)?; +fn spi(subargs: SpiArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -312,6 +311,9 @@ fn spi(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: SpiArgs::command(), name: "spi", run: spi } +pub type Args = SpiArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + spi(args, context) + } } diff --git a/cmd/stackmargin/src/lib.rs b/cmd/stackmargin/src/lib.rs index e4a346a1c..26a9a3174 100644 --- a/cmd/stackmargin/src/lib.rs +++ b/cmd/stackmargin/src/lib.rs @@ -28,22 +28,23 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use std::{collections::HashSet, convert::TryInto}; #[derive(Parser, Debug)] #[clap(name = "stackmargin", about = env!("CARGO_PKG_DESCRIPTION"))] -struct StackmarginArgs { +pub struct StackmarginArgs { /// Tasks to check (leave empty to check all tasks) tasks: Vec, } #[rustfmt::skip::macros(println, bail)] -fn stackmargin(context: &mut ExecutionContext) -> Result<()> { - let subargs = StackmarginArgs::try_parse_from(&context.cli.cmd)?; +fn stackmargin( + subargs: StackmarginArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_or_dump_booted(hubris)?; @@ -161,10 +162,9 @@ fn stackmargin(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { - app: StackmarginArgs::command(), - name: "stackmargin", - run: stackmargin, +pub type Args = StackmarginArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + stackmargin(args, context) } } diff --git a/cmd/stmsecure/Cargo.toml b/cmd/stmsecure/Cargo.toml index 14a11d9a0..d553537ad 100644 --- a/cmd/stmsecure/Cargo.toml +++ b/cmd/stmsecure/Cargo.toml @@ -12,4 +12,3 @@ parse_int.workspace = true humility.workspace = true humility-arch-arm.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true diff --git a/cmd/stmsecure/src/lib.rs b/cmd/stmsecure/src/lib.rs index d09cd072f..6560e09af 100644 --- a/cmd/stmsecure/src/lib.rs +++ b/cmd/stmsecure/src/lib.rs @@ -28,11 +28,10 @@ //! ``` use anyhow::{Result, anyhow}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::core::Core; use humility_arch_arm::ARMRegister; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; const FLASH_OPT_KEY1: u32 = 0x0819_2A3B; const FLASH_OPT_KEY2: u32 = 0x4C5D_6E7F; @@ -52,7 +51,13 @@ const FLASH_SCAR_PRG1: u32 = 0x5200_2034; #[derive(Parser, Debug)] #[clap(name = "stmsecure", about = env!("CARGO_PKG_DESCRIPTION"))] -enum StmSecureArgs { +pub struct StmSecureArgs { + #[clap(subcommand)] + cmd: StmSecureCmd, +} + +#[derive(clap::Subcommand, Debug)] +pub enum StmSecureCmd { /// Show status about secure region settings Status, /// Enable Read Out Protection (RDP) i.e. can't read flash from debugger @@ -221,7 +226,7 @@ fn stmsecure_setsecureregion( // We have to use the delightful ROM API in order to write this register core.halt()?; - // Set up the structure at 0x2000_0000 + // Set up the pub structure at 0x2000_0000 // typedef struct // { // uint32_t sizeInBytes; /**< pass 0 for an empty secure area */ @@ -294,24 +299,29 @@ fn stmsecure_swapbanks(core: &mut dyn Core) -> Result<()> { } #[rustfmt::skip::macros(format)] -fn stmsecure(context: &mut ExecutionContext) -> Result<()> { - let subargs = StmSecureArgs::try_parse_from(&context.cli.cmd)?; +fn stmsecure( + subargs: StmSecureArgs, + context: &mut ExecutionContext, +) -> Result<()> { let core = &mut *context.cli.attach_probe(None)?; - match subargs { - StmSecureArgs::Status => stmsecure_status(core), - StmSecureArgs::SetSecureBit => stmsecure_lockbit_set(core), - StmSecureArgs::UnsetSecureBit => stmsecure_lockbit_unset(core), - StmSecureArgs::SetSecureRegion { address, size, doit } => { + match subargs.cmd { + StmSecureCmd::Status => stmsecure_status(core), + StmSecureCmd::SetSecureBit => stmsecure_lockbit_set(core), + StmSecureCmd::UnsetSecureBit => stmsecure_lockbit_unset(core), + StmSecureCmd::SetSecureRegion { address, size, doit } => { stmsecure_setsecureregion(core, address, size, doit) } - StmSecureArgs::UnsetSecureRegion => stmsecure_unsetsecureregion(core), - StmSecureArgs::SetRDP => stmsecure_rdpset(core), - StmSecureArgs::UnsetRDP => stmsecure_rdpunset(core), - StmSecureArgs::SwapBanks => stmsecure_swapbanks(core), + StmSecureCmd::UnsetSecureRegion => stmsecure_unsetsecureregion(core), + StmSecureCmd::SetRDP => stmsecure_rdpset(core), + StmSecureCmd::UnsetRDP => stmsecure_rdpunset(core), + StmSecureCmd::SwapBanks => stmsecure_swapbanks(core), } } -pub fn init() -> Command { - Command { app: StmSecureArgs::command(), name: "stmsecure", run: stmsecure } +pub type Args = StmSecureArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + stmsecure(args, context) + } } diff --git a/cmd/tasks/Cargo.toml b/cmd/tasks/Cargo.toml index a23ca5096..864e0784e 100644 --- a/cmd/tasks/Cargo.toml +++ b/cmd/tasks/Cargo.toml @@ -13,7 +13,6 @@ parse_int.workspace = true humility.workspace = true humility-arch-arm.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-doppel.workspace = true humility-stack.workspace = true diff --git a/cmd/tasks/src/lib.rs b/cmd/tasks/src/lib.rs index 596baad88..50df1257c 100644 --- a/cmd/tasks/src/lib.rs +++ b/cmd/tasks/src/lib.rs @@ -112,13 +112,12 @@ //! use anyhow::{Context, Result, anyhow, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use humility::core::Core; use humility::hubris::*; use humility::reflect::{self, Format, Load}; use humility_arch_arm::ARMRegister; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_doppel::{self as doppel, Task, TaskDesc, TaskId, TaskState}; use num_traits::FromPrimitive; use std::collections::{BTreeMap, HashMap}; @@ -126,7 +125,7 @@ use std::io::Write; #[derive(Parser, Debug)] #[clap(name = "tasks", about = env!("CARGO_PKG_DESCRIPTION"))] -struct TasksArgs { +pub struct TasksArgs { /// show registers #[clap(long, short)] registers: bool, @@ -183,8 +182,7 @@ fn print_regs( Ok(()) } -fn tasks(context: &mut ExecutionContext) -> Result<()> { - let subargs = TasksArgs::try_parse_from(&context.cli.cmd)?; +fn tasks(subargs: TasksArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_or_dump_booted(hubris)?; @@ -923,6 +921,9 @@ fn explain_recv( Ok(()) } -pub fn init() -> Command { - Command { app: TasksArgs::command(), name: "tasks", run: tasks } +pub type Args = TasksArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + tasks(args, context) + } } diff --git a/cmd/test/Cargo.toml b/cmd/test/Cargo.toml index 77149dda9..ca977a3ab 100644 --- a/cmd/test/Cargo.toml +++ b/cmd/test/Cargo.toml @@ -14,6 +14,5 @@ hif.workspace = true humility-hiffy.workspace = true humility.workspace = true humility-cortex.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true cmd-tasks.workspace = true diff --git a/cmd/test/src/lib.rs b/cmd/test/src/lib.rs index b190bffba..08607da92 100644 --- a/cmd/test/src/lib.rs +++ b/cmd/test/src/lib.rs @@ -91,12 +91,11 @@ //! use anyhow::{Context, Result, bail}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; use hif::*; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::*; use std::fmt; use std::fs::OpenOptions; @@ -104,7 +103,7 @@ use std::io::{BufWriter, Write}; #[derive(Parser, Debug)] #[clap(name = "test", about = env!("CARGO_PKG_DESCRIPTION"))] -struct TestArgs { +pub struct TestArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 3000, value_name = "timeout_ms", @@ -161,8 +160,7 @@ impl fmt::Display for TestResult { } } -fn test(context: &mut ExecutionContext) -> Result<()> { - let subargs = TestArgs::try_parse_from(&context.cli.cmd)?; +fn test(subargs: TestArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -286,6 +284,9 @@ fn test(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: TestArgs::command(), name: "test", run: test } +pub type Args = TestArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + test(args, context) + } } diff --git a/cmd/tofino-eeprom/Cargo.toml b/cmd/tofino-eeprom/Cargo.toml index 147e56162..c71d91d0d 100644 --- a/cmd/tofino-eeprom/Cargo.toml +++ b/cmd/tofino-eeprom/Cargo.toml @@ -11,7 +11,6 @@ indicatif.workspace = true parse_int.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/tofino-eeprom/src/lib.rs b/cmd/tofino-eeprom/src/lib.rs index 833685f6c..47cbd5eac 100644 --- a/cmd/tofino-eeprom/src/lib.rs +++ b/cmd/tofino-eeprom/src/lib.rs @@ -7,13 +7,12 @@ //! Tools to interact with the Tofino EEPROM use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use indicatif::{ProgressBar, ProgressStyle}; use humility::core::Core; use humility::hubris::*; -use humility_cmd::Command; use humility_hiffy::HiffyContext; use humility_idol::{HubrisIdol, IdolArgument}; @@ -25,7 +24,7 @@ const EEPROM_SIZE_BYTES: usize = 65536; #[derive(Parser, Debug)] #[clap(name = "tofino-eeprom", about = env!("CARGO_PKG_DESCRIPTION"))] -struct EepromArgs { +pub struct EepromArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 15000, value_name = "timeout_ms", @@ -140,8 +139,7 @@ impl<'a> EepromHandler<'a> { //////////////////////////////////////////////////////////////////////////////// -fn eeprom(context: &mut ExecutionContext) -> Result<()> { - let subargs = EepromArgs::try_parse_from(&context.cli.cmd)?; +fn eeprom(subargs: EepromArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; let mut worker = EepromHandler::new(hubris, core, subargs.timeout)?; @@ -159,6 +157,9 @@ fn eeprom(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: EepromArgs::command(), name: "tofino-eeprom", run: eeprom } +pub type Args = EepromArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + eeprom(args, context) + } } diff --git a/cmd/validate/Cargo.toml b/cmd/validate/Cargo.toml index 1893fe535..4daaef862 100644 --- a/cmd/validate/Cargo.toml +++ b/cmd/validate/Cargo.toml @@ -13,7 +13,6 @@ parse_int.workspace = true idol.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/validate/src/lib.rs b/cmd/validate/src/lib.rs index 3b7707afc..36c46f9bd 100644 --- a/cmd/validate/src/lib.rs +++ b/cmd/validate/src/lib.rs @@ -43,19 +43,18 @@ //! use anyhow::{Result, anyhow}; -use clap::{CommandFactory, Parser}; +use clap::Parser; use colored::Colorize; use hif::*; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use humility_cli::{ExecutionContext, HumilitySubcommand}; use humility_hiffy::{HiffyContext, IpcError}; use humility_i2c::I2cArgs; use humility_idol::{self as idol, HubrisIdol}; #[derive(Parser, Debug)] #[clap(name = "validate", about = env!("CARGO_PKG_DESCRIPTION"))] -struct ValidateArgs { +pub struct ValidateArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -131,8 +130,10 @@ fn list(hubris: &HubrisArchive, hargs: &Option) -> Result<()> { Ok(()) } -fn validate(context: &mut ExecutionContext) -> Result<()> { - let subargs = ValidateArgs::try_parse_from(&context.cli.cmd)?; +fn validate( + subargs: ValidateArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -273,6 +274,9 @@ fn validate(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: ValidateArgs::command(), name: "validate", run: validate } +pub type Args = ValidateArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + validate(args, context) + } } diff --git a/cmd/vpd/src/lib.rs b/cmd/vpd/src/lib.rs index 6f7334fcb..b9b9f807d 100644 --- a/cmd/vpd/src/lib.rs +++ b/cmd/vpd/src/lib.rs @@ -103,12 +103,12 @@ //! will be locked and the command will return with a *non-zero* exit status. use anyhow::{Context, Result, bail}; -use clap::{ArgGroup, CommandFactory, Parser}; +use clap::{ArgGroup, Parser}; use hif::*; use humility::core::Core; use humility::hubris::*; -use humility_cli::ExecutionContext; -use humility_cmd::{Command, Dumper}; +use humility_cli::{ExecutionContext, HumilitySubcommand}; +use humility_cmd::Dumper; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; use indicatif::{ProgressBar, ProgressStyle}; @@ -120,7 +120,7 @@ use std::io::{Read, Seek, SeekFrom, Write}; name = "vpd", about = env!("CARGO_PKG_DESCRIPTION"), group = ArgGroup::new("command").multiple(false), )] -struct VpdArgs { +pub struct VpdArgs { /// sets timeout #[clap( long, short = 'T', default_value_t = 5000, value_name = "timeout_ms", @@ -711,8 +711,7 @@ fn vpd_lock_all( Ok(()) } -fn vpd(context: &mut ExecutionContext) -> Result<()> { - let subargs = VpdArgs::try_parse_from(&context.cli.cmd)?; +fn vpd(subargs: VpdArgs, context: &mut ExecutionContext) -> Result<()> { let hubris = &context.cli.archive()?; let core = &mut *context.cli.attach_live_booted(hubris)?; @@ -733,6 +732,9 @@ fn vpd(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: VpdArgs::command(), name: "vpd", run: vpd } +pub type Args = VpdArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + vpd(args, context) + } } diff --git a/cmd/writeword/Cargo.toml b/cmd/writeword/Cargo.toml index e89f7f569..59ebbf44e 100644 --- a/cmd/writeword/Cargo.toml +++ b/cmd/writeword/Cargo.toml @@ -7,7 +7,6 @@ description = "writes one or more memory words" [dependencies] humility = { workspace = true } humility-cli = { workspace = true } -humility-cmd = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } parse_int = { workspace = true } diff --git a/cmd/writeword/src/lib.rs b/cmd/writeword/src/lib.rs index a031fe945..db8dc4ffa 100644 --- a/cmd/writeword/src/lib.rs +++ b/cmd/writeword/src/lib.rs @@ -48,13 +48,12 @@ //! use anyhow::{Result, bail}; -use clap::{CommandFactory, Parser}; -use humility_cli::ExecutionContext; -use humility_cmd::Command; +use clap::Parser; +use humility_cli::{ExecutionContext, HumilitySubcommand}; #[derive(Parser, Debug)] #[clap(name = "writeword", about = env!("CARGO_PKG_DESCRIPTION"))] -struct WritewordArgs { +pub struct WritewordArgs { /// address to write to #[clap(value_parser = parse_int::parse::,)] address: u32, @@ -64,8 +63,10 @@ struct WritewordArgs { value: Vec, } -fn writeword(context: &mut ExecutionContext) -> Result<()> { - let subargs = WritewordArgs::try_parse_from(&context.cli.cmd)?; +fn writeword( + subargs: WritewordArgs, + context: &mut ExecutionContext, +) -> Result<()> { let hubris = context.cli.try_archive()?; let core = &mut *context.cli.attach_probe(hubris.as_ref())?; if subargs.address & 0b11 != 0 { @@ -81,6 +82,9 @@ fn writeword(context: &mut ExecutionContext) -> Result<()> { Ok(()) } -pub fn init() -> Command { - Command { app: WritewordArgs::command(), name: "writeword", run: writeword } +pub type Args = WritewordArgs; +impl HumilitySubcommand for Args { + fn run(args: Args, context: &mut ExecutionContext) -> Result<()> { + writeword(args, context) + } } diff --git a/humility-bin/Cargo.toml b/humility-bin/Cargo.toml index 485929ecc..191ee98af 100644 --- a/humility-bin/Cargo.toml +++ b/humility-bin/Cargo.toml @@ -22,8 +22,9 @@ version = "0.12.17" license = "MPL-2.0" [build-dependencies] -cargo_metadata = { workspace = true } anyhow = { workspace = true } +cargo_metadata = { workspace = true } +heck = { workspace = true } # Any dependency marked with option is to allow compiling without libusb [dependencies] @@ -118,4 +119,3 @@ probes = ["humility-cli/probes", "cmd-reset", "cmd-lsusb", "cmd-flash", "cmd-deb [[bin]] name = "humility" path = "src/main.rs" - diff --git a/humility-bin/build.rs b/humility-bin/build.rs index aa4b7d62f..6d12f2f56 100644 --- a/humility-bin/build.rs +++ b/humility-bin/build.rs @@ -3,6 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use anyhow::Result; +use heck::*; use std::collections::BTreeSet; use std::env; use std::fs::File; @@ -26,47 +27,78 @@ fn main() -> Result<()> { write!( output, r##" - -// -// Our generated command description. -// -struct CommandDescription {{ - init: fn() -> Command, - docmsg: &'static str, -}} - -fn dcmds() -> Vec {{ - vec![ +#[derive(::clap::Parser, Debug)] +pub enum Subcommand {{ "## )?; + // + let banned = if std::env::var_os("CARGO_FEATURE_PROBES").is_none() { + // These are everything that can potentially pull in libusb + ["probe-rs", "humility-probes-core", "rusb"].into_iter().collect() + } else { + BTreeSet::new() + }; for id in &metadata.workspace_members { let package = metadata.packages.iter().find(|p| &p.id == id).unwrap().clone(); - if let Some(cmd) = package.name.strip_prefix("humility-cmd-") { - if std::env::var_os("CARGO_FEATURE_PROBES").is_none() && - // These are everything that can potentially pull in libusb - package.dependencies.iter().any(|d| d.name == "probe-rs" || d.name == "humility-probes-core" || d.name == "rusb") - { - continue; - } - cmds.insert(cmd.to_string().replace('-', "_")); + if let Some(cmd) = package.name.strip_prefix("humility-cmd-") + && !package.dependencies.iter().any(|d| banned.contains(&*d.name)) + { + cmds.insert(cmd.to_string()); } } for cmd in cmds.iter() { writeln!( output, - r##" CommandDescription {{ - init: cmd_{}::init, - docmsg: "For additional documentation, run \"humility doc {}\"." - }},"##, - cmd, cmd + " {}(cmd_{}::Args),", + cmd.to_upper_camel_case(), + cmd.to_snake_case() )?; } - write!(output, " ]\n}}")?; + writeln!( + output, + "}} + +pub fn dispatch(c: Subcommand, ctx: &mut ::humility_cli::ExecutionContext) -> anyhow::Result<()> {{ + use ::humility_cli::HumilitySubcommand; + match c {{" + )?; + for cmd in cmds.iter() { + writeln!( + output, + " Subcommand::{}(args) => cmd_{}::Args::run(args, ctx),", + cmd.to_upper_camel_case(), + cmd.to_snake_case(), + )?; + } + writeln!( + output, + " }} +}} + +pub fn name(c: &Subcommand) -> String {{ + use ::clap::{{CommandFactory}}; + match c {{ + " + )?; + + for cmd in cmds.iter() { + writeln!( + output, + " Subcommand::{}(_) => cmd_{}::Args::command().get_name().to_owned(),", + cmd.to_upper_camel_case(), + cmd.to_snake_case(), + )?; + } + writeln!( + output, + " }} +}}" + )?; Ok(()) } diff --git a/humility-bin/src/cmd.rs b/humility-bin/src/cmd.rs index c2d8d8d76..c48cf0ea0 100644 --- a/humility-bin/src/cmd.rs +++ b/humility-bin/src/cmd.rs @@ -2,49 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use anyhow::{Context, Result}; -use clap::Command as ClapCommand; -use humility_cli::ExecutionContext; -use humility_cmd::Command; -use std::collections::HashMap; - -// -// Our build.rs creates cmds.rs, which looks at our workspace to assemble -// the commands, and creates a function (`dcmds`) that we call to get -// a vector of them. -// +// Our `build.rs` creates `cmds.rs`, which looks at our workspace to assemble +// the commands, and creates an `enum Subcommand` with all subcommands include!(concat!(env!("OUT_DIR"), "/cmds.rs")); - -pub fn init( - command: ClapCommand, -) -> (HashMap<&'static str, Command>, ClapCommand) { - let mut cmds = HashMap::new(); - let mut rval = command; - - let dcmds = dcmds(); - - for dcmd in dcmds { - let cmd = (dcmd.init)(); - let app = cmd.app.clone(); - let name = cmd.name; - - cmds.insert(name, cmd); - - rval = rval.subcommand(app.after_help(dcmd.docmsg)); - } - - (cmds, rval) -} - -pub fn subcommand( - context: &mut ExecutionContext, - commands: &HashMap<&'static str, Command>, -) -> Result<()> { - let cmd = context.cli.cmd[0].as_str(); - - let command = commands - .get(cmd) - .with_context(|| format!("command {} not found", cmd))?; - - (command.run)(context) -} diff --git a/humility-bin/src/main.rs b/humility-bin/src/main.rs index f122ced2c..45be823a6 100644 --- a/humility-bin/src/main.rs +++ b/humility-bin/src/main.rs @@ -2,45 +2,70 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use std::collections::HashMap; -use std::ffi::OsString; - -use clap::ArgMatches; -use humility_cli::Cli; -use humility_cmd::Command; - -use anyhow::Result; -use clap::CommandFactory; -use clap::FromArgMatches; -use clap::Parser; - +use clap::{ArgGroup, CommandFactory, FromArgMatches, Parser}; mod cmd; +use humility_cli::{Cli, ExecutionContext}; + +/// Main CLI entry point +/// +/// The distinction between [`Cli`] and [`OuterCli`] is necessary to break a +/// dependency loop: the `Cli` is stored in the [`ExecutionContext`]; commands +/// need to take the `ExecutionContext`; and the `OuterCli` needs to depend on +/// commands. +#[derive(Parser, Debug)] +#[clap( + name = "humility", max_term_width = 80, + group = ArgGroup::new("hubris").multiple(false), + disable_version_flag = true, +)] +struct OuterCli { + #[clap(flatten)] + cli: Cli, + + #[clap(subcommand)] + cmd: Option, +} -fn main() -> Result<()> { - let (commands, m, args) = match parse_args(std::env::args_os()) { - Some(s) => s, - None => std::process::exit(1), +fn main() -> std::process::ExitCode { + let m = OuterCli::command().get_matches(); + let outer_cli = match OuterCli::from_arg_matches(&m) { + Ok(c) => c, + Err(e) => { + eprint!("{e:#}"); + return std::process::ExitCode::FAILURE; + } }; - - if let Some(s) = version(&args) { - println!("{}", s); - std::process::exit(0); + let OuterCli { cli, cmd } = outer_cli; + if let Some(s) = version(&cli) { + eprintln!("{s}"); + return std::process::ExitCode::SUCCESS; }; - let mut context = humility_cli::ExecutionContext::new(args.clone(), &m)?; + let log_level = if cli.verbose { "trace" } else { "warn" }; + let mut context = match ExecutionContext::new(cli, &m) { + Ok(ctx) => ctx, + Err(e) => { + eprintln!("failed to build execution context: {e:#}"); + return std::process::ExitCode::FAILURE; + } + }; - let log_level = if args.verbose { "trace" } else { "warn" }; + let Some(cmd) = cmd else { + eprintln!("humility failed: subcommand expected (--help to list)"); + return std::process::ExitCode::FAILURE; + }; + let name = cmd::name(&cmd); let env = env_logger::Env::default().filter_or("RUST_LOG", log_level); env_logger::init_from_env(env); - if let Err(err) = cmd::subcommand(&mut context, &commands) { - eprintln!("humility {} failed: {:?}", args.cmd[0], err); - std::process::exit(1); + if let Err(err) = cmd::dispatch(cmd, &mut context) { + eprintln!("humility {name} failed: {:?}", err); + std::process::ExitCode::FAILURE + } else { + std::process::ExitCode::SUCCESS } - - Ok(()) } #[cfg(feature = "probes")] @@ -62,42 +87,7 @@ pub(crate) fn version(cli: &Cli) -> Option { } } -pub(crate) fn parse_args( - input: I, -) -> Option<(HashMap<&'static str, Command>, ArgMatches, Cli)> -where - I: IntoIterator, - T: Into + Clone, -{ - // This isn't hugely efficient, but we actually parse our arguments - // twice: the first is with our subcommands grafted into our - // arguments to get us a unified help and error message in the event - // of any parsing value or request for a help message; if that works, - // we parse our arguments again but relying on the - // external_subcommand to directive to allow our subcommand to do any - // parsing on its own. - let (commands, command) = cmd::init(Cli::command()); - - let input: Vec<_> = input.into_iter().collect(); - let input2 = input.clone(); - - let m = match command.try_get_matches_from(input) { - Ok(m) => m, - Err(e) => { - e.print().unwrap(); - return None; - } - }; - - let _args = Cli::from_arg_matches(&m); - - // If we're here, we know that our arguments pass muster from the Clap - // perspective. - Some((commands, m, Cli::parse_from(input2))) -} - #[test] fn validate_clap() { - let (_, clap) = cmd::init(Cli::command()); - clap.clone().debug_assert(); + OuterCli::command().debug_assert() } diff --git a/humility-cli/src/lib.rs b/humility-cli/src/lib.rs index 5fea7801f..ab3f29470 100644 --- a/humility-cli/src/lib.rs +++ b/humility-cli/src/lib.rs @@ -5,7 +5,7 @@ pub mod env; use anyhow::{Context, Result, anyhow, bail}; -use clap::{ArgGroup, ArgMatches, Parser, parser::ValueSource}; +use clap::{ArgMatches, Parser, parser::ValueSource}; use env::Environment; use humility::{ core::Core, @@ -15,11 +15,6 @@ use humility::{ use std::time::Duration; #[derive(Parser, Debug, Clone)] -#[clap( - name = "humility", max_term_width = 80, - group = ArgGroup::new("hubris").multiple(false), - disable_version_flag = true, -)] pub struct Cli { /// verbose messages #[clap(long, short)] @@ -114,10 +109,6 @@ pub struct Cli { conflicts_with = "hubris" )] pub list_targets: bool, - - /// Subcommand to execute - #[clap(trailing_var_arg = true)] - pub cmd: Vec, } impl Cli { @@ -336,6 +327,11 @@ impl Cli { } } +/// Trait representing a Humility subcommand +pub trait HumilitySubcommand: Parser { + fn run(args: Self, context: &mut ExecutionContext) -> Result<()>; +} + pub struct ExecutionContext { pub environment: Option, pub cli: Cli, @@ -477,11 +473,6 @@ impl ExecutionContext { _ => None, }; - if cli.cmd.is_empty() { - eprintln!("humility failed: subcommand expected (--help to list)"); - std::process::exit(1); - } - // // Check to see if we have both a dump and an archive. Because these // conflict with one another but because we allow both of them to be diff --git a/humility-cmd/Cargo.toml b/humility-cmd/Cargo.toml index 53a0c6b8d..eeb30f08e 100644 --- a/humility-cmd/Cargo.toml +++ b/humility-cmd/Cargo.toml @@ -2,10 +2,3 @@ name = "humility-cmd" version = "0.1.0" edition.workspace = true - -[dependencies] -anyhow.workspace = true -clap.workspace = true - -humility.workspace = true -humility-cli.workspace = true diff --git a/humility-cmd/src/lib.rs b/humility-cmd/src/lib.rs index 83e1a9223..3e8a4d516 100644 --- a/humility-cmd/src/lib.rs +++ b/humility-cmd/src/lib.rs @@ -2,21 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use anyhow::Result; -use clap::Command as ClapCommand; - -pub struct Command { - pub app: ClapCommand, - pub name: &'static str, - pub run: fn(&mut humility_cli::ExecutionContext) -> Result<()>, -} - -impl Command { - pub fn short_description(&self) -> String { - self.app.get_about().unwrap().to_string() - } -} - pub struct Dumper { /// Word size, in bytes pub size: usize, From 00588c884c629aadde89cec8f3982f3be2e02c6c Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Wed, 13 May 2026 14:35:45 -0700 Subject: [PATCH 5/9] Rename humility-cmd -> humility-hexdump --- Cargo.lock | 34 +++++++++---------- Cargo.toml | 4 +-- cmd/gimlet/Cargo.toml | 2 +- cmd/gimlet/src/lib.rs | 2 +- cmd/hiffy/Cargo.toml | 2 +- cmd/hiffy/src/lib.rs | 2 +- cmd/i2c/Cargo.toml | 2 +- cmd/i2c/src/lib.rs | 2 +- cmd/ibc/Cargo.toml | 4 +-- cmd/lpc55gpio/Cargo.toml | 2 +- cmd/qspi/Cargo.toml | 2 +- cmd/qspi/src/lib.rs | 2 +- cmd/readmem/Cargo.toml | 2 +- cmd/readmem/src/lib.rs | 2 +- cmd/rencm/Cargo.toml | 2 +- cmd/rencm/src/lib.rs | 2 +- cmd/spctrl/Cargo.toml | 2 +- cmd/spctrl/src/lib.rs | 2 +- cmd/spi/Cargo.toml | 2 +- cmd/spi/src/lib.rs | 2 +- cmd/stackmargin/Cargo.toml | 2 +- cmd/vpd/Cargo.toml | 2 +- cmd/vpd/src/lib.rs | 2 +- humility-bin/Cargo.toml | 2 +- {humility-cmd => humility-hexdump}/Cargo.toml | 2 +- {humility-cmd => humility-hexdump}/src/lib.rs | 0 26 files changed, 43 insertions(+), 43 deletions(-) rename {humility-cmd => humility-hexdump}/Cargo.toml (67%) rename {humility-cmd => humility-hexdump}/src/lib.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index b65aa0219..a211d72eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1639,7 +1639,6 @@ dependencies = [ "heck", "hif", "humility-cli", - "humility-cmd", "humility-cmd-auxflash", "humility-cmd-console-proxy", "humility-cmd-counters", @@ -1697,6 +1696,7 @@ dependencies = [ "humility-cmd-writeword", "humility-core", "humility-cortex", + "humility-hexdump", "indexmap 2.14.0", "indicatif", "jep106 0.3.0", @@ -1729,10 +1729,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "humility-cmd" -version = "0.1.0" - [[package]] name = "humility-cmd-auxflash" version = "0.1.0" @@ -1942,8 +1938,8 @@ dependencies = [ "gimlet-inspector-protocol", "hubpack", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "indexmap 2.14.0", "parse_int", "serde", @@ -1985,8 +1981,8 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-hiffy", "humility-idol", "idol", @@ -2041,7 +2037,7 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", + "humility-hexdump", "humility-hiffy", "humility-i2c", "humility-log", @@ -2058,8 +2054,8 @@ dependencies = [ "colored", "hif", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-hiffy", "humility-idol", "idol", @@ -2088,7 +2084,7 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", + "humility-hexdump", "humility-hiffy", "parse_int", ] @@ -2257,8 +2253,8 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-hiffy", "humility-idol", "indicatif", @@ -2274,8 +2270,8 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-log", "parse-size", "parse_int", @@ -2332,8 +2328,8 @@ dependencies = [ "csv", "hif", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-hiffy", "humility-i2c", "idt8a3xxxx", @@ -2433,7 +2429,7 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", + "humility-hexdump", "humility-hiffy", "parse_int", ] @@ -2464,8 +2460,8 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-hiffy", "parse_int", ] @@ -2477,8 +2473,8 @@ dependencies = [ "anyhow", "clap", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", ] [[package]] @@ -2564,8 +2560,8 @@ dependencies = [ "clap", "hif", "humility-cli", - "humility-cmd", "humility-core", + "humility-hexdump", "humility-hiffy", "humility-idol", "idol", @@ -2679,6 +2675,10 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "humility-hexdump" +version = "0.1.0" + [[package]] name = "humility-hiffy" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index b82bac501..3ea6b7608 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,11 @@ members = [ "humility-arch-cortex", "humility-auxflash", "humility-bin", - "humility-cmd", "humility-cli", "humility-core", "humility-doppel", "humility-dump-agent", + "humility-hexdump", "humility-hiffy", "humility-i2c", "humility-idol", @@ -114,10 +114,10 @@ humility = { path = "./humility-core", package = "humility-core" } humility-arch-arm = { path = "./humility-arch-arm" } humility-auxflash = { path = "./humility-auxflash" } humility-cortex = { path = "./humility-arch-cortex" } -humility-cmd = { path = "./humility-cmd" } humility-cli = { path = "./humility-cli", default-features = false } humility-dump-agent = { path = "./humility-dump-agent" } humility-doppel = { path = "./humility-doppel" } +humility-hexdump = { path = "./humility-hexdump" } humility-hiffy = { path = "./humility-hiffy" } humility-i2c = { path = "./humility-i2c" } humility-idol = { path = "./humility-idol" } diff --git a/cmd/gimlet/Cargo.toml b/cmd/gimlet/Cargo.toml index 9bf93c8bc..cc948232c 100644 --- a/cmd/gimlet/Cargo.toml +++ b/cmd/gimlet/Cargo.toml @@ -6,8 +6,8 @@ description = "Gimlet-specific diagnostic commands" [dependencies] humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true hubpack.workspace = true gimlet-inspector-protocol.workspace = true diff --git a/cmd/gimlet/src/lib.rs b/cmd/gimlet/src/lib.rs index 940ac577e..db7aa1fae 100644 --- a/cmd/gimlet/src/lib.rs +++ b/cmd/gimlet/src/lib.rs @@ -20,7 +20,7 @@ use anyhow::{Context, Result, bail}; use clap::{ArgGroup, Parser}; use humility::net::ScopedV6Addr; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; /// This is defined in the gimlet TOML. const HARDCODED_PORT: u16 = 23547; diff --git a/cmd/hiffy/Cargo.toml b/cmd/hiffy/Cargo.toml index 0533a12c0..60f873805 100644 --- a/cmd/hiffy/Cargo.toml +++ b/cmd/hiffy/Cargo.toml @@ -14,7 +14,7 @@ hif.workspace = true idol.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/hiffy/src/lib.rs b/cmd/hiffy/src/lib.rs index 0ee677674..208b0c92f 100644 --- a/cmd/hiffy/src/lib.rs +++ b/cmd/hiffy/src/lib.rs @@ -51,7 +51,7 @@ use clap::Parser; use humility::hubris::*; use humility::warn; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use humility_idol as idol; use std::io::IsTerminal; diff --git a/cmd/i2c/Cargo.toml b/cmd/i2c/Cargo.toml index 5d2716a71..52c4af448 100644 --- a/cmd/i2c/Cargo.toml +++ b/cmd/i2c/Cargo.toml @@ -13,7 +13,7 @@ indicatif.workspace = true hif.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true humility-i2c.workspace = true humility-log.workspace = true diff --git a/cmd/i2c/src/lib.rs b/cmd/i2c/src/lib.rs index 1c335d2a5..24f02beef 100644 --- a/cmd/i2c/src/lib.rs +++ b/cmd/i2c/src/lib.rs @@ -94,7 +94,7 @@ use anyhow::{Result, bail}; use clap::Parser; use hif::*; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use humility_log::msg; diff --git a/cmd/ibc/Cargo.toml b/cmd/ibc/Cargo.toml index 95231a519..485c84d60 100644 --- a/cmd/ibc/Cargo.toml +++ b/cmd/ibc/Cargo.toml @@ -12,10 +12,10 @@ parse_int.workspace = true zerocopy.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true -humility-idol.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true +humility-idol.workspace = true hif.workspace = true idol.workspace = true diff --git a/cmd/lpc55gpio/Cargo.toml b/cmd/lpc55gpio/Cargo.toml index 94238ca59..80b7007b1 100644 --- a/cmd/lpc55gpio/Cargo.toml +++ b/cmd/lpc55gpio/Cargo.toml @@ -11,5 +11,5 @@ anyhow.workspace = true parse_int.workspace = true humility-cli.workspace = true -humility-cmd.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true diff --git a/cmd/qspi/Cargo.toml b/cmd/qspi/Cargo.toml index d13c31fe5..a55201c72 100644 --- a/cmd/qspi/Cargo.toml +++ b/cmd/qspi/Cargo.toml @@ -14,7 +14,7 @@ log.workspace = true sha2.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true diff --git a/cmd/qspi/src/lib.rs b/cmd/qspi/src/lib.rs index e2218fc55..53b036aff 100644 --- a/cmd/qspi/src/lib.rs +++ b/cmd/qspi/src/lib.rs @@ -84,7 +84,7 @@ use humility::core::Core; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use humility_idol::{HubrisIdol, IdolArgument}; use sha2::{Digest, Sha256}; diff --git a/cmd/readmem/Cargo.toml b/cmd/readmem/Cargo.toml index dfb1962d2..76db57373 100644 --- a/cmd/readmem/Cargo.toml +++ b/cmd/readmem/Cargo.toml @@ -6,8 +6,8 @@ description = "read and display memory region" [dependencies] humility = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } +humility-hexdump = { workspace = true } humility-log = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/readmem/src/lib.rs b/cmd/readmem/src/lib.rs index 948b5d462..d65b23721 100644 --- a/cmd/readmem/src/lib.rs +++ b/cmd/readmem/src/lib.rs @@ -119,7 +119,7 @@ use anyhow::{Result, bail}; use clap::Parser; use humility::hubris::*; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use std::convert::TryInto; use std::io::Write; use std::path::PathBuf; diff --git a/cmd/rencm/Cargo.toml b/cmd/rencm/Cargo.toml index 1de586534..f99f09c9d 100644 --- a/cmd/rencm/Cargo.toml +++ b/cmd/rencm/Cargo.toml @@ -16,7 +16,7 @@ serde.workspace = true csv.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true humility-i2c.workspace = true diff --git a/cmd/rencm/src/lib.rs b/cmd/rencm/src/lib.rs index c91034175..b8eab358f 100644 --- a/cmd/rencm/src/lib.rs +++ b/cmd/rencm/src/lib.rs @@ -11,7 +11,7 @@ use humility::core::Core; use humility::hubris::*; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use humility_i2c::I2cArgs; diff --git a/cmd/spctrl/Cargo.toml b/cmd/spctrl/Cargo.toml index 010ec9933..b2098e6ab 100644 --- a/cmd/spctrl/Cargo.toml +++ b/cmd/spctrl/Cargo.toml @@ -10,6 +10,6 @@ clap.workspace = true anyhow.workspace = true parse_int.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true diff --git a/cmd/spctrl/src/lib.rs b/cmd/spctrl/src/lib.rs index 68d8973e4..810f9cb5a 100644 --- a/cmd/spctrl/src/lib.rs +++ b/cmd/spctrl/src/lib.rs @@ -45,7 +45,7 @@ //! ``` use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use std::str; diff --git a/cmd/spi/Cargo.toml b/cmd/spi/Cargo.toml index 91c06f875..8d553d93b 100644 --- a/cmd/spi/Cargo.toml +++ b/cmd/spi/Cargo.toml @@ -11,6 +11,6 @@ anyhow.workspace = true parse_int.workspace = true humility.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true diff --git a/cmd/spi/src/lib.rs b/cmd/spi/src/lib.rs index 1d842afe1..362498904 100644 --- a/cmd/spi/src/lib.rs +++ b/cmd/spi/src/lib.rs @@ -34,7 +34,7 @@ use humility::hubris::*; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use std::convert::TryInto; diff --git a/cmd/stackmargin/Cargo.toml b/cmd/stackmargin/Cargo.toml index c0495b6cf..b5334228d 100644 --- a/cmd/stackmargin/Cargo.toml +++ b/cmd/stackmargin/Cargo.toml @@ -6,7 +6,7 @@ description = "calculate and print stack margins by task" [dependencies] humility = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true } +humility-hexdump = { workspace = true } clap = { workspace = true } anyhow = { workspace = true } diff --git a/cmd/vpd/Cargo.toml b/cmd/vpd/Cargo.toml index 463dff275..0c48d723a 100644 --- a/cmd/vpd/Cargo.toml +++ b/cmd/vpd/Cargo.toml @@ -18,8 +18,8 @@ indicatif.workspace = true serde.workspace = true ron.workspace = true -humility-cmd.workspace = true humility-cli.workspace = true +humility-hexdump.workspace = true humility-hiffy.workspace = true humility-idol.workspace = true humility.workspace = true diff --git a/cmd/vpd/src/lib.rs b/cmd/vpd/src/lib.rs index b9b9f807d..9faad5a18 100644 --- a/cmd/vpd/src/lib.rs +++ b/cmd/vpd/src/lib.rs @@ -108,7 +108,7 @@ use hif::*; use humility::core::Core; use humility::hubris::*; use humility_cli::{ExecutionContext, HumilitySubcommand}; -use humility_cmd::Dumper; +use humility_hexdump::Dumper; use humility_hiffy::*; use humility_idol::{self as idol, HubrisIdol}; use indicatif::{ProgressBar, ProgressStyle}; diff --git a/humility-bin/Cargo.toml b/humility-bin/Cargo.toml index 191ee98af..a8b4fc3de 100644 --- a/humility-bin/Cargo.toml +++ b/humility-bin/Cargo.toml @@ -33,8 +33,8 @@ hif = { workspace = true } spd = { workspace = true } humility = { workspace = true } humility-cortex = { workspace = true } -humility-cmd = { workspace = true } humility-cli = { workspace = true, default-features = false } +humility-hexdump = { workspace = true } cmd-auxflash = { workspace = true } cmd-console-proxy = { workspace = true } cmd-counters = { workspace = true } diff --git a/humility-cmd/Cargo.toml b/humility-hexdump/Cargo.toml similarity index 67% rename from humility-cmd/Cargo.toml rename to humility-hexdump/Cargo.toml index eeb30f08e..1229ec99a 100644 --- a/humility-cmd/Cargo.toml +++ b/humility-hexdump/Cargo.toml @@ -1,4 +1,4 @@ [package] -name = "humility-cmd" +name = "humility-hexdump" version = "0.1.0" edition.workspace = true diff --git a/humility-cmd/src/lib.rs b/humility-hexdump/src/lib.rs similarity index 100% rename from humility-cmd/src/lib.rs rename to humility-hexdump/src/lib.rs From 4c980caab88330a0036226d0335def052144035f Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Wed, 13 May 2026 14:42:00 -0700 Subject: [PATCH 6/9] Update README --- DEVELOPING.mkdn | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/DEVELOPING.mkdn b/DEVELOPING.mkdn index cdb27bbbc..de08cfc6e 100644 --- a/DEVELOPING.mkdn +++ b/DEVELOPING.mkdn @@ -36,11 +36,7 @@ So you've decided to add a subcommand to Humility. Here's what you need to do. make sure any new name starts with `humility-cmd-` (e.g. `humility-cmd-yourcommand`). -2. Review the settings in the `init` routine you cribbed from to make sure they - reflect your subcommand. In particular, the name must appear a second time in - the `name:` field. - -3. Cite your new subcommand from the root `Cargo.toml`. This needs to happen in +2. Cite your new subcommand from the root `Cargo.toml`. This needs to happen in three places using two different names: in the `workspace.members` element using the relative path (e.g. `cmd/yourcommand`); in the `workspace.dependencies` section using the name of your package with the @@ -48,10 +44,10 @@ So you've decided to add a subcommand to Humility. Here's what you need to do. `dependencies` table with a line reading `cmd-yourcommand = {workspace = true}`. -4. Regenerate the README file by running `cargo xtask readme`. The `xtask` bit +3. Regenerate the README file by running `cargo xtask readme`. The `xtask` bit there is very important. -5. If you're adding a new command, you almost certainly want to bump Humility's +4. If you're adding a new command, you almost certainly want to bump Humility's patch version. This makes it easier to tell whether users have the command. Doing this requires an extra step compared to a normal Rust package; see the previous section in this file. From 2adabfa0f9f4d187e5d09229e5fae79030a1e1e8 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 21 May 2026 12:11:56 -0400 Subject: [PATCH 7/9] Introduce extension trait for attaching This saves some steps for humility as a library --- humility-probes-core/src/lib.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/humility-probes-core/src/lib.rs b/humility-probes-core/src/lib.rs index 89ca2e881..e813cfeac 100644 --- a/humility-probes-core/src/lib.rs +++ b/humility-probes-core/src/lib.rs @@ -227,3 +227,16 @@ pub fn attach_for_flashing( ) -> Result> { attach_to_chip(probe, Some(chip), speed_khz) } + +/// Extension trait to make it easier for libraries to attach +/// to chips. It is encourageed to extend this trait as +/// needed to make developer's lives easier. +pub trait HubrisAttach { + fn attach(&self, probe: &str) -> Result>; +} + +impl HubrisAttach for humility::hubris::HubrisArchive { + fn attach(&self, probe: &str) -> Result> { + attach_to_chip(probe, self.chip().as_deref(), None) + } +} From ed75a4f37e17aff33689da6ea499073a63ccc884 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 21 May 2026 11:58:41 -0400 Subject: [PATCH 8/9] Add `HubrisArchive::load_from_path` For library functions this is a nice shortcut if we don't need to directly manipulate the `RawHubrisArchive` --- humility-core/src/hubris.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/humility-core/src/hubris.rs b/humility-core/src/hubris.rs index effb7eb79..773deafa1 100644 --- a/humility-core/src/hubris.rs +++ b/humility-core/src/hubris.rs @@ -1336,6 +1336,13 @@ impl HubrisArchive { inlined } + pub fn load_from_path + std::fmt::Debug + Copy>( + path: P, + ) -> Result { + let hubris = RawHubrisArchive::load(path)?; + Self::load(hubris, None) + } + pub fn load( hubris: RawHubrisArchive, task_dump: Option, From d8440ce777deaa185a2142c3530ae14794d7d057 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Tue, 19 May 2026 15:40:08 -0400 Subject: [PATCH 9/9] I bet this can be improved --- Cargo.lock | 1 + humility-hiffy/Cargo.toml | 4 + humility-hiffy/examples/sequencer.rs | 136 +++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 humility-hiffy/examples/sequencer.rs diff --git a/Cargo.lock b/Cargo.lock index a211d72eb..08dcc85ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2688,6 +2688,7 @@ dependencies = [ "humility-core", "humility-doppel", "humility-idol", + "humility-probes-core", "idol", "log", "postcard", diff --git a/humility-hiffy/Cargo.toml b/humility-hiffy/Cargo.toml index a7b94d3ea..6dd22ef12 100644 --- a/humility-hiffy/Cargo.toml +++ b/humility-hiffy/Cargo.toml @@ -15,3 +15,7 @@ humility.workspace = true humility-doppel.workspace = true humility-idol.workspace = true log.workspace = true + +[dev-dependencies] +humility-probes-core.workspace = true + diff --git a/humility-hiffy/examples/sequencer.rs b/humility-hiffy/examples/sequencer.rs new file mode 100644 index 000000000..a5000e544 --- /dev/null +++ b/humility-hiffy/examples/sequencer.rs @@ -0,0 +1,136 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +use humility::core::Core; +use humility::hubris::HubrisArchive; +use humility_idol::HubrisIdol; +use humility_probes_core::HubrisAttach; + +#[derive(Debug, PartialEq, Eq)] +struct FixYourParsing; + +#[derive(Debug)] +enum PowerState { + A2, + A2PlusFans, + A0, + A0PlusHP, + A0Thermtrip, + A0Reset, +} + +impl PowerState { + fn to_string(&self) -> String { + match self { + PowerState::A2 => "A2".to_string(), + PowerState::A2PlusFans => "A2PlusFans".to_string(), + PowerState::A0 => "A0".to_string(), + PowerState::A0PlusHP => "A0PlusHP".to_string(), + PowerState::A0Thermtrip => "A0Thermtrip".to_string(), + PowerState::A0Reset => "A0Reset".to_string(), + } + } +} + +impl std::str::FromStr for PowerState { + type Err = FixYourParsing; + + fn from_str(s: &str) -> Result { + match s { + "A2" => Ok(Self::A2), + "A2PlusFans" => Ok(Self::A2PlusFans), + "A0" => Ok(Self::A0), + "A0PlusHP" => Ok(Self::A0PlusHP), + "A0Thermtrip" => Ok(Self::A0Thermtrip), + "A0Reset" => Ok(Self::A0Reset), + _ => Err(FixYourParsing), + } + } +} + +fn get_power_state( + hubris: &HubrisArchive, + core: &mut dyn Core, + context: &mut humility_hiffy::HiffyContext, +) -> PowerState { + let get_op = hubris.get_idol_command("Sequencer.get_state").unwrap(); + + let state: Result = + humility_hiffy::hiffy_call( + &hubris, + core, + context, + &get_op, + &[], + None, + None, + ) + .map_err(|e| match e { + humility_hiffy::HiffyError::Hiffy(s) => s, + _ => panic!("hmmm this is ugly"), + }); + + let state = humility_hiffy::hiffy_format_result(&hubris, state); + + state.parse::().unwrap() +} + +fn set_power_state( + hubris: &HubrisArchive, + core: &mut dyn Core, + context: &mut humility_hiffy::HiffyContext, + state: PowerState, +) -> String { + let set_op = hubris.get_idol_command("Sequencer.set_state").unwrap(); + + let state = state.to_string(); + let args = vec![("state", humility_idol::IdolArgument::String(&state))]; + + let state: Result = + humility_hiffy::hiffy_call( + &hubris, core, context, &set_op, &args, None, None, + ) + .map_err(|e| match e { + humility_hiffy::HiffyError::Hiffy(s) => s, + _ => panic!("hmmm this is ugly"), + }); + + humility_hiffy::hiffy_format_result(&hubris, state) +} + +fn main() { + let hubris = std::env::var("HUMILITY_ARCHIVE").unwrap(); + let probe = std::env::var("HUMILITY_PROBE").unwrap(); + + let hubris = HubrisArchive::load_from_path(&hubris).unwrap(); + + let core = &mut *hubris.attach(&probe).unwrap(); + + let mut context = humility_hiffy::HiffyContext::new( + &hubris, + core, + std::time::Duration::from_millis(10000), + ) + .unwrap(); + + let state = get_power_state(&hubris, core, &mut context); + + match state { + PowerState::A0 | PowerState::A0PlusHP => { + println!("I'm in A0! going to go to A2 now!"); + let result = + set_power_state(&hubris, core, &mut context, PowerState::A2); + println!("I was {result}"); + } + PowerState::A2 | PowerState::A2PlusFans => { + println!("I'm in A2! going to go to A0 now!"); + let result = + set_power_state(&hubris, core, &mut context, PowerState::A0); + println!("I was {result}"); + } + _ => { + println!("{state:?} makes my state machine too hard"); + } + } +}