Skip to content

Commit

Permalink
resp: Enhance multi-row decode support
Browse files Browse the repository at this point in the history
  • Loading branch information
ohsayan committed Jun 26, 2024
1 parent b3926c0 commit ccaa450
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ version = "0.8.8"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# internal deps
sky-derive = "0.2.2"
sky-derive = "0.2.3"
# external deps
tokio = { version = "1.38.0", features = ["full"] }
native-tls = "0.2.12"
Expand Down
21 changes: 21 additions & 0 deletions examples/multi_row.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use skytable::{query, response::Rows, Config, Query, Response};

#[derive(Query, Response)]
pub struct User {
username: String,
password: String,
followers: u64,
email: Option<String>,
}

fn main() {
let mut db = Config::new_default("user", "password").connect().unwrap();
let users: Rows<User> = db
.query_parse(&query!(
"select all username, password, followers, email from myspace.mymodel limit ?",
1000u64
))
.unwrap();
// assume the first row has username set to 'sayan'
assert_eq!(users[0].username, "sayan");
}
66 changes: 65 additions & 1 deletion src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
//! ```
//!
use crate::error::{ClientResult, Error, ParseError};
use {
crate::error::{ClientResult, Error, ParseError},
std::ops::Deref,
};

/// The value directly returned by the server without any additional type parsing and/or casting
#[derive(Debug, PartialEq, Clone)]
Expand Down Expand Up @@ -92,6 +95,13 @@ pub struct Row {
values: Vec<Value>,
}

impl Deref for Row {
type Target = [Value];
fn deref(&self) -> &Self::Target {
&self.values
}
}

impl Row {
pub(crate) fn new(values: Vec<Value>) -> Self {
Self { values }
Expand Down Expand Up @@ -267,6 +277,15 @@ macro_rules! from_response_row {
Ok(($($elem::from_value(values.next().unwrap())?),*,))
}
}
impl<$($elem: FromValue),*> FromRow for ($($elem),*,) {
fn from_row(row: Row) -> ClientResult<Self> {
if row.values().len() != $size {
return Err(Error::ParseError(ParseError::TypeMismatch));
}
let mut values = row.into_values().into_iter();
Ok(($($elem::from_value(values.next().unwrap())?),*,))
}
}
)*
}
}
Expand Down Expand Up @@ -323,3 +342,48 @@ impl FromResponse for Vec<Row> {
}
}
}

/// Trait for parsing a row into a custom type
pub trait FromRow: Sized {
/// Parse a row into a custom type
fn from_row(row: Row) -> ClientResult<Self>;
}

impl FromRow for Row {
fn from_row(row: Row) -> ClientResult<Self> {
Ok(row)
}
}

#[derive(Debug, PartialEq)]
/// A collection of rows
pub struct Rows<T: FromRow = Row>(Vec<T>);

impl<T: FromRow> Rows<T> {
/// Consume the [`Rows`] object and get all the rows as a vector
pub fn into_rows(self) -> Vec<T> {
self.0
}
}

impl<T: FromRow> FromResponse for Rows<T> {
fn from_response(resp: Response) -> ClientResult<Self> {
match resp {
Response::Rows(rows) => {
let mut ret = vec![];
for row in rows {
ret.push(T::from_row(row)?);
}
Ok(Self(ret))
}
_ => Err(Error::ParseError(ParseError::ResponseMismatch)),
}
}
}

impl<T: FromRow> Deref for Rows<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.0
}
}

0 comments on commit ccaa450

Please sign in to comment.