feat: impl std error to error
* *BREAKING CHANGES*: refac errors and add main struct with inner enum kind * Add Result type
This commit is contained in:
parent
dcfe82f6e7
commit
4a267f66b9
12 changed files with 91 additions and 76 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "sonic-channel"
|
||||
version = "0.1.0-rc2"
|
||||
version = "0.1.0-rc3"
|
||||
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
|
||||
description = "Rust client for sonic search backend"
|
||||
categories = ["api-bindings"]
|
||||
|
|
|
@ -18,7 +18,7 @@ version = "0.1.0"
|
|||
authors = ["Me <user@rust-lang.org>"]
|
||||
|
||||
[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")?;
|
||||
|
|
|
@ -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<A: ToSocketAddrs>(addr: A) -> Result<Self, SonicError> {
|
||||
let stream = TcpStream::connect(addr).map_err(|_| SonicError::ConnectToServer)?;
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<Self> {
|
||||
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<SC: StreamCommand>(&self, command: &SC) -> Result<(), SonicError> {
|
||||
fn write<SC: StreamCommand>(&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<String, SonicError> {
|
||||
fn read(&self, max_read_lines: usize) -> Result<String> {
|
||||
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<SC: StreamCommand>(&self, command: SC) -> Result<SC::Response, SonicError> {
|
||||
pub fn run_command<SC: StreamCommand>(&self, command: SC) -> Result<SC::Response> {
|
||||
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<S: ToString>(&mut self, mode: ChannelMode, password: S) -> Result<(), SonicError> {
|
||||
pub fn start<S: ToString>(&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 {
|
||||
|
|
|
@ -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<Self::Response, SonicError>;
|
||||
fn receive(&self, message: String) -> Result<Self::Response>;
|
||||
}
|
||||
|
|
|
@ -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<<Self as StreamCommand>::Response, SonicError> {
|
||||
fn receive(&self, message: String) -> Result<Self::Response> {
|
||||
dbg!(&message);
|
||||
Ok(message == "PONG\r\n")
|
||||
}
|
||||
|
|
|
@ -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<<Self as StreamCommand>::Response, SonicError> {
|
||||
fn receive(&self, message: String) -> Result<Self::Response> {
|
||||
dbg!(&message);
|
||||
Ok(message == "OK\r\n")
|
||||
}
|
||||
|
|
|
@ -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<Self::Response, SonicError> {
|
||||
fn receive(&self, message: String) -> Result<Self::Response> {
|
||||
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 {
|
||||
|
|
|
@ -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<<Self as StreamCommand>::Response, SonicError> {
|
||||
fn receive(&self, message: String) -> Result<Self::Response> {
|
||||
dbg!(&message);
|
||||
Ok(message.starts_with("ENDED "))
|
||||
}
|
||||
|
|
|
@ -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<Self::Response, SonicError> {
|
||||
fn receive(&self, message: String) -> Result<Self::Response> {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(RE_START_RECEIVED_MESSAGE).unwrap();
|
||||
}
|
||||
|
@ -40,12 +40,11 @@ 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 =
|
||||
|
@ -60,3 +59,4 @@ impl StreamCommand for StartCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
42
src/result.rs
Normal file
42
src/result.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue