summaryrefslogtreecommitdiffstats
path: root/openpgp/src/cert/parser/low_level/lexer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/cert/parser/low_level/lexer.rs')
-rw-r--r--openpgp/src/cert/parser/low_level/lexer.rs156
1 files changed, 156 insertions, 0 deletions
diff --git a/openpgp/src/cert/parser/low_level/lexer.rs b/openpgp/src/cert/parser/low_level/lexer.rs
new file mode 100644
index 00000000..70ef8622
--- /dev/null
+++ b/openpgp/src/cert/parser/low_level/lexer.rs
@@ -0,0 +1,156 @@
+use std::fmt;
+
+use crate::Error;
+use crate::Packet;
+use crate::packet::Tag;
+use crate::cert::SubkeyBinding;
+use crate::cert::UserIDBinding;
+use crate::cert::UserAttributeBinding;
+use crate::cert::UnknownBinding;
+
+use crate::packet::key;
+
+// The type of the parser's input.
+//
+// The parser iterators over tuples consisting of the token's starting
+// position, the token itself, and the token's ending position.
+pub(crate) type LexerItem<Tok, Loc, Error>
+ = ::std::result::Result<(Loc, Tok, Loc), Error>;
+
+/// The components of an OpenPGP Message.
+#[derive(Debug, Clone, PartialEq)]
+pub enum Token {
+ /// A `PublicKey` packet.
+ PublicKey(Option<Packet>),
+ /// A `SecretKey` packet.
+ SecretKey(Option<Packet>),
+
+ /// A `PublicSubkey` packet.
+ PublicSubkey(Option<Packet>),
+ /// A `SecretSubkey` packet.
+ SecretSubkey(Option<Packet>),
+
+ /// A `UserID` packet.
+ UserID(Option<Packet>),
+ /// A `UserAttribute` packet.
+ UserAttribute(Option<Packet>),
+
+ /// A `Signature` packet.
+ Signature(Option<Packet>),
+
+ /// A `Trust` packet
+ Trust(Option<Packet>),
+
+ /// An `Unknown` packet.
+ Unknown(Tag, Option<Packet>),
+}
+
+/// Internal data-structure used by the parser.
+///
+/// Due to the way the parser code is generated, it must be marked as
+/// public. But, since this module is not public, it will not
+/// actually be exported to used of the library.
+pub enum Component {
+ SubkeyBinding(SubkeyBinding<key::PublicParts>),
+ UserIDBinding(UserIDBinding),
+ UserAttributeBinding(UserAttributeBinding),
+ UnknownBinding(UnknownBinding),
+}
+
+impl<'a> From<&'a Token> for Tag {
+ fn from(token: &'a Token) -> Self {
+ match token {
+ &Token::PublicKey(_) => Tag::PublicKey,
+ &Token::SecretKey(_) => Tag::SecretKey,
+ &Token::PublicSubkey(_) => Tag::PublicSubkey,
+ &Token::SecretSubkey(_) => Tag::SecretSubkey,
+ &Token::UserID(_) => Tag::UserID,
+ &Token::UserAttribute(_) => Tag::UserAttribute,
+ &Token::Signature(_) => Tag::Signature,
+ &Token::Trust(_) => Tag::Trust,
+ &Token::Unknown(tag, _) => tag,
+ }
+ }
+}
+
+impl From<Token> for Tag {
+ fn from(token: Token) -> Self {
+ (&token).into()
+ }
+}
+
+impl From<Token> for Option<Packet> {
+ fn from(token: Token) -> Self {
+ match token {
+ Token::PublicKey(p @ Some(_)) => p,
+ Token::SecretKey(p @ Some(_)) => p,
+ Token::PublicSubkey(p @ Some(_)) => p,
+ Token::SecretSubkey(p @ Some(_)) => p,
+ Token::UserID(p @ Some(_)) => p,
+ Token::UserAttribute(p @ Some(_)) => p,
+ Token::Signature(p @ Some(_)) => p,
+ Token::Trust(p @ Some(_)) => p,
+ Token::Unknown(_, p @ Some(_)) => p,
+
+ Token::PublicKey(None)
+ | Token::SecretKey(None)
+ | Token::PublicSubkey(None)
+ | Token::SecretSubkey(None)
+ | Token::UserID(None)
+ | Token::UserAttribute(None)
+ | Token::Signature(None)
+ | Token::Trust(None)
+ | Token::Unknown(_, None)
+ => None,
+ }
+ }
+}
+
+impl From<Packet> for Option<Token> {
+ fn from(p: Packet) -> Self {
+ match p {
+ p @ Packet::PublicKey(_) => Some(Token::PublicKey(Some(p))),
+ p @ Packet::SecretKey(_) => Some(Token::SecretKey(Some(p))),
+ p @ Packet::PublicSubkey(_) => Some(Token::PublicSubkey(Some(p))),
+ p @ Packet::SecretSubkey(_) => Some(Token::SecretSubkey(Some(p))),
+ p @ Packet::UserID(_) => Some(Token::UserID(Some(p))),
+ p @ Packet::UserAttribute(_) => Some(Token::UserAttribute(Some(p))),
+ p @ Packet::Signature(_) => Some(Token::Signature(Some(p))),
+ p @ Packet::Trust(_) => Some(Token::Trust(Some(p))),
+ p @ Packet::Unknown(_) => Some(Token::Unknown(p.tag(), Some(p))),
+ _ => None,
+ }
+ }
+}
+
+impl fmt::Display for Token {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(&format!("{:?}", self)[..])
+ }
+}
+
+pub(crate) struct Lexer<'input> {
+ iter: Box<dyn Iterator<Item=(usize, &'input Token)> + 'input>,
+}
+
+impl<'input> Iterator for Lexer<'input> {
+ type Item = LexerItem<Token, usize, Error>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let n = self.iter.next().map(|(pos, tok)| (pos, tok.clone()));
+ if let Some((pos, tok)) = n {
+ Some(Ok((pos, tok, pos)))
+ } else {
+ None
+ }
+ }
+}
+
+impl<'input> Lexer<'input> {
+ /// Uses a raw sequence of tokens as input to the parser.
+ pub(crate) fn from_tokens(raw: &'input [Token]) -> Self {
+ Lexer {
+ iter: Box::new(raw.iter().enumerate())
+ }
+ }
+}