From aaf2147117da119fba87986e10ea012d9fe6c74c Mon Sep 17 00:00:00 2001 From: Artemciy Date: Fri, 27 Feb 2015 18:18:15 +0300 Subject: [PATCH] Rust upgrade. --- src/client/connecter.rs | 6 ++-- src/client/mod.rs | 65 ++++++++++++++++++++------------------- src/client/server_info.rs | 12 +++----- src/client/stream.rs | 18 +++++------ src/command.rs | 11 ++++--- src/common.rs | 2 +- src/error.rs | 30 ++++++++++-------- src/extension.rs | 38 ++++++++++++----------- src/lib.rs | 8 ++--- src/mailer/address.rs | 10 +++--- src/mailer/header.rs | 20 ++++++------ src/mailer/mod.rs | 12 ++++---- src/response.rs | 34 ++++++++++---------- src/tools.rs | 6 ++-- src/transaction.rs | 10 +++--- 15 files changed, 145 insertions(+), 137 deletions(-) diff --git a/src/client/connecter.rs b/src/client/connecter.rs index 4525dac..d18be6d 100644 --- a/src/client/connecter.rs +++ b/src/client/connecter.rs @@ -11,9 +11,9 @@ //! TODO -use std::io::IoResult; -use std::io::net::ip::SocketAddr; -use std::io::net::tcp::TcpStream; +use std::old_io::IoResult; +use std::old_io::net::ip::SocketAddr; +use std::old_io::net::tcp::TcpStream; /// A trait for the concept of opening a stream connected to a IP socket address. pub trait Connecter { diff --git a/src/client/mod.rs b/src/client/mod.rs index 42bbbcd..ec9a90d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -9,10 +9,11 @@ //! SMTP client +use std::ascii::AsciiExt; use std::string::String; use std::error::FromError; -use std::io::net::tcp::TcpStream; -use std::io::net::ip::{SocketAddr, ToSocketAddr}; +use std::old_io::net::tcp::TcpStream; +use std::old_io::net::ip::{SocketAddr, ToSocketAddr}; use uuid::Uuid; @@ -33,18 +34,18 @@ pub mod connecter; pub mod stream; /// Represents the configuration of a client -#[deriving(Clone)] +#[derive(Clone,Debug)] pub struct Configuration { /// Maximum connection reuse /// /// Zero means no limitation - pub connection_reuse_count_limit: uint, + pub connection_reuse_count_limit: usize, /// Enable connection reuse pub enable_connection_reuse: bool, /// Maximum recipients - pub destination_recipient_limit: uint, + pub destination_recipient_limit: usize, /// Maximum line length - pub line_length_limit: uint, + pub line_length_limit: usize, /// Name sent during HELO or EHLO pub hello_name: String, } @@ -64,7 +65,7 @@ pub struct Client { /// Panic state panic: bool, /// Connection reuse counter - connection_reuse_count: uint, + connection_reuse_count: usize, /// Current message id current_message: Option, /// Configuration of the client @@ -72,16 +73,16 @@ pub struct Client { } macro_rules! try_smtp ( - ($err: expr $client: ident) => ({ + ($err: expr, $client: ident) => ({ match $err { Ok(val) => val, - Err(err) => close_and_return_err!(err $client), + Err(err) => close_and_return_err!(err, $client), } }) ); macro_rules! close_and_return_err ( - ($err: expr $client: ident) => ({ + ($err: expr, $client: ident) => ({ if !$client.panic { $client.panic = true; $client.close(); @@ -94,7 +95,7 @@ macro_rules! check_command_sequence ( ($command: ident $client: ident) => ({ if !$client.state.is_allowed(&$command) { close_and_return_err!( - Response{code: 503, message: Some("Bad sequence of commands".to_string())} $client + Response{code: 503, message: Some("Bad sequence of commands".to_string())}, $client ); } }) @@ -141,7 +142,7 @@ impl Client { } /// Set the maximum number of emails sent using one connection - pub fn set_connection_reuse_count_limit(&mut self, count: uint) { + pub fn set_connection_reuse_count_limit(&mut self, count: usize) { self.configuration.connection_reuse_count_limit = count } @@ -189,16 +190,16 @@ impl Client { if let Err(error) = self.ehlo() { match error.kind { ErrorKind::PermanentError(Response{code: 550, message: _}) => { - try_smtp!(self.helo() self); + try_smtp!(self.helo(), self); }, _ => { - try_smtp!(Err(error) self) + try_smtp!(Err(error), self) }, }; } // Print server information - debug!("server {}", self.server_info.as_ref().unwrap()); + //debug!("server {}", self.server_info.as_ref().unwrap()); } self.current_message = Some(Uuid::new_v4()); @@ -210,17 +211,17 @@ impl Client { let message = email.message(); // Mail - try_smtp!(self.mail(from_address.as_slice()) self); + try_smtp!(self.mail(from_address.as_slice()), self); // Recipient // TODO Return rejected addresses // TODO Limit the number of recipients for to_address in to_addresses.iter() { - try_smtp!(self.rcpt(to_address.as_slice()) self); + try_smtp!(self.rcpt(to_address.as_slice()), self); } // Data - try_smtp!(self.data() self); + try_smtp!(self.data(), self); // Message content self.message(message.as_slice()) @@ -234,15 +235,15 @@ impl Client { // Connect should not be called when the client is already connected if self.stream.is_some() { - close_and_return_err!("The connection is already established" self); + close_and_return_err!("The connection is already established", self); } // Try to connect self.stream = Some(try!(Connecter::connect(self.server_addr))); // Log the connection - info!("connection established to {}", - self.stream.as_mut().unwrap().peer_name().unwrap()); + //info!("connection established to {}", + // self.stream.as_mut().unwrap().peer_name().unwrap()); let result = try!(self.stream.as_mut().unwrap().get_reply()); @@ -255,7 +256,7 @@ impl Client { fn command(&mut self, command: Command) -> SmtpResult { // for now we do not support SMTPUTF8 if !command.is_ascii() { - close_and_return_err!("Non-ASCII string" self); + close_and_return_err!("Non-ASCII string", self); } self.send_server(command, None) @@ -279,7 +280,7 @@ impl Client { message, MESSAGE_ENDING ), None => self.stream.as_mut().unwrap().send_and_get_response( - command.to_string().as_slice(), CRLF + format! ("{}", command) .as_slice(), CRLF ), }); @@ -334,7 +335,7 @@ impl Client { None => close_and_return_err!(Response{ code: 503, message: Some("Bad sequence of commands".to_string()), - } self), + }, self), }; // Checks message encoding according to the server's capability @@ -350,7 +351,7 @@ impl Client { if result.is_ok() { // Log the mail command - info!("{}: from=<{}>", self.current_message.as_ref().unwrap(), from_address); + //info!("{}: from=<{}>", self.current_message.as_ref().unwrap(), from_address); } result @@ -364,7 +365,7 @@ impl Client { if result.is_ok() { // Log the rcpt command - info!("{}: to=<{}>", self.current_message.as_ref().unwrap(), to_address); + //info!("{}: to=<{}>", self.current_message.as_ref().unwrap(), to_address); } result @@ -383,13 +384,13 @@ impl Client { None => close_and_return_err!(Response{ code: 503, message: Some("Bad sequence of commands".to_string()), - } self) + }, self) }; // Check message encoding if !server_info.supports_feature(Extension::EightBitMime).is_some() { - if !message_content.is_ascii() { - close_and_return_err!("Server does not accepts UTF-8 strings" self); + if !message_content.as_bytes().is_ascii() { + close_and_return_err!("Server does not accepts UTF-8 strings", self); } } @@ -399,7 +400,7 @@ impl Client { close_and_return_err!(Response{ code: 552, message: Some("Message exceeds fixed maximum message size".to_string()), - } self); + }, self); } } @@ -409,8 +410,8 @@ impl Client { // Increment the connection reuse counter self.connection_reuse_count = self.connection_reuse_count + 1; // Log the message - info!("{}: conn_use={}, size={}, status=sent ({})", self.current_message.as_ref().unwrap(), - self.connection_reuse_count, message_content.len(), result.as_ref().ok().unwrap()); + //info!("{}: conn_use={}, size={}, status=sent ({})", self.current_message.as_ref().unwrap(), + // self.connection_reuse_count, message_content.len(), result.as_ref().ok().unwrap()); } self.current_message = None; diff --git a/src/client/server_info.rs b/src/client/server_info.rs index 5090146..1e9f577 100644 --- a/src/client/server_info.rs +++ b/src/client/server_info.rs @@ -10,12 +10,12 @@ //! Information about a server use std::fmt; -use std::fmt::{Show, Formatter}; +use std::fmt::{Display, Formatter}; use extension::Extension; /// Contains information about an SMTP server -#[deriving(Clone)] +#[derive(Clone,Debug)] pub struct ServerInfo { /// Server name /// @@ -28,16 +28,14 @@ pub struct ServerInfo { pub esmtp_features: Option>, } -impl Show for ServerInfo { +impl Display for ServerInfo { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.write( - format!("{} with {}", + write!(f, "{} with {}", self.name, match self.esmtp_features { - Some(ref features) => features.to_string(), + Some(ref features) => format! ("{:?}", features), None => "no supported features".to_string(), } - ).as_bytes() ) } } diff --git a/src/client/stream.rs b/src/client/stream.rs index 472c15a..47d910d 100644 --- a/src/client/stream.rs +++ b/src/client/stream.rs @@ -9,17 +9,17 @@ //! TODO -use std::io::net::tcp::TcpStream; -use std::io::IoResult; +use std::old_io::net::tcp::TcpStream; +use std::old_io::IoResult; use std::str::from_utf8; use std::vec::Vec; use std::error::FromError; use error::SmtpResult; use response::Response; -use tools::{escape_crlf, escape_dot}; +use tools::{escape_dot}; -static BUFFER_SIZE: uint = 1024; +static BUFFER_SIZE: usize = 1024; /// TODO pub trait ClientStream { @@ -36,7 +36,7 @@ impl ClientStream for TcpStream { fn send_and_get_response(&mut self, string: &str, end: &str) -> SmtpResult { try!(self.write_str(format!("{}{}", escape_dot(string), end).as_slice())); - debug!("Wrote: {}", escape_crlf(escape_dot(string).as_slice())); + //debug!("Wrote: {}", escape_crlf(escape_dot(string).as_slice())); self.get_reply() } @@ -54,7 +54,7 @@ impl ClientStream for TcpStream { Ok(bytes_read) => { more = bytes_read == BUFFER_SIZE; if bytes_read > 0 { - from_utf8(buf.slice_to(bytes_read)).unwrap() + from_utf8(&buf[..bytes_read]).unwrap() } else { "" } @@ -64,7 +64,7 @@ impl ClientStream for TcpStream { }; result.push_str(response); } - debug!("Read: {}", escape_crlf(result.as_slice())); + //debug!("Read: {}", escape_crlf(result.as_slice())); return Ok(result); } @@ -73,8 +73,8 @@ impl ClientStream for TcpStream { let response = try!(self.read_into_string()); match response.as_slice().parse::() { - Some(response) => Ok(response), - None => Err(FromError::from_error("Could not parse response")) + Ok(response) => Ok(response), + Err(_) => Err(FromError::from_error("Could not parse response")) } } } diff --git a/src/command.rs b/src/command.rs index 8c9892f..226fd2c 100644 --- a/src/command.rs +++ b/src/command.rs @@ -11,8 +11,9 @@ #![unstable] +use std::ascii::AsciiExt; use std::error::FromError; -use std::fmt::{Show, Formatter, Result}; +use std::fmt::{Display, Formatter, Result}; use response::Response; use error::SmtpResult; @@ -22,7 +23,7 @@ use common::SP; /// /// We do not implement the following SMTP commands, as they were deprecated in RFC 5321 /// and must not be used by clients: `SEND`, `SOML`, `SAML`, `TURN`. -#[deriving(PartialEq,Eq,Clone)] +#[derive(PartialEq,Eq,Clone,Debug)] pub enum Command { /// A fake command to represent the connection step Connect, @@ -54,9 +55,9 @@ pub enum Command { Quit, } -impl Show for Command { +impl Display for Command { fn fmt(&self, f: &mut Formatter) -> Result { - f.write( match *self { + write! (f, "{}", match *self { Command::Connect => "CONNECT".to_string(), Command::StartTls => "STARTTLS".to_string(), Command::ExtendedHello(ref my_hostname) => format!("EHLO {}", my_hostname), @@ -76,7 +77,7 @@ impl Show for Command { Command::Help(Some(ref argument)) => format!("HELP {}", argument), Command::Noop => "NOOP".to_string(), Command::Quit => "QUIT".to_string(), - }.as_bytes()) + }) } } diff --git a/src/common.rs b/src/common.rs index 46980da..1ca1c28 100644 --- a/src/common.rs +++ b/src/common.rs @@ -11,7 +11,7 @@ #![unstable] -use std::io::net::ip::Port; +use std::old_io::net::ip::Port; /// Default smtp port pub static SMTP_PORT: Port = 25; diff --git a/src/error.rs b/src/error.rs index 291afa4..1d3c4e4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,14 +12,16 @@ #![unstable] use std::error::Error; -use std::io::IoError; +use std::old_io::IoError; use std::error::FromError; +use std::fmt::{Display, Formatter}; +use std::fmt::Error as FmtError; use response::Response; use self::ErrorKind::{TransientError, PermanentError, UnknownError, InternalIoError}; /// An enum of all error kinds. -#[deriving(PartialEq, Eq, Clone, Show)] +#[derive(PartialEq, Eq, Clone, Debug)] pub enum ErrorKind { /// Transient error /// @@ -36,7 +38,7 @@ pub enum ErrorKind { } /// smtp error type -#[deriving(PartialEq, Eq, Clone, Show)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct SmtpError { /// Error kind pub kind: ErrorKind, @@ -71,7 +73,7 @@ impl FromError for SmtpError { let kind = match response.code/100 { 4 => TransientError(response), 5 => PermanentError(response), - _ => UnknownError(response.to_string()), + _ => UnknownError(format! ("{:?}", response)), }; let desc = match kind { TransientError(_) => "a permanent error occured during the SMTP transaction", @@ -97,6 +99,17 @@ impl FromError<&'static str> for SmtpError { } } +impl Display for SmtpError { + fn fmt (&self, fmt: &mut Formatter) -> Result<(), FmtError> { + match self.kind { + TransientError(ref response) => write! (fmt, "{:?}", response), + PermanentError(ref response) => write! (fmt, "{:?}", response), + UnknownError(ref string) => write! (fmt, "{}", string), + InternalIoError(ref err) => write! (fmt, "{:?}", err.detail), + } + } +} + impl Error for SmtpError { fn description(&self) -> &str { match self.kind { @@ -105,15 +118,6 @@ impl Error for SmtpError { } } - fn detail(&self) -> Option { - match self.kind { - TransientError(ref response) => Some(response.to_string()), - PermanentError(ref response) => Some(response.to_string()), - UnknownError(ref string) => Some(string.to_string()), - InternalIoError(ref err) => err.detail.clone(), - } - } - fn cause(&self) -> Option<&Error> { match self.kind { InternalIoError(ref err) => Some(&*err as &Error), diff --git a/src/extension.rs b/src/extension.rs index 20add9e..5bccbc6 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -12,14 +12,15 @@ #![unstable] use std::str::FromStr; -use std::fmt::{Show, Formatter, Result}; +use std::fmt::{Display, Formatter, Result}; +use std::result::Result as RResult; use common::CRLF; use response::Response; use self::Extension::{EightBitMime, SmtpUtfEight, StartTls, Size}; /// Supported ESMTP keywords -#[deriving(PartialEq,Eq,Copy,Clone)] +#[derive(PartialEq,Eq,Copy,Clone,Debug)] pub enum Extension { /// 8BITMIME keyword /// @@ -36,38 +37,39 @@ pub enum Extension { /// SIZE keyword /// /// RFC 1427 : https://tools.ietf.org/html/rfc1427 - Size(uint), + Size(usize), } -impl Show for Extension { +impl Display for Extension { fn fmt(&self, f: &mut Formatter) -> Result { - f.write( + write! (f, "{}", match self { &EightBitMime => "8BITMIME".to_string(), &SmtpUtfEight => "SMTPUTF8".to_string(), &StartTls => "STARTTLS".to_string(), &Size(ref size) => format!("SIZE={}", size) - }.as_bytes() + } ) } } impl FromStr for Extension { // TODO: check RFC - fn from_str(s: &str) -> Option { + type Err = &'static str; + fn from_str(s: &str) -> RResult { let splitted : Vec<&str> = s.splitn(1, ' ').collect(); match splitted.len() { 1 => match splitted[0] { - "8BITMIME" => Some(EightBitMime), - "SMTPUTF8" => Some(SmtpUtfEight), - "STARTTLS" => Some(StartTls), - _ => None, + "8BITMIME" => Ok(EightBitMime), + "SMTPUTF8" => Ok(SmtpUtfEight), + "STARTTLS" => Ok(StartTls), + _ => Err("Unknown extension"), }, - 2 => match (splitted[0], splitted[1].parse::()) { - ("SIZE", Some(size)) => Some(Size(size)), - _ => None, + 2 => match (splitted[0], splitted[1].parse::()) { + ("SIZE", Ok(size)) => Ok(Size(size)), + _ => Err("Can't parse size"), }, - _ => None, + _ => Err("Empty extension?"), } } } @@ -87,9 +89,9 @@ impl Extension { /// Parses supported ESMTP features pub fn parse_esmtp_response(message: &str) -> Option> { let mut esmtp_features = Vec::new(); - for line in message.split_str(CRLF) { - if let Some(Response{code: 250, message}) = line.parse::() { - if let Some(keyword) = message.unwrap().as_slice().parse::() { + for line in message.split(CRLF) { + if let Ok(Response{code: 250, message}) = line.parse::() { + if let Ok(keyword) = message.unwrap().as_slice().parse::() { esmtp_features.push(keyword); }; } diff --git a/src/lib.rs b/src/lib.rs index 8eff186..751b564 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,12 +127,12 @@ #![crate_type = "lib"] #![doc(html_root_url = "http://amousset.github.io/rust-smtp/smtp/")] -#![experimental] -#![feature(phase, macro_rules, default_type_params)] -#![deny(missing_docs, warnings)] +#![deny(missing_docs)] -#![feature(phase)] #[phase(plugin, link)] extern crate log; +#![feature(plugin,core,old_io,io)] +#![plugin(log)] +extern crate log; extern crate time; extern crate uuid; diff --git a/src/mailer/address.rs b/src/mailer/address.rs index 6b104d9..ce18e5c 100644 --- a/src/mailer/address.rs +++ b/src/mailer/address.rs @@ -9,7 +9,7 @@ //! Simple SMTP "address" (very incomplete) -use std::fmt::{Show, Formatter, Result}; +use std::fmt::{Display, Formatter, Result}; use common::SP; @@ -39,7 +39,7 @@ impl<'a> ToAddress for (&'a str, &'a str) { } /// Contains an address with an optionnal alias -#[deriving(PartialEq,Eq,Clone)] +#[derive(PartialEq,Eq,Clone,Debug)] pub struct Address { /// The address address: String, @@ -47,12 +47,12 @@ pub struct Address { alias: Option, } -impl Show for Address { +impl Display for Address { fn fmt(&self, f: &mut Formatter) -> Result { - f.write(match self.alias { + write! (f, "{}", match self.alias { Some(ref alias_string) => format!("{}{}<{}>", alias_string, SP, self.address.as_slice()), None => self.address.clone(), - }.as_bytes()) + }) } } diff --git a/src/mailer/header.rs b/src/mailer/header.rs index 9a66cc2..9097a92 100644 --- a/src/mailer/header.rs +++ b/src/mailer/header.rs @@ -11,7 +11,7 @@ use time::Tm; -use std::fmt::{Show, Formatter, Result}; +use std::fmt::{Display, Formatter, Result}; use common::{SP, COLON}; use mailer::address::Address; @@ -36,7 +36,7 @@ impl<'a> ToHeader for (&'a str, &'a str) { } /// Contains a header -#[deriving(PartialEq,Eq,Clone)] +#[derive(PartialEq,Eq,Clone,Debug)] pub enum Header { /// `To` To(Address), @@ -62,9 +62,9 @@ pub enum Header { Other(String, String), } -impl Show for Header { +impl Display for Header { fn fmt(&self, f: &mut Formatter) -> Result { - f.write(format!("{}{}{}{}", + write! (f, "{}{}{}{}", match *self { Header::To(_) => "To", Header::From(_) => "From", @@ -80,18 +80,18 @@ impl Show for Header { }, COLON, SP, match *self { - Header::To(ref address) => address.to_string(), - Header::From(ref address) => address.to_string(), - Header::Cc(ref address) => address.to_string(), - Header::ReplyTo(ref address) => address.to_string(), - Header::Sender(ref address) => address.to_string(), + Header::To(ref address) => format! ("{}", address), + Header::From(ref address) => format! ("{}", address), + Header::Cc(ref address) => format! ("{}", address), + Header::ReplyTo(ref address) => format! ("{}", address), + Header::Sender(ref address) => format! ("{}", address), Header::Date(ref date) => Tm::rfc822(date).to_string(), Header::Subject(ref subject) => subject.clone(), Header::MimeVersion => "1.0".to_string(), Header::ContentType(ref string) => string.clone(), Header::MessageId(ref string) => string.clone(), Header::Other(_, ref value) => value.clone(), - }).as_bytes()) + }) } } diff --git a/src/mailer/mod.rs b/src/mailer/mod.rs index 5da2e14..ef571e5 100644 --- a/src/mailer/mod.rs +++ b/src/mailer/mod.rs @@ -9,7 +9,7 @@ //! Simple email (very incomplete) -use std::fmt::{Show, Formatter, Result}; +use std::fmt::{Display, Formatter, Result}; use time::{now, Tm}; @@ -22,7 +22,7 @@ pub mod header; pub mod address; /// Simple email representation -#[deriving(PartialEq,Eq,Clone)] +#[derive(PartialEq,Eq,Clone,Debug)] pub struct Email { /// Array of headers headers: Vec
, @@ -34,14 +34,14 @@ pub struct Email { from: Option, } -impl Show for Email { +impl Display for Email { fn fmt(&self, f: &mut Formatter) -> Result { let mut formatted_headers = String::new(); for header in self.headers.iter() { - formatted_headers.push_str(header.to_string().as_slice()); + formatted_headers.push_str(format! ("{}", header) .as_slice()); formatted_headers.push_str(CRLF); } - f.write(format!("{}{}{}", formatted_headers, CRLF, self.body).as_bytes()) + write! (f, "{}{}{}", formatted_headers, CRLF, self.body) } } @@ -147,7 +147,7 @@ impl SendableEmail for Email { } fn message(&self) -> String { - self.to_string() + format! ("{}", self) } /// Adds a `Message-ID` header diff --git a/src/response.rs b/src/response.rs index 323af1c..0849560 100644 --- a/src/response.rs +++ b/src/response.rs @@ -12,14 +12,15 @@ #![unstable] use std::str::FromStr; -use std::fmt::{Show, Formatter, Result}; +use std::fmt::{Display, Formatter, Result}; +use std::result::Result as RResult; use tools::remove_trailing_crlf; /// Contains an SMTP reply, with separed code and message /// /// The text message is optional, only the code is mandatory -#[deriving(PartialEq,Eq,Clone)] +#[derive(PartialEq,Eq,Clone,Debug)] pub struct Response { /// Server response code pub code: u16, @@ -27,43 +28,44 @@ pub struct Response { pub message: Option } -impl Show for Response { +impl Display for Response { fn fmt(&self, f: &mut Formatter) -> Result { - f.write( + write! (f, "{}", match self.clone().message { Some(message) => format!("{} {}", self.code, message), None => format!("{}", self.code), - }.as_bytes() + } ) } } impl FromStr for Response { - fn from_str(s: &str) -> Option { + type Err = &'static str; + fn from_str(s: &str) -> RResult { // If the string is too short to be a response code if s.len() < 3 { - None + Err("len < 3") // If we have only a code, with or without a trailing space - } else if s.len() == 3 || (s.len() == 4 && s.slice(3,4) == " ") { - match s.slice_to(3).parse::() { - Some(code) => Some(Response{ + } else if s.len() == 3 || (s.len() == 4 && &s[3..4] == " ") { + match s[..3].parse::() { + Ok(code) => Ok(Response{ code: code, message: None }), - None => None, + Err(_) => Err("Can't parse the code"), } // If we have a code and a message } else { match ( - s.slice_to(3).parse::(), - vec![" ", "-"].contains(&s.slice(3,4)), - (remove_trailing_crlf(s.slice_from(4))) + s[..3].parse::(), + vec![" ", "-"].contains(&&s[3..4]), + (remove_trailing_crlf(&s[4..])) ) { - (Some(code), true, message) => Some(Response{ + (Ok(code), true, message) => Ok(Response{ code: code, message: Some(message.to_string()) }), - _ => None, + _ => Err("Error parsing a code with a message"), } } } diff --git a/src/tools.rs b/src/tools.rs index c171a6e..9d1118d 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -17,9 +17,9 @@ use common::{CR, LF, CRLF}; #[inline] pub fn remove_trailing_crlf(string: &str) -> &str { if string.ends_with(CRLF) { - string.slice_to(string.len() - 2) + &string[.. string.len() - 2] } else if string.ends_with(CR) { - string.slice_to(string.len() - 1) + &string[.. string.len() - 1] } else { string } @@ -28,7 +28,7 @@ pub fn remove_trailing_crlf(string: &str) -> &str { /// Returns the first word of a string, or the string if it contains no space #[inline] pub fn get_first_word(string: &str) -> &str { - string.split_str(CRLF).next().unwrap().splitn(1, ' ').next().unwrap() + string.split(CRLF).next().unwrap().splitn(1, ' ').next().unwrap() } /// Returns the string replacing all the CRLF with "\" diff --git a/src/transaction.rs b/src/transaction.rs index dcd9b04..7d7f89e 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -12,13 +12,13 @@ #![unstable] use std::fmt; -use std::fmt::{Show, Formatter}; +use std::fmt::{Display, Formatter}; use command::Command; use self::TransactionState::{Unconnected, Connected, HelloSent, MailSent, RecipientSent, DataSent}; /// Contains the state of the current transaction -#[deriving(PartialEq,Eq,Copy)] +#[derive(PartialEq,Eq,Copy,Debug)] pub enum TransactionState { /// No connection was established Unconnected, @@ -34,9 +34,9 @@ pub enum TransactionState { DataSent, } -impl Show for TransactionState { +impl Display for TransactionState { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.write( + write! (f, "{}", match *self { Unconnected => "Unconnected", Connected => "Connected", @@ -44,7 +44,7 @@ impl Show for TransactionState { MailSent => "MailSent", RecipientSent => "RecipientSent", DataSent => "DataSent", - }.as_bytes() + } ) } }