From 455923648b254e9ea74bd05d1af46ab50a6a07eb Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 22 Dec 2020 12:46:52 +0100 Subject: openpgp: Implement str::FromStr for KeyHandle. - We implement str::FromStr for Fingerprint and KeyID. Also implement it for KeyHandle. --- openpgp/src/keyhandle.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/openpgp/src/keyhandle.rs b/openpgp/src/keyhandle.rs index e3d56820..70e4dbda 100644 --- a/openpgp/src/keyhandle.rs +++ b/openpgp/src/keyhandle.rs @@ -205,6 +205,25 @@ impl PartialEq for KeyHandle { } } +impl std::str::FromStr for KeyHandle { + type Err = anyhow::Error; + + fn from_str(s: &str) -> std::result::Result { + let bytes = &crate::fmt::hex::decode_pretty(s)?[..]; + match Fingerprint::from_bytes(bytes) { + fpr @ Fingerprint::Invalid(_) => { + match KeyID::from_bytes(bytes) { + // If it can't be parsed as either a Fingerprint or a + // KeyID, return Fingerprint::Invalid. + KeyID::Invalid(_) => Ok(fpr.into()), + kid => Ok(kid.into()), + } + } + fpr => Ok(fpr.into()), + } + } +} + impl KeyHandle { /// Returns the raw identifier as a byte slice. pub fn as_bytes(&self) -> &[u8] { @@ -316,4 +335,31 @@ mod tests { let handle = KeyHandle::KeyID(KeyID::Invalid(Box::new([10, 2]))); assert_eq!(format!("{:x}", handle), "0a02"); } + + #[test] + fn parse() -> Result<()> { + let handle: KeyHandle = + "0123 4567 89AB CDEF 0123 4567 89AB CDEF 0123 4567".parse()?; + assert_match!(&KeyHandle::Fingerprint(Fingerprint::V4(_)) = &handle); + assert_eq!(handle.as_bytes(), + [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67]); + + let handle: KeyHandle = "89AB CDEF 0123 4567".parse()?; + assert_match!(&KeyHandle::KeyID(KeyID::V4(_)) = &handle); + assert_eq!(handle.as_bytes(), + [0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67]); + + // Invalid handles are parsed as invalid Fingerprints, not + // invalid KeyIDs. + let handle: KeyHandle = "4567 89AB CDEF 0123 4567".parse()?; + assert_match!(&KeyHandle::Fingerprint(Fingerprint::Invalid(_)) = &handle); + assert_eq!(handle.as_bytes(), + [0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67]); + + let handle: Result = "INVALID CHARACTERS".parse(); + assert!(handle.is_err()); + + Ok(()) + } } -- cgit v1.2.3