From 74044d2e4ff247446642e43721503e93a66cf7d8 Mon Sep 17 00:00:00 2001 From: Daniel Akhterov Date: Fri, 14 Jun 2019 17:33:26 -0700 Subject: [PATCH] Add ErrPacket --- mason-mariadb/src/protocol/server.rs | 86 +++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/mason-mariadb/src/protocol/server.rs b/mason-mariadb/src/protocol/server.rs index 2810eae6..5f7542dd 100644 --- a/mason-mariadb/src/protocol/server.rs +++ b/mason-mariadb/src/protocol/server.rs @@ -13,7 +13,7 @@ pub trait Deserialize: Sized { pub enum Message { InitialHandshakePacket(InitialHandshakePacket), OkPacket(OkPacket), - // ErrPacket(ErrPacket), + ErrPacket(ErrPacket), } bitflags! { @@ -76,6 +76,18 @@ pub struct OkPacket { pub value: Option, } +#[derive(Default, Debug)] +pub struct ErrPacket { + pub error_code: u16, + pub stage: Option, + pub max_stage: Option, + pub progress: Option, + pub progress_info: Option, + pub sql_state_marker: Option, + pub sql_state: Option, + pub error_message: Option, +} + impl Message { pub fn deserialize(buf: &mut BytesMut) -> Result, Error> { let length = buf[0] + buf[1] << 8 + buf[2] << 16; @@ -171,6 +183,7 @@ impl Deserialize for InitialHandshakePacket { } } +#[inline] fn deserialize_int_lenenc(buf: &Vec, index: &usize) -> (Option, usize) { match buf[*index] { 0xFB => (None, *index + 1), @@ -182,10 +195,37 @@ fn deserialize_int_lenenc(buf: &Vec, index: &usize) -> (Option, usize } } +#[inline] +fn deserialize_int_3(buf: &Vec, index: &usize) -> (u32, usize) { + ((buf[*index] + buf[index + 1] << 8 + buf[*index + 2] << 16) as u32, index + 3) +} + +#[inline] fn deserialize_int_2(buf: &Vec, index: &usize) -> (u16, usize) { (LittleEndian::read_u16(&buf[*index..]), index + 2) } +#[inline] +fn deserialize_int_1(buf: &Vec, index: &usize) -> (u8, usize) { + (buf[*index], index + 1) +} + +#[inline] +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) +} + +#[inline] +fn deserialize_string_fix(buf: &Vec, index: &usize, length: usize) -> (Bytes, usize) { + (Bytes::from(&buf[*index..index + length as usize]), index + length as usize) +} + +#[inline] +fn deserialize_string_eof(buf: &Vec, index: &usize) -> (Bytes, usize) { + (Bytes::from(&buf[*index..]), buf.len()) +} + impl Deserialize for OkPacket { fn deserialize(buf: &mut Vec) -> Result { let mut index = 1; @@ -211,3 +251,47 @@ 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 mut stage = None; + let mut max_stage = None; + let mut progress = None; + let mut progress_info = None; + + let mut sql_state_marker = None; + let mut sql_state = None; + let mut error_message = None; + + // 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); + + + } 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); + } else { + let (d_error_message, index) = deserialize_string_eof(&buf, &index); + error_message = Some(d_error_message); + } + } + + Ok(ErrPacket::default()) + } +}