No side effect deserialization -> side effects

This commit is contained in:
Daniel Akhterov 2019-06-15 19:11:27 -07:00 committed by Daniel Akhterov
parent 17c86ed3ec
commit 92ff441d42
2 changed files with 109 additions and 84 deletions

View file

@ -2,76 +2,120 @@ use byteorder::{ByteOrder, LittleEndian};
use bytes::Bytes;
#[inline]
pub fn deserialize_int_lenenc(buf: &Vec<u8>, index: &usize) -> (Option<usize>, usize) {
pub fn deserialize_int_lenenc(buf: &Vec<u8>, index: &mut usize) -> Option<usize> {
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<lenenc> 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<u8>, index: &usize) -> (u64, usize) {
(LittleEndian::read_u64(&buf[*index..]), index + 8)
pub fn deserialize_int_8(buf: &Vec<u8>, index: &mut usize) -> u64 {
let value = LittleEndian::read_u64(&buf[*index..]);
*index += 8;
value
}
#[inline]
pub fn deserialize_int_4(buf: &Vec<u8>, index: &usize) -> (u32, usize) {
(LittleEndian::read_u32(&buf[*index..]), index + 4)
pub fn deserialize_int_4(buf: &Vec<u8>, index: &mut usize) -> u32 {
let value = LittleEndian::read_u32(&buf[*index..]);
*index += 4;
value
}
#[inline]
pub fn deserialize_int_3(buf: &Vec<u8>, index: &usize) -> (u32, usize) {
(LittleEndian::read_u24(&buf[*index..]), index + 3)
pub fn deserialize_int_3(buf: &Vec<u8>, index: &mut usize) -> u32 {
let value = LittleEndian::read_u24(&buf[*index..]);
*index += 3;
value
}
#[inline]
pub fn deserialize_int_2(buf: &Vec<u8>, index: &usize) -> (u16, usize) {
(LittleEndian::read_u16(&buf[*index..]), index + 2)
pub fn deserialize_int_2(buf: &Vec<u8>, index: &mut usize) -> u16 {
let value = LittleEndian::read_u16(&buf[*index..]);
*index += 2;
value
}
#[inline]
pub fn deserialize_int_1(buf: &Vec<u8>, index: &usize) -> (u8, usize) {
(buf[*index], index + 1)
pub fn deserialize_int_1(buf: &Vec<u8>, index: &mut usize) -> u8 {
let value = buf[*index];
*index += 1;
value
}
#[inline]
pub fn deserialize_string_lenenc(buf: &Vec<u8>, 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<u8>, 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<u8>, 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<u8>, 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<u8>, index: &usize) -> (Bytes, usize) {
(Bytes::from(&buf[*index..]), buf.len())
pub fn deserialize_string_eof(buf: &Vec<u8>, index: &mut usize) -> Bytes {
let value = Bytes::from(&buf[*index..]);
*index = buf.len();
value
}
#[inline]
pub fn deserialize_string_null(buf: &Vec<u8>, index: &usize) -> (Bytes, usize) {
pub fn deserialize_string_null(buf: &Vec<u8>, 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<u8>, 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<u8>, 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<u8>, 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<u8>, 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<u8>, index: &usize) -> (Bytes, usize) {
(Bytes::from(&buf[*index..]), buf.len())
pub fn deserialize_byte_eof(buf: &Vec<u8>, index: &mut usize) -> Bytes {
let value = Bytes::from(&buf[*index..]);
*index = buf.len();
value
}

View file

@ -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<u8>) -> Result<Self, Error>;
@ -129,42 +129,38 @@ impl Deserialize for InitialHandshakePacket {
fn deserialize(buf: &mut Vec<u8>) -> Result<Self, Error> {
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<Bytes> = 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<u8>) -> Result<Self, Error> {
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<u8>) -> Result<Self, Error> {
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));
}
}