bc_envelope_cli/
utils.rs

1use std::{collections::HashSet, io::Read};
2use anyhow::{ bail, Result };
3use bc_components::XID;
4use bc_envelope::prelude::*;
5use bc_xid::XIDDocument;
6
7pub fn read_password(prompt: &str, password: Option<&str>) -> Result<String> {
8    if let Some(password) = password {
9        Ok(password.to_string())
10    } else {
11        rpassword::prompt_password(prompt).map_err(Into::into)
12    }
13}
14
15pub fn read_argument(argument: Option<&str>) -> Result<String> {
16    let mut string = String::new();
17    if argument.is_none() {
18        std::io::stdin().read_to_string(&mut string)?;
19    } else {
20        string = argument.as_ref().unwrap().to_string();
21    }
22    if string.is_empty() {
23        bail!("No argument provided");
24    }
25    Ok(string.to_string())
26}
27
28pub fn read_envelope(envelope: Option<&str>) -> Result<Envelope> {
29    let mut ur_string = String::new();
30    if envelope.is_none() {
31        std::io::stdin().read_line(&mut ur_string)?;
32    } else {
33        ur_string = envelope.as_ref().unwrap().to_string();
34    }
35    if ur_string.is_empty() {
36        bail!("No envelope provided");
37    }
38    // Just try to parse the envelope as a ur:envelope string first
39    if let Ok(envelope) = Envelope::from_ur_string(ur_string.trim()) {
40        Ok(envelope)
41    // If that fails, try to parse the envelope as a ur:<any> string
42    } else if let Ok(ur) = UR::from_ur_string(ur_string.trim()) {
43        let cbor = ur.cbor();
44        // Try to parse the CBOR into an envelope
45        if let Ok(envelope) = Envelope::from_tagged_cbor(cbor) {
46            Ok(envelope)
47        } else if ur.ur_type_str() == "xid" {
48            let xid = XID::from_untagged_cbor(ur.cbor())?;
49            let doc = XIDDocument::from(xid);
50            Ok(doc.into_envelope())
51        } else {
52            todo!();
53        }
54    } else {
55        bail!("Invalid envelope");
56    }
57}
58
59pub fn parse_digest(target: &str) -> Result<Digest> {
60    let ur = UR::from_ur_string(target)?;
61    let digest = match ur.ur_type_str() {
62        "digest" => { Digest::from_ur(&ur)? }
63        "envelope" => { Envelope::from_ur(&ur)?.digest().into_owned() }
64        _ => {
65            bail!("Invalid digest type: {}", ur.ur_type_str());
66        }
67    };
68    Ok(digest)
69}
70
71pub fn parse_digests(target: &str) -> Result<HashSet<Digest>> {
72    let target = target.trim();
73    if target.is_empty() {
74        Ok(HashSet::new())
75    } else {
76        target.split(' ').map(parse_digest).collect::<Result<HashSet<Digest>>>()
77    }
78}