Skip to content

Commit 7c939c4

Browse files
committed
Implement typed arrays
1 parent 74526bf commit 7c939c4

File tree

3 files changed

+96
-10
lines changed

3 files changed

+96
-10
lines changed

src/actions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
//! use skytable::{actions::Actions, Connection};
3434
//! let mut con = Connection::new("127.0.0.1", 2003).unwrap();
3535
//! con.set("x", "100").unwrap();
36-
//! assert_eq!(con.get("x").unwrap(), Vec::from("100"));
36+
//! assert_eq!(con.get("x").unwrap(), "100");
3737
//!
3838
//! ```
3939

src/deserializer.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ pub enum Element {
7575
FlatArray(Vec<Vec<u8>>),
7676
/// A response code
7777
RespCode(RespCode),
78+
/// An array of unicode strings
79+
StrArray(Vec<String>),
80+
/// An array of binary strings
81+
BinArray(Vec<Vec<u8>>),
7882
}
7983

8084
#[derive(Debug, PartialEq)]
@@ -325,14 +329,30 @@ impl<'a> Parser<'a> {
325329
fn parse_next_element(&mut self) -> ParseResult<Element> {
326330
if let Some(tsymbol) = self.buffer.get(self.cursor) {
327331
// so we have a tsymbol; nice, let's match it
328-
// but advance the cursor before doing that
332+
// but advance the cursor before doing that (skip)
329333
self.incr_cursor();
330334
let ret = match *tsymbol {
331335
b'?' => Element::Binstr(self.parse_next_binstr()?),
332336
b'+' => Element::Str(self.parse_next_string()?),
333337
b':' => Element::UnsignedInt(self.parse_next_u64()?),
334338
b'&' => Element::Array(self.parse_next_array()?),
335339
b'!' => Element::RespCode(self.parse_next_respcode()?),
340+
b'@' => {
341+
// hmmm, a typed array; let's check the tsymbol
342+
if let Some(array_type) = self.buffer.get(self.cursor) {
343+
// got tsymbol, let's skip it
344+
self.incr_cursor();
345+
match array_type {
346+
b'+' => Element::StrArray(self.parse_next_typed_array_str()?),
347+
b'?' => Element::BinArray(self.parse_next_typed_array_bin()?),
348+
_ => return Err(ParseError::UnknownDatatype),
349+
}
350+
} else {
351+
// if we couldn't fetch a tsymbol, there wasn't enough
352+
// data left
353+
return Err(ParseError::NotEnough);
354+
}
355+
}
336356
b'_' => Element::FlatArray(self.parse_next_flat_array()?),
337357
_ => return Err(ParseError::UnknownDatatype),
338358
};
@@ -342,6 +362,37 @@ impl<'a> Parser<'a> {
342362
Err(ParseError::NotEnough)
343363
}
344364
}
365+
/// The cursor should have passed the `@+` chars
366+
fn parse_next_typed_array_str(&mut self) -> ParseResult<Vec<String>> {
367+
let (start, stop) = self.read_line();
368+
if let Some(our_size_chunk) = self.buffer.get(start..stop) {
369+
// so we have a size chunk; let's get the size
370+
let array_size = Self::parse_into_usize(our_size_chunk)?;
371+
let mut array = Vec::with_capacity(array_size);
372+
for _ in 0..array_size {
373+
// no tsymbol, just elements and their sizes
374+
array.push(self.parse_next_string()?);
375+
}
376+
Ok(array)
377+
} else {
378+
Err(ParseError::NotEnough)
379+
}
380+
}
381+
/// The cursor should have passed the `@?` chars
382+
fn parse_next_typed_array_bin(&mut self) -> ParseResult<Vec<Vec<u8>>> {
383+
let (start, stop) = self.read_line();
384+
if let Some(our_size_chunk) = self.buffer.get(start..stop) {
385+
// got size chunk, let's get the size
386+
let array_size = Self::parse_into_usize(our_size_chunk)?;
387+
let mut array = Vec::with_capacity(array_size);
388+
for _ in 0..array_size {
389+
array.push(self.parse_next_binstr()?);
390+
}
391+
Ok(array)
392+
} else {
393+
Err(ParseError::NotEnough)
394+
}
395+
}
345396
/// The cursor should have passed the tsymbol
346397
fn parse_next_flat_array(&mut self) -> ParseResult<Vec<Vec<u8>>> {
347398
let (start, stop) = self.read_line();
@@ -427,3 +478,33 @@ impl<'a> Parser<'a> {
427478
}
428479
}
429480
}
481+
482+
#[test]
483+
fn test_typed_str_array() {
484+
let typed_array_packet = "*1\n@+3\n3\nthe\n3\ncat\n6\nmeowed\n".as_bytes();
485+
let (parsed, forward) = Parser::new(typed_array_packet).parse().unwrap();
486+
assert_eq!(forward, typed_array_packet.len());
487+
assert_eq!(
488+
parsed,
489+
RawResponse::SimpleQuery(Element::StrArray(vec![
490+
"the".to_owned(),
491+
"cat".to_owned(),
492+
"meowed".to_owned()
493+
]))
494+
);
495+
}
496+
497+
#[test]
498+
fn test_typed_bin_array() {
499+
let typed_array_packet = "*1\n@?3\n3\nthe\n3\ncat\n6\nmeowed\n".as_bytes();
500+
let (parsed, forward) = Parser::new(typed_array_packet).parse().unwrap();
501+
assert_eq!(forward, typed_array_packet.len());
502+
assert_eq!(
503+
parsed,
504+
RawResponse::SimpleQuery(Element::BinArray(vec![
505+
Vec::from("the"),
506+
Vec::from("cat"),
507+
Vec::from("meowed")
508+
]))
509+
);
510+
}

src/lib.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
//! let mut con = Connection::new("127.0.0.1", 2003)?;
5858
//! let query = Query::from("heya");
5959
//! let res = con.run_simple_query(&query)?;
60-
//! assert_eq!(res, Response::Item(Element::String(Vec::from("HEY"))));
60+
//! assert_eq!(res, Response::Item(Element::Binstr(Vec::from("HEY"))));
6161
//! Ok(())
6262
//! }
6363
//! ```
@@ -154,6 +154,7 @@ cfg_sync!(
154154
///
155155
/// ## Example (sync)
156156
/// ```no_run
157+
/// use skytable::ConnectionBuilder;
157158
/// let con =
158159
/// ConnectionBuilder::new()
159160
/// .set_host("127.0.0.1")
@@ -163,13 +164,17 @@ cfg_sync!(
163164
/// ```
164165
///
165166
/// ## Example (async)
166-
/// ```no_run
167-
/// let con =
168-
/// ConnectionBuilder::new()
169-
/// .set_host("127.0.0.1")
170-
/// .set_port(2003)
171-
/// .get_async_connection()
172-
/// .unwrap();
167+
/// ```no_test
168+
/// use skytable::ConnectionBuilder;
169+
/// async fn main() {
170+
/// let con =
171+
/// ConnectionBuilder::new()
172+
/// .set_host("127.0.0.1")
173+
/// .set_port(2003)
174+
/// .get_async_connection()
175+
/// .await
176+
/// .unwrap();
177+
/// }
173178
/// ```
174179
pub struct ConnectionBuilder<'a> {
175180
port: Option<u16>,

0 commit comments

Comments
 (0)