From 92ff441d42adbb325fa8081db54a7b95ea946fbb Mon Sep 17 00:00:00 2001 From: Daniel Akhterov Date: Sat, 15 Jun 2019 19:11:27 -0700 Subject: [PATCH] No side effect deserialization -> side effects --- mason-mariadb/src/protocol/deserialize.rs | 108 +++++++++++++++------- mason-mariadb/src/protocol/server.rs | 85 +++++++---------- 2 files changed, 109 insertions(+), 84 deletions(-) diff --git a/mason-mariadb/src/protocol/deserialize.rs b/mason-mariadb/src/protocol/deserialize.rs index 1b00c9ca..9b73776c 100644 --- a/mason-mariadb/src/protocol/deserialize.rs +++ b/mason-mariadb/src/protocol/deserialize.rs @@ -2,76 +2,120 @@ use byteorder::{ByteOrder, LittleEndian}; use bytes::Bytes; #[inline] -pub fn deserialize_int_lenenc(buf: &Vec, index: &usize) -> (Option, usize) { +pub fn deserialize_int_lenenc(buf: &Vec, index: &mut usize) -> Option { match buf[*index] { - 0xFB => (None, *index + 1), - 0xFC => (Some(LittleEndian::read_u16(&buf[*index + 1..]) as usize), *index + 2), - 0xFD => (Some((buf[*index + 1] + buf[*index + 2] << 8 + buf[*index + 3] << 16) as usize), *index + 3), - 0xFE => (Some(LittleEndian::read_u64(&buf[*index..]) as usize), *index + 8), + 0xFB => { + *index += 1; + None + } + 0xFC => { + let value = Some(LittleEndian::read_u16(&buf[*index + 1..]) as usize); + *index += 3; + value + } + 0xFD => { + let value = + Some((buf[*index + 1] + buf[*index + 2] << 8 + buf[*index + 3] << 16) as usize); + *index += 4; + value + } + 0xFE => { + let value = Some(LittleEndian::read_u64(&buf[*index..]) as usize); + *index += 9; + value + } 0xFF => panic!("int unprocessable first byte 0xFF"), - _ => (Some(buf[*index] as usize), *index + 1), + _ => { + let value = Some(buf[*index] as usize); + *index += 2; + value + } } } #[inline] -pub fn deserialize_int_8(buf: &Vec, index: &usize) -> (u64, usize) { - (LittleEndian::read_u64(&buf[*index..]), index + 8) +pub fn deserialize_int_8(buf: &Vec, index: &mut usize) -> u64 { + let value = LittleEndian::read_u64(&buf[*index..]); + *index += 8; + value } #[inline] -pub fn deserialize_int_4(buf: &Vec, index: &usize) -> (u32, usize) { - (LittleEndian::read_u32(&buf[*index..]), index + 4) +pub fn deserialize_int_4(buf: &Vec, index: &mut usize) -> u32 { + let value = LittleEndian::read_u32(&buf[*index..]); + *index += 4; + value } #[inline] -pub fn deserialize_int_3(buf: &Vec, index: &usize) -> (u32, usize) { - (LittleEndian::read_u24(&buf[*index..]), index + 3) +pub fn deserialize_int_3(buf: &Vec, index: &mut usize) -> u32 { + let value = LittleEndian::read_u24(&buf[*index..]); + *index += 3; + value } #[inline] -pub fn deserialize_int_2(buf: &Vec, index: &usize) -> (u16, usize) { - (LittleEndian::read_u16(&buf[*index..]), index + 2) +pub fn deserialize_int_2(buf: &Vec, index: &mut usize) -> u16 { + let value = LittleEndian::read_u16(&buf[*index..]); + *index += 2; + value } #[inline] -pub fn deserialize_int_1(buf: &Vec, index: &usize) -> (u8, usize) { - (buf[*index], index + 1) +pub fn deserialize_int_1(buf: &Vec, index: &mut usize) -> u8 { + let value = buf[*index]; + *index += 1; + value } #[inline] -pub fn deserialize_string_lenenc(buf: &Vec, index: &usize) -> (Bytes, usize) { - let (length, index) = deserialize_int_3(&buf, &index); - (Bytes::from(&buf[index..index + length as usize]), index + length as usize) +pub fn deserialize_string_lenenc(buf: &Vec, index: &mut usize) -> Bytes { + let length = deserialize_int_3(&buf, &mut *index); + let value = Bytes::from(&buf[*index..*index + length as usize]); + *index = *index + length as usize; + value } #[inline] -pub fn deserialize_string_fix(buf: &Vec, index: &usize, length: usize) -> (Bytes, usize) { - (Bytes::from(&buf[*index..index + length as usize]), index + length as usize) +pub fn deserialize_string_fix(buf: &Vec, index: &mut usize, length: usize) -> Bytes { + let value = Bytes::from(&buf[*index..*index + length as usize]); + *index = *index + length as usize; + value } #[inline] -pub fn deserialize_string_eof(buf: &Vec, index: &usize) -> (Bytes, usize) { - (Bytes::from(&buf[*index..]), buf.len()) +pub fn deserialize_string_eof(buf: &Vec, index: &mut usize) -> Bytes { + let value = Bytes::from(&buf[*index..]); + *index = buf.len(); + value } #[inline] -pub fn deserialize_string_null(buf: &Vec, index: &usize) -> (Bytes, usize) { +pub fn deserialize_string_null(buf: &Vec, index: &mut usize) -> Bytes { let null_index = memchr::memchr(b'\0', &buf[*index..]).unwrap(); - (Bytes::from(&buf[*index..null_index]), null_index + 1) + let value = Bytes::from(&buf[*index..null_index]); + *index = null_index + 1; + value } #[inline] -pub fn deserialize_byte_fix(buf: &Vec, index: &usize, length: usize) -> (Bytes, usize) { - (Bytes::from(&buf[*index..index + length as usize]), index + length as usize) +pub fn deserialize_byte_fix(buf: &Vec, index: &mut usize, length: usize) -> Bytes { + let value = Bytes::from(&buf[*index..*index + length as usize]); + *index = *index + length as usize; + value } #[inline] -pub fn deserialize_byte_lenenc(buf: &Vec, index: &usize) -> (Bytes, usize) { - let (length, index) = deserialize_int_3(&buf, &index); - (Bytes::from(&buf[index..index + length as usize]), index + length as usize) +pub fn deserialize_byte_lenenc(buf: &Vec, index: &mut usize) -> Bytes { + let length = deserialize_int_3(&buf, &mut *index); + let value = Bytes::from(&buf[*index..*index + length as usize]); + *index = *index + length as usize; + value } #[inline] -pub fn deserialize_byte_eof(buf: &Vec, index: &usize) -> (Bytes, usize) { - (Bytes::from(&buf[*index..]), buf.len()) +pub fn deserialize_byte_eof(buf: &Vec, index: &mut usize) -> Bytes { + let value = Bytes::from(&buf[*index..]); + *index = buf.len(); + value } diff --git a/mason-mariadb/src/protocol/server.rs b/mason-mariadb/src/protocol/server.rs index 74ec9609..e647dbdc 100644 --- a/mason-mariadb/src/protocol/server.rs +++ b/mason-mariadb/src/protocol/server.rs @@ -1,9 +1,9 @@ // Reference: https://mariadb.com/kb/en/library/connection -use byteorder::{ByteOrder, LittleEndian}; -use failure::{Error, err_msg}; -use bytes::{Bytes, BytesMut}; use crate::protocol::deserialize::*; +use byteorder::{ByteOrder, LittleEndian}; +use bytes::{Bytes, BytesMut}; +use failure::{err_msg, Error}; pub trait Deserialize: Sized { fn deserialize(buf: &mut Vec) -> Result; @@ -129,42 +129,38 @@ impl Deserialize for InitialHandshakePacket { fn deserialize(buf: &mut Vec) -> Result { let mut index = 0; - let (length, index) = deserialize_int_3(&buf, &index); + let length = deserialize_int_3(&buf, &mut index); if buf.len() != length as usize { return Err(err_msg("Lengths to do not match")); } - let mut sequence_number = 0; - (sequence_number, index) = deserialize_int_1(&buf, &index); + let sequence_number = deserialize_int_1(&buf, &mut index); if sequence_number != 0 { return Err(err_msg("Squence Number of Initial Handshake Packet is not 0")); } - let (protocol_version, index) = deserialize_int_1(&buf, &index); - let (server_version, index) = deserialize_string_null(&buf, &index); - let (connection_id, index) = deserialize_int_4(&buf, &index); - let (auth_seed, index) = deserialize_string_fix(&buf, &index, 8); + let protocol_version = deserialize_int_1(&buf, &mut index); + let server_version = deserialize_string_null(&buf, &mut index); + let connection_id = deserialize_int_4(&buf, &mut index); + let auth_seed = deserialize_string_fix(&buf, &mut index, 8); // Skip reserved byte index += 1; - let (cap, index) = deserialize_int_2(&buf, &index); - let mut capabilities = Capabilities::from_bits(cap.into()).unwrap(); + let mut capabilities = + Capabilities::from_bits(deserialize_int_2(&buf, &mut index).into()).unwrap(); - let (collation, index) = deserialize_int_1(&buf, &index); + let collation = deserialize_int_1(&buf, &mut index); + let status = deserialize_int_2(&buf, &mut index); - let (status, index) = deserialize_int_2(&buf, &index); - - let (cap, index) = deserialize_int_2(&buf, &index); - capabilities |= Capabilities::from_bits(cap.into()).unwrap(); + capabilities |= + Capabilities::from_bits(deserialize_int_2(&buf, &mut index).into()).unwrap(); let mut plugin_data_length = 0; if !(capabilities & Capabilities::PLUGIN_AUTH).is_empty() { - let (plugin, i) = deserialize_int_1(&buf, &index); - plugin_data_length = plugin; - index = i; + plugin_data_length = deserialize_int_1(&buf, &mut index); } else { // Skip reserve byte index += 1; @@ -174,9 +170,8 @@ impl Deserialize for InitialHandshakePacket { index += 6; if (capabilities & Capabilities::CLIENT_MYSQL).is_empty() { - let (cap, i) = deserialize_int_4(&buf, &index); - capabilities |= Capabilities::from_bits(cap.into()).unwrap(); - index = i; + capabilities |= + Capabilities::from_bits(deserialize_int_4(&buf, &mut index).into()).unwrap(); } else { // Skip filler index += 4; @@ -186,13 +181,9 @@ impl Deserialize for InitialHandshakePacket { let mut auth_plugin_name: Option = None; if !(capabilities & Capabilities::SECURE_CONNECTION).is_empty() { let len = std::cmp::max(12, plugin_data_length as usize - 9); - let (scram, i) = deserialize_string_fix(&buf, &index, len); - scramble = Some(scram); - index = i; + scramble = Some(deserialize_string_fix(&buf, &mut index, len)); } else { - let (plugin, i) = deserialize_string_null(&buf, &index); - let auth_plugin_name = Some(plugin); - index = i; + auth_plugin_name = Some(deserialize_string_null(&buf, &mut index)); } Ok(InitialHandshakePacket { @@ -215,10 +206,10 @@ impl Deserialize for InitialHandshakePacket { impl Deserialize for OkPacket { fn deserialize(buf: &mut Vec) -> Result { let mut index = 1; - let (affected_rows, index) = deserialize_int_lenenc(&buf, &index); - let (last_insert_id, index) = deserialize_int_lenenc(&buf, &index); - let (server_status, index) = deserialize_int_2(&buf, &index); - let (warning_count, index) = deserialize_int_2(&buf, &index); + let affected_rows = deserialize_int_lenenc(&buf, &mut index); + let last_insert_id = deserialize_int_lenenc(&buf, &mut index); + let server_status = deserialize_int_2(&buf, &mut index); + let warning_count = deserialize_int_2(&buf, &mut index); // Assuming CLIENT_SESSION_TRACK is unsupported let session_state_info = None; @@ -241,7 +232,7 @@ impl Deserialize for OkPacket { impl Deserialize for ErrPacket { fn deserialize(buf: &mut Vec) -> Result { let mut index = 1; - let (error_code, index) = deserialize_int_2(&buf, &index); + let error_code = deserialize_int_2(&buf, &mut index); let mut stage = None; let mut max_stage = None; @@ -254,27 +245,17 @@ impl Deserialize for ErrPacket { // Progress Reporting if error_code == 0xFFFF { - let (d_stage, index) = deserialize_int_1(&buf, &index); - let (d_max_stage, index) = deserialize_int_1(&buf, &index); - let (d_progress, index) = deserialize_int_3(&buf, &index); - let (d_progress_info, index) = deserialize_string_lenenc(&buf, &index); - stage = Some(d_stage); - max_stage = Some(d_max_stage); - progress = Some(d_progress); - progress_info = Some(d_progress_info); - - + stage = Some(deserialize_int_1(&buf, &mut index)); + max_stage = Some(deserialize_int_1(&buf, &mut index)); + progress = Some(deserialize_int_3(&buf, &mut index)); + progress_info = Some(deserialize_string_lenenc(&buf, &mut index)); } else { if buf[index] == b'#' { - let (d_sql_state_marker, index) = deserialize_string_fix(&buf, &index, 1); - let (d_sql_state, index) = deserialize_string_fix(&buf, &index, 5); - let (d_error_message, index) = deserialize_string_eof(&buf, &index); - sql_state_marker = Some(d_sql_state_marker); - sql_state = Some(d_sql_state); - error_message = Some(d_error_message); + sql_state_marker = Some(deserialize_string_fix(&buf, &mut index, 1)); + sql_state = Some(deserialize_string_fix(&buf, &mut index, 5)); + error_message = Some(deserialize_string_eof(&buf, &mut index)); } else { - let (d_error_message, index) = deserialize_string_eof(&buf, &index); - error_message = Some(d_error_message); + error_message = Some(deserialize_string_eof(&buf, &mut index)); } }