use std::fmt;
use crate::cert::raw::RawCert;
use crate::packet::Key;
use crate::packet::key;
pub struct KeyIter<'a, P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
key_iter: Box<dyn Iterator<Item=Key<key::PublicParts,
key::UnspecifiedRole>>
+ Send + Sync + 'a>,
returned_primary: bool,
want_primary: bool,
_p: std::marker::PhantomData<P>,
_r: std::marker::PhantomData<R>,
}
assert_send_and_sync!(KeyIter<'_, P, R>
where P: key::KeyParts,
R: key::KeyRole,
);
impl<'a, P, R> fmt::Debug for KeyIter<'a, P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("KeyIter")
.field("want_primary", &self.want_primary)
.finish()
}
}
macro_rules! impl_iterator {
($parts:path, $role:path, $item:ty) => {
impl<'a> Iterator for KeyIter<'a, $parts, $role>
{
type Item = $item;
fn next(&mut self) -> Option<Self::Item> {
self.next_common()
}
}
}
}
impl_iterator!(key::PublicParts, key::UnspecifiedRole,
Key<key::PublicParts, key::UnspecifiedRole>);
impl_iterator!(key::PublicParts, key::SubordinateRole,
Key<key::PublicParts, key::SubordinateRole>);
impl<'a, P, R> KeyIter<'a, P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
fn next_common(&mut self) -> Option<Key<P, R>>
{
tracer!(false, "KeyIter::next", 0);
t!("{:?}", self);
loop {
if ! self.returned_primary {
if ! self.want_primary {
let _ = self.key_iter.next();
}
self.returned_primary = true;
}
let key = self.key_iter.next()?
.parts_into_unspecified()
.role_into_unspecified();
let key = if let Ok(key) = P::convert_key(key) {
key
} else {
continue;
};
let key = R::convert_key(key);
return Some(key);
}
}
}
impl<'a, P, R> KeyIter<'a, P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
pub(crate) fn new(cert: &'a RawCert) -> Self where Self: 'a {
KeyIter {
key_iter: Box::new(cert.keys_internal()),
want_primary: true,
returned_primary: false,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
}
}
pub fn subkeys(self) -> KeyIter<'a, P, key::SubordinateRole> {
KeyIter {
key_iter: self.key_iter,
want_primary: false,
returned_primary: self.returned_primary,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
}
}
}