sequoia_openpgp/types/
compression_level.rs

1//! Common code for the compression writers.
2
3use crate::{
4    Error,
5    Result,
6};
7
8/// Compression level.
9///
10/// This value is used by the encoders to tune their compression
11/// strategy.  The level is restricted to levels commonly used by
12/// compression libraries, `0` to `9`, where `0` means no compression,
13/// `1` means fastest compression, `6` being a good default, and
14/// meaning `9` best compression.
15///
16/// Note that compression is [dangerous when used naively].
17///
18/// [dangerous when used naively]: https://mailarchive.ietf.org/arch/msg/openpgp/2FQUVt6Dw8XAsaMELyo5BNlh2pM
19#[cfg_attr(feature = "compression-deflate", doc = r##"
20To mitigate some of these issues messages should [use padding].
21
22[use padding]: crate::serialize::stream::padding
23
24# Examples
25
26Write a message using the given [CompressionAlgorithm]:
27
28[CompressionAlgorithm]: super::CompressionAlgorithm
29
30```
31use sequoia_openpgp as openpgp;
32# fn main() -> openpgp::Result<()> {
33use std::io::Write;
34use openpgp::serialize::stream::{Message, Compressor, LiteralWriter};
35use openpgp::serialize::stream::padding::Padder;
36use openpgp::types::{CompressionAlgorithm, CompressionLevel};
37
38let mut sink = Vec::new();
39let message = Message::new(&mut sink);
40let message = Compressor::new(message)
41    .algo(CompressionAlgorithm::Zlib)
42#   .algo(CompressionAlgorithm::Uncompressed)
43    .level(CompressionLevel::fastest())
44    .build()?;
45
46let message = Padder::new(message).build()?;
47
48let mut message = LiteralWriter::new(message).build()?;
49message.write_all(b"Hello world.")?;
50message.finalize()?;
51# Ok(()) }
52```
53"##)]
54#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
55pub struct CompressionLevel(u8);
56assert_send_and_sync!(CompressionLevel);
57
58impl Default for CompressionLevel {
59    fn default() -> Self {
60        Self(6)
61    }
62}
63
64impl CompressionLevel {
65    /// Creates a new compression level.
66    ///
67    /// `level` must be in range `0..10`, where `0` means no
68    /// compression, `1` means fastest compression, `6` being a good
69    /// default, and meaning `9` best compression.
70    pub fn new(level: u8) -> Result<CompressionLevel> {
71        if level < 10 {
72            Ok(Self(level))
73        } else {
74            Err(Error::InvalidArgument(
75                format!("compression level out of range: {}", level)).into())
76        }
77    }
78
79    /// No compression.
80    pub fn none() -> CompressionLevel {
81        Self(0)
82    }
83
84    /// Fastest compression.
85    pub fn fastest() -> CompressionLevel {
86        Self(1)
87    }
88    /// Best compression.
89    pub fn best() -> CompressionLevel {
90        Self(9)
91    }
92}
93
94#[cfg(feature = "compression-deflate")]
95mod into_deflate_compression {
96    use flate2::Compression;
97    use super::*;
98
99    impl From<CompressionLevel> for Compression {
100        fn from(l: CompressionLevel) -> Self {
101            Compression::new(l.0 as u32)
102        }
103    }
104}
105
106#[cfg(feature = "compression-bzip2")]
107mod into_bzip2_compression {
108    use bzip2::Compression;
109    use super::*;
110
111    impl From<CompressionLevel> for Compression {
112        fn from(l: CompressionLevel) -> Self {
113            Compression::new(l.0 as u32)
114        }
115    }
116}