From 4a267f66b9d38e9954102ebd89046fd16b7880d6 Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Sun, 19 Jul 2020 10:17:53 +0300 Subject: [PATCH] feat: impl std error to error * *BREAKING CHANGES*: refac errors and add main struct with inner enum kind * Add Result type --- Cargo.toml | 2 +- README.md | 6 +++--- src/channel.rs | 27 +++++++++++++-------------- src/commands/mod.rs | 6 ++++-- src/commands/ping.rs | 4 ++-- src/commands/push.rs | 4 ++-- src/commands/query.rs | 12 ++++++------ src/commands/quit.rs | 4 ++-- src/commands/start.rs | 30 +++++++++++++++--------------- src/errors.rs | 27 --------------------------- src/lib.rs | 3 +-- src/result.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 91 insertions(+), 76 deletions(-) delete mode 100644 src/errors.rs create mode 100644 src/result.rs diff --git a/Cargo.toml b/Cargo.toml index c29d8cc..4da3f2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sonic-channel" -version = "0.1.0-rc2" +version = "0.1.0-rc3" authors = ["Dmitriy Pleshevskiy "] description = "Rust client for sonic search backend" categories = ["api-bindings"] diff --git a/README.md b/README.md index 02de6f1..af14eac 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ version = "0.1.0" authors = ["Me "] [dependencies] -sonic-channel = { version = "0.1" } +sonic-channel = { version = "0.1.0-rc3" } ``` @@ -29,7 +29,7 @@ sonic-channel = { version = "0.1" } ```rust use sonic_channel::*; -fn main() -> Result<(), SonicError> { +fn main() -> result::Result<()> { let mut channel = SonicChannel::connect("localhost:1491")?; channel.start(ChannelMode::Search, "SecretPassword")?; @@ -45,7 +45,7 @@ fn main() -> Result<(), SonicError> { ```rust use sonic_channel::*; -fn main() -> Result<(), SonicError> { +fn main() -> result::Result<()> { let mut channel = SonicChannel::connect("localhost:1491")?; channel.start(ChannelMode::Ingest, "SecretPassword")?; diff --git a/src/channel.rs b/src/channel.rs index 8811e93..e9a0534 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -1,5 +1,5 @@ use crate::commands::*; -use crate::errors::SonicError; +use crate::result::*; use std::fmt; use std::io::{BufRead, BufReader, BufWriter, Write}; use std::net::{TcpStream, ToSocketAddrs}; @@ -26,9 +26,8 @@ macro_rules! init_commands { pub fn $fn_name $(<$($lt)+>)? ( &self, $($arg_name: $arg_type),* - ) -> Result< + ) -> crate::result::Result< <$cmd_name as crate::commands::StreamCommand>::Response, - crate::errors::SonicError > { let command = $cmd_name { $($arg_name,)* ..Default::default() }; self.run_command(command) @@ -74,7 +73,7 @@ impl ChannelMode { } impl fmt::Display for ChannelMode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> { write!(f, "{}", self.to_str()) } } @@ -88,8 +87,8 @@ pub struct SonicChannel { } impl SonicChannel { - pub fn connect(addr: A) -> Result { - let stream = TcpStream::connect(addr).map_err(|_| SonicError::ConnectToServer)?; + pub fn connect(addr: A) -> Result { + let stream = TcpStream::connect(addr).map_err(|_| Error::new(ErrorKind::ConnectToServer))?; let channel = SonicChannel { stream, @@ -104,21 +103,21 @@ impl SonicChannel { if message.starts_with("CONNECTED") { Ok(channel) } else { - Err(SonicError::ConnectToServer) + Err(Error::new(ErrorKind::ConnectToServer)) } } - fn write(&self, command: &SC) -> Result<(), SonicError> { + fn write(&self, command: &SC) -> Result<()> { let mut writer = BufWriter::with_capacity(self.max_buffer_size, &self.stream); let message = command.message(); dbg!(&message); writer .write_all(message.as_bytes()) - .map_err(|_| SonicError::WriteToStream)?; + .map_err(|_| Error::new(ErrorKind::WriteToStream))?; Ok(()) } - fn read(&self, max_read_lines: usize) -> Result { + fn read(&self, max_read_lines: usize) -> Result { let mut reader = BufReader::with_capacity(self.max_buffer_size, &self.stream); let mut message = String::new(); @@ -126,23 +125,23 @@ impl SonicChannel { while lines_read < max_read_lines { reader .read_line(&mut message) - .map_err(|_| SonicError::ReadStream)?; + .map_err(|_| Error::new(ErrorKind::ReadStream))?; lines_read += 1; } Ok(message) } - pub fn run_command(&self, command: SC) -> Result { + pub fn run_command(&self, command: SC) -> Result { self.write(&command)?; let message = self.read(SC::READ_LINES_COUNT)?; command.receive(message) } #[cfg(any(feature = "ingest", feature = "search", feature = "control"))] - pub fn start(&mut self, mode: ChannelMode, password: S) -> Result<(), SonicError> { + pub fn start(&mut self, mode: ChannelMode, password: S) -> Result<()> { if self.mode.is_some() { - return Err(SonicError::RunCommand); + return Err(Error::new(ErrorKind::RunCommand)); } let command = StartCommand { diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 275575c..6226a89 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,6 +1,8 @@ mod quit; mod start; + mod ping; + #[cfg(feature = "ingest")] mod push; #[cfg(feature = "search")] @@ -15,7 +17,7 @@ pub use push::PushCommand; #[cfg(feature = "search")] pub use query::QueryCommand; -use crate::errors::SonicError; +use crate::result::Result; pub trait StreamCommand { type Response; @@ -24,5 +26,5 @@ pub trait StreamCommand { fn message(&self) -> String; - fn receive(&self, message: String) -> Result; + fn receive(&self, message: String) -> Result; } diff --git a/src/commands/ping.rs b/src/commands/ping.rs index 365e25a..88ff755 100644 --- a/src/commands/ping.rs +++ b/src/commands/ping.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::errors::SonicError; +use crate::result::*; #[derive(Debug, Default)] pub struct PingCommand; @@ -11,7 +11,7 @@ impl StreamCommand for PingCommand { String::from("PING\r\n") } - fn receive(&self, message: String) -> Result<::Response, SonicError> { + fn receive(&self, message: String) -> Result { dbg!(&message); Ok(message == "PONG\r\n") } diff --git a/src/commands/push.rs b/src/commands/push.rs index 33f1d58..3cad05a 100644 --- a/src/commands/push.rs +++ b/src/commands/push.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::errors::SonicError; +use crate::result::Result; #[derive(Debug, Default)] pub struct PushCommand<'a> { @@ -25,7 +25,7 @@ impl StreamCommand for PushCommand<'_> { message } - fn receive(&self, message: String) -> Result<::Response, SonicError> { + fn receive(&self, message: String) -> Result { dbg!(&message); Ok(message == "OK\r\n") } diff --git a/src/commands/query.rs b/src/commands/query.rs index 47b964a..a99af8a 100644 --- a/src/commands/query.rs +++ b/src/commands/query.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::errors::SonicError; +use crate::result::*; use regex::Regex; const RE_QUERY_RECEIVED_MESSAGE: &str = r"(?x) @@ -36,7 +36,7 @@ impl StreamCommand for QueryCommand<'_> { message } - fn receive(&self, message: String) -> Result { + fn receive(&self, message: String) -> Result { lazy_static! { static ref RE: Regex = Regex::new(RE_QUERY_RECEIVED_MESSAGE).unwrap(); } @@ -44,14 +44,14 @@ impl StreamCommand for QueryCommand<'_> { dbg!(&message); match RE.captures(&message) { - None => Err(SonicError::QueryResponseError( + None => Err(Error::new(ErrorKind::QueryResponseError( "Sonic response are wrong. Please write issue to github.", - )), + ))), Some(caps) => { if &caps["pending_query_id"] != &caps["event_query_id"] { - Err(SonicError::QueryResponseError( + Err(Error::new(ErrorKind::QueryResponseError( "Pending id and event id don't match", - )) + ))) } else if caps["objects"].is_empty() { Ok(vec![]) } else { diff --git a/src/commands/quit.rs b/src/commands/quit.rs index 6bca685..ae8cad4 100644 --- a/src/commands/quit.rs +++ b/src/commands/quit.rs @@ -1,5 +1,5 @@ use super::StreamCommand; -use crate::errors::SonicError; +use crate::result::Result; #[derive(Debug, Default)] pub struct QuitCommand; @@ -11,7 +11,7 @@ impl StreamCommand for QuitCommand { String::from("QUIT\r\n") } - fn receive(&self, message: String) -> Result<::Response, SonicError> { + fn receive(&self, message: String) -> Result { dbg!(&message); Ok(message.starts_with("ENDED ")) } diff --git a/src/commands/start.rs b/src/commands/start.rs index 8bb8de9..f0e8e71 100644 --- a/src/commands/start.rs +++ b/src/commands/start.rs @@ -1,6 +1,6 @@ use super::StreamCommand; use crate::channel::ChannelMode; -use crate::errors::SonicError; +use crate::result::*; use regex::Regex; const RE_START_RECEIVED_MESSAGE: &str = r"(?x) @@ -32,7 +32,7 @@ impl StreamCommand for StartCommand { format!("START {} {}\r\n", self.mode, self.password) } - fn receive(&self, message: String) -> Result { + fn receive(&self, message: String) -> Result { lazy_static! { static ref RE: Regex = Regex::new(RE_START_RECEIVED_MESSAGE).unwrap(); } @@ -40,22 +40,22 @@ impl StreamCommand for StartCommand { dbg!(&message); match RE.captures(&message) { - None => Err(SonicError::SwitchMode), + None => Err(Error::new(ErrorKind::SwitchMode)), Some(caps) => { if self.mode.to_str() != &caps["mode"] { - return Err(SonicError::SwitchMode); + return Err(Error::new(ErrorKind::SwitchMode)); + } else { + let protocol_version: usize = + caps["protocol"].parse().expect("Must be digit by regex"); + let max_buffer_size: usize = + caps["buffer_size"].parse().expect("Must be digit by regex"); + + Ok(StartCommandResponse { + protocol_version, + max_buffer_size, + mode: self.mode, + }) } - - let protocol_version: usize = - caps["protocol"].parse().expect("Must be digit by regex"); - let max_buffer_size: usize = - caps["buffer_size"].parse().expect("Must be digit by regex"); - - Ok(StartCommandResponse { - protocol_version, - max_buffer_size, - mode: self.mode, - }) } } } diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 266d445..0000000 --- a/src/errors.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::fmt; - - -#[derive(Debug)] -pub enum SonicError { - ConnectToServer, - WriteToStream, - ReadStream, - SwitchMode, - RunCommand, - QueryResponseError(&'static str), -} - -impl fmt::Display for SonicError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - let message = match self { - SonicError::ConnectToServer => String::from("Cannot connect to server"), - SonicError::WriteToStream => String::from("Cannot write data to stream"), - SonicError::ReadStream => String::from("Cannot read sonic response from stream"), - SonicError::SwitchMode => String::from("Cannot switch channel mode"), - SonicError::RunCommand => String::from("Cannot run command in current mode"), - SonicError::QueryResponseError(message) => format!("Error in query response: {}", message) - }; - - write!(f, "{}", message) - } -} diff --git a/src/lib.rs b/src/lib.rs index 880327b..e66a917 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,10 @@ mod channel; mod commands; -mod errors; +pub mod result; pub use channel::*; pub use commands::*; -pub use errors::*; #[macro_use] extern crate lazy_static; diff --git a/src/result.rs b/src/result.rs new file mode 100644 index 0000000..5dd2ebc --- /dev/null +++ b/src/result.rs @@ -0,0 +1,42 @@ +use std::error::Error as StdError; +use std::fmt; + +pub type Result = std::result::Result; + +#[derive(Debug)] +pub struct Error { + kind: ErrorKind, +} + +impl StdError for Error {} + +impl Error { + pub fn new(kind: ErrorKind) -> Self { + Error { kind } + } +} + +#[derive(Debug)] +pub enum ErrorKind { + ConnectToServer, + WriteToStream, + ReadStream, + SwitchMode, + RunCommand, + QueryResponseError(&'static str), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> { + match self.kind { + ErrorKind::ConnectToServer => write!(f, "Cannot connect to server"), + ErrorKind::WriteToStream => write!(f, "Cannot write data to stream"), + ErrorKind::ReadStream => write!(f, "Cannot read sonic response from stream"), + ErrorKind::SwitchMode => write!(f, "Cannot switch channel mode"), + ErrorKind::RunCommand => write!(f, "Cannot run command in current mode"), + ErrorKind::QueryResponseError(message) => { + write!(f, "Error in query response: {}", message) + } + } + } +}