diff --git a/tor-netdoc/src/authcert.rs b/tor-netdoc/src/authcert.rs index 96610fb41..49e4b8d9d 100644 --- a/tor-netdoc/src/authcert.rs +++ b/tor-netdoc/src/authcert.rs @@ -82,6 +82,11 @@ impl AuthCert { result } + /// Return an iterator yielding authority certificates from a string. + pub fn parse_multiple(s: &str) -> impl Iterator> + '_ { + AuthCertIterator(NetDocReader::new(s)) + } + /// Return true if this certificate is expired at a given time, or /// not yet valid at that time. pub fn is_expired_at(&self, when: time::SystemTime) -> bool { @@ -202,6 +207,38 @@ impl AuthCert { expires, }) } + + /// Skip tokens from the reader until the next token (if any) is + /// the start of cert. + fn advance_reader_to_next(reader: &mut NetDocReader<'_, AuthCertKW>) { + use AuthCertKW::*; + let iter = reader.iter(); + while let Some(Ok(item)) = iter.peek() { + if item.get_kwd() == DIR_KEY_CERTIFICATE_VERSION { + return; + } + iter.next(); + } + } +} + +struct AuthCertIterator<'a>(NetDocReader<'a, AuthCertKW>); + +impl<'a> Iterator for AuthCertIterator<'a> { + type Item = Result; + fn next(&mut self) -> Option> { + if self.0.is_exhausted() { + return None; + } + + let result = AuthCert::take_from_reader(&mut self.0); + if result.is_err() { + // XXXX Verify that at least one item was consumed from the + // XXXX reader! + AuthCert::advance_reader_to_next(&mut self.0); + } + Some(result.map_err(|e| e.within(self.0.str()))) + } } #[cfg(test)] diff --git a/tor-netdoc/src/tokenize.rs b/tor-netdoc/src/tokenize.rs index 7daeaa945..75a2c39d7 100644 --- a/tor-netdoc/src/tokenize.rs +++ b/tor-netdoc/src/tokenize.rs @@ -582,6 +582,11 @@ impl<'a, K: Keyword> NetDocReader<'a, K> { self.pause_at(|_| false) } + /// Return true if there are no more items in this NetDocReader. + pub fn is_exhausted(&mut self) -> bool { + self.iter().peek().is_none() + } + /// Give an error if there are remaining tokens in this NetDocReader. pub fn should_be_exhausted(&mut self) -> Result<()> { match self.iter().peek() {