bc_envelope_cli/
utils.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use std::{collections::HashSet, io::Read};
use anyhow::{ bail, Result };
use bc_components::XID;
use bc_envelope::prelude::*;
use bc_xid::XIDDocument;

pub fn read_password(prompt: &str, password: Option<&str>) -> Result<String> {
    if let Some(password) = password {
        Ok(password.to_string())
    } else {
        rpassword::prompt_password(prompt).map_err(Into::into)
    }
}

pub fn read_argument(argument: Option<&str>) -> Result<String> {
    let mut string = String::new();
    if argument.is_none() {
        std::io::stdin().read_to_string(&mut string)?;
    } else {
        string = argument.as_ref().unwrap().to_string();
    }
    if string.is_empty() {
        bail!("No argument provided");
    }
    Ok(string.to_string())
}

pub fn read_envelope(envelope: Option<&str>) -> Result<Envelope> {
    let mut ur_string = String::new();
    if envelope.is_none() {
        std::io::stdin().read_line(&mut ur_string)?;
    } else {
        ur_string = envelope.as_ref().unwrap().to_string();
    }
    if ur_string.is_empty() {
        bail!("No envelope provided");
    }
    // Just try to parse the envelope as a ur:envelope string first
    if let Ok(envelope) = Envelope::from_ur_string(ur_string.trim()) {
        Ok(envelope)
    // If that fails, try to parse the envelope as a ur:<any> string
    } else if let Ok(ur) = UR::from_ur_string(ur_string.trim()) {
        let cbor = ur.cbor();
        // Try to parse the CBOR into an envelope
        if let Ok(envelope) = Envelope::from_tagged_cbor(cbor) {
            Ok(envelope)
        } else if ur.ur_type_str() == "xid" {
            let xid = XID::from_untagged_cbor(ur.cbor())?;
            let doc = XIDDocument::from(xid);
            Ok(doc.into_envelope())
        } else {
            todo!();
        }
    } else {
        bail!("Invalid envelope");
    }
}

pub fn parse_digest(target: &str) -> Result<Digest> {
    let ur = UR::from_ur_string(target)?;
    let digest = match ur.ur_type_str() {
        "digest" => { Digest::from_ur(&ur)? }
        "envelope" => { Envelope::from_ur(&ur)?.digest().into_owned() }
        _ => {
            bail!("Invalid digest type: {}", ur.ur_type_str());
        }
    };
    Ok(digest)
}

pub fn parse_digests(target: &str) -> Result<HashSet<Digest>> {
    let target = target.trim();
    if target.is_empty() {
        Ok(HashSet::new())
    } else {
        target.split(' ').map(parse_digest).collect::<Result<HashSet<Digest>>>()
    }
}