diff --git a/irc-proto/src/command.rs b/irc-proto/src/command.rs index f0ec551..0b67cb3 100644 --- a/irc-proto/src/command.rs +++ b/irc-proto/src/command.rs @@ -3,7 +3,9 @@ use std::ascii::AsciiExt; use std::str::FromStr; use error::MessageParseError; -use proto::{ChannelExt, ChannelMode, Mode, Response, UserMode}; +use chan::ChannelExt; +use mode::{ChannelMode, Mode, UserMode}; +use response::Response; /// List of all client commands as defined in [RFC 2812](http://tools.ietf.org/html/rfc2812). This /// also includes commands from the diff --git a/irc-proto/src/error.rs b/irc-proto/src/error.rs new file mode 100644 index 0000000..3d3bd12 --- /dev/null +++ b/irc-proto/src/error.rs @@ -0,0 +1,76 @@ +//! IRC protocol errors using `failure`. + +use std::io::Error as IoError; + +/// A `Result` type for IRC `ProtocolErrors`. +pub type Result = ::std::result::Result; + +/// An IRC protocol error. +#[derive(Debug, Fail)] +pub enum ProtocolError { + /// An internal I/O error. + #[fail(display = "an io error occurred")] + Io(#[cause] IoError), + + /// Error for invalid messages. + #[fail(display = "invalid message: {}", string)] + InvalidMessage { + /// The string that failed to parse. + string: String, + /// The detailed message parsing error. + #[cause] + cause: MessageParseError, + }, +} + +impl From for ProtocolError { + fn from(e: IoError) -> ProtocolError { + ProtocolError::Io(e) + } +} + +/// Errors that occur when parsing messages. +#[derive(Debug, Fail)] +pub enum MessageParseError { + /// The message was empty. + #[fail(display = "empty message")] + EmptyMessage, + + /// The command was invalid (i.e. missing). + #[fail(display = "invalid command")] + InvalidCommand, + + /// The mode string was malformed. + #[fail(display = "invalid mode string: {}", string)] + InvalidModeString { + /// The invalid mode string. + string: String, + /// The detailed mode parsing error. + #[cause] + cause: ModeParseError, + }, + + /// The subcommand used was invalid. + #[fail(display = "invalid {} subcommand: {}", cmd, sub)] + InvalidSubcommand { + /// The command whose invalid subcommand was referenced. + cmd: &'static str, + /// The invalid subcommand. + sub: String, + } +} + +/// Errors that occur while parsing mode strings. +#[derive(Debug, Fail)] +pub enum ModeParseError { + /// Invalid modifier used in a mode string (only + and - are valid). + #[fail(display = "invalid mode modifier: {}", modifier)] + InvalidModeModifier { + /// The invalid mode modifier. + modifier: char, + }, + + /// Missing modifier used in a mode string. + #[fail(display = "missing mode modifier")] + MissingModeModifier, +} diff --git a/irc-proto/src/irc.rs b/irc-proto/src/irc.rs index e10ae27..4a8768f 100644 --- a/irc-proto/src/irc.rs +++ b/irc-proto/src/irc.rs @@ -3,8 +3,8 @@ use bytes::BytesMut; use tokio_io::codec::{Decoder, Encoder}; use error; -use proto::line::LineCodec; -use proto::message::Message; +use line::LineCodec; +use message::Message; /// An IRC codec built around an inner codec. pub struct IrcCodec { @@ -36,7 +36,7 @@ impl IrcCodec { impl Decoder for IrcCodec { type Item = Message; - type Error = error::IrcError; + type Error = error::ProtocolError; fn decode(&mut self, src: &mut BytesMut) -> error::Result> { self.inner.decode(src).and_then(|res| { @@ -47,7 +47,7 @@ impl Decoder for IrcCodec { impl Encoder for IrcCodec { type Item = Message; - type Error = error::IrcError; + type Error = error::ProtocolError; fn encode(&mut self, msg: Message, dst: &mut BytesMut) -> error::Result<()> { diff --git a/irc-proto/src/lib.rs b/irc-proto/src/lib.rs index f0fb2ae..0de1bc2 100644 --- a/irc-proto/src/lib.rs +++ b/irc-proto/src/lib.rs @@ -11,6 +11,7 @@ extern crate tokio_io; pub mod caps; pub mod chan; pub mod command; +pub mod error; pub mod irc; pub mod line; pub mod message; diff --git a/irc-proto/src/line.rs b/irc-proto/src/line.rs index 2e1ade2..1b84a10 100644 --- a/irc-proto/src/line.rs +++ b/irc-proto/src/line.rs @@ -28,7 +28,7 @@ impl LineCodec { impl Decoder for LineCodec { type Item = String; - type Error = error::IrcError; + type Error = error::ProtocolError; fn decode(&mut self, src: &mut BytesMut) -> error::Result> { if let Some(n) = src.as_ref().iter().position(|b| *b == b'\n') { @@ -53,7 +53,7 @@ impl Decoder for LineCodec { impl Encoder for LineCodec { type Item = String; - type Error = error::IrcError; + type Error = error::ProtocolError; fn encode(&mut self, msg: String, dst: &mut BytesMut) -> error::Result<()> { // Encode the message using the codec's encoding. diff --git a/irc-proto/src/message.rs b/irc-proto/src/message.rs index 9d9d62b..d1470c8 100644 --- a/irc-proto/src/message.rs +++ b/irc-proto/src/message.rs @@ -4,8 +4,9 @@ use std::fmt::{Display, Formatter, Result as FmtResult}; use std::str::FromStr; use error; -use error::{IrcError, MessageParseError}; -use proto::{Command, ChannelExt}; +use error::{ProtocolError, MessageParseError}; +use chan::ChannelExt; +use command::Command; /// A data structure representing an IRC message according to the protocol specification. It /// consists of a collection of IRCv3 tags, a prefix (describing the source of the message), and @@ -170,11 +171,11 @@ impl From for Message { } impl FromStr for Message { - type Err = IrcError; + type Err = ProtocolError; fn from_str(s: &str) -> Result { if s.is_empty() { - return Err(IrcError::InvalidMessage { + return Err(ProtocolError::InvalidMessage { string: s.to_owned(), cause: MessageParseError::EmptyMessage, }) @@ -232,7 +233,7 @@ impl FromStr for Message { cmd } // If there's no arguments but the "command" starts with colon, it's not a command. - None if state.starts_with(':') => return Err(IrcError::InvalidMessage { + None if state.starts_with(':') => return Err(ProtocolError::InvalidMessage { string: s.to_owned(), cause: MessageParseError::InvalidCommand, }), @@ -247,7 +248,7 @@ impl FromStr for Message { let args: Vec<_> = state.splitn(14, ' ').filter(|s| !s.is_empty()).collect(); Message::with_tags(tags, prefix, command, args, suffix).map_err(|e| { - IrcError::InvalidMessage { + ProtocolError::InvalidMessage { string: s.to_owned(), cause: e, } diff --git a/irc-proto/src/mode.rs b/irc-proto/src/mode.rs index 806104f..dff3f5b 100644 --- a/irc-proto/src/mode.rs +++ b/irc-proto/src/mode.rs @@ -4,7 +4,7 @@ use std::fmt; use error::MessageParseError; use error::MessageParseError::InvalidModeString; use error::ModeParseError::*; -use proto::Command; +use command::Command; /// A marker trait for different kinds of Modes. pub trait ModeType: fmt::Display + fmt::Debug + Clone + PartialEq {