summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/guide-exploring-openpgp.rs6
-rw-r--r--ffi/src/openpgp.rs83
-rw-r--r--openpgp/src/armor.rs4
-rw-r--r--openpgp/src/lib.rs16
-rw-r--r--openpgp/src/message.rs490
-rw-r--r--openpgp/src/packet.rs29
-rw-r--r--openpgp/src/parse/key.rs6
-rw-r--r--openpgp/src/parse/message_parser.rs317
-rw-r--r--openpgp/src/parse/mod.rs28
-rw-r--r--openpgp/src/parse/parse.rs4
-rw-r--r--openpgp/src/parse/subpacket.rs36
-rw-r--r--openpgp/src/serialize/mod.rs44
-rw-r--r--openpgp/src/serialize/stream.rs24
-rw-r--r--openpgp/src/tpk.rs16
-rw-r--r--tool/src/sqv.rs6
15 files changed, 153 insertions, 956 deletions
diff --git a/examples/guide-exploring-openpgp.rs b/examples/guide-exploring-openpgp.rs
index bc05a7e1..a2bd1517 100644
--- a/examples/guide-exploring-openpgp.rs
+++ b/examples/guide-exploring-openpgp.rs
@@ -38,10 +38,10 @@ fn main() {
);
// Parse message.
- let message = openpgp::Message::from_reader(&mut reader).unwrap();
+ let pile = openpgp::PacketPile::from_reader(&mut reader).unwrap();
// Iterate over children.
- for (i, p) in message.children().enumerate() {
+ for (i, p) in pile.children().enumerate() {
println!("{}: {:?}", i, p);
}
@@ -49,7 +49,7 @@ fn main() {
println!();
// Parse into TPK.
- let tpk = openpgp::TPK::from_message(message).unwrap();
+ let tpk = openpgp::TPK::from_packet_pile(pile).unwrap();
println!("Fingerprint: {}", tpk.fingerprint());
// List userids.
diff --git a/ffi/src/openpgp.rs b/ffi/src/openpgp.rs
index 8bddf426..fb213cdc 100644
--- a/ffi/src/openpgp.rs
+++ b/ffi/src/openpgp.rs
@@ -10,7 +10,7 @@ use libc::{uint8_t, uint64_t, c_char, c_int, size_t};
extern crate openpgp;
-use self::openpgp::{armor, Fingerprint, KeyID, Message, TPK, Packet};
+use self::openpgp::{armor, Fingerprint, KeyID, PacketPile, TPK, Packet};
use self::openpgp::parse::{PacketParser};
use self::openpgp::serialize::Serialize;
@@ -229,88 +229,88 @@ pub extern "system" fn sq_armor_writer_new(inner: Option<&'static mut Box<Write>
}
-/* openpgp::Message. */
+/* openpgp::PacketPile. */
/// Deserializes the OpenPGP message stored in a `std::io::Read`
/// object.
///
/// Although this method is easier to use to parse an OpenPGP
-/// message than a `PacketParser` or a `MessageParser`, this
+/// message than a `PacketParser` or a `PacketPileParser`, this
/// interface buffers the whole message in memory. Thus, the
/// caller must be certain that the *deserialized* message is not
/// too large.
///
/// Note: this interface *does* buffer the contents of packets.
#[no_mangle]
-pub extern "system" fn sq_message_from_reader(ctx: Option<&mut Context>,
- reader: Option<&mut Box<Read>>)
- -> *mut Message {
+pub extern "system" fn sq_packet_pile_from_reader(ctx: Option<&mut Context>,
+ reader: Option<&mut Box<Read>>)
+ -> *mut PacketPile {
let ctx = ctx.expect("Context is NULL");
let reader = reader.expect("Reader is NULL");
- fry_box!(ctx, Message::from_reader(reader))
+ fry_box!(ctx, PacketPile::from_reader(reader))
}
/// Deserializes the OpenPGP message stored in the file named by
/// `filename`.
///
-/// See `sq_message_from_reader` for more details and caveats.
+/// See `sq_packet_pile_from_reader` for more details and caveats.
#[no_mangle]
-pub extern "system" fn sq_message_from_file(ctx: Option<&mut Context>,
- filename: *const c_char)
- -> *mut Message {
+pub extern "system" fn sq_packet_pile_from_file(ctx: Option<&mut Context>,
+ filename: *const c_char)
+ -> *mut PacketPile {
let ctx = ctx.expect("Context is NULL");
assert!(! filename.is_null());
let filename = unsafe {
CStr::from_ptr(filename).to_string_lossy().into_owned()
};
- fry_box!(ctx, Message::from_file(&filename))
+ fry_box!(ctx, PacketPile::from_file(&filename))
}
/// Deserializes the OpenPGP message stored in the provided buffer.
///
-/// See `sq_message_from_reader` for more details and caveats.
+/// See `sq_packet_pile_from_reader` for more details and caveats.
#[no_mangle]
-pub extern "system" fn sq_message_from_bytes(ctx: Option<&mut Context>,
- b: *const uint8_t, len: size_t)
- -> *mut Message {
+pub extern "system" fn sq_packet_pile_from_bytes(ctx: Option<&mut Context>,
+ b: *const uint8_t, len: size_t)
+ -> *mut PacketPile {
let ctx = ctx.expect("Context is NULL");
assert!(!b.is_null());
let buf = unsafe {
slice::from_raw_parts(b, len as usize)
};
- fry_box!(ctx, Message::from_bytes(buf))
+ fry_box!(ctx, PacketPile::from_bytes(buf))
}
-/// Frees the message.
+/// Frees the packet_pile.
#[no_mangle]
-pub extern "system" fn sq_message_free(message: *mut Message) {
- if message.is_null() {
+pub extern "system" fn sq_packet_pile_free(packet_pile: *mut PacketPile) {
+ if packet_pile.is_null() {
return
}
unsafe {
- drop(Box::from_raw(message));
+ drop(Box::from_raw(packet_pile));
}
}
-/// Clones the Message.
+/// Clones the PacketPile.
#[no_mangle]
-pub extern "system" fn sq_message_clone(message: Option<&Message>)
- -> *mut Message {
- let message = message.expect("Message is NULL");
- box_raw!(message.clone())
+pub extern "system" fn sq_packet_pile_clone(packet_pile: Option<&PacketPile>)
+ -> *mut PacketPile {
+ let packet_pile = packet_pile.expect("PacketPile is NULL");
+ box_raw!(packet_pile.clone())
}
-/// Serializes the message.
+/// Serializes the packet pile.
#[no_mangle]
-pub extern "system" fn sq_message_serialize(ctx: Option<&mut Context>,
- message: Option<&Message>,
- writer: Option<&mut Box<Write>>)
- -> Status {
+pub extern "system" fn sq_packet_pile_serialize(ctx: Option<&mut Context>,
+ packet_pile: Option<&PacketPile>,
+ writer: Option<&mut Box<Write>>)
+ -> Status {
let ctx = ctx.expect("Context is NULL");
- let message = message.expect("Message is NULL");
+ let packet_pile = packet_pile.expect("PacketPile is NULL");
let writer = writer.expect("Writer is NULL");
- fry_status!(ctx, message.serialize(writer))
+ fry_status!(ctx, packet_pile.serialize(writer))
}
@@ -343,18 +343,18 @@ pub extern "system" fn sq_tpk_from_file(ctx: Option<&mut Context>,
///
/// Consumes `m`.
#[no_mangle]
-pub extern "system" fn sq_tpk_from_message(ctx: Option<&mut Context>,
- m: *mut Message)
- -> *mut TPK {
+pub extern "system" fn sq_tpk_from_packet_pile(ctx: Option<&mut Context>,
+ m: *mut PacketPile)
+ -> *mut TPK {
let ctx = ctx.expect("Context is NULL");
assert!(! m.is_null());
let m = unsafe { Box::from_raw(m) };
- fry_box!(ctx, TPK::from_message(*m))
+ fry_box!(ctx, TPK::from_packet_pile(*m))
}
/// Returns the first TPK found in `buf`.
///
-/// `buf` must be an OpenPGP encoded message.
+/// `buf` must be an OpenPGP-encoded TPK.
#[no_mangle]
pub extern "system" fn sq_tpk_from_bytes(ctx: Option<&mut Context>,
b: *const uint8_t, len: size_t)
@@ -516,7 +516,8 @@ pub extern "system" fn sq_skesk_decrypt(ctx: Option<&mut Context>,
/* openpgp::parse. */
-/// Starts parsing an OpenPGP message stored in a `sq_reader_t` object.
+/// Starts parsing OpenPGP packets stored in a `sq_reader_t`
+/// object.
///
/// This function returns a `PacketParser` for the first packet in
/// the stream.
@@ -531,7 +532,7 @@ pub extern "system" fn sq_packet_parser_from_reader<'a>
.unwrap_or(ptr::null_mut())
}
-/// Starts parsing an OpenPGP message stored in a file named `path`.
+/// Starts parsing OpenPGP packets stored in a file named `path`.
///
/// This function returns a `PacketParser` for the first packet in
/// the stream.
@@ -549,7 +550,7 @@ pub extern "system" fn sq_packet_parser_from_file
.unwrap_or(ptr::null_mut())
}
-/// Starts parsing an OpenPGP message stored in a buffer.
+/// Starts parsing OpenPGP packets stored in a buffer.
///
/// This function returns a `PacketParser` for the first packet in
/// the stream.
diff --git a/openpgp/src/armor.rs b/openpgp/src/armor.rs
index d85c90eb..eb1e6a53 100644
--- a/openpgp/src/armor.rs
+++ b/openpgp/src/armor.rs
@@ -50,7 +50,9 @@ const LINE_ENDING: &str = "\n";
/// [RFC 4880, section 6.2]: https://tools.ietf.org/html/rfc4880#section-6.2
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Kind {
- /// A generic OpenPGP message.
+ /// A generic OpenPGP message. (Since its structure hasn't been
+ /// validated, in this crate's terminology, this is just a
+ /// `PacketPile`.)
Message,
/// A transferable public key.
PublicKey,
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs
index 55efb498..09ff0112 100644
--- a/openpgp/src/lib.rs
+++ b/openpgp/src/lib.rs
@@ -95,7 +95,7 @@ pub use pkesk::PKESK;
mod reader;
pub use reader::Reader;
-mod message;
+mod packet_pile;
pub mod constants;
use constants::{
PublicKeyAlgorithm,
@@ -340,9 +340,9 @@ pub struct UserAttribute {
///
/// A literal packet contains unstructured data. Since the size can
/// be very large, it is advised to process messages containing such
-/// packets using a `PacketParser` or a `MessageParser` and process
+/// packets using a `PacketParser` or a `PacketPileParser` and process
/// the data in a streaming manner rather than the using the
-/// `Message::from_file` and related interfaces.
+/// `PacketPile::from_file` and related interfaces.
///
/// See [Section 5.9 of RFC 4880] for details.
///
@@ -474,17 +474,17 @@ impl Packet {
}
}
-/// A `Message` holds a deserialized OpenPGP message.
+/// A `PacketPile` holds a deserialized sequence of OpenPGP messages.
///
/// To deserialize an OpenPGP usage, use either [`PacketParser`],
-/// [`MessageParser`], or [`Message::from_file`] (or related
+/// [`PacketPileParser`], or [`PacketPile::from_file`] (or related
/// routines).
///
/// [`PacketParser`]: parse/struct.PacketParser.html
-/// [`MessageParser`]: parse/struct.MessageParser.html
-/// [`Message::from_file`]: struct.Message.html#method.from_file
+/// [`PacketPileParser`]: parse/struct.PacketPileParser.html
+/// [`PacketPile::from_file`]: struct.PacketPile.html#method.from_file
#[derive(PartialEq, Clone)]
-pub struct Message {
+pub struct PacketPile {
// At the top level, we have a sequence of packets, which may be
// containers.
top_level: Container,
diff --git a/openpgp/src/message.rs b/openpgp/src/message.rs
deleted file mode 100644
index f07e52ae..00000000
--- a/openpgp/src/message.rs
+++ /dev/null
@@ -1,490 +0,0 @@
-use std::fmt;
-use std::slice;
-use std::vec;
-use std::io;
-use std::path::Path;
-use std::fs::File;
-
-use buffered_reader::BufferedReader;
-use buffered_reader::BufferedReaderGeneric;
-use buffered_reader::BufferedReaderMemory;
-
-use Result;
-use Packet;
-use packet::{Container, PacketIter};
-use Message;
-use parse::PacketParser;
-use parse::PacketParserBuilder;
-use parse::Cookie;
-
-#[cfg(test)]
-macro_rules! bytes {
- ( $x:expr ) => { include_bytes!(concat!("../tests/data/messages/", $x)) };
-}
-
-#[cfg(test)]
-use std::path::PathBuf;
-
-#[cfg(test)]
-fn path_to(artifact: &str) -> PathBuf {
- [env!("CARGO_MANIFEST_DIR"), "tests", "data", "messages", artifact]
- .iter().collect()
-}
-
-impl fmt::Debug for Message {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Message")
- .field("packets", &self.top_level.packets)
- .finish()
- }
-}
-
-impl Message {
- /// Turns a vector of [`Packet`s] into a `Message`.
- ///
- /// This is a simple wrapper function; it does not process the
- /// packets in any way.
- ///
- /// [`Packet`s]: enum.Packet.html
- pub fn from_packets(p: Vec<Packet>) -> Self {
- Message { top_level: Container { packets: p } }
- }
-
- /// Turns a [`Packet`] into a `Message`.
- ///
- /// This is a simple wrapper function; it does not process the
- /// packets in any way.
- ///
- /// [`Packet`]: enum.Packet.html
- pub fn from_packet(p: Packet) -> Self {
- let mut top_level = Vec::with_capacity(1);
- top_level.push(p);
- Self::from_packets(top_level)
- }
-
- /// Pretty prints the message to stderr.
- ///
- /// This function is primarily intended for debugging purposes.
- pub fn pretty_print(&self) {
- self.top_level.pretty_print(0);
- }
-
- /// Returns the packet at the location described by `pathspec`.
- ///
- /// `pathspec` is a slice of the form `[ 0, 1, 2 ]`. Each element
- /// is the index of packet in a container. Thus, the previous
- /// path specification means: return the third child of the second
- /// child of the first top-level packet. In other words, the
- /// starred packet in the following tree:
- ///
- /// ```text
- /// Message
- /// / | \
- /// 0 1 2 ...
- /// / \
- /// / \
- /// 0 1 ...
- /// / | \ ...
- /// 0 1 2
- /// *
- /// ```
- ///
- /// And, `[ 10 ]` means return the 11th top-level packet.
- ///
- /// Note: there is no packet at the root. Thus, the path `[]`
- /// returns None.
- pub fn path_ref(&self, pathspec: &[usize]) -> Option<&Packet> {
- let mut packet : Option<&Packet> = None;
-
- let mut cont = Some(&self.top_level);
- for i in pathspec {
- if let Some(ref c) = cont.take() {
- if *i < c.packets.len() {
- let p = &c.packets[*i];
- packet = Some(p);
- cont = p.children.as_ref();
- continue;
- }
- }
-
- return None;
- }
- return packet;
- }
-
- /// Returns an iterator over all of the packet's descendants, in
- /// depth-first order.
- pub fn descendants(&self) -> PacketIter {
- self.top_level.descendants()
- }
-
- /// Returns an iterator over the top-level packets.
- pub fn children<'a>(&'a self) -> slice::Iter<'a, Packet> {
- self.top_level.children()
- }
-
- /// Returns an `IntoIter` over the top-level packets.
- pub fn into_children(self) -> vec::IntoIter<Packet> {
- self.top_level.into_children()
- }
-
-
- pub(crate) fn from_buffered_reader<'a>(bio: Box<'a + BufferedReader<Cookie>>)
- -> Result<Message> {
- PacketParserBuilder::from_buffered_reader(bio)?
- .buffer_unread_content()
- .to_message()
- }
-
- /// Deserializes the OpenPGP message stored in a `std::io::Read`
- /// object.
- ///
- /// Although this method is easier to use to parse an OpenPGP
- /// message than a [`PacketParser`] or a [`MessageParser`], this
- /// interface buffers the whole message in memory. Thus, the
- /// caller must be certain that the *deserialized* message is not
- /// too large.
- ///
- /// Note: this interface *does* buffer the contents of packets.
- ///
- /// [`PacketParser`]: parse/struct.PacketParser.html
- /// [`MessageParser`]: parse/struct.MessageParser.html
- pub fn from_reader<'a, R: 'a + io::Read>(reader: R) -> Result<Message> {
- let bio = BufferedReaderGeneric::with_cookie(
- reader, None, Cookie::default());
- Message::from_buffered_reader(Box::new(bio))
- }
-
- /// Deserializes the OpenPGP message stored in the file named by
- /// `path`.
- ///
- /// See `from_reader` for more details and caveats.
- pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Message> {
- Message::from_reader(File::open(path)?)
- }
-
- /// Deserializes the OpenPGP message stored in the provided buffer.
- ///
- /// See `from_reader` for more details and caveats.
- pub fn from_bytes(data: &[u8]) -> Result<Message> {
- let bio = BufferedReaderMemory::with_cookie(
- data, Cookie::default());
- Message::from_buffered_reader(Box::new(bio))
- }
-
- /// Reads all of the packets from a `PacketParser`, and turns them
- /// into a message.
- ///
- /// Note: this assumes that `ppo` points to a top-level packet.
- pub fn from_packet_parser<'a>(ppo: Option<PacketParser<'a>>)
- -> Result<Message>
- {
- // Things are not going to work out if we don't start with a
- // top-level packet. We should only pop until
- // ppo.recursion_depth and leave the rest of the message, but
- // it is hard to imagine that that is what the caller wants.
- // Instead of hiding that error, fail fast.
- if let Some(ref pp) = ppo {
- assert_eq!(pp.recursion_depth, 0);
- }
-
- // Create a top-level container.
- let mut top_level = Container::new();
-
- let mut last_position = 0;
-
- if ppo.is_none() {
- // Empty message.
- return Ok(Message::from_packets(Vec::new()));
- }
- let mut pp = ppo.unwrap();
-
- 'outer: loop {
- let (mut packet, mut position, mut ppo, _) = pp.recurse()?;
-
- let mut relative_position : isize = position - last_position;
- assert!(relative_position <= 1);
-
- // Find the right container for `packet`.
- let mut container = &mut top_level;
- // If we recurse, don't create the new container here.
- for _ in 0..(position - if relative_position > 0 { 1 } else { 0 }) {
- // Do a little dance to prevent container from
- // being reborrowed and preventing us from
- // assigning to it.
- let tmp = container;
- let packets_len = tmp.packets.len();
- let p = &mut tmp.packets[packets_len - 1];
-
- container = p.children.as_mut().unwrap();
- }
-
- if relative_position < 0 {
- relative_position = 0;
- }
-
- // If next packet will be inserted in the same container
- // or the current container's child, we don't need to walk
- // the tree from the root.
- loop {
- if relative_position == 1 {
- // Create a new container.
- let tmp = container;
- let i = tmp.packets.len() - 1;
- assert!(tmp.packets[i].children.is_none());
- tmp.packets[i].children = Some(Container::new());
- container = tmp.packets[i].children.as_mut().unwrap();
- }
-
- container.packets.push(packet);
-
- if ppo.is_none() {
- break 'outer;
- }
-
- pp = ppo.unwrap();
-
- last_position = position;
- position = pp.recursion_depth as isize;
- relative_position = position - last_position;
- if position < last_position {
- // There was a pop, we need to restart from the
- // root.
- break;
- }
-
- let result = pp.recurse()?;
- packet = result.0;
- assert_eq!(position, result.1);
- ppo = result.2;
- }
- }
-
- return Ok(Message { top_level: top_level });
- }
-}
-
-impl<'a> PacketParserBuilder<'a> {
- /// Finishes configuring the `PacketParser` and returns a fully
- /// parsed message.
- ///
- /// Note: calling this function does not change the default
- /// settings `PacketParserSettings`. Thus, by default, the
- /// content of packets will *not* be buffered.
- ///
- /// Note: to avoid denial of service attacks, the `PacketParser`
- /// interface should be preferred unless the size of the message
- /// is known to fit in memory.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use openpgp::Result;
- /// # use openpgp::Message;
- /// # use openpgp::parse::{PacketParser,PacketParserBuilder};
- /// # f(include_bytes!("../tests/data/messages/public-key.gpg"));
- /// #
- /// # fn f(message_data: &[u8]) -> Result<Message> {
- /// let message = PacketParserBuilder::from_bytes(message_data)?
- /// .buffer_unread_content()
- /// .to_message()?;
- /// # return Ok(message);
- /// # }
- /// ```
- pub fn to_message(self) -> Result<Message> {
- Message::from_packet_parser(self.finalize()?)
- }
-}
-
-#[cfg(test)]
-mod message_test {
- use super::*;
-
- use std::io::Read;
-
- #[test]
- fn deserialize_test_1 () {
- // XXX: This test should be more thorough. Right now, we mostly
- // just rely on the fact that an assertion is not thrown.
-
- // A flat message.
- let message = Message::from_bytes(bytes!("public-key.gpg")).unwrap();
- eprintln!("Message has {} top-level packets.",
- message.children().len());
- eprintln!("Message: {:?}", message);
-
- let mut count = 0;
- for (i, p) in message.descendants().enumerate() {
- eprintln!("{}: {:?}", i, p);
- count += 1;
- }
-
- assert_eq!(count, 61);
- }
-
- #[test]
- fn deserialize_test_2 () {
- // A message containing a compressed packet that contains a
- // literal packet.
- let path = path_to("compressed-data-algo-1.gpg");
- let message = Message::from_file(&path).unwrap();
- eprintln!("Message has {} top-level packets.",
- message.children().len());
- eprintln!("Message: {:?}", message);
-
- let mut count = 0;
- for (i, p) in message.descendants().enumerate() {
- eprintln!("{}: {:?}", i, p);
- count += 1;
- }
- assert_eq!(count, 2);
- }
-
- #[test]
- fn deserialize_test_3 () {
- let path = path_to("signed.gpg");
- let message = Message::from_file(&path).unwrap();
- eprintln!("Message has {} top-level packets.",
- message.children().len());
- eprintln!("Message: {:?}", message);
-
- let mut count = 0;
- for (i, p) in message.descendants().enumerate() {
- count += 1;
- eprintln!("{}: {:?}", i, p);
- }
- // We expect 6 packets.
- assert_eq!(count, 6);
- }
-
- // dkg's key contains packets from different OpenPGP
- // implementations. And, it even includes some v3 signatures.
- //
- // lutz's key is a v3 key.
- #[test]
- fn torture() {
- let data = bytes!("../keys/dkg.gpg");
- let mut mp = PacketParserBuilder::from_bytes(data).unwrap()
- //.trace()
- .buffer_unread_content()
- .to_message_parser().unwrap();
-
- while mp.recurse() {
- //let pp = mp.ppo.as_mut().unwrap();
- //eprintln!("{:?}", pp);
- }
- let message = mp.finish();
- //message.pretty_print();
- assert_eq!(message.children().len(), 1450);
-
- let data = bytes!("../keys/lutz.gpg");
- let mut mp = PacketParserBuilder::from_bytes(data).unwrap()
- //.trace()
- .buffer_unread_content()
- .to_message_parser().unwrap();
-
- while mp.recurse() {
- let pp = mp.ppo.as_mut().unwrap();
- eprintln!("{:?}", pp);
- }
- let message = mp.finish();
- message.pretty_print();
- assert_eq!(message.children().len(), 77);
- }
-
- #[test]
- fn compression_quine_test_1 () {
- // Use the Message::from_file interface to parse an OpenPGP
- // quine.
- let path = path_to("compression-quine.gpg");
- let max_recursion_depth = 128;
- let message = PacketParserBuilder::from_file(path).unwrap()
- .max_recursion_depth(max_recursion_depth)
- .to_message().unwrap();
-
- let mut count = 0;
- for (i, p) in message.descendants().enumerate() {
- count += 1;
- if false {
- eprintln!("{}: p: {:?}", i, p);
- }
- }
-
- assert_eq!(count, 1 + max_recursion_depth);
- }
-
- #[test]
- fn compression_quine_test_2 () {
- // Use the iterator interface to parse an OpenPGP quine.
- let path = path_to("compression-quine.gpg");
- let max_recursion_depth = 255;
- let mut ppo : Option<PacketParser>
- = PacketParserBuilder::from_file(path).unwrap()
- .max_recursion_depth(max_recursion_depth)
- .finalize().unwrap();
-
- let mut count : usize = 0;
- loop {
- if let Some(pp2) = ppo {
- count += 1;
-
- let (_packet, packet_depth, pp2, pp_depth)
- = pp2.recurse().unwrap();
- eprintln!("{}, {}", packet_depth, pp_depth);
- assert_eq!(packet_depth as usize, count - 1);
- if pp2.is_some() {
- assert_eq!(pp_depth as usize, count);
- }
- ppo = pp2;