fix(mysql): handle MySQL sending more or less bytes than we expect for an integer type

This commit is contained in:
Ryan Leckey 2020-06-11 03:34:03 -07:00
parent e5a7619344
commit e9a562f89a
2 changed files with 54 additions and 54 deletions

View file

@ -1,3 +1,5 @@
use std::convert::TryInto;
use byteorder::{ByteOrder, LittleEndian};
use crate::decode::Decode;
@ -7,17 +9,6 @@ use crate::mysql::protocol::text::{ColumnFlags, ColumnType};
use crate::mysql::{MySql, MySqlTypeInfo, MySqlValueFormat, MySqlValueRef};
use crate::types::Type;
fn int_accepts(ty: &MySqlTypeInfo) -> bool {
matches!(
ty.r#type,
ColumnType::Tiny
| ColumnType::Short
| ColumnType::Long
| ColumnType::Int24
| ColumnType::LongLong
) && !ty.flags.contains(ColumnFlags::UNSIGNED)
}
impl Type<MySql> for i8 {
fn type_info() -> MySqlTypeInfo {
MySqlTypeInfo::binary(ColumnType::Tiny)
@ -74,16 +65,34 @@ impl Encode<'_, MySql> for i64 {
}
}
fn int_accepts(ty: &MySqlTypeInfo) -> bool {
matches!(
ty.r#type,
ColumnType::Tiny
| ColumnType::Short
| ColumnType::Long
| ColumnType::Int24
| ColumnType::LongLong
) && !ty.flags.contains(ColumnFlags::UNSIGNED)
}
fn int_decode(value: MySqlValueRef<'_>) -> Result<i64, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Text => value.as_str()?.parse()?,
MySqlValueFormat::Binary => {
let buf = value.as_bytes()?;
LittleEndian::read_int(buf, buf.len())
}
})
}
impl Decode<'_, MySql> for i8 {
fn accepts(ty: &MySqlTypeInfo) -> bool {
int_accepts(ty)
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => value.as_bytes()?[0] as i8,
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
int_decode(value)?.try_into().map_err(Into::into)
}
}
@ -93,10 +102,7 @@ impl Decode<'_, MySql> for i16 {
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => LittleEndian::read_i16(value.as_bytes()?),
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
int_decode(value)?.try_into().map_err(Into::into)
}
}
@ -106,10 +112,7 @@ impl Decode<'_, MySql> for i32 {
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => LittleEndian::read_i32(value.as_bytes()?),
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
int_decode(value)?.try_into().map_err(Into::into)
}
}
@ -119,9 +122,6 @@ impl Decode<'_, MySql> for i64 {
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => LittleEndian::read_i64(value.as_bytes()?),
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
int_decode(value)?.try_into().map_err(Into::into)
}
}

View file

@ -1,3 +1,5 @@
use std::convert::TryInto;
use byteorder::{ByteOrder, LittleEndian};
use crate::decode::Decode;
@ -15,17 +17,6 @@ fn uint_type_info(ty: ColumnType) -> MySqlTypeInfo {
}
}
fn uint_accepts(ty: &MySqlTypeInfo) -> bool {
matches!(
ty.r#type,
ColumnType::Tiny
| ColumnType::Short
| ColumnType::Long
| ColumnType::Int24
| ColumnType::LongLong
) && ty.flags.contains(ColumnFlags::UNSIGNED)
}
impl Type<MySql> for u8 {
fn type_info() -> MySqlTypeInfo {
uint_type_info(ColumnType::Tiny)
@ -82,16 +73,34 @@ impl Encode<'_, MySql> for u64 {
}
}
fn uint_accepts(ty: &MySqlTypeInfo) -> bool {
matches!(
ty.r#type,
ColumnType::Tiny
| ColumnType::Short
| ColumnType::Long
| ColumnType::Int24
| ColumnType::LongLong
) && ty.flags.contains(ColumnFlags::UNSIGNED)
}
fn uint_decode(value: MySqlValueRef<'_>) -> Result<u64, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Text => value.as_str()?.parse()?,
MySqlValueFormat::Binary => {
let buf = value.as_bytes()?;
LittleEndian::read_uint(buf, buf.len())
}
})
}
impl Decode<'_, MySql> for u8 {
fn accepts(ty: &MySqlTypeInfo) -> bool {
uint_accepts(ty)
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => value.as_bytes()?[0] as u8,
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
uint_decode(value)?.try_into().map_err(Into::into)
}
}
@ -101,10 +110,7 @@ impl Decode<'_, MySql> for u16 {
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => LittleEndian::read_u16(value.as_bytes()?),
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
uint_decode(value)?.try_into().map_err(Into::into)
}
}
@ -114,10 +120,7 @@ impl Decode<'_, MySql> for u32 {
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => LittleEndian::read_u32(value.as_bytes()?),
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
uint_decode(value)?.try_into().map_err(Into::into)
}
}
@ -127,9 +130,6 @@ impl Decode<'_, MySql> for u64 {
}
fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
MySqlValueFormat::Binary => LittleEndian::read_u64(value.as_bytes()?),
MySqlValueFormat::Text => value.as_str()?.parse()?,
})
uint_decode(value)?.try_into().map_err(Into::into)
}
}