1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
use std::fmt;
#[cfg(test)]
use quickcheck::{Arbitrary, Gen};
use crate::packet;
use crate::Packet;
use crate::types::CompressionAlgorithm;
/// Holds a compressed data packet.
///
/// A compressed data packet is a container. See [Section 5.6 of RFC
/// 4880] for details.
///
/// When the parser encounters a compressed data packet with an
/// unknown compress algorithm, it returns an `Unknown` packet instead
/// of a `CompressedData` packet.
///
/// [Section 5.6 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.6
// IMPORTANT: If you add fields to this struct, you need to explicitly
// IMPORTANT: implement PartialEq, Eq, and Hash.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CompressedData {
/// CTB packet header fields.
pub(crate) common: packet::Common,
/// Algorithm used to compress the payload.
algo: CompressionAlgorithm,
/// This is a container packet.
container: packet::Container,
}
assert_send_and_sync!(CompressedData);
impl std::ops::Deref for CompressedData {
type Target = packet::Container;
fn deref(&self) -> &Self::Target {
&self.container
}
}
impl std::ops::DerefMut for CompressedData {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.container
}
}
impl fmt::Debug for CompressedData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("CompressedData")
.field("algo", &self.algo)
.field("container", &self.container)
.finish()
}
}
impl CompressedData {
/// Returns a new `CompressedData` packet.
pub fn new(algo: CompressionAlgorithm) -> Self {
CompressedData {
common: Default::default(),
algo,
container: Default::default(),
}
}
/// Gets the compression algorithm.
pub fn algo(&self) -> CompressionAlgorithm {
self.algo
}
/// Sets the compression algorithm.
pub fn set_algo(&mut self, algo: CompressionAlgorithm) -> CompressionAlgorithm {
::std::mem::replace(&mut self.algo, algo)
}
/// Adds a new packet to the container.
#[cfg(test)]
pub fn push(mut self, packet: Packet) -> Self {
self.container.children_mut().unwrap().push(packet);
self
}
/// Inserts a new packet to the container at a particular index.
/// If `i` is 0, the new packet is insert at the front of the
/// container. If `i` is one, it is inserted after the first
/// packet, etc.
#[cfg(test)]
pub fn insert(mut self, i: usize, packet: Packet) -> Self {
self.container.children_mut().unwrap().insert(i, packet);
self
}
}
impl From<CompressedData> for Packet {
fn from(s: CompressedData) -> Self {
Packet::CompressedData(s)
}
}
#[cfg(test)]
impl Arbitrary for CompressedData {
fn arbitrary(g: &mut Gen) -> Self {
use crate::serialize::SerializeInto;
use crate::arbitrary_helper::gen_arbitrary_from_range;
loop {
let a =
CompressionAlgorithm::from(gen_arbitrary_from_range(0..4, g));
if a.is_supported() {
let mut c = CompressedData::new(a);
// We arbitrarily chose to create packets with
// processed bodies, so that
// Packet::from_bytes(c.to_vec()) will roundtrip them.
c.set_body(packet::Body::Processed(
Packet::arbitrary(g).to_vec().unwrap()
));
return c;
}
}
}
}