diff options
Diffstat (limited to 'internals/src/encoder/mod.rs')
-rw-r--r-- | internals/src/encoder/mod.rs | 751 |
1 files changed, 392 insertions, 359 deletions
diff --git a/internals/src/encoder/mod.rs b/internals/src/encoder/mod.rs index 760da2f..61a710d 100644 --- a/internals/src/encoder/mod.rs +++ b/internals/src/encoder/mod.rs @@ -18,29 +18,22 @@ use std::borrow::Cow; use std::str; use failure::Fail; -use soft_ascii_string::{SoftAsciiStr, SoftAsciiChar}; +use soft_ascii_string::{SoftAsciiChar, SoftAsciiStr}; +use error::{EncodingError, EncodingErrorKind, UNKNOWN, US_ASCII, UTF_8}; use grammar::is_atext; -use ::utils::{ - is_utf8_continuation_byte, - vec_insert_bytes -}; -use ::MailType; -use ::error::{ - EncodingError, EncodingErrorKind, - UNKNOWN, UTF_8, US_ASCII -}; - -#[cfg(feature="traceing")] -#[cfg_attr(test, macro_use)] -mod trace; +use utils::{is_utf8_continuation_byte, vec_insert_bytes}; +use MailType; + #[cfg_attr(test, macro_use)] mod encodable; +#[cfg(feature = "traceing")] +#[cfg_attr(test, macro_use)] +mod trace; - -#[cfg(feature="traceing")] -pub use self::trace::*; pub use self::encodable::*; +#[cfg(feature = "traceing")] +pub use self::trace::*; /// as specified in RFC 5322 not including CRLF pub const LINE_LEN_SOFT_LIMIT: usize = 78; @@ -50,29 +43,27 @@ pub const LINE_LEN_HARD_LIMIT: usize = 998; pub const NEWLINE: &str = "\r\n"; pub const NEWLINE_WITH_SPACE: &str = "\r\n "; - /// EncodingBuffer for a Mail providing a buffer for encodable traits. pub struct EncodingBuffer { mail_type: MailType, buffer: Vec<u8>, - #[cfg(feature="traceing")] - pub trace: Vec<TraceToken> + #[cfg(feature = "traceing")] + pub trace: Vec<TraceToken>, } impl EncodingBuffer { - /// Create a new buffer only allowing input compatible with a the specified mail type. pub fn new(mail_type: MailType) -> Self { EncodingBuffer { mail_type, buffer: Vec::new(), - #[cfg(feature="traceing")] - trace: Vec::new() + #[cfg(feature = "traceing")] + trace: Vec::new(), } } /// Returns the mail type for which the buffer was created. - pub fn mail_type( &self ) -> MailType { + pub fn mail_type(&self) -> MailType { self.mail_type } @@ -80,11 +71,11 @@ impl EncodingBuffer { /// a mutable reference to the current string buffer /// pub fn writer(&mut self) -> EncodingWriter { - #[cfg(not(feature="traceing"))] + #[cfg(not(feature = "traceing"))] { EncodingWriter::new(self.mail_type, &mut self.buffer) } - #[cfg(feature="traceing")] + #[cfg(feature = "traceing")] { EncodingWriter::new(self.mail_type, &mut self.buffer, &mut self.trace) } @@ -98,27 +89,29 @@ impl EncodingBuffer { /// writes /// - if `func` succeeded `handle.finish_header()` is called pub fn write_header_line<FN>(&mut self, func: FN) -> Result<(), EncodingError> - where FN: FnOnce(&mut EncodingWriter) -> Result<(), EncodingError> + where + FN: FnOnce(&mut EncodingWriter) -> Result<(), EncodingError>, { - let mut handle = self.writer(); + let mut handle = self.writer(); match func(&mut handle) { Ok(()) => { handle.finish_header(); Ok(()) - }, + } Err(e) => { handle.undo_header(); Err(e) } } - } pub fn write_blank_line(&mut self) { //TODO/BENCH push_str vs. extends(&[u8]) self.buffer.extend(NEWLINE.as_bytes()); - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::BlankLine); } + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::BlankLine); + } } /// writes a body to the internal buffer, without verifying it's correctness @@ -142,16 +135,15 @@ impl EncodingBuffer { /// /// This can fail if a body does not contain valid utf8. pub fn as_str(&self) -> Result<&str, EncodingError> { - str::from_utf8(self.buffer.as_slice()) - .map_err(|err| { - EncodingError::from(( - err.context(EncodingErrorKind::InvalidTextEncoding { - expected_encoding: UTF_8, - got_encoding: UNKNOWN - }), - self.mail_type() - )) - }) + str::from_utf8(self.buffer.as_slice()).map_err(|err| { + EncodingError::from(( + err.context(EncodingErrorKind::InvalidTextEncoding { + expected_encoding: UTF_8, + got_encoding: UNKNOWN, + }), + self.mail_type(), + )) + }) } /// Converts the internal buffer into an utf-8 string if possible. @@ -168,10 +160,8 @@ impl EncodingBuffer { pub fn as_slice(&self) -> &[u8] { &self.buffer } - } - impl Into<Vec<u8>> for EncodingBuffer { fn into(self) -> Vec<u8> { self.buffer @@ -184,10 +174,14 @@ impl Into<(MailType, Vec<u8>)> for EncodingBuffer { } } -#[cfg(feature="traceing")] +#[cfg(feature = "traceing")] impl Into<(MailType, Vec<u8>, Vec<TraceToken>)> for EncodingBuffer { fn into(self) -> (MailType, Vec<u8>, Vec<TraceToken>) { - let EncodingBuffer { mail_type, buffer, trace } = self; + let EncodingBuffer { + mail_type, + buffer, + trace, + } = self; (mail_type, buffer, trace) } } @@ -211,7 +205,7 @@ impl Into<(MailType, Vec<u8>, Vec<TraceToken>)> for EncodingBuffer { /// pub struct EncodingWriter<'a> { buffer: &'a mut Vec<u8>, - #[cfg(feature="traceing")] + #[cfg(feature = "traceing")] trace: &'a mut Vec<TraceToken>, mail_type: MailType, line_start_idx: usize, @@ -228,16 +222,15 @@ pub struct EncodingWriter<'a> { /// represents if if a FWS was just marked (opt-FWS) or was written out last_fws_has_char: bool, header_start_idx: usize, - #[cfg(feature="traceing")] - trace_start_idx: usize + #[cfg(feature = "traceing")] + trace_start_idx: usize, } -#[cfg(feature="traceing")] +#[cfg(feature = "traceing")] impl<'a> Drop for EncodingWriter<'a> { - fn drop(&mut self) { use std::thread; - if !thread::panicking() && self.has_unfinished_parts() { + if !thread::panicking() && self.has_unfinished_parts() { // we really should panic as the back buffer i.e. the mail will contain // some partially written header which definitely is a bug panic!("dropped Handle which partially wrote header to back buffer (use `finish_header` or `discard`)") @@ -246,12 +239,8 @@ impl<'a> Drop for EncodingWriter<'a> { } impl<'inner> EncodingWriter<'inner> { - - #[cfg(not(feature="traceing"))] - fn new( - mail_type: MailType, - buffer: &'inner mut Vec<u8>, - ) -> Self { + #[cfg(not(feature = "traceing"))] + fn new(mail_type: MailType, buffer: &'inner mut Vec<u8>) -> Self { let start_idx = buffer.len(); EncodingWriter { buffer, @@ -266,11 +255,11 @@ impl<'inner> EncodingWriter<'inner> { } } - #[cfg(feature="traceing")] + #[cfg(feature = "traceing")] fn new( mail_type: MailType, buffer: &'inner mut Vec<u8>, - trace: &'inner mut Vec<TraceToken> + trace: &'inner mut Vec<TraceToken>, ) -> Self { let start_idx = buffer.len(); let trace_start_idx = trace.len(); @@ -285,7 +274,7 @@ impl<'inner> EncodingWriter<'inner> { content_before_fws: false, header_start_idx: start_idx, last_fws_has_char: false, - trace_start_idx + trace_start_idx, } } @@ -297,8 +286,10 @@ impl<'inner> EncodingWriter<'inner> { self.content_since_fws = false; self.content_before_fws = false; self.header_start_idx = start_idx; - #[cfg(feature="traceing")] - { self.trace_start_idx = self.trace.len(); } + #[cfg(feature = "traceing")] + { + self.trace_start_idx = self.trace.len(); + } } /// Returns true if this type thinks we are in the process of writing a header. @@ -331,8 +322,10 @@ impl<'inner> EncodingWriter<'inner> { /// # Trace (test build only) /// does push a `MarkFWS` Token pub fn mark_fws_pos(&mut self) { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::MarkFWS) } + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::MarkFWS) + } self.content_before_fws |= self.content_since_fws; self.content_since_fws = false; self.last_fws_idx = self.buffer.len(); @@ -348,9 +341,11 @@ impl<'inner> EncodingWriter<'inner> { /// /// # Trace (test build only) /// does push `NowChar` and then can push `Text`,`CRLF` - pub fn write_char(&mut self, ch: SoftAsciiChar) -> Result<(), EncodingError> { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowChar) } + pub fn write_char(&mut self, ch: SoftAsciiChar) -> Result<(), EncodingError> { + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowChar) + } let mut buffer = [0xff_u8; 4]; let ch: char = ch.into(); let slice = ch.encode_utf8(&mut buffer); @@ -372,13 +367,14 @@ impl<'inner> EncodingWriter<'inner> { /// # Trace (test build only) /// does push `NowStr` and then can push `Text`,`CRLF` /// - pub fn write_str(&mut self, s: &SoftAsciiStr) -> Result<(), EncodingError> { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowStr) } + pub fn write_str(&mut self, s: &SoftAsciiStr) -> Result<(), EncodingError> { + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowStr) + } self.internal_write_str(s.as_str()) } - /// writes a utf8 str into a buffer for an internationalized mail /// /// # Error (ConditionalWriteResult) @@ -394,12 +390,15 @@ impl<'inner> EncodingWriter<'inner> { /// /// # Trace (test build only) /// does push `NowUtf8` and then can push `Text`,`CRLF` - pub fn write_if_utf8<'short>(&'short mut self, s: &str) - -> ConditionalWriteResult<'short, 'inner> - { + pub fn write_if_utf8<'short>( + &'short mut self, + s: &str, + ) -> ConditionalWriteResult<'short, 'inner> { if self.mail_type().is_internationalized() { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowUtf8) } + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowUtf8) + } self.internal_write_str(s).into() } else { ConditionalWriteResult::ConditionFailure(self) @@ -408,16 +407,18 @@ impl<'inner> EncodingWriter<'inner> { pub fn write_utf8(&mut self, s: &str) -> Result<(), EncodingError> { if self.mail_type().is_internationalized() { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowUtf8) } + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowUtf8) + } self.internal_write_str(s) } else { let mut err = EncodingError::from(( EncodingErrorKind::InvalidTextEncoding { expected_encoding: US_ASCII, - got_encoding: UTF_8 + got_encoding: UTF_8, }, - self.mail_type() + self.mail_type(), )); let raw_line = &self.buffer[self.line_start_idx..]; let mut line = String::from_utf8_lossy(raw_line).into_owned(); @@ -454,12 +455,15 @@ impl<'inner> EncodingWriter<'inner> { /// # Trace (test build only) /// does push `NowAText` and then can push `Text` /// - pub fn write_if_atext<'short>(&'short mut self, s: &str) - -> ConditionalWriteResult<'short, 'inner> - { - if s.chars().all( |ch| is_atext( ch, self.mail_type() ) ) { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowAText) } + pub fn write_if_atext<'short>( + &'short mut self, + s: &str, + ) -> ConditionalWriteResult<'short, 'inner> { + if s.chars().all(|ch| is_atext(ch, self.mail_type())) { + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowAText) + } // the ascii or not aspect is already converted by `is_atext` self.internal_write_str(s).into() } else { @@ -471,13 +475,19 @@ impl<'inner> EncodingWriter<'inner> { /// then writes it _without additional checks_ to the buffer if `cond` returned /// true /// - pub fn write_if<'short, FN>(&'short mut self, s: &str, cond: FN) - -> ConditionalWriteResult<'short, 'inner> - where FN: FnOnce(&str) -> bool + pub fn write_if<'short, FN>( + &'short mut self, + s: &str, + cond: FN, + ) -> ConditionalWriteResult<'short, 'inner> + where + FN: FnOnce(&str) -> bool, { if cond(s) { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowCondText) } + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowCondText) + } // the ascii or not aspect is already converted by `is_atext` self.internal_write_str(s).into() } else { @@ -509,9 +519,11 @@ impl<'inner> EncodingWriter<'inner> { /// /// through is gives a different tracing its roughly equivalent. /// - pub fn write_str_unchecked( &mut self, s: &str) -> Result<(), EncodingError> { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::NowUnchecked) } + pub fn write_str_unchecked(&mut self, s: &str) -> Result<(), EncodingError> { + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::NowUnchecked) + } self.internal_write_str(s) } @@ -523,9 +535,13 @@ impl<'inner> EncodingWriter<'inner> { /// is written correctly. So you _normally_ should /// not use it. pub fn commit_partial_header(&mut self) { - #[cfg(feature="traceing")] - { if let Some(&TraceToken::End) = self.trace.last() {} - else { self.trace.push(TraceToken::End) } } + #[cfg(feature = "traceing")] + { + if let Some(&TraceToken::End) = self.trace.last() { + } else { + self.trace.push(TraceToken::End) + } + } self.reinit(); } @@ -548,9 +564,13 @@ impl<'inner> EncodingWriter<'inner> { /// will not generate multiple `End` tokens, just one pub fn finish_header(&mut self) { self.start_new_line(); - #[cfg(feature="traceing")] - { if let Some(&TraceToken::End) = self.trace.last() {} - else { self.trace.push(TraceToken::End) } } + #[cfg(feature = "traceing")] + { + if let Some(&TraceToken::End) = self.trace.last() { + } else { + self.trace.push(TraceToken::End) + } + } self.reinit(); } @@ -565,13 +585,13 @@ impl<'inner> EncodingWriter<'inner> { /// pub fn undo_header(&mut self) { self.buffer.truncate(self.header_start_idx); - #[cfg(feature="traceing")] - { self.trace.truncate(self.trace_start_idx); } + #[cfg(feature = "traceing")] + { + self.trace.truncate(self.trace_start_idx); + } self.reinit(); } - - //---------------------------------------------------------------------------------------------/ //-/////////////////////////// methods only using the public iface /////////////////////////-/ @@ -594,8 +614,6 @@ impl<'inner> EncodingWriter<'inner> { let _ = self.write_char(SoftAsciiChar::from_unchecked(' ')); } - - //---------------------------------------------------------------------------------------------/ //-/////////////////////////// private methods ////////////////////////-/ @@ -603,7 +621,7 @@ impl<'inner> EncodingWriter<'inner> { /// while we could implement a undo option it makes /// little sense for the use case the generally available /// `undo_header` is enough. - fn internal_write_str(&mut self, s: &str) -> Result<(), EncodingError> { + fn internal_write_str(&mut self, s: &str) -> Result<(), EncodingError> { if s.is_empty() { return Ok(()); } @@ -631,13 +649,15 @@ impl<'inner> EncodingWriter<'inner> { /// removing the blank line (not that WS are only ' ' and '\r') fn start_new_line(&mut self) { if self.line_has_content() { - #[cfg(feature="traceing")] - { self.trace.push(TraceToken::CRLF) } + #[cfg(feature = "traceing")] + { + self.trace.push(TraceToken::CRLF) + } self.buffer.push(b'\r'); self.buffer.push(b'\n'); } else { - #[cfg(feature="traceing")] + #[cfg(feature = "traceing")] { if self.buffer.len() > self.line_start_idx { self.trace.push(TraceToken::TruncateToCRLF); @@ -653,18 +673,16 @@ impl<'inner> EncodingWriter<'inner> { self.content_since_fws = false; self.content_before_fws = false; self.last_fws_idx = self.line_start_idx; - } fn break_line_on_fws(&mut self) -> bool { if self.content_before_fws && self.last_fws_idx > self.line_start_idx { - let newline = - if self.last_fws_has_char { - debug_assert!([b' ', b'\t'].contains(&self.buffer[self.last_fws_idx])); - NEWLINE - } else { - NEWLINE_WITH_SPACE - }; + let newline = if self.last_fws_has_char { + debug_assert!([b' ', b'\t'].contains(&self.buffer[self.last_fws_idx])); + NEWLINE + } else { + NEWLINE_WITH_SPACE + }; vec_insert_bytes(&mut self.buffer, self.last_fws_idx, newline.as_bytes()); self.line_start_idx = self.last_fws_idx + 2; @@ -732,7 +750,7 @@ impl<'inner> EncodingWriter<'inner> { } self.buffer.extend(unchecked_utf8_char.as_bytes()); - #[cfg(feature="traceing")] + #[cfg(feature = "traceing")] { //FIXME[rust/nll]: just use a `if let`-`else` with NLL's let need_new = @@ -747,7 +765,6 @@ impl<'inner> EncodingWriter<'inner> { string.push_str(unchecked_utf8_char); self.trace.push(TraceToken::Text(string)) } - } // we can't allow "blank" lines @@ -763,53 +780,47 @@ impl<'inner> EncodingWriter<'inner> { pub enum ConditionalWriteResult<'a, 'b: 'a> { Ok, ConditionFailure(&'a mut EncodingWriter<'b>), - GeneralFailure(EncodingError) + GeneralFailure(EncodingError), } impl<'a, 'b: 'a> From<Result<(), EncodingError>> for ConditionalWriteResult<'a, 'b> { fn from(v: Result<(), EncodingError>) -> Self { match v { Ok(()) => ConditionalWriteResult::Ok, - Err(e) => ConditionalWriteResult::GeneralFailure(e) + Err(e) => ConditionalWriteResult::GeneralFailure(e), } } } impl<'a, 'b: 'a> ConditionalWriteResult<'a, 'b> { - #[inline] pub fn handle_condition_failure<FN>(self, func: FN) -> Result<(), EncodingError> - where FN: FnOnce(&mut EncodingWriter) -> Result<(), EncodingError> + where + FN: FnOnce(&mut EncodingWriter) -> Result<(), EncodingError>, { use self::ConditionalWriteResult as CWR; match self { CWR::Ok => Ok(()), - CWR::ConditionFailure(handle) => { - func(handle) - }, - CWR::GeneralFailure(err) => Err(err) + CWR::ConditionFailure(handle) => func(handle), + CWR::GeneralFailure(err) => Err(err), } } } - - - - #[cfg(test)] mod test { - use soft_ascii_string::{ SoftAsciiChar, SoftAsciiStr}; - use ::MailType; - use ::error::EncodingErrorKind; + use error::EncodingErrorKind; + use soft_ascii_string::{SoftAsciiChar, SoftAsciiStr}; + use MailType; + use super::EncodingBuffer as _Encoder; use super::TraceToken::*; - use super::{EncodingBuffer as _Encoder}; mod test_test_utilities { - use encoder::TraceToken::*; use super::super::simplify_trace_tokens; + use encoder::TraceToken::*; #[test] fn does_simplify_tokens_strip_nows() { @@ -827,21 +838,23 @@ mod test { Text("up!".into()), CRLF, NowAText, - Text("abc".into()) + Text("abc".into()), ]; let out = simplify_trace_tokens(inp); - assert_eq!(out, vec![ - Text("h".into()), - CRLF, - Text("y yo".into()), - CRLF, - Text(", what's".into()), - CRLF, - Text("up!".into()), - CRLF, - Text("abc".into()) - ]) - + assert_eq!( + out, + vec![ + Text("h".into()), + CRLF, + Text("y yo".into()), + CRLF, + Text(", what's".into()), + CRLF, + Text("up!".into()), + CRLF, + Text("abc".into()) + ] + ) } #[test] @@ -856,53 +869,36 @@ mod test { NowUnchecked, Text(" up! ".into()), NowAText, - Text("abc".into()) + Text("abc".into()), ]; let out = simplify_trace_tokens(inp); - assert_eq!(out, vec![ - Text("hy yo, what's up! abc".into()) - ]); + assert_eq!(out, vec![Text("hy yo, what's up! abc".into())]); } #[test] fn simplify_works_with_empty_text() { - let inp = vec![ - NowStr, - Text("".into()), - CRLF, - ]; - assert_eq!(simplify_trace_tokens(inp), vec![ - Text("".into()), - CRLF - ]) + let inp = vec![NowStr, Text("".into()), CRLF]; + assert_eq!(simplify_trace_tokens(inp), vec![Text("".into()), CRLF]) } #[test] fn simplify_works_with_trailing_empty_text() { - let inp = vec![ - Text("a".into()), - CRLF, - Text("".into()), - ]; - assert_eq!(simplify_trace_tokens(inp), vec![ - Text("a".into()), - CRLF, - Text("".into()) - ]) + let inp = vec![Text("a".into()), CRLF, Text("".into())]; + assert_eq!( + simplify_trace_tokens(inp), + vec![Text("a".into()), CRLF, Text("".into())] + ) } - } mod EncodableInHeader { #![allow(non_snake_case)] - use super::super::*; use self::TraceToken::*; + use super::super::*; #[test] fn is_implemented_for_closures() { - let closure = enc_func!(|handle: &mut EncodingWriter| { - handle.write_utf8("hy ho") - }); + let closure = enc_func!(|handle: &mut EncodingWriter| { handle.write_utf8("hy ho") }); let mut encoder = EncodingBuffer::new(MailType::Internationalized); { @@ -910,20 +906,17 @@ mod test { assert_ok!(closure.encode(&mut handle)); handle.finish_header(); } - assert_eq!(encoder.trace.as_slice(), &[ - NowUtf8, - Text("hy ho".into()), - CRLF, - End - ]) + assert_eq!( + encoder.trace.as_slice(), + &[NowUtf8, Text("hy ho".into()), CRLF, End] + ) } } - mod EncodingBuffer { #![allow(non_snake_case)] + use super::_Encoder as EncodingBuffer; use super::*; - use super::{ _Encoder as EncodingBuffer }; #[test] fn new_encoder() { @@ -943,23 +936,18 @@ mod test { assert_eq!( encoder.as_slice(), - concat!( - "una body\r\n", - "\r\n", - "another body\r\n" - ).as_bytes() + concat!("una body\r\n", "\r\n", "another body\r\n").as_bytes() ) } } - mod EncodingWriter { #![allow(non_snake_case)] use std::mem; use std::str; + use super::_Encoder as EncodingBuffer; use super::*; - use super::{ _Encoder as EncodingBuffer }; #[test] fn commit_partial_and_drop_does_not_panic() { @@ -977,8 +965,7 @@ mod test { let mut encoder = EncodingBuffer::new(MailType::Ascii); { let mut handle = encoder.writer(); - assert_ok!( - handle.write_str(SoftAsciiStr::from_unchecked("Header-One: 12"))); + assert_ok!(handle.write_str(SoftAsciiStr::from_unchecked("Header-One: 12"))); handle.undo_header(); } assert_eq!(encoder.as_slice(), b""); @@ -1024,19 +1011,22 @@ mod test { let mut encoder = EncodingBuffer::new(MailType::Ascii); { let mut handle = encoder.writer(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str("Header-One: 12\r\n ").unwrap())); + assert_ok!( + handle.write_str(SoftAsciiStr::from_str("Header-One: 12\r\n ").unwrap()) + ); handle.finish_header(); } assert_eq!(encoder.as_slice(), b"Header-One: 12\r\n"); } - #[test] fn finish_can_handle_fws() { let mut encoder = EncodingBuffer::new(MailType::Ascii); { let mut handle = encoder.writer(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str("Header-One: 12 +\r\n 4").unwrap())); + assert_ok!( + handle.write_str(SoftAsciiStr::from_str("Header-One: 12 +\r\n 4").unwrap()) + ); handle.finish_header(); } assert_eq!(encoder.as_slice(), b"Header-One: 12 +\r\n 4\r\n"); @@ -1047,14 +1037,14 @@ mod test { let mut encoder = EncodingBuffer::new(MailType::Ascii); { let mut handle = encoder.writer(); - assert_ok!(handle.write_str( - SoftAsciiStr::from_str("Header-One: 12 +\r\n 4 ").unwrap())); + assert_ok!( + handle.write_str(SoftAsciiStr::from_str("Header-One: 12 +\r\n 4 ").unwrap()) + ); handle.finish_header(); } assert_eq!(encoder.as_slice(), b"Header-One: 12 +\r\n 4 \r\n"); } - #[test] fn orphan_lf_error() { let mut encoder = EncodingBuffer::new(MailType::Ascii); @@ -1097,7 +1087,7 @@ mod test { assert_eq!(encoder.as_slice(), b"H: a\r\n"); } - #[test] + #[test] fn soft_line_limit_can_be_breached() { let mut encoder = EncodingBuffer::new(MailType::Ascii); { @@ -1130,15 +1120,18 @@ mod test { let mut handle = encoder.writer(); assert_ok!(handle.write_str(SoftAsciiStr::from_str("A23456789:").unwrap())); handle.mark_fws_pos(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str(concat!( - "20_3456789", - "30_3456789", - "40_3456789", - "50_3456789", - "60_3456789", - "70_3456789", - "12345678XX" - )).unwrap())); + assert_ok!(handle.write_str( + SoftAsciiStr::from_str(concat!( + "20_3456789", + "30_3456789", + "40_3456789", + "50_3456789", + "60_3456789", + "70_3456789", + "12345678XX" + )) + .unwrap() + )); handle.finish_header(); } assert_eq!( @@ -1163,15 +1156,18 @@ mod test { let mut handle = encoder.writer(); assert_ok!(handle.write_str(SoftAsciiStr::from_str("A23456789:").unwrap())); handle.write_fws(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str(concat!( - "20_3456789", - "30_3456789", - "40_3456789", - "50_3456789", - "60_3456789", - "70_3456789", - "12345678XX" - )).unwrap())); + assert_ok!(handle.write_str( + SoftAsciiStr::from_str(concat!( + "20_3456789", + "30_3456789", + "40_3456789", + "50_3456789", + "60_3456789", + "70_3456789", + "12345678XX" + )) + .unwrap() + )); handle.finish_header(); } @@ -1190,7 +1186,6 @@ mod test { ); } - #[test] fn to_long_unbreakable_line() { let mut encoder = EncodingBuffer::new(MailType::Ascii); @@ -1198,18 +1193,21 @@ mod test { let mut handle = encoder.writer(); assert_ok!(handle.write_str(SoftAsciiStr::from_str("A23456789:").unwrap())); handle.mark_fws_pos(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str(concat!( - "10_3456789", - "20_3456789", - "30_3456789", - "40_3456789", - "50_3456789", - "60_3456789", - "70_3456789", - "80_3456789", - "90_3456789", - "00_3456789", - )).unwrap())); + assert_ok!(handle.write_str( + SoftAsciiStr::from_str(concat!( + "10_3456789", + "20_3456789", + "30_3456789", + "40_3456789", + "50_3456789", + "60_3456789", + "70_3456789", + "80_3456789", + "90_3456789", + "00_3456789", + )) + .unwrap() + )); handle.finish_header(); } assert_eq!( @@ -1237,22 +1235,28 @@ mod test { let mut handle = encoder.writer(); assert_ok!(handle.write_str(SoftAsciiStr::from_str("A23456789:").unwrap())); handle.mark_fws_pos(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str(concat!( - "10_3456789", - "20_3456789", - "30_3456789", - "40_3456789", - "50_3456789", - "60_3456789", - "70_3456789", - )).unwrap())); + assert_ok!(handle.write_str( + SoftAsciiStr::from_str(concat!( + "10_3456789", + "20_3456789", + "30_3456789", + "40_3456789", + "50_3456789", + "60_3456789", + "70_3456789", + )) + .unwrap() + )); handle.mark_fws_pos(); - assert_ok!(handle.write_str(SoftAsciiStr::from_str(concat!( - "10_3456789", - "20_3456789", - "30_3456789", - "40_3456789", - )).unwrap())); + assert_ok!(handle.write_str( + SoftAsciiStr::from_str(concat!( + "10_3456789", + "20_3456789", + "30_3456789", + "40_3456789", + )) + .unwrap() + )); handle.finish_header(); } assert_eq!( @@ -1281,18 +1285,24 @@ mod test { let mut handle = encoder.writer(); for x in 0..998 { if let Err(_) = handle.write_char(SoftAsciiChar::from_unchecked('X')) { - panic!("error when writing char nr.: {:?}", x+1) + panic!("error when writing char nr.: {:?}", x + 1) } } let res = &[ - handle.write_char(SoftAsciiChar::from_unchecked('X')).is_err(), - handle.write_char(SoftAsciiChar::from_unchecked('X')).is_err(), - handle.write_char(SoftAsciiChar::from_unchecked('X')).is_err(), - handle.write_char(SoftAsciiChar::from_unchecked('X')).is_err(), + handle + .write_char(SoftAsciiChar::from_unchecked('X')) + .is_err(), + handle + .write_char(SoftAsciiChar::from_unchecked('X')) + .is_err(), + handle + .write_char(SoftAsciiChar::from_unchecked('X')) + .is_err(), + handle + .write_char(SoftAsciiChar::from_unchecked('X')) + .is_err(), ]; - assert_eq!( - res, &[true, true, true, true] - ); + assert_eq!(res, &[true, true, true, true]); handle.undo_header(); } } @@ -1333,14 +1343,18 @@ mod test { let mut encoder = EncodingBuffer::new(MailType::Ascii); { let mut handle = encoder.writer(); - assert_ok!(handle.write_if_atext("hoho") - .handle_condition_failure(|_|panic!("no condition failur expected"))); + assert_ok!(handle + .write_if_atext("hoho") + .handle_condition_failure(|_| panic!("no condition failur expected"))); let mut had_cond_failure = false; - assert_ok!(handle.write_if_atext("a(b") - .handle_condition_failure(|_| {had_cond_failure=true; Ok(())})); + assert_ok!(handle.write_if_atext("a(b").handle_condition_failure(|_| { + had_cond_failure = true; + Ok(()) + })); assert!(had_cond_failure); - assert_ok!(handle.write_if_atext("") - |