Skip to content

Commit

Permalink
removed some memory allocations when parsing data
Browse files Browse the repository at this point in the history
  • Loading branch information
krojew committed Feb 26, 2021
1 parent d2ed3f6 commit ae5bf3b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 66 deletions.
69 changes: 33 additions & 36 deletions src/frame/frame_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ impl FromCursor for CDRSError {
let additional_info = AdditionalErrorInfo::from_cursor_with_code(&mut cursor, error_code)?;

Ok(CDRSError {
error_code: error_code,
message: message,
additional_info: additional_info,
error_code,
message,
additional_info,
})
}
}
Expand Down Expand Up @@ -164,9 +164,9 @@ impl FromCursor for UnavailableError {
let alive = CInt::from_cursor(&mut cursor)?;

Ok(UnavailableError {
cl: cl,
required: required,
alive: alive,
cl,
required,
alive,
})
}
}
Expand All @@ -192,10 +192,10 @@ impl FromCursor for WriteTimeoutError {
let write_type = WriteType::from_cursor(&mut cursor)?;

Ok(WriteTimeoutError {
cl: cl,
received: received,
blockfor: blockfor,
write_type: write_type,
cl,
received,
blockfor,
write_type,
})
}
}
Expand Down Expand Up @@ -224,13 +224,13 @@ impl FromCursor for ReadTimeoutError {
let cl = Consistency::from_cursor(&mut cursor)?;
let received = CInt::from_cursor(&mut cursor)?;
let blockfor = CInt::from_cursor(&mut cursor)?;
let data_present = try_from_bytes(cursor_next_value(&mut cursor, 1)?.as_slice())? as u8;
let data_present = try_from_bytes(cursor_fill_value(&mut cursor, &mut [0])?)? as u8;

Ok(ReadTimeoutError {
cl: cl,
received: received,
blockfor: blockfor,
data_present: data_present,
cl,
received,
blockfor,
data_present,
})
}
}
Expand All @@ -250,7 +250,7 @@ pub struct ReadFailureError {
}

impl ReadFailureError {
/// Shows if replica has resonded to a query.
/// Shows if replica has responded to a query.
pub fn replica_has_responded(&self) -> bool {
self.data_present != 0
}
Expand All @@ -262,14 +262,14 @@ impl FromCursor for ReadFailureError {
let received = CInt::from_cursor(&mut cursor)?;
let blockfor = CInt::from_cursor(&mut cursor)?;
let num_failures = CInt::from_cursor(&mut cursor)?;
let data_present = try_from_bytes(cursor_next_value(&mut cursor, 1)?.as_slice())? as u8;
let data_present = try_from_bytes(cursor_fill_value(&mut cursor, &mut [0])?)? as u8;

Ok(ReadFailureError {
cl: cl,
received: received,
blockfor: blockfor,
num_failures: num_failures,
data_present: data_present,
cl,
received,
blockfor,
num_failures,
data_present,
})
}
}
Expand All @@ -292,9 +292,9 @@ impl FromCursor for FunctionFailureError {
let arg_types = CStringList::from_cursor(&mut cursor)?;

Ok(FunctionFailureError {
keyspace: keyspace,
function: function,
arg_types: arg_types,
keyspace,
function,
arg_types,
})
}
}
Expand Down Expand Up @@ -324,11 +324,11 @@ impl FromCursor for WriteFailureError {
let write_type = WriteType::from_cursor(&mut cursor)?;

Ok(WriteFailureError {
cl: cl,
received: received,
blockfor: blockfor,
num_failures: num_failures,
write_type: write_type,
cl,
received,
blockfor,
num_failures,
write_type,
})
}
}
Expand All @@ -347,7 +347,7 @@ pub enum WriteType {
UnloggedBatch,
/// The write was a counter write (batched or not)
Counter,
/// The failure occured during the write to the batch log when a (logged) batch
/// The failure occurred during the write to the batch log when a (logged) batch
/// write was requested.
BatchLog,
}
Expand Down Expand Up @@ -381,10 +381,7 @@ impl FromCursor for AlreadyExistsError {
let ks = CString::from_cursor(&mut cursor)?;
let table = CString::from_cursor(&mut cursor)?;

Ok(AlreadyExistsError {
ks: ks,
table: table,
})
Ok(AlreadyExistsError { ks, table })
}
}

Expand All @@ -402,6 +399,6 @@ impl FromCursor for UnpreparedError {
fn from_cursor(mut cursor: &mut io::Cursor<&[u8]>) -> error::Result<UnpreparedError> {
let id = CBytesShort::from_cursor(&mut cursor)?;

Ok(UnpreparedError { id: id })
Ok(UnpreparedError { id })
}
}
15 changes: 7 additions & 8 deletions src/frame/frame_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ impl FromBytes for ResultKind {

impl FromCursor for ResultKind {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<ResultKind> {
cursor_next_value(&mut cursor, INT_LEN as u64)
.and_then(|bytes| ResultKind::from_bytes(bytes.as_slice()))
cursor_fill_value(&mut cursor, &mut [0; INT_LEN]).and_then(ResultKind::from_bytes)
}
}

Expand Down Expand Up @@ -458,8 +457,8 @@ impl FromBytes for ColType {

impl FromCursor for ColType {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<ColType> {
cursor_next_value(&mut cursor, SHORT_LEN as u64)
.and_then(|bytes| ColType::from_bytes(bytes.as_slice()))
cursor_fill_value(&mut cursor, &mut [0; SHORT_LEN])
.and_then(ColType::from_bytes)
.map_err(Into::into)
}
}
Expand Down Expand Up @@ -537,7 +536,7 @@ impl FromCursor for CUdt {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<CUdt> {
let ks = CString::from_cursor(&mut cursor)?;
let udt_name = CString::from_cursor(&mut cursor)?;
let n = try_from_bytes(cursor_next_value(&mut cursor, SHORT_LEN as u64)?.as_slice())?;
let n = try_from_bytes(cursor_fill_value(&mut cursor, &mut [0; SHORT_LEN])?)?;
let mut descriptions = Vec::with_capacity(n as usize);
for _ in 0..n {
let name = CString::from_cursor(&mut cursor)?;
Expand All @@ -563,7 +562,7 @@ pub struct CTuple {

impl FromCursor for CTuple {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<CTuple> {
let n = try_from_bytes(cursor_next_value(&mut cursor, SHORT_LEN as u64)?.as_slice())?;
let n = try_from_bytes(cursor_fill_value(&mut cursor, &mut [0; SHORT_LEN])?)?;
let mut types = Vec::with_capacity(n as usize);
for _ in 0..n {
let col_type = ColTypeOption::from_cursor(&mut cursor)?;
Expand Down Expand Up @@ -623,9 +622,9 @@ impl FromCursor for PreparedMetadata {
};
let pk_index_results: Vec<Option<i16>> = (0..pk_count)
.map(|_| {
cursor_next_value(&mut cursor, SHORT_LEN as u64)
cursor_fill_value(&mut cursor, &mut [0; SHORT_LEN])
.ok()
.and_then(|b| try_i16_from_bytes(b.as_slice()).ok())
.and_then(|b| try_i16_from_bytes(b).ok())
})
.collect();

Expand Down
7 changes: 3 additions & 4 deletions src/frame/frame_supported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::io::Cursor;

use crate::error;
use crate::frame::FromCursor;
use crate::types::{cursor_next_value, try_from_bytes, CString, CStringList, SHORT_LEN};
use crate::types::{cursor_fill_value, try_from_bytes, CString, CStringList, SHORT_LEN};

#[derive(Debug)]
pub struct BodyResSupported {
Expand All @@ -12,16 +12,15 @@ pub struct BodyResSupported {

impl FromCursor for BodyResSupported {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<BodyResSupported> {
let l =
try_from_bytes(cursor_next_value(&mut cursor, SHORT_LEN as u64)?.as_slice())? as usize;
let l = try_from_bytes(cursor_fill_value(&mut cursor, &mut [0; SHORT_LEN])?)? as usize;
let mut data: HashMap<String, Vec<String>> = HashMap::with_capacity(l);
for _ in 0..l {
let name = CString::from_cursor(&mut cursor)?.into_plain();
let val = CStringList::from_cursor(&mut cursor)?.into_plain();
data.insert(name, val);
}

Ok(BodyResSupported { data: data })
Ok(BodyResSupported { data })
}
}

Expand Down
51 changes: 33 additions & 18 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub fn try_to_n_bytes(int: u64, n: usize) -> io::Result<Vec<u8>> {
///
/// # Panics
///
/// It panics if given unisigned integer could not be converted in an array of n bytes
/// It panics if given unsigned integer could not be converted in an array of n bytes
pub fn to_n_bytes(int: u64, n: usize) -> Vec<u8> {
try_to_n_bytes(int, n).unwrap()
}
Expand Down Expand Up @@ -163,7 +163,7 @@ pub fn try_from_bytes(bytes: &[u8]) -> Result<u64, io::Error> {
c.read_uint::<BigEndian>(l)
}

/// Tryies to decode bytes array into `u16`.
/// Tries to decode bytes array into `u16`.
pub fn try_u16_from_bytes(bytes: &[u8]) -> Result<u16, io::Error> {
let mut c = Cursor::new(bytes);
c.read_u16::<BigEndian>()
Expand Down Expand Up @@ -249,7 +249,7 @@ pub fn to_short(int: i16) -> Vec<u8> {
bytes
}

/// Convers integer into Cassandra's [int]
/// Converts integer into Cassandra's [int]
///
/// # Panics
///
Expand All @@ -262,7 +262,7 @@ pub fn to_int(int: i32) -> Vec<u8> {
bytes
}

/// Convers integer into Cassandra's [int]
/// Converts integer into Cassandra's [int]
///
/// # Panics
///
Expand Down Expand Up @@ -322,7 +322,7 @@ pub fn to_u_short(int: u16) -> Vec<u8> {
bytes
}

/// Convers integer into Cassandra's [int]
/// Converts integer into Cassandra's [int]
///
/// # Panics
///
Expand All @@ -335,7 +335,7 @@ pub fn to_u(int: u32) -> Vec<u8> {
bytes
}

/// Convers integer into Cassandra's `int`
/// Converts integer into Cassandra's `int`
///
/// # Panics
///
Expand Down Expand Up @@ -417,8 +417,9 @@ impl FromCursor for CString {
/// from_cursor gets Cursor who's position is set such that it should be a start of a [string].
/// It reads required number of bytes and returns a String
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CString> {
let len_bytes = cursor_next_value(&mut cursor, SHORT_LEN as u64)?;
let len: u64 = try_from_bytes(len_bytes.as_slice())?;
let mut buff = [0; SHORT_LEN];
let len_bytes = cursor_fill_value(&mut cursor, &mut buff)?;
let len: u64 = try_from_bytes(len_bytes)?;
let body_bytes = cursor_next_value(&mut cursor, len)?;

String::from_utf8(body_bytes)
Expand Down Expand Up @@ -465,8 +466,9 @@ impl FromCursor for CStringLong {
/// from_cursor gets Cursor who's position is set such that it should be a start of a [string].
/// It reads required number of bytes and returns a String
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CStringLong> {
let len_bytes = cursor_next_value(&mut cursor, INT_LEN as u64)?;
let len: u64 = try_from_bytes(len_bytes.as_slice())?;
let mut buff = [0; INT_LEN];
let len_bytes = cursor_fill_value(&mut cursor, &mut buff)?;
let len: u64 = try_from_bytes(len_bytes)?;
let body_bytes = cursor_next_value(&mut cursor, len)?;

String::from_utf8(body_bytes)
Expand Down Expand Up @@ -645,8 +647,9 @@ pub type CInt = i32;

impl FromCursor for CInt {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CInt> {
let bytes = cursor_next_value(&mut cursor, INT_LEN as u64)?;
try_i32_from_bytes(bytes.as_slice()).map_err(Into::into)
let mut buff = [0; INT_LEN];
let bytes = cursor_fill_value(&mut cursor, &mut buff)?;
try_i32_from_bytes(bytes).map_err(Into::into)
}
}

Expand All @@ -655,23 +658,25 @@ pub type CIntShort = i16;

impl FromCursor for CIntShort {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CIntShort> {
let bytes = cursor_next_value(&mut cursor, SHORT_LEN as u64)?;
try_i16_from_bytes(bytes.as_slice()).map_err(Into::into)
let mut buff = [0; SHORT_LEN];
let bytes = cursor_fill_value(&mut cursor, &mut buff)?;
try_i16_from_bytes(bytes).map_err(Into::into)
}
}

// Use extended Rust Vec<u8> as Cassandra [bytes]
impl FromBytes for Vec<u8> {
fn from_bytes(bytes: &[u8]) -> CDRSResult<Vec<u8>> {
let mut cursor = Cursor::new(bytes);
let len_bytes = cursor_next_value(&mut cursor, SHORT_LEN as u64)?;
let len: u64 = try_from_bytes(len_bytes.as_slice())?;
let mut buff = [0; SHORT_LEN];
let len_bytes = cursor_fill_value(&mut cursor, &mut buff)?;
let len: u64 = try_from_bytes(len_bytes)?;

cursor_next_value(&mut cursor, len).map_err(Into::into)
}
}

/// The structure wich represets Cassandra [inet]
/// The structure which represents Cassandra [inet]
/// (https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L222).
#[derive(Debug)]
pub struct CInet {
Expand All @@ -680,7 +685,7 @@ pub struct CInet {

impl FromCursor for CInet {
fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult<CInet> {
let n = cursor_next_value(&mut cursor, 1)?[0];
let n = cursor_fill_value(&mut cursor, &mut [0])?[0];
let ip = decode_inet(cursor_next_value(&mut cursor, n as u64)?.as_slice())?;
let port = CInt::from_cursor(&mut cursor)?;
let socket_addr = SocketAddr::new(ip, port as u16);
Expand All @@ -701,6 +706,16 @@ pub fn cursor_next_value(cursor: &mut Cursor<&[u8]>, len: u64) -> CDRSResult<Vec
Ok(buff)
}

pub fn cursor_fill_value<'a>(
cursor: &mut Cursor<&[u8]>,
buff: &'a mut [u8],
) -> CDRSResult<&'a [u8]> {
let current_position = cursor.position();
cursor.read_exact(buff)?;
cursor.set_position(current_position + buff.len() as u64);
Ok(buff)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit ae5bf3b

Please sign in to comment.