Skip to content

Commit

Permalink
Merge pull request #49 from accidentaldevelopment/custom-line-wrap
Browse files Browse the repository at this point in the history
Add line_wrap to encoding config
  • Loading branch information
jcreekmore authored Jul 25, 2023
2 parents b32d04e + 7e1f40b commit bc5d3bb
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased
- trim `proptest` features to prevent an MSRV break for testing
- make EncodeConfig struct extendable and add a line_wrap config option

# 2.0.1

Expand Down
79 changes: 63 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ pub enum LineEnding {
#[derive(Debug, Clone, Copy)]
pub struct EncodeConfig {
/// Line ending to use during encoding
pub line_ending: LineEnding,
line_ending: LineEnding,

/// Line length to use during encoding
line_wrap: usize,
}

/// A representation of Pem-encoded data
Expand Down Expand Up @@ -234,6 +237,34 @@ impl HeaderMap {
}
}

impl EncodeConfig {
/// Create a new encode config with default values.
pub fn new() -> Self {
Self::default()
}

/// Set the line ending to use for the encoding.
pub fn set_line_ending(mut self, line_ending: LineEnding) -> Self {
self.line_ending = line_ending;
self
}

/// Set the line length to use for the encoding.
pub fn set_line_wrap(mut self, line_wrap: usize) -> Self {
self.line_wrap = line_wrap;
self
}
}

impl Default for EncodeConfig {
fn default() -> Self {
Self {
line_ending: LineEnding::CRLF,
line_wrap: LINE_WRAP,
}
}
}

impl Pem {
/// Create a new Pem struct
pub fn new(tag: impl ToString, contents: impl Into<Vec<u8>>) -> Pem {
Expand Down Expand Up @@ -461,12 +492,7 @@ pub fn parse_many<B: AsRef<[u8]>>(input: B) -> Result<Vec<Pem>> {
/// encode(&pem);
/// ```
pub fn encode(pem: &Pem) -> String {
encode_config(
pem,
EncodeConfig {
line_ending: LineEnding::CRLF,
},
)
encode_config(pem, EncodeConfig::default())
}

/// Encode a PEM struct into a PEM-encoded data string with additional
Expand All @@ -477,7 +503,7 @@ pub fn encode(pem: &Pem) -> String {
/// use pem::{Pem, encode_config, EncodeConfig, LineEnding};
///
/// let pem = Pem::new("FOO", [1, 2, 3, 4]);
/// encode_config(&pem, EncodeConfig { line_ending: LineEnding::LF });
/// encode_config(&pem, EncodeConfig::new().set_line_ending(LineEnding::LF));
/// ```
pub fn encode_config(pem: &Pem, config: EncodeConfig) -> String {
let line_ending = match config.line_ending {
Expand All @@ -500,7 +526,7 @@ pub fn encode_config(pem: &Pem, config: EncodeConfig) -> String {
}
output.push_str(line_ending);
}
for c in contents.as_bytes().chunks(LINE_WRAP) {
for c in contents.as_bytes().chunks(config.line_wrap) {
output.push_str(&format!("{}{}", str::from_utf8(c).unwrap(), line_ending));
}
output.push_str(&format!("-----END {}-----{}", pem.tag, line_ending));
Expand Down Expand Up @@ -540,7 +566,7 @@ pub fn encode_many(pems: &[Pem]) -> String {
/// Pem::new("FOO", [1, 2, 3, 4]),
/// Pem::new("BAR", [5, 6, 7, 8]),
/// ];
/// encode_many_config(&data, EncodeConfig { line_ending: LineEnding::LF });
/// encode_many_config(&data, EncodeConfig::new().set_line_ending(LineEnding::LF));
/// ```
pub fn encode_many_config(pems: &[Pem], config: EncodeConfig) -> String {
let line_ending = match config.line_ending {
Expand Down Expand Up @@ -644,6 +670,17 @@ ijoUXIDruJQEGFGvZTsi1D2RehXiT90CIQC4HOQUYKCydB7oWi1SHDokFW2yFyo6
/+lf3fgNjPI6OQIgUPmTFXciXxT1msh3gFLf3qt2Kv8wbr9Ad9SXjULVpGkCIB+g
RzHX0lkJl9Stshd/7Gbt65/QYq+v+xvAeT0CoyIg
-----END RSA PUBLIC KEY-----
";

const SAMPLE_DEFAULT_LINE_WRAP: &str = "-----BEGIN TEST-----\r
AQIDBA==\r
-----END TEST-----\r
";

const SAMPLE_CUSTOM_LINE_WRAP_4: &str = "-----BEGIN TEST-----\r
AQID\r
BA==\r
-----END TEST-----\r
";

#[test]
Expand Down Expand Up @@ -731,6 +768,20 @@ RzHX0lkJl9Stshd/7Gbt65/QYq+v+xvAeT0CoyIg
assert_eq!(parse_many(input), Err(PemError::MissingBeginTag));
}

#[test]
fn test_encode_default_line_wrap() {
let pem = Pem::new("TEST", vec![1, 2, 3, 4]);
assert_eq!(encode(&pem), SAMPLE_DEFAULT_LINE_WRAP);
}

#[test]
fn test_encode_custom_line_wrap_4() {
let pem = Pem::new("TEST", vec![1, 2, 3, 4]);
assert_eq!(
encode_config(&pem, EncodeConfig::default().set_line_wrap(4)),
SAMPLE_CUSTOM_LINE_WRAP_4
);
}
#[test]
fn test_encode_empty_contents() {
let pem = Pem::new("FOO", vec![]);
Expand Down Expand Up @@ -762,9 +813,7 @@ RzHX0lkJl9Stshd/7Gbt65/QYq+v+xvAeT0CoyIg
#[test]
fn test_encode_config_contents() {
let pem = Pem::new("FOO", [1, 2, 3, 4]);
let config = EncodeConfig {
line_ending: LineEnding::LF,
};
let config = EncodeConfig::default().set_line_ending(LineEnding::LF);
let encoded = encode_config(&pem, config);
assert!(!encoded.is_empty());

Expand All @@ -775,9 +824,7 @@ RzHX0lkJl9Stshd/7Gbt65/QYq+v+xvAeT0CoyIg
#[test]
fn test_encode_many_config() {
let pems = parse_many(SAMPLE_LF).unwrap();
let config = EncodeConfig {
line_ending: LineEnding::LF,
};
let config = EncodeConfig::default().set_line_ending(LineEnding::LF);
let encoded = encode_many_config(&pems, config);

assert_eq!(SAMPLE_LF, encoded);
Expand Down

0 comments on commit bc5d3bb

Please sign in to comment.