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}