use std::collections::BTreeMap;
use std::convert::TryInto;
use std::iter::Peekable;
use crate::armor;
use crate::composed::Deserializable;
use crate::errors::Result;
use crate::packet::{Packet, Signature};
use crate::ser::Serialize;
use crate::types::PublicKeyTrait;
use crate::types::Tag;
#[derive(Debug, Clone)]
pub struct StandaloneSignature {
pub signature: Signature,
}
impl StandaloneSignature {
pub fn new(signature: Signature) -> Self {
StandaloneSignature { signature }
}
pub fn to_armored_writer(
&self,
writer: &mut impl std::io::Write,
headers: Option<&BTreeMap<String, String>>,
) -> Result<()> {
armor::write(self, armor::BlockType::Signature, writer, headers)
}
pub fn to_armored_bytes(&self, headers: Option<&BTreeMap<String, String>>) -> Result<Vec<u8>> {
let mut buf = Vec::new();
self.to_armored_writer(&mut buf, headers)?;
Ok(buf)
}
pub fn to_armored_string(&self, headers: Option<&BTreeMap<String, String>>) -> Result<String> {
Ok(::std::str::from_utf8(&self.to_armored_bytes(headers)?)?.to_string())
}
pub fn verify(&self, key: &impl PublicKeyTrait, content: &[u8]) -> Result<()> {
self.signature.verify(key, content)
}
}
impl Serialize for StandaloneSignature {
fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
crate::packet::write_packet(writer, &self.signature)
}
}
impl Deserializable for StandaloneSignature {
fn from_packets<'a, I: Iterator<Item = Packet> + 'a>(
packets: std::iter::Peekable<I>,
) -> Box<dyn Iterator<Item = Result<Self>> + 'a> {
Box::new(SignatureParser { source: packets })
}
}
pub struct SignatureParser<I: Sized + Iterator<Item = Packet>> {
source: Peekable<I>,
}
impl<I: Sized + Iterator<Item = Packet>> Iterator for SignatureParser<I> {
type Item = Result<StandaloneSignature>;
fn next(&mut self) -> Option<Self::Item> {
next(self.source.by_ref())
}
}
fn next<I: Iterator<Item = Packet>>(
packets: &mut Peekable<I>,
) -> Option<Result<StandaloneSignature>> {
if let Some(packet) = packets.by_ref().next() {
match packet.tag() {
Tag::Signature => return Some(packet.try_into().map(StandaloneSignature::new)),
_ => return Some(Err(format_err!("unexpected packet {:?}", packet.tag()))),
}
}
None
}