From ae5bf3bb6bf893f5d1943a8d90337baaa231608d Mon Sep 17 00:00:00 2001 From: Kamil Rojewski Date: Fri, 26 Feb 2021 18:25:29 +0100 Subject: [PATCH] removed some memory allocations when parsing data --- src/frame/frame_error.rs | 69 +++++++++++++++++------------------- src/frame/frame_result.rs | 15 ++++---- src/frame/frame_supported.rs | 7 ++-- src/types/mod.rs | 51 ++++++++++++++++---------- 4 files changed, 76 insertions(+), 66 deletions(-) diff --git a/src/frame/frame_error.rs b/src/frame/frame_error.rs index a6a3d3f1..f040726a 100644 --- a/src/frame/frame_error.rs +++ b/src/frame/frame_error.rs @@ -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, }) } } @@ -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, }) } } @@ -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, }) } } @@ -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, }) } } @@ -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 } @@ -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, }) } } @@ -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, }) } } @@ -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, }) } } @@ -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, } @@ -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 }) } } @@ -402,6 +399,6 @@ impl FromCursor for UnpreparedError { fn from_cursor(mut cursor: &mut io::Cursor<&[u8]>) -> error::Result { let id = CBytesShort::from_cursor(&mut cursor)?; - Ok(UnpreparedError { id: id }) + Ok(UnpreparedError { id }) } } diff --git a/src/frame/frame_result.rs b/src/frame/frame_result.rs index 4c72f540..8a21be06 100644 --- a/src/frame/frame_result.rs +++ b/src/frame/frame_result.rs @@ -50,8 +50,7 @@ impl FromBytes for ResultKind { impl FromCursor for ResultKind { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result { - 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) } } @@ -458,8 +457,8 @@ impl FromBytes for ColType { impl FromCursor for ColType { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result { - 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) } } @@ -537,7 +536,7 @@ impl FromCursor for CUdt { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result { 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)?; @@ -563,7 +562,7 @@ pub struct CTuple { impl FromCursor for CTuple { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result { - 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)?; @@ -623,9 +622,9 @@ impl FromCursor for PreparedMetadata { }; let pk_index_results: Vec> = (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(); diff --git a/src/frame/frame_supported.rs b/src/frame/frame_supported.rs index b0b7b6f2..cb566bc8 100644 --- a/src/frame/frame_supported.rs +++ b/src/frame/frame_supported.rs @@ -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 { @@ -12,8 +12,7 @@ pub struct BodyResSupported { impl FromCursor for BodyResSupported { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result { - 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> = HashMap::with_capacity(l); for _ in 0..l { let name = CString::from_cursor(&mut cursor)?.into_plain(); @@ -21,7 +20,7 @@ impl FromCursor for BodyResSupported { data.insert(name, val); } - Ok(BodyResSupported { data: data }) + Ok(BodyResSupported { data }) } } diff --git a/src/types/mod.rs b/src/types/mod.rs index eb304c01..49453edf 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -132,7 +132,7 @@ pub fn try_to_n_bytes(int: u64, n: usize) -> io::Result> { /// /// # 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 { try_to_n_bytes(int, n).unwrap() } @@ -163,7 +163,7 @@ pub fn try_from_bytes(bytes: &[u8]) -> Result { c.read_uint::(l) } -/// Tryies to decode bytes array into `u16`. +/// Tries to decode bytes array into `u16`. pub fn try_u16_from_bytes(bytes: &[u8]) -> Result { let mut c = Cursor::new(bytes); c.read_u16::() @@ -249,7 +249,7 @@ pub fn to_short(int: i16) -> Vec { bytes } -/// Convers integer into Cassandra's [int] +/// Converts integer into Cassandra's [int] /// /// # Panics /// @@ -262,7 +262,7 @@ pub fn to_int(int: i32) -> Vec { bytes } -/// Convers integer into Cassandra's [int] +/// Converts integer into Cassandra's [int] /// /// # Panics /// @@ -322,7 +322,7 @@ pub fn to_u_short(int: u16) -> Vec { bytes } -/// Convers integer into Cassandra's [int] +/// Converts integer into Cassandra's [int] /// /// # Panics /// @@ -335,7 +335,7 @@ pub fn to_u(int: u32) -> Vec { bytes } -/// Convers integer into Cassandra's `int` +/// Converts integer into Cassandra's `int` /// /// # Panics /// @@ -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 { - 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) @@ -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 { - 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) @@ -645,8 +647,9 @@ pub type CInt = i32; impl FromCursor for CInt { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult { - 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) } } @@ -655,8 +658,9 @@ pub type CIntShort = i16; impl FromCursor for CIntShort { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult { - 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) } } @@ -664,14 +668,15 @@ impl FromCursor for CIntShort { impl FromBytes for Vec { fn from_bytes(bytes: &[u8]) -> CDRSResult> { 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 { @@ -680,7 +685,7 @@ pub struct CInet { impl FromCursor for CInet { fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> CDRSResult { - 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); @@ -701,6 +706,16 @@ pub fn cursor_next_value(cursor: &mut Cursor<&[u8]>, len: u64) -> CDRSResult( + 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::*;