Skip to content

Commit f7623e9

Browse files
committed
Simplify error handling
1 parent d82e2fb commit f7623e9

File tree

6 files changed

+84
-95
lines changed

6 files changed

+84
-95
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ fn main() -> std::io::Result<()> {
4343
Now let's run a `Query`! Change the previous code block to:
4444

4545
```rust
46-
use skytable::{Connection, Query, Response, Element};
47-
fn main() -> std::io::Result<()> {
46+
use skytable::{error, Connection, Query, Element};
47+
fn main() -> Result<(), error::Error> {
4848
let mut con = Connection::new("127.0.0.1", 2003)?;
4949
let query = Query::from("heya");
5050
let res = con.run_simple_query(&query)?;
51-
assert_eq!(res, Response::Item(Element::String("HEY!".to_owned())));
51+
assert_eq!(res, Element::String("HEY!".to_owned()));
5252
Ok(())
5353
}
5454
```

src/actions.rs

Lines changed: 35 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
//!
3838
//! ```
3939
40+
use crate::error::{Error, SkyhashError};
4041
use crate::types::Array;
4142
use crate::types::FlatElement;
4243
use crate::types::SnapshotResult;
@@ -47,54 +48,34 @@ use crate::IntoSkyhashAction;
4748
use crate::IntoSkyhashBytes;
4849
use crate::Query;
4950
use crate::RespCode;
50-
use crate::Response;
51+
use crate::SkyResult;
5152

5253
cfg_async!(
5354
use core::{future::Future, pin::Pin};
5455
);
55-
use std::io::ErrorKind;
5656

5757
/// The error string returned when the snapshot engine is busy
5858
pub const ERR_SNAPSHOT_BUSY: &str = "err-snapshot-busy";
5959
/// The error string returned when periodic snapshots are busy
6060
pub const ERR_SNAPSHOT_DISABLED: &str = "err-snapshot-disabled";
6161

62-
/// Errors while running actions
63-
#[derive(Debug)]
64-
#[non_exhaustive]
65-
pub enum ActionError {
66-
/// The server sent data but we failed to parse it
67-
ParseError,
68-
/// The server sent an unexpected data type for this action
69-
UnexpectedDataType,
70-
/// The server sent an unknown data type that we cannot parse
71-
UnknownDataType,
72-
/// The server sent an invalid response
73-
InvalidResponse,
74-
/// An I/O error occurred while running this action
75-
IoError(ErrorKind),
76-
/// The server returned a response code **other than the one that should have been returned
77-
/// for this action** (if any)
78-
Code(RespCode),
79-
}
80-
8162
cfg_async!(
8263
/// A special result that is returned when running actions (async)
8364
pub type AsyncResult<'s, T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 's>>;
8465
#[doc(hidden)]
8566
pub trait AsyncSocket: Send + Sync {
86-
fn run(&mut self, q: Query) -> AsyncResult<std::io::Result<Response>>;
67+
fn run(&mut self, q: Query) -> AsyncResult<SkyResult>;
8768
}
8869
impl<T> AsyncActions for T where T: AsyncSocket {}
8970
);
9071

9172
/// A special result that is returned when running actions
92-
pub type ActionResult<T> = Result<T, ActionError>;
73+
pub type ActionResult<T> = Result<T, Error>;
9374

9475
cfg_sync!(
9576
#[doc(hidden)]
9677
pub trait SyncSocket {
97-
fn run(&mut self, q: Query) -> std::io::Result<Response>;
78+
fn run(&mut self, q: Query) -> SkyResult;
9879
}
9980
impl<T> Actions for T where T: SyncSocket {}
10081
);
@@ -103,12 +84,8 @@ macro_rules! gen_match {
10384
($ret:expr, $($($mtch:pat)+ $(if $exp:expr)*, $expect:expr),*) => {
10485
match $ret {
10586
$($(Ok($mtch))|* $(if $exp:expr)* => Ok($expect),)*
106-
Ok(Response::InvalidResponse) => Err(ActionError::InvalidResponse),
107-
Ok(Response::ParseError) => Err(ActionError::ParseError),
108-
Ok(Response::UnsupportedDataType) => Err(ActionError::UnknownDataType),
109-
Ok(Response::Item(Element::RespCode(code))) => Err(ActionError::Code(code)),
110-
Ok(Response::Item(_)) => Err(ActionError::UnexpectedDataType),
111-
Err(e) => Err(ActionError::IoError(e.kind())),
87+
Ok(_) => Err(SkyhashError::UnexpectedDataType.into()),
88+
Err(e) => Err(e),
11289
}
11390
};
11491
}
@@ -155,52 +132,52 @@ implement_actions!(
155132
/// Get the number of keys present in the database
156133
fn dbsize() -> usize {
157134
{ Query::from("dbsize") }
158-
Response::Item(Element::UnsignedInt(int)) => int as usize
135+
Element::UnsignedInt(int) => int as usize
159136
}
160137
/// Deletes a single or a number of keys
161138
///
162139
/// This will return the number of keys that were deleted
163140
fn del(key: impl IntoSkyhashAction + 's) -> usize {
164141
{ Query::from("del").arg(key) }
165-
Response::Item(Element::UnsignedInt(int)) => int as usize
142+
Element::UnsignedInt(int) => int as usize
166143
}
167144
/// Checks if a key (or keys) exist(s)
168145
///
169146
/// This will return the number of keys that do exist
170147
fn exists(key: impl IntoSkyhashAction + 's) -> usize {
171148
{ Query::from("exists").arg(key) }
172-
Response::Item(Element::UnsignedInt(int)) => int as usize
149+
Element::UnsignedInt(int) => int as usize
173150
}
174151
/// Removes all the keys present in the database
175152
fn flushdb() -> () {
176153
{ Query::from("flushdb") }
177-
Response::Item(Element::RespCode(RespCode::Okay)) => {}
154+
Element::RespCode(RespCode::Okay) => {}
178155
}
179156
/// Get the value of a key
180157
fn get(key: impl IntoSkyhashBytes + 's) -> String {
181158
{ Query::from("get").arg(key)}
182-
Response::Item(Element::Str(st)) => st
159+
Element::String(st) => st
183160
}
184161
/// Get the length of a key
185162
fn keylen(key: impl IntoSkyhashBytes + 's) -> usize {
186163
{ Query::from("keylen").arg(key)}
187-
Response::Item(Element::UnsignedInt(int)) => int as usize
164+
Element::UnsignedInt(int) => int as usize
188165
}
189166
/// Returns a vector of keys
190167
///
191168
/// Do note that the order might be completely meaningless
192169
fn lskeys(count: usize) -> Vec<FlatElement> {
193170
{ Query::from("lskeys").arg(count)}
194-
Response::Item(Element::Array(Array::Flat(arr))) => arr
171+
Element::Array(Array::Flat(arr)) => arr
195172
}
196173
/// Get multiple keys
197174
///
198175
/// This returns a vector of [`Element`]s which either contain the values
199176
/// as strings or contains `Not Found (Code: 1)` response codes
200177
fn mget(keys: impl IntoSkyhashAction+ 's) -> Array {
201178
{ Query::from("mget").arg(keys)}
202-
Response::Item(Element::Array(Array::Bin(brr))) => Array::Bin(brr),
203-
Response::Item(Element::Array(Array::Str(srr))) => Array::Str(srr)
179+
Element::Array(Array::Bin(brr)) => Array::Bin(brr),
180+
Element::Array(Array::Str(srr)) => Array::Str(srr)
204181
}
205182
/// Creates a snapshot
206183
///
@@ -209,15 +186,16 @@ implement_actions!(
209186
/// which is normal behavior and _not an inherent error_
210187
fn mksnap() -> SnapshotResult {
211188
{ Query::from("mksnap")}
212-
Response::Item(Element::RespCode(RespCode::Okay)) => SnapshotResult::Okay,
213-
Response::Item(Element::RespCode(RespCode::ErrorString(er))) => {
189+
Element::RespCode(RespCode::Okay) => SnapshotResult::Okay,
190+
Element::RespCode(RespCode::ErrorString(er)) => {
214191
match er.as_str() {
215192
ERR_SNAPSHOT_BUSY => SnapshotResult::Busy,
216193
ERR_SNAPSHOT_DISABLED => SnapshotResult::Disabled,
217-
_ => return Err(ActionError::InvalidResponse)
194+
_ => return Err(SkyhashError::InvalidResponse.into())
218195
}
219196
}
220197
}
198+
221199
/// Sets the value of multiple keys and values and returns the number of keys that were set
222200
///
223201
/// ## Panics
@@ -231,7 +209,7 @@ implement_actions!(
231209
assert!(keys.incr_len_by() == values.incr_len_by(), "The number of keys and values for mset must be equal");
232210
Query::from("mset")._push_alt_iter(keys, values)
233211
}
234-
Response::Item(Element::UnsignedInt(int)) => int as usize
212+
Element::UnsignedInt(int) => int as usize
235213
}
236214
/// Updates the value of multiple keys and values and returns the number of keys that were updated
237215
///
@@ -246,34 +224,34 @@ implement_actions!(
246224
assert!(keys.incr_len_by() == values.incr_len_by(), "The number of keys and values for mupdate must be equal");
247225
Query::from("mset")._push_alt_iter(keys, values)
248226
}
249-
Response::Item(Element::UnsignedInt(int)) => int as usize
227+
Element::UnsignedInt(int) => int as usize
250228
}
251229
/// Consumes a key if it exists
252230
///
253231
/// This should return either the corresponding values of the provided keys or `Not Found`
254232
/// error codes
255233
fn pop(keys: impl IntoSkyhashBytes + 's) -> Str {
256234
{ Query::from("POP").arg(keys) }
257-
Response::Item(Element::Str(st)) => Str::Unicode(st),
258-
Response::Item(Element::Binstr(bstr)) => Str::Binary(bstr)
235+
Element::String(st) => Str::Unicode(st),
236+
Element::Binstr(bstr) => Str::Binary(bstr)
259237
}
260238
/// Consumes the provided keys if they exist
261239
fn mpop(keys: impl IntoSkyhashAction + 's) -> Array {
262240
{ Query::from("mpop").arg(keys)}
263-
Response::Item(Element::Array(Array::Bin(brr))) => Array::Bin(brr),
264-
Response::Item(Element::Array(Array::Str(srr))) => Array::Str(srr)
241+
Element::Array(Array::Bin(brr)) => Array::Bin(brr),
242+
Element::Array(Array::Str(srr)) => Array::Str(srr)
265243
}
266244
/// Deletes all the provided keys if they exist or doesn't do anything at all. This method
267245
/// will return true if all the provided keys were deleted, else it will return false
268246
fn sdel(keys: impl IntoSkyhashAction + 's) -> bool {
269247
{ Query::from("sdel").arg(keys) }
270-
Response::Item(Element::RespCode(RespCode::Okay)) => true,
271-
Response::Item(Element::RespCode(RespCode::NotFound)) => false
248+
Element::RespCode(RespCode::Okay) => true,
249+
Element::RespCode(RespCode::NotFound) => false
272250
}
273251
/// Set the value of a key
274252
fn set(key: impl IntoSkyhashBytes + 's, value: impl IntoSkyhashBytes + 's) -> () {
275253
{ Query::from("set").arg(key).arg(value) }
276-
Response::Item(Element::RespCode(RespCode::Okay)) => {}
254+
Element::RespCode(RespCode::Okay) => {}
277255
}
278256
/// Sets the value of all the provided keys or does nothing. This method will return true if all the keys
279257
/// were set or will return false if none were set
@@ -292,8 +270,8 @@ implement_actions!(
292270
);
293271
Query::from("sset")._push_alt_iter(keys, values)
294272
}
295-
Response::Item(Element::RespCode(RespCode::Okay)) => true,
296-
Response::Item(Element::RespCode(RespCode::OverwriteError)) => false
273+
Element::RespCode(RespCode::Okay) => true,
274+
Element::RespCode(RespCode::OverwriteError) => false
297275
}
298276
/// Updates the value of all the provided keys or does nothing. This method will return true if all the keys
299277
/// were updated or will return false if none were updated
@@ -312,13 +290,13 @@ implement_actions!(
312290
);
313291
Query::from("supdate")._push_alt_iter(keys, values)
314292
}
315-
Response::Item(Element::RespCode(RespCode::Okay)) => true,
316-
Response::Item(Element::RespCode(RespCode::NotFound)) => false
293+
Element::RespCode(RespCode::Okay) => true,
294+
Element::RespCode(RespCode::NotFound) => false
317295
}
318296
/// Update the value of a key
319297
fn update(key: impl IntoSkyhashBytes + 's, value: impl IntoSkyhashBytes + 's) -> () {
320298
{ Query::from("update").arg(key).arg(value) }
321-
Response::Item(Element::RespCode(RespCode::Okay)) => {}
299+
Element::RespCode(RespCode::Okay) => {}
322300
}
323301
/// Updates or sets all the provided keys and returns the number of keys that were set
324302
///
@@ -336,6 +314,6 @@ implement_actions!(
336314
);
337315
Query::from("uset")._push_alt_iter(keys, values)
338316
}
339-
Response::Item(Element::UnsignedInt(int)) => int as usize
317+
Element::UnsignedInt(int) => int as usize
340318
}
341319
);

src/aio.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
//!
2626
2727
use crate::deserializer::{ParseError, Parser, RawResponse};
28+
use crate::error::SkyhashError;
2829
use crate::IoResult;
29-
use crate::{Query, Response};
30+
use crate::Query;
31+
use crate::SkyResult;
3032
use bytes::{Buf, BytesMut};
31-
use std::io::{Error, ErrorKind};
33+
use std::io::{Error as IoError, ErrorKind};
3234
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufWriter};
3335
use tokio::net::TcpStream;
3436

@@ -40,24 +42,24 @@ macro_rules! impl_async_methods {
4042
impl $ty {
4143
/// This function will write a [`Query`] to the stream and read the response from the
4244
/// server. It will then determine if the returned response is complete or incomplete
43-
/// or invalid and return an appropriate variant of [`Response`] wrapped in [`IoResult`]
45+
/// or invalid and return an appropriate variant of [`Error`](crate::error::Error) wrapped in [`IoResult`]
4446
/// for any I/O errors that may occur
4547
///
4648
/// ## Panics
4749
/// This method will panic if the [`Query`] supplied is empty (i.e has no arguments)
48-
pub async fn run_simple_query(&mut self, query: &Query) -> IoResult<Response> {
50+
pub async fn run_simple_query(&mut self, query: &Query) -> SkyResult {
4951
assert!(query.len() != 0, "A `Query` cannot be of zero length!");
5052
query.write_query_to(&mut self.stream).await?;
5153
self.stream.flush().await?;
5254
loop {
5355
if 0usize == self.stream.read_buf(&mut self.buffer).await? {
54-
return Err(Error::from(ErrorKind::ConnectionReset));
56+
return Err(IoError::from(ErrorKind::ConnectionReset).into());
5557
}
5658
match self.try_response() {
5759
Ok((query, forward_by)) => {
5860
self.buffer.advance(forward_by);
5961
match query {
60-
RawResponse::SimpleQuery(s) => return Ok(Response::Item(s)),
62+
RawResponse::SimpleQuery(s) => return Ok(s),
6163
RawResponse::PipelinedQuery(_) => {
6264
unimplemented!("Pipelined queries aren't implemented yet")
6365
}
@@ -67,14 +69,16 @@ macro_rules! impl_async_methods {
6769
ParseError::NotEnough => (),
6870
ParseError::BadPacket | ParseError::UnexpectedByte => {
6971
self.buffer.clear();
70-
return Ok(Response::InvalidResponse);
72+
return Err(SkyhashError::InvalidResponse.into());
73+
}
74+
ParseError::DataTypeError => {
75+
return Err(SkyhashError::ParseError.into())
7176
}
72-
ParseError::DataTypeError => return Ok(Response::ParseError),
7377
ParseError::Empty => {
74-
return Err(Error::from(ErrorKind::ConnectionReset))
78+
return Err(IoError::from(ErrorKind::ConnectionReset).into())
7579
}
7680
ParseError::UnknownDatatype => {
77-
return Ok(Response::UnsupportedDataType)
81+
return Err(SkyhashError::UnknownDataType.into())
7882
}
7983
},
8084
}
@@ -90,7 +94,7 @@ macro_rules! impl_async_methods {
9094
}
9195
}
9296
impl crate::actions::AsyncSocket for $ty {
93-
fn run(&mut self, q: Query) -> crate::actions::AsyncResult<std::io::Result<Response>> {
97+
fn run(&mut self, q: Query) -> crate::actions::AsyncResult<SkyResult> {
9498
Box::pin(async move { self.run_simple_query(&q).await })
9599
}
96100
}

src/deserializer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ pub(super) struct Parser<'a> {
6565
///
6666
/// This enum represents the data types supported by the Skyhash Protocol
6767
pub enum Element {
68-
/// Arrays can be nested! Their `<tsymbol>` is `&`
68+
/// Array types
6969
Array(Array),
7070
/// An unicode string value; `<tsymbol>` is `+`
71-
Str(String),
71+
String(String),
7272
/// A binary string (`?`)
7373
Binstr(Vec<u8>),
7474
/// An unsigned integer value; `<tsymbol>` is `:`
@@ -369,7 +369,7 @@ impl<'a> Parser<'a> {
369369
self.incr_cursor();
370370
let ret = match *tsymbol {
371371
b'?' => Element::Binstr(self.parse_next_binstr()?),
372-
b'+' => Element::Str(self.parse_next_string()?),
372+
b'+' => Element::String(self.parse_next_string()?),
373373
b':' => Element::UnsignedInt(self.parse_next_u64()?),
374374
b'&' => Element::Array(Array::Recursive(self.parse_next_array()?)),
375375
b'!' => Element::RespCode(self.parse_next_respcode()?),

0 commit comments

Comments
 (0)