cmail_rpgp/composed/
any.rs

1use std::io::{BufRead, Read};
2
3use buffer_redux::BufReader;
4
5use crate::{
6    armor::{self, BlockType, Dearmor},
7    cleartext::CleartextSignedMessage,
8    errors::Result,
9    Deserializable, Message, SignedPublicKey, SignedSecretKey, StandaloneSignature,
10};
11
12/// A flexible representation of what can be represented in an armor file.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Any {
15    Cleartext(CleartextSignedMessage),
16    PublicKey(SignedPublicKey),
17    SecretKey(SignedSecretKey),
18    Message(Message),
19    Signature(StandaloneSignature),
20}
21
22impl Any {
23    /// Parse armored ascii data.
24    pub fn from_armor(bytes: impl Read) -> Result<(Self, armor::Headers)> {
25        Self::from_armor_buf(BufReader::new(bytes))
26    }
27
28    /// Parse a single armor encoded composition.
29    pub fn from_string(input: &str) -> Result<(Self, armor::Headers)> {
30        Self::from_armor_buf(input.as_bytes())
31    }
32
33    /// Parse armored ascii data.
34    pub fn from_armor_buf<R: BufRead>(input: R) -> Result<(Self, armor::Headers)> {
35        let dearmor = armor::Dearmor::new(input);
36        let (typ, headers, has_leading_data, rest) = dearmor.read_only_header()?;
37
38        match typ {
39            // Standard PGP types
40            BlockType::PublicKey => {
41                let dearmor = Dearmor::after_header(typ, headers.clone(), rest);
42                let key = SignedPublicKey::from_bytes(dearmor)?;
43                Ok((Self::PublicKey(key), headers))
44            }
45            BlockType::PrivateKey => {
46                let dearmor = Dearmor::after_header(typ, headers.clone(), rest);
47                let key = SignedSecretKey::from_bytes(dearmor)?;
48                Ok((Self::SecretKey(key), headers))
49            }
50            BlockType::Message => {
51                let dearmor = Dearmor::after_header(typ, headers.clone(), rest);
52                let msg = Message::from_bytes(dearmor)?;
53                Ok((Self::Message(msg), headers))
54            }
55            BlockType::Signature => {
56                let dearmor = Dearmor::after_header(typ, headers.clone(), rest);
57                let sig = StandaloneSignature::from_bytes(dearmor)?;
58                Ok((Self::Signature(sig), headers))
59            }
60            BlockType::CleartextMessage => {
61                ensure!(
62                    !has_leading_data,
63                    "must not have leading data for a cleartext message"
64                );
65                let (sig, headers) =
66                    CleartextSignedMessage::from_armor_after_header(rest, headers)?;
67                Ok((Self::Cleartext(sig), headers))
68            }
69            _ => unimplemented_err!("unsupported block type: {}", typ),
70        }
71    }
72}