diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-03-26 17:21:32 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-03-26 17:21:32 +0100 |
commit | 89337646884b59c894329432eea960be4b3e335e (patch) | |
tree | 349136c28ee05b1ba71773c3ff8b1a0d7e2865a2 /openpgp/src/packet_pile.rs | |
parent | e26c4d5a8fb582ec2a3c4c373536913aa2d0a468 (diff) |
openpgp: Change packet bodies to be tristate.
- Packet bodies can now be either unprocessed (e.g. compressed,
encrypted), processed (e.g. uncompressed, decrypted), or
structured (e.g. parsed into packets).
- Make the container types deref to Container, and container deref
to packet bodies.
- This cleanly avoids the confusion when serializing containers: We
can serialize compressed data packets with either body, but we can
only serialize encryption containers with unprocessed bodies.
- Fixes #187.
Diffstat (limited to 'openpgp/src/packet_pile.rs')
-rw-r--r-- | openpgp/src/packet_pile.rs | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/openpgp/src/packet_pile.rs b/openpgp/src/packet_pile.rs index 0cc8ce35..36c21613 100644 --- a/openpgp/src/packet_pile.rs +++ b/openpgp/src/packet_pile.rs @@ -85,6 +85,11 @@ impl From<Packet> for PacketPile { } impl PacketPile { + /// Returns an error if operating on a non-container packet. + fn error() -> crate::Error { + crate::Error::InvalidOperation("Not a container packet".into()) + } + /// Pretty prints the message to stderr. /// /// This function is primarily intended for debugging purposes. @@ -123,11 +128,13 @@ impl PacketPile { let mut cont = Some(&self.top_level); for i in pathspec { if let Some(ref c) = cont.take() { - if *i < c.children_ref().len() { - let p = &c.children_ref()[*i]; - packet = Some(p); - cont = p.container_ref(); - continue; + if let Some(children) = c.children_ref() { + if *i < children.len() { + let p = &children[*i]; + packet = Some(p); + cont = p.container_ref(); + continue; + } } } @@ -146,11 +153,7 @@ impl PacketPile { for (level, &i) in pathspec.iter().enumerate() { let tmp = container; - if i >= tmp.children_ref().len() { - return None; - } - - let p = &mut tmp.children_mut()[i]; + let p = tmp.children_mut().and_then(|c| c.get_mut(i))?; if level == pathspec.len() - 1 { return Some(p) @@ -190,7 +193,7 @@ impl PacketPile { /// literal.set_body(b"old".to_vec()); /// let mut compressed = /// CompressedData::new(CompressionAlgorithm::Uncompressed); - /// compressed.children_mut().push(literal.into()); + /// compressed.children_mut().unwrap().push(literal.into()); /// let mut pile = PacketPile::from(Packet::from(compressed)); /// /// // Replace the literal data packet. @@ -218,12 +221,15 @@ impl PacketPile { let tmp = container; if level == pathspec.len() - 1 { - if i + count > tmp.children_ref().len() { + if tmp.children_ref().map(|c| i + count > c.len()) + .unwrap_or(true) + { return Err(Error::IndexOutOfRange.into()); } // Out with the old... let old = tmp.children_mut() + .expect("checked above") .drain(i..i + count) .collect::<Vec<Packet>>(); assert_eq!(old.len(), count); @@ -231,20 +237,21 @@ impl PacketPile { // In with the new... let mut tail = tmp.children_mut() + .expect("checked above") .drain(i..) .collect::<Vec<Packet>>(); - tmp.children_mut().append(&mut packets); - tmp.children_mut().append(&mut tail); + tmp.children_mut().expect("checked above").append(&mut packets); + tmp.children_mut().expect("checked above").append(&mut tail); return Ok(old) } - if i >= tmp.children_ref().len() { + if tmp.children_ref().map(|c| i >= c.len()).unwrap_or(true) { return Err(Error::IndexOutOfRange.into()); } - match tmp.children_ref()[i] { + match tmp.children_ref().expect("checked above")[i] { // The structured container types. Packet::CompressedData(_) | Packet::SEIP(_) @@ -252,7 +259,8 @@ impl PacketPile { => (), // Ok. _ => return Err(Error::IndexOutOfRange.into()), } - container = tmp.children_mut()[i].container_mut() + container = + tmp.children_mut().expect("checked above")[i].container_mut() .expect("The above packets are structured containers"); } @@ -262,17 +270,17 @@ impl PacketPile { /// Returns an iterator over all of the packet's descendants, in /// depth-first order. pub fn descendants(&self) -> packet::Iter { - self.top_level.descendants() + self.top_level.descendants().expect("toplevel is a container") } /// Returns an iterator over the top-level packets. pub fn children<'a>(&'a self) -> slice::Iter<'a, Packet> { - self.top_level.children() + self.top_level.children().expect("toplevel is a container") } /// Returns an `IntoIter` over the top-level packets. pub fn into_children(self) -> vec::IntoIter<Packet> { - self.top_level.into_children() + self.top_level.into_children().expect("toplevel is a container") } @@ -325,8 +333,11 @@ impl PacketPile { // being reborrowed and preventing us from // assigning to it. let tmp = container; - let packets_len = tmp.children_ref().len(); - let p = &mut tmp.children_mut()[packets_len - 1]; + let packets_len = + tmp.children_ref().ok_or_else(Self::error)?.len(); + let p = &mut tmp.children_mut() + .ok_or_else(Self::error)? + [packets_len - 1]; container = p.container_mut().unwrap(); } @@ -342,11 +353,14 @@ impl PacketPile { if relative_position == 1 { // Create a new container. let tmp = container; - let i = tmp.children_ref().len() - 1; - container = tmp.children_mut()[i].container_mut().unwrap(); + let i = + tmp.children_ref().ok_or_else(Self::error)?.len() - 1; + container = tmp.children_mut() + .ok_or_else(Self::error)? + [i].container_mut().unwrap(); } - container.children_mut().push(packet); + container.children_mut().unwrap().push(packet); if ppr.is_none() { break 'outer; @@ -597,11 +611,10 @@ mod test { // Get the rest of the content and put the initial byte that // we stole back. - let mut content = packet.body().unwrap().to_vec(); + let mut content = packet.processed_body().unwrap().to_vec(); content.insert(0, data[0]); - let content = &content.into_boxed_slice()[..]; - let ppr = PacketParser::from_bytes(content).unwrap(); + let ppr = PacketParser::from_bytes(&content).unwrap(); let pp = ppr.unwrap(); if let Packet::Literal(_) = pp.packet { } else { @@ -634,7 +647,7 @@ mod test { } let mut seip = SEIP1::new(); - seip.children_mut().push(cd.into()); + seip.children_mut().unwrap().push(cd.into()); packets.push(seip.into()); eprintln!("{:#?}", packets); @@ -809,7 +822,7 @@ mod test { assert_eq!(top_level.len(), 1); let values = top_level[0] - .children() + .children().unwrap() .map(|p| { if let Packet::Literal(ref literal) = p { literal.body() |