umshctl/command/
tables.rs1use anyhow::{Result, bail};
10
11use umsh::ulcp_wire::ids::prop;
12
13use super::persist;
14use super::values::KeyArg;
15use crate::App;
16use crate::output::{address, hex};
17
18#[derive(Debug, clap::Subcommand)]
19pub enum TableOp {
20 List,
22 Add {
24 #[arg(value_name = "KEY")]
25 key: KeyArg,
26 },
27 Remove {
29 #[arg(value_name = "KEY")]
30 key: KeyArg,
31 },
32}
33
34fn digest_text(prop: u32, digest: &[u8]) -> String {
38 if prop == prop::DEV_CHANNEL_KEYS {
39 hex(digest)
40 } else {
41 address(digest)
42 }
43}
44
45pub async fn run(app: &mut App, key: u32, noun: &str, op: Option<TableOp>) -> Result<()> {
46 let no_save = app.no_save;
47 let device = app.device()?;
48 match op.unwrap_or(TableOp::List) {
49 TableOp::List => {
50 let value = device.get_prop(key).await?;
51 let digest_len = if key == prop::DEV_CHANNEL_KEYS { 2 } else { 32 };
52 if value.is_empty() {
53 println!("no device {noun}s provisioned");
54 } else if !value.len().is_multiple_of(digest_len) {
55 bail!("malformed device {noun} listing");
56 } else {
57 for digest in value.chunks(digest_len) {
58 println!("{}", digest_text(key, digest));
59 }
60 }
61 Ok(())
62 }
63 TableOp::Add { key: item } => {
64 let digest = device.insert_prop_item(key, &item.0).await?;
65 println!("device {noun} added (digest {})", digest_text(key, &digest));
66 persist(device, no_save).await
67 }
68 TableOp::Remove { key: item } => {
69 let digest = device.remove_prop_item(key, &item.0).await?;
70 println!(
71 "device {noun} removed (digest {})",
72 digest_text(key, &digest)
73 );
74 persist(device, no_save).await
75 }
76 }
77}