diesel/mysql/types/
primitives.rs
1use crate::deserialize::{self, FromSql};
2use crate::mysql::{Mysql, MysqlValue, NumericRepresentation};
3use crate::result::Error::DeserializationError;
4use crate::sql_types::{BigInt, Binary, Double, Float, Integer, SmallInt, Text};
5use crate::Queryable;
6use std::error::Error;
7use std::str::{self, FromStr};
8
9fn decimal_to_integer<T>(bytes: &[u8]) -> deserialize::Result<T>
10where
11 T: FromStr,
12 T::Err: Error + Send + Sync + 'static,
13{
14 let string = str::from_utf8(bytes)?;
15 let mut split = string.split('.');
16 let integer_portion = split.next().unwrap_or_default();
17 let _decimal_portion = split.next().unwrap_or_default();
18 if split.next().is_some() {
19 Err(format!("Invalid decimal format: {string:?}").into())
20 } else {
21 Ok(integer_portion.parse()?)
22 }
23}
24
25#[allow(clippy::cast_possible_truncation)] fn f32_to_i64(f: f32) -> deserialize::Result<i64> {
27 if f <= i64::MAX as f32 && f >= i64::MIN as f32 {
28 Ok(f.trunc() as i64)
29 } else {
30 Err(Box::new(DeserializationError(
31 "Numeric overflow/underflow occurred".into(),
32 )) as _)
33 }
34}
35
36#[allow(clippy::cast_possible_truncation)] fn f64_to_i64(f: f64) -> deserialize::Result<i64> {
38 if f <= i64::MAX as f64 && f >= i64::MIN as f64 {
39 Ok(f.trunc() as i64)
40 } else {
41 Err(Box::new(DeserializationError(
42 "Numeric overflow/underflow occurred".into(),
43 )) as _)
44 }
45}
46
47#[cfg(feature = "mysql_backend")]
48impl FromSql<SmallInt, Mysql> for i16 {
49 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
50 match value.numeric_value()? {
51 NumericRepresentation::Tiny(x) => Ok(x.into()),
52 NumericRepresentation::Small(x) => Ok(x),
53 NumericRepresentation::Medium(x) => x.try_into().map_err(|_| {
54 Box::new(DeserializationError(
55 "Numeric overflow/underflow occurred".into(),
56 )) as _
57 }),
58 NumericRepresentation::Big(x) => x.try_into().map_err(|_| {
59 Box::new(DeserializationError(
60 "Numeric overflow/underflow occurred".into(),
61 )) as _
62 }),
63 NumericRepresentation::Float(x) => f32_to_i64(x)?.try_into().map_err(|_| {
64 Box::new(DeserializationError(
65 "Numeric overflow/underflow occurred".into(),
66 )) as _
67 }),
68 NumericRepresentation::Double(x) => f64_to_i64(x)?.try_into().map_err(|_| {
69 Box::new(DeserializationError(
70 "Numeric overflow/underflow occurred".into(),
71 )) as _
72 }),
73 NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
74 }
75 }
76}
77
78#[cfg(feature = "mysql_backend")]
79impl FromSql<Integer, Mysql> for i32 {
80 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
81 match value.numeric_value()? {
82 NumericRepresentation::Tiny(x) => Ok(x.into()),
83 NumericRepresentation::Small(x) => Ok(x.into()),
84 NumericRepresentation::Medium(x) => Ok(x),
85 NumericRepresentation::Big(x) => x.try_into().map_err(|_| {
86 Box::new(DeserializationError(
87 "Numeric overflow/underflow occurred".into(),
88 )) as _
89 }),
90 NumericRepresentation::Float(x) => f32_to_i64(x).and_then(|i| {
91 i.try_into().map_err(|_| {
92 Box::new(DeserializationError(
93 "Numeric overflow/underflow occurred".into(),
94 )) as _
95 })
96 }),
97 NumericRepresentation::Double(x) => f64_to_i64(x).and_then(|i| {
98 i.try_into().map_err(|_| {
99 Box::new(DeserializationError(
100 "Numeric overflow/underflow occurred".into(),
101 )) as _
102 })
103 }),
104 NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
105 }
106 }
107}
108
109#[cfg(feature = "mysql_backend")]
110impl FromSql<BigInt, Mysql> for i64 {
111 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
112 match value.numeric_value()? {
113 NumericRepresentation::Tiny(x) => Ok(x.into()),
114 NumericRepresentation::Small(x) => Ok(x.into()),
115 NumericRepresentation::Medium(x) => Ok(x.into()),
116 NumericRepresentation::Big(x) => Ok(x),
117 NumericRepresentation::Float(x) => f32_to_i64(x),
118 NumericRepresentation::Double(x) => f64_to_i64(x),
119 NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
120 }
121 }
122}
123
124#[cfg(feature = "mysql_backend")]
125impl FromSql<Float, Mysql> for f32 {
126 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
127 match value.numeric_value()? {
128 NumericRepresentation::Tiny(x) => Ok(x.into()),
129 NumericRepresentation::Small(x) => Ok(x.into()),
130 NumericRepresentation::Medium(x) => Ok(x as Self),
131 NumericRepresentation::Big(x) => Ok(x as Self),
132 NumericRepresentation::Float(x) => Ok(x),
133 #[allow(clippy::cast_possible_truncation)]
135 NumericRepresentation::Double(x) => Ok(x as Self),
136 NumericRepresentation::Decimal(bytes) => Ok(str::from_utf8(bytes)?.parse()?),
137 }
138 }
139}
140
141#[cfg(feature = "mysql_backend")]
142impl FromSql<Double, Mysql> for f64 {
143 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
144 match value.numeric_value()? {
145 NumericRepresentation::Tiny(x) => Ok(x.into()),
146 NumericRepresentation::Small(x) => Ok(x.into()),
147 NumericRepresentation::Medium(x) => Ok(x.into()),
148 NumericRepresentation::Big(x) => Ok(x as Self),
149 NumericRepresentation::Float(x) => Ok(x.into()),
150 NumericRepresentation::Double(x) => Ok(x),
151 NumericRepresentation::Decimal(bytes) => Ok(str::from_utf8(bytes)?.parse()?),
152 }
153 }
154}
155
156#[cfg(feature = "mysql_backend")]
162impl FromSql<Text, Mysql> for *const str {
163 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
164 let string = str::from_utf8(value.as_bytes())?;
165 Ok(string as *const str)
166 }
167}
168
169#[cfg(feature = "mysql_backend")]
170impl Queryable<Text, Mysql> for *const str {
171 type Row = Self;
172
173 fn build(row: Self::Row) -> deserialize::Result<Self> {
174 Ok(row)
175 }
176}
177
178#[cfg(feature = "mysql_backend")]
184impl FromSql<Binary, Mysql> for *const [u8] {
185 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
186 Ok(value.as_bytes() as *const [u8])
187 }
188}
189
190#[cfg(feature = "mysql_backend")]
191impl Queryable<Binary, Mysql> for *const [u8] {
192 type Row = Self;
193
194 fn build(row: Self::Row) -> deserialize::Result<Self> {
195 Ok(row)
196 }
197}