summaryrefslogtreecommitdiffstats
path: root/headers/src/header_components/message_id.rs
diff options
context:
space:
mode:
Diffstat (limited to 'headers/src/header_components/message_id.rs')
-rw-r--r--headers/src/header_components/message_id.rs243
1 files changed, 118 insertions, 125 deletions
diff --git a/headers/src/header_components/message_id.rs b/headers/src/header_components/message_id.rs
index 6ee8a61..e2bed1e 100644
--- a/headers/src/header_components/message_id.rs
+++ b/headers/src/header_components/message_id.rs
@@ -1,20 +1,16 @@
-use std::fmt::{self, Display};
use nom::IResult;
+use std::fmt::{self, Display};
+#[cfg(feature = "serde")]
+use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use soft_ascii_string::{SoftAsciiChar, SoftAsciiStr, SoftAsciiString};
use vec1::Vec1;
-#[cfg(feature="serde")]
-use serde::{
- Serialize, Serializer,
- Deserialize, Deserializer,
- de::Error
-};
+use data::{Input, SimpleItem};
+use error::ComponentCreationError;
+use internals::encoder::{EncodableInHeader, EncodingWriter};
use internals::error::EncodingError;
-use internals::encoder::{EncodingWriter, EncodableInHeader};
-use ::{HeaderTryFrom, HeaderTryInto};
-use ::error::ComponentCreationError;
-use ::data::{ Input, SimpleItem };
+use {HeaderTryFrom, HeaderTryInto};
/// # Implementation Details
///
@@ -25,94 +21,98 @@ use ::data::{ Input, SimpleItem };
/// only supports the later one.
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct MessageId {
- message_id: SimpleItem
+ message_id: SimpleItem,
}
-
impl MessageId {
-
/// creates a message id from a string without checking for validity
///
/// The string is expected to have the format `<left_part> "@" <right_part>`,
/// i.e. it should not include the `"<"`, `">"` surrounding message id's in
/// more or less all places they are used.
pub fn from_unchecked(string: String) -> Self {
- let item =
- match SoftAsciiString::from_string(string) {
- Ok(ascii) => ascii.into(),
- Err(err) => err.into_source().into()
- };
+ let item = match SoftAsciiString::from_string(string) {
+ Ok(ascii) => ascii.into(),
+ Err(err) => err.into_source().into(),
+ };
MessageId { message_id: item }
}
- pub fn new(left_part: &SoftAsciiStr, right_part: &SoftAsciiStr)
- -> Result<Self, ComponentCreationError>
- {
- use self::{parser_parts as parser};
+ pub fn new(
+ left_part: &SoftAsciiStr,
+ right_part: &SoftAsciiStr,
+ ) -> Result<Self, ComponentCreationError> {
+ use self::parser_parts as parser;
match parser::id_left(left_part.as_str()) {
- IResult::Done( "", _part ) => {},
+ IResult::Done("", _part) => {}
_other => {
return Err(ComponentCreationError::new_with_str(
- "MessageId", format!("{}@{}", left_part, right_part)));
+ "MessageId",
+ format!("{}@{}", left_part, right_part),
+ ));
}
}
match parser::id_right(right_part.as_str()) {
- IResult::Done( "", _part ) => {},
+ IResult::Done("", _part) => {}
_other => {
return Err(ComponentCreationError::new_with_str(
- "MessageId", format!("{}@{}", left_part, right_part)));
+ "MessageId",
+ format!("{}@{}", left_part, right_part),
+ ));
}
}
- let id = SoftAsciiString::from_unchecked(
- format!("{}@{}", left_part, right_part));
+ let id = SoftAsciiString::from_unchecked(format!("{}@{}", left_part, right_part));
let item = SimpleItem::Ascii(id.into());
Ok(MessageId { message_id: item })
}
//FIXME make into AsRef<str> for MessageId
- pub fn as_str( &self ) -> &str {
+ pub fn as_str(&self) -> &str {
self.message_id.as_str()
}
}
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
impl Serialize for MessageId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where S: Serializer
+ where
+ S: Serializer,
{
serializer.serialize_str(self.as_str())
}
}
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for MessageId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where D: Deserializer<'de>
+ where
+ D: Deserializer<'de>,
{
let as_string = String::deserialize(deserializer)?;
let as_ascii = SoftAsciiStr::from_str(&as_string)
.map_err(|err| D::Error::custom(format!("message id is not ascii: {}", err)))?;
- let split_point =
- if as_ascii.as_str().ends_with("]") {
- as_ascii.as_str()
- .bytes()
- .rposition(|bch| bch == b'[')
- .and_then(|pos| pos.checked_sub(1))
- .ok_or_else(|| D::Error::custom("invalid message id format"))?
- } else {
- as_ascii.as_str()
- .bytes()
- .rposition(|bch| bch == b'@')
- .ok_or_else(|| D::Error::custom("invalid message id format"))?
- };
+ let split_point = if as_ascii.as_str().ends_with("]") {
+ as_ascii
+ .as_str()
+ .bytes()
+ .rposition(|bch| bch == b'[')
+ .and_then(|pos| pos.checked_sub(1))
+ .ok_or_else(|| D::Error::custom("invalid message id format"))?
+ } else {
+ as_ascii
+ .as_str()
+ .bytes()
+ .rposition(|bch| bch == b'@')
+ .ok_or_else(|| D::Error::custom("invalid message id format"))?
+ };
let left_part = &as_ascii[..split_point];
- let right_part = &as_ascii[split_point+1..];
+ let right_part = &as_ascii[split_point + 1..];
MessageId::new(left_part, right_part)
.map_err(|err| D::Error::custom(format!("invalid message id format: {}", err)))
}
@@ -125,37 +125,41 @@ impl Display for MessageId {
}
impl<T> HeaderTryFrom<T> for MessageId
- where T: HeaderTryInto<Input>
+where
+ T: HeaderTryInto<Input>,
{
- fn try_from( input: T ) -> Result<Self, ComponentCreationError> {
+ fn try_from(input: T) -> Result<Self, ComponentCreationError> {
use self::parser_parts::parse_message_id;
let input = input.try_into()?;
match parse_message_id(input.as_str()) {
- IResult::Done( "", _msg_id ) => {},
+ IResult::Done("", _msg_id) => {}
_other => {
- return Err(ComponentCreationError::new_with_str("MessageId", input.as_str()));
+ return Err(ComponentCreationError::new_with_str(
+ "MessageId",
+ input.as_str(),
+ ));
}
}
-
- Ok( MessageId { message_id: input.into() } )
+ Ok(MessageId {
+ message_id: input.into(),
+ })
}
}
-impl EncodableInHeader for MessageId {
-
+impl EncodableInHeader for MessageId {
fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> {
handle.mark_fws_pos();
- handle.write_char( SoftAsciiChar::from_unchecked('<') )?;
+ handle.write_char(SoftAsciiChar::from_unchecked('<'))?;
match self.message_id {
- SimpleItem::Ascii( ref ascii ) => handle.write_str( ascii )?,
- SimpleItem::Utf8( ref utf8 ) => handle.write_utf8( utf8 )?
+ SimpleItem::Ascii(ref ascii) => handle.write_str(ascii)?,
+ SimpleItem::Utf8(ref utf8) => handle.write_utf8(utf8)?,
}
- handle.write_char( SoftAsciiChar::from_unchecked('>') )?;
+ handle.write_char(SoftAsciiChar::from_unchecked('>'))?;
handle.mark_fws_pos();
- Ok( () )
+ Ok(())
}
fn boxed_clone(&self) -> Box<EncodableInHeader> {
@@ -164,18 +168,17 @@ impl EncodableInHeader for MessageId {
}
#[derive(Debug, Clone)]
-#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
-pub struct MessageIdList( pub Vec1<MessageId> );
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct MessageIdList(pub Vec1<MessageId>);
-deref0!{ +mut MessageIdList => Vec1<MessageId> }
-
-impl EncodableInHeader for MessageIdList {
+deref0! { +mut MessageIdList => Vec1<MessageId> }
+impl EncodableInHeader for MessageIdList {
fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> {
for msg_id in self.iter() {
- msg_id.encode( handle )?;
+ msg_id.encode(handle)?;
}
- Ok( () )
+ Ok(())
}
fn boxed_clone(&self) -> Box<EncodableInHeader> {
@@ -183,19 +186,13 @@ impl EncodableInHeader for MessageIdList {
}
}
-
mod parser_parts {
- use nom::IResult;
use internals::grammar::{is_atext, is_dtext};
use internals::MailType;
+ use nom::IResult;
- pub fn parse_message_id( input: &str) -> IResult<&str, (&str, &str)> {
- do_parse!( input,
- l: id_left >>
- char!( '@' ) >>
- r: id_right >>
- (l, r)
- )
+ pub fn parse_message_id(input: &str) -> IResult<&str, (&str, &str)> {
+ do_parse!(input, l: id_left >> char!('@') >> r: id_right >> (l, r))
}
pub fn id_left(input: &str) -> IResult<&str, &str> {
@@ -203,51 +200,51 @@ mod parser_parts {
}
pub fn id_right(input: &str) -> IResult<&str, &str> {
- alt!(
- input,
- no_fold_literal |
- dot_atom_text
- )
+ alt!(input, no_fold_literal | dot_atom_text)
}
- fn no_fold_literal( input: &str ) -> IResult<&str, &str> {
- recognize!( input,
+ fn no_fold_literal(input: &str) -> IResult<&str, &str> {
+ recognize!(
+ input,
tuple!(
- char!( '[' ),
- take_while!( call!( is_dtext, MailType::Internationalized ) ),
- char!( ']' )
+ char!('['),
+ take_while!(call!(is_dtext, MailType::Internationalized)),
+ char!(']')
)
)
}
fn dot_atom_text(input: &str) -> IResult<&str, &str> {
- recognize!( input, tuple!(
- take_while1!( call!( is_atext, MailType::Internationalized ) ),
- many0!(tuple!(
- char!( '.' ),
- take_while1!( call!( is_atext, MailType::Internationalized ) )
- ))
- ) )
+ recognize!(
+ input,
+ tuple!(
+ take_while1!(call!(is_atext, MailType::Internationalized)),
+ many0!(tuple!(
+ char!('.'),
+ take_while1!(call!(is_atext, MailType::Internationalized))
+ ))
+ )
+ )
}
#[cfg(test)]
mod test {
- use nom;
use super::*;
+ use nom;
#[test]
fn rec_dot_atom_text_no_dot() {
- match dot_atom_text( "abc" ) {
- IResult::Done( "", "abc" ) => {},
- other => panic!("excepted Done(\"\",\"abc\") got {:?}", other )
+ match dot_atom_text("abc") {
+ IResult::Done("", "abc") => {}
+ other => panic!("excepted Done(\"\",\"abc\") got {:?}", other),
}
}
#[test]
fn rec_dot_atom_text_dots() {
- match dot_atom_text( "abc.def.ghi" ) {
- IResult::Done( "", "abc.def.ghi" ) => {},
- other => panic!("excepted Done(\"\",\"abc.def.ghi\") got {:?}", other )
+ match dot_atom_text("abc.def.ghi") {
+ IResult::Done("", "abc.def.ghi") => {}
+ other => panic!("excepted Done(\"\",\"abc.def.ghi\") got {:?}", other),
}
}
@@ -255,35 +252,33 @@ mod parser_parts {
fn rec_dot_atom_text_no_end_dot() {
let test_str = "abc.";
let need_size = test_str.len() + 1;
- match dot_atom_text( test_str ) {
- IResult::Incomplete( nom::Needed::Size( ns ) ) if ns == need_size => {}
- other => panic!("excepted Incomplete(Complete) got {:?}", other )
+ match dot_atom_text(test_str) {
+ IResult::Incomplete(nom::Needed::Size(ns)) if ns == need_size => {}
+ other => panic!("excepted Incomplete(Complete) got {:?}", other),
}
}
#[test]
fn rec_dot_atom_text_no_douple_dot() {
- match dot_atom_text( "abc..de" ) {
- IResult::Done( "..de", "abc" ) => {},
- other => panic!( "excepted Done(\"..de\",\"abc\") got {:?}", other )
+ match dot_atom_text("abc..de") {
+ IResult::Done("..de", "abc") => {}
+ other => panic!("excepted Done(\"..de\",\"abc\") got {:?}", other),
}
}
#[test]
fn rec_dot_atom_text_no_start_dot() {
- match dot_atom_text( ".abc" ) {
- IResult::Error( .. ) => {},
- other => panic!( "expected error got {:?}", other )
+ match dot_atom_text(".abc") {
+ IResult::Error(..) => {}
+ other => panic!("expected error got {:?}", other),
}
}
-
-
#[test]
fn no_empty() {
- match dot_atom_text( "" ) {
- IResult::Incomplete( nom::Needed::Size( 1 ) ) => {},
- other => panic!( "excepted Incomplete(Size(1)) got {:?}", other )
+ match dot_atom_text("") {
+ IResult::Incomplete(nom::Needed::Size(1)) => {}
+ other => panic!("excepted Incomplete(Size(1)) got {:?}", other),
}
}
}
@@ -291,11 +286,11 @@ mod parser_parts {
#[cfg(test)]
mod test {
- use internals::MailType;
- use internals::encoder::EncodingBuffer;
use super::*;
+ use internals::encoder::EncodingBuffer;
+ use internals::MailType;
- ec_test!{ new, {
+ ec_test! { new, {
MessageId::new(
SoftAsciiStr::from_unchecked("just.me"),
SoftAsciiStr::from_unchecked("[127.0.0.1]")
@@ -306,7 +301,7 @@ mod test {
MarkFWS
]}
- ec_test!{ simple, {
+ ec_test! { simple, {
MessageId::try_from( "affen@haus" )?
} => ascii => [
MarkFWS,
@@ -316,7 +311,7 @@ mod test {
MarkFWS
]}
- ec_test!{ utf8, {
+ ec_test! { utf8, {
MessageId::try_from( "↓@↑.utf8")?
} => utf8 => [
MarkFWS,
@@ -328,12 +323,12 @@ mod test {
fn utf8_fails() {
let mut encoder = EncodingBuffer::new(MailType::Ascii);
let mut handle = encoder.writer();
- let mid = MessageId::try_from( "abc@øpunny.code" ).unwrap();
- assert_err!(mid.encode( &mut handle ));
+ let mid = MessageId::try_from("abc@øpunny.code").unwrap();
+ assert_err!(mid.encode(&mut handle));
handle.undo_header();
}
- ec_test!{ multipls, {
+ ec_test! { multipls, {
let fst = MessageId::try_from( "affen@haus" )?;
let snd = MessageId::try_from( "obst@salat" )?;
MessageIdList( vec1! [
@@ -349,5 +344,3 @@ mod test {
MarkFWS,
]}
}
-
-