mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-04 16:25:19 +00:00
fix: change u8::MAX to std::u8::MAX
This commit is contained in:
parent
401ffd19e6
commit
771d423c6f
@ -2,179 +2,192 @@ use bigdecimal::{BigDecimal, Signed};
|
|||||||
use num_bigint::{BigInt, Sign};
|
use num_bigint::{BigInt, Sign};
|
||||||
|
|
||||||
use crate::decode::Decode;
|
use crate::decode::Decode;
|
||||||
use crate::encode::{Encode};
|
use crate::encode::Encode;
|
||||||
use crate::types::Type;
|
|
||||||
use crate::mysql::protocol::TypeId;
|
|
||||||
use crate::mysql::{MySql, MySqlValue, MySqlTypeInfo, MySqlData};
|
|
||||||
use crate::Error;
|
|
||||||
use crate::io::Buf;
|
use crate::io::Buf;
|
||||||
|
use crate::mysql::protocol::TypeId;
|
||||||
|
use crate::mysql::{MySql, MySqlData, MySqlTypeInfo, MySqlValue};
|
||||||
|
use crate::types::Type;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
const SIGN_NEG: u8 = 0x2D;
|
const SIGN_NEG: u8 = 0x2D;
|
||||||
const SCALE_START: u8 = 0x2E;
|
const SCALE_START: u8 = 0x2E;
|
||||||
|
|
||||||
impl Type<MySql> for BigDecimal {
|
impl Type<MySql> for BigDecimal {
|
||||||
fn type_info() -> MySqlTypeInfo {
|
fn type_info() -> MySqlTypeInfo {
|
||||||
MySqlTypeInfo::new(TypeId::NEWDECIMAL)
|
MySqlTypeInfo::new(TypeId::NEWDECIMAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encode<MySql> for BigDecimal {
|
impl Encode<MySql> for BigDecimal {
|
||||||
fn encode(&self, buf: &mut Vec<u8>) {
|
fn encode(&self, buf: &mut Vec<u8>) {
|
||||||
let size = Encode::<MySql>::size_hint(self) - 1;
|
let size = Encode::<MySql>::size_hint(self) - 1;
|
||||||
|
|
||||||
assert!(size <= u8::MAX as usize, "Too large size");
|
assert!(size <= std::u8::MAX as usize, "Too large size");
|
||||||
|
|
||||||
buf.push(size as u8);
|
buf.push(size as u8);
|
||||||
|
|
||||||
if self.is_negative() {
|
if self.is_negative() {
|
||||||
buf.push(SIGN_NEG);
|
buf.push(SIGN_NEG);
|
||||||
}
|
|
||||||
|
|
||||||
let (bi, scale) = self.as_bigint_and_exponent();
|
|
||||||
let (_, mut radix) = bi.to_radix_be(10);
|
|
||||||
let mut scale_index: Option<usize> = None;
|
|
||||||
|
|
||||||
if scale < 0 {
|
|
||||||
radix.append(&mut vec![0u8; -scale as usize]);
|
|
||||||
} else {
|
|
||||||
let scale = scale as usize;
|
|
||||||
if scale >= radix.len() {
|
|
||||||
let mut radix_temp = vec![0u8; scale - radix.len() + 1];
|
|
||||||
radix_temp.append(&mut radix);
|
|
||||||
radix = radix_temp;
|
|
||||||
scale_index = Some(0);
|
|
||||||
} else {
|
|
||||||
scale_index = Some(radix.len() - scale - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, data) in radix.iter().enumerate() {
|
|
||||||
buf.push(*data + 0x30);
|
|
||||||
if let Some(si) = scale_index {
|
|
||||||
if si == i {
|
|
||||||
buf.push(SCALE_START);
|
|
||||||
scale_index = None;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 15, -2 => 1500
|
let (bi, scale) = self.as_bigint_and_exponent();
|
||||||
/// 15, 1 => 1.5
|
let (_, mut radix) = bi.to_radix_be(10);
|
||||||
/// 15, 2 => 0.15
|
let mut scale_index: Option<usize> = None;
|
||||||
/// 15, 3 => 0.015
|
|
||||||
|
|
||||||
fn size_hint(&self) -> usize {
|
if scale < 0 {
|
||||||
let (bi, scale) = self.as_bigint_and_exponent();
|
radix.append(&mut vec![0u8; -scale as usize]);
|
||||||
let (_, radix) = bi.to_radix_be(10);
|
} else {
|
||||||
let mut s = radix.len();
|
let scale = scale as usize;
|
||||||
|
if scale >= radix.len() {
|
||||||
|
let mut radix_temp = vec![0u8; scale - radix.len() + 1];
|
||||||
|
radix_temp.append(&mut radix);
|
||||||
|
radix = radix_temp;
|
||||||
|
scale_index = Some(0);
|
||||||
|
} else {
|
||||||
|
scale_index = Some(radix.len() - scale - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if scale < 0 {
|
for (i, data) in radix.iter().enumerate() {
|
||||||
s = s + (-scale) as usize
|
buf.push(*data + 0x30);
|
||||||
} else if scale > 0 {
|
if let Some(si) = scale_index {
|
||||||
let scale = scale as usize;
|
if si == i {
|
||||||
if scale >= s {
|
buf.push(SCALE_START);
|
||||||
s = scale + 1
|
scale_index = None;
|
||||||
}
|
}
|
||||||
s = s + 1;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_negative() {
|
/// 15, -2 => 1500
|
||||||
s = s + 1;
|
/// 15, 1 => 1.5
|
||||||
|
/// 15, 2 => 0.15
|
||||||
|
/// 15, 3 => 0.015
|
||||||
|
|
||||||
|
fn size_hint(&self) -> usize {
|
||||||
|
let (bi, scale) = self.as_bigint_and_exponent();
|
||||||
|
let (_, radix) = bi.to_radix_be(10);
|
||||||
|
let mut s = radix.len();
|
||||||
|
|
||||||
|
if scale < 0 {
|
||||||
|
s = s + (-scale) as usize
|
||||||
|
} else if scale > 0 {
|
||||||
|
let scale = scale as usize;
|
||||||
|
if scale >= s {
|
||||||
|
s = scale + 1
|
||||||
|
}
|
||||||
|
s = s + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_negative() {
|
||||||
|
s = s + 1;
|
||||||
|
}
|
||||||
|
s + 1
|
||||||
}
|
}
|
||||||
s + 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_, MySql> for BigDecimal {
|
impl Decode<'_, MySql> for BigDecimal {
|
||||||
fn decode(value: MySqlValue) -> crate::Result<Self> {
|
fn decode(value: MySqlValue) -> crate::Result<Self> {
|
||||||
match value.try_get()? {
|
match value.try_get()? {
|
||||||
MySqlData::Binary(mut binary) => {
|
MySqlData::Binary(mut binary) => {
|
||||||
let len = binary.get_u8()?;
|
let len = binary.get_u8()?;
|
||||||
let mut negative = false;
|
let mut negative = false;
|
||||||
let mut scale: Option<i64> = None;
|
let mut scale: Option<i64> = None;
|
||||||
let mut v: Vec<u8> = Vec::with_capacity(len as usize);
|
let mut v: Vec<u8> = Vec::with_capacity(len as usize);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if binary.len() < 1 {
|
if binary.len() < 1 {
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
let data = binary.get_u8()?;
|
let data = binary.get_u8()?;
|
||||||
match data {
|
match data {
|
||||||
SIGN_NEG => {
|
SIGN_NEG => {
|
||||||
if !negative {
|
if !negative {
|
||||||
negative = true;
|
negative = true;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Decode(format!("Unexpected byte: {:X?}", data).into()));
|
return Err(Error::Decode(
|
||||||
}
|
format!("Unexpected byte: {:X?}", data).into(),
|
||||||
},
|
));
|
||||||
SCALE_START => {
|
}
|
||||||
if scale.is_none() {
|
}
|
||||||
scale = Some(0);
|
SCALE_START => {
|
||||||
} else {
|
if scale.is_none() {
|
||||||
return Err(Error::Decode(format!("Unexpected byte: {:X?}", data).into()));
|
scale = Some(0);
|
||||||
}
|
} else {
|
||||||
},
|
return Err(Error::Decode(
|
||||||
0x30..=0x39 => {
|
format!("Unexpected byte: {:X?}", data).into(),
|
||||||
scale = scale.map(|s| s + 1);
|
));
|
||||||
v.push(data - 0x30);
|
}
|
||||||
},
|
}
|
||||||
_ => return Err(Error::Decode(format!("Unexpected byte: {:X?}", data).into())),
|
0x30..=0x39 => {
|
||||||
}
|
scale = scale.map(|s| s + 1);
|
||||||
|
v.push(data - 0x30);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::Decode(
|
||||||
|
format!("Unexpected byte: {:X?}", data).into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = BigInt::from_radix_be(
|
||||||
|
if negative { Sign::Minus } else { Sign::Plus },
|
||||||
|
v.as_slice(),
|
||||||
|
10,
|
||||||
|
)
|
||||||
|
.ok_or(Error::Decode("Can't convert to BigInt".into()))?;
|
||||||
|
|
||||||
|
Ok(BigDecimal::new(r, scale.unwrap_or(0)))
|
||||||
|
}
|
||||||
|
MySqlData::Text(_) => Err(Error::Decode(
|
||||||
|
"`BigDecimal` can only be decoded from the binary protocol".into(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = BigInt::from_radix_be(
|
|
||||||
if negative { Sign::Minus } else { Sign::Plus },
|
|
||||||
v.as_slice(),
|
|
||||||
10,
|
|
||||||
).ok_or(Error::Decode("Can't convert to BigInt".into()))?;
|
|
||||||
|
|
||||||
Ok(BigDecimal::new(r, scale.unwrap_or(0)))
|
|
||||||
},
|
|
||||||
MySqlData::Text(_) => {
|
|
||||||
Err(Error::Decode(
|
|
||||||
"`BigDecimal` can only be decoded from the binary protocol".into(),
|
|
||||||
))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encode_decimal() {
|
fn test_encode_decimal() {
|
||||||
let v = BigDecimal::new(BigInt::from(-105), 2);
|
let v = BigDecimal::new(BigInt::from(-105), 2);
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
v.encode(&mut buf);
|
v.encode(&mut buf);
|
||||||
assert_eq!(buf, vec![0x05, 0x2D, 0x31, 0x2E, 0x30, 0x35]);
|
assert_eq!(buf, vec![0x05, 0x2D, 0x31, 0x2E, 0x30, 0x35]);
|
||||||
|
|
||||||
let v = BigDecimal::new(BigInt::from(-105), -3);
|
let v = BigDecimal::new(BigInt::from(-105), -3);
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
v.encode(&mut buf);
|
v.encode(&mut buf);
|
||||||
assert_eq!(buf, vec![0x07, 0x2D, 0x31, 0x30, 0x35, 0x30, 0x30, 0x30]);
|
assert_eq!(buf, vec![0x07, 0x2D, 0x31, 0x30, 0x35, 0x30, 0x30, 0x30]);
|
||||||
|
|
||||||
let v = BigDecimal::new(BigInt::from(105), 5);
|
let v = BigDecimal::new(BigInt::from(105), 5);
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
v.encode(&mut buf);
|
v.encode(&mut buf);
|
||||||
assert_eq!(buf, vec![0x07, 0x30, 0x2E, 0x30, 0x30, 0x31, 0x30, 0x35]);
|
assert_eq!(buf, vec![0x07, 0x30, 0x2E, 0x30, 0x30, 0x31, 0x30, 0x35]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_decimal() {
|
fn test_decode_decimal() {
|
||||||
let buf: Vec<u8> = vec![0x05, 0x2D, 0x31, 0x2E, 0x30, 0x35];
|
let buf: Vec<u8> = vec![0x05, 0x2D, 0x31, 0x2E, 0x30, 0x35];
|
||||||
let v = BigDecimal::decode(MySqlValue::binary(
|
let v = BigDecimal::decode(MySqlValue::binary(
|
||||||
MySqlTypeInfo::new(TypeId::NEWDECIMAL), buf.as_slice(),
|
MySqlTypeInfo::new(TypeId::NEWDECIMAL),
|
||||||
)).unwrap();
|
buf.as_slice(),
|
||||||
assert_eq!(v.to_string(), "-1.05");
|
))
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(v.to_string(), "-1.05");
|
||||||
|
|
||||||
let buf: Vec<u8> = vec![0x04, 0x30, 0x2E, 0x30, 0x35];
|
let buf: Vec<u8> = vec![0x04, 0x30, 0x2E, 0x30, 0x35];
|
||||||
let v = BigDecimal::decode(MySqlValue::binary(
|
let v = BigDecimal::decode(MySqlValue::binary(
|
||||||
MySqlTypeInfo::new(TypeId::NEWDECIMAL), buf.as_slice(),
|
MySqlTypeInfo::new(TypeId::NEWDECIMAL),
|
||||||
)).unwrap();
|
buf.as_slice(),
|
||||||
assert_eq!(v.to_string(), "0.05");
|
))
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(v.to_string(), "0.05");
|
||||||
|
|
||||||
let buf: Vec<u8> = vec![0x06, 0x2D, 0x39, 0x30, 0x30, 0x30, 0x30];
|
let buf: Vec<u8> = vec![0x06, 0x2D, 0x39, 0x30, 0x30, 0x30, 0x30];
|
||||||
let v = BigDecimal::decode(MySqlValue::binary(
|
let v = BigDecimal::decode(MySqlValue::binary(
|
||||||
MySqlTypeInfo::new(TypeId::NEWDECIMAL), buf.as_slice(),
|
MySqlTypeInfo::new(TypeId::NEWDECIMAL),
|
||||||
)).unwrap();
|
buf.as_slice(),
|
||||||
assert_eq!(v.to_string(), "-90000");
|
))
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(v.to_string(), "-90000");
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user