cmail_rpgp/composed/
signature.rs1use std::iter::Peekable;
2
3use crate::composed::Deserializable;
4use crate::errors::Result;
5use crate::packet::{Packet, Signature};
6use crate::ser::Serialize;
7use crate::types::PublicKeyTrait;
8use crate::types::Tag;
9use crate::{armor, ArmorOptions};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct StandaloneSignature {
14 pub signature: Signature,
15}
16
17impl StandaloneSignature {
18 pub fn new(signature: Signature) -> Self {
19 StandaloneSignature { signature }
20 }
21
22 pub fn to_armored_writer(
23 &self,
24 writer: &mut impl std::io::Write,
25 opts: ArmorOptions<'_>,
26 ) -> Result<()> {
27 armor::write(
28 self,
29 armor::BlockType::Signature,
30 writer,
31 opts.headers,
32 opts.include_checksum,
33 )
34 }
35
36 pub fn to_armored_bytes(&self, opts: ArmorOptions<'_>) -> Result<Vec<u8>> {
37 let mut buf = Vec::new();
38
39 self.to_armored_writer(&mut buf, opts)?;
40
41 Ok(buf)
42 }
43
44 pub fn to_armored_string(&self, opts: ArmorOptions<'_>) -> Result<String> {
45 let res = String::from_utf8(self.to_armored_bytes(opts)?).map_err(|e| e.utf8_error())?;
46 Ok(res)
47 }
48
49 pub fn verify(&self, key: &impl PublicKeyTrait, content: &[u8]) -> Result<()> {
51 self.signature.verify(key, content)
52 }
53}
54
55impl Serialize for StandaloneSignature {
56 fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
57 crate::packet::write_packet(writer, &self.signature)
58 }
59}
60
61impl Deserializable for StandaloneSignature {
62 fn from_packets<'a, I: Iterator<Item = Result<Packet>> + 'a>(
64 packets: std::iter::Peekable<I>,
65 ) -> Box<dyn Iterator<Item = Result<Self>> + 'a> {
66 Box::new(SignatureParser { source: packets })
67 }
68
69 fn matches_block_type(typ: armor::BlockType) -> bool {
70 matches!(typ, armor::BlockType::Signature)
71 }
72}
73
74pub struct SignatureParser<I: Sized + Iterator<Item = Result<Packet>>> {
75 source: Peekable<I>,
76}
77
78impl<I: Sized + Iterator<Item = Result<Packet>>> Iterator for SignatureParser<I> {
79 type Item = Result<StandaloneSignature>;
80
81 fn next(&mut self) -> Option<Self::Item> {
82 next(self.source.by_ref())
83 }
84}
85
86fn next<I: Iterator<Item = Result<Packet>>>(
87 packets: &mut Peekable<I>,
88) -> Option<Result<StandaloneSignature>> {
89 match packets.by_ref().next() {
90 Some(Ok(packet)) => match packet.tag() {
91 Tag::Signature => Some(packet.try_into().map(StandaloneSignature::new)),
92 _ => Some(Err(format_err!("unexpected packet {:?}", packet.tag()))),
93 },
94 Some(Err(e)) => Some(Err(e)),
95 None => None,
96 }
97}