sequoia_openpgp/cert/raw/iter.rs
1use std::fmt;
2
3use crate::cert::raw::RawCert;
4use crate::packet::Key;
5use crate::packet::key;
6
7/// A key iterator for `RawCert`s.
8///
9/// This is returned by [`RawCert::keys`]. It is analogous to
10/// [`KeyAmalgamationIter`], but for `RawCert`s.
11///
12/// [`KeyAmalgamationIter`]: crate::cert::amalgamation::key::KeyAmalgamationIter
13pub struct KeyIter<'a, P, R>
14 where P: key::KeyParts,
15 R: key::KeyRole,
16{
17 key_iter: Box<dyn Iterator<Item=Key<key::PublicParts,
18 key::UnspecifiedRole>>
19 + Send + Sync + 'a>,
20
21 // Whether the primary key has been returned.
22 returned_primary: bool,
23 // Whether the primary key should be returned.
24 want_primary: bool,
25
26 _p: std::marker::PhantomData<P>,
27 _r: std::marker::PhantomData<R>,
28}
29assert_send_and_sync!(KeyIter<'_, P, R>
30 where P: key::KeyParts,
31 R: key::KeyRole,
32);
33
34impl<'a, P, R> fmt::Debug for KeyIter<'a, P, R>
35 where P: key::KeyParts,
36 R: key::KeyRole,
37{
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 f.debug_struct("KeyIter")
40 .field("want_primary", &self.want_primary)
41 .finish()
42 }
43}
44
45macro_rules! impl_iterator {
46 ($parts:path, $role:path, $item:ty) => {
47 impl<'a> Iterator for KeyIter<'a, $parts, $role>
48 {
49 type Item = $item;
50
51 fn next(&mut self) -> Option<Self::Item> {
52 // We unwrap the result of the conversion. But, this
53 // is safe by construction: next_common only returns
54 // keys that can be correctly converted.
55 self.next_common()
56 }
57 }
58 }
59}
60
61impl_iterator!(key::PublicParts, key::UnspecifiedRole,
62 Key<key::PublicParts, key::UnspecifiedRole>);
63impl_iterator!(key::PublicParts, key::SubordinateRole,
64 Key<key::PublicParts, key::SubordinateRole>);
65
66impl<'a, P, R> KeyIter<'a, P, R>
67 where P: key::KeyParts,
68 R: key::KeyRole,
69{
70 fn next_common(&mut self) -> Option<Key<P, R>>
71 {
72 tracer!(false, "KeyIter::next", 0);
73 t!("{:?}", self);
74
75 loop {
76 if ! self.returned_primary {
77 if ! self.want_primary {
78 // Discard the primary key.
79 let _ = self.key_iter.next();
80 }
81 self.returned_primary = true;
82 }
83
84 let key = self.key_iter.next()?
85 .parts_into_unspecified()
86 .role_into_unspecified();
87 let key = if let Ok(key) = P::convert_key(key) {
88 key
89 } else {
90 // The caller wants secret keys, but this is no secret
91 // key, skip it.
92 continue;
93 };
94 let key = R::convert_key(key);
95
96 // Apply any filters.
97
98 return Some(key);
99 }
100 }
101}
102
103impl<'a, P, R> KeyIter<'a, P, R>
104 where P: key::KeyParts,
105 R: key::KeyRole,
106{
107 /// Returns a new `KeyIter` instance.
108 pub(crate) fn new(cert: &'a RawCert) -> Self where Self: 'a {
109 KeyIter {
110 key_iter: Box::new(cert.keys_internal()),
111
112 want_primary: true,
113 returned_primary: false,
114
115 _p: std::marker::PhantomData,
116 _r: std::marker::PhantomData,
117 }
118 }
119
120 /// Changes the iterator to only return subkeys.
121 ///
122 /// This function also changes the return type. Instead of the
123 /// iterator returning a [`Key`] whose role is
124 /// [`key::UnspecifiedRole`], the role is [`key::SubordinateRole`]
125 ///
126 /// # Examples
127 ///
128 /// ```rust
129 /// # use sequoia_openpgp as openpgp;
130 /// # use openpgp::Result;
131 /// # use openpgp::cert::prelude::*;
132 /// # use openpgp::cert::raw::RawCertParser;
133 /// # use openpgp::parse::Parse;
134 /// # use openpgp::serialize::Serialize;
135 /// #
136 /// # fn main() -> Result<()> {
137 /// # let (cert, _) = CertBuilder::new()
138 /// # .add_signing_subkey()
139 /// # .add_certification_subkey()
140 /// # .add_transport_encryption_subkey()
141 /// # .add_storage_encryption_subkey()
142 /// # .add_authentication_subkey()
143 /// # .generate()?;
144 /// #
145 /// # let mut bytes = Vec::new();
146 /// # cert.serialize(&mut bytes);
147 /// # let mut parser = RawCertParser::from_bytes(&bytes)?;
148 /// #
149 /// # let rawcert = parser.next().expect("have one").expect("valid");
150 /// # assert!(parser.next().is_none());
151 /// # let mut i = 0;
152 /// for subkey in rawcert.keys().subkeys() {
153 /// // Use it.
154 /// println!("{}", subkey.fingerprint());
155 /// # i += 1;
156 /// }
157 /// # assert_eq!(i, 5);
158 /// # Ok(())
159 /// # }
160 /// ```
161 ///
162 pub fn subkeys(self) -> KeyIter<'a, P, key::SubordinateRole> {
163 KeyIter {
164 key_iter: self.key_iter,
165
166 want_primary: false,
167 returned_primary: self.returned_primary,
168
169 _p: std::marker::PhantomData,
170 _r: std::marker::PhantomData,
171 }
172 }
173}