fastnum/decimal/udec/extras/diesel/
mysql.rs1use core::fmt::{Debug, Display, Write};
2
3use diesel::{
4 deserialize::{self, FromSql},
5 mysql::{Mysql, MysqlType, MysqlValue},
6 serialize::{self, IsNull, Output, ToSql},
7 sql_types::Numeric,
8};
9
10use crate::decimal::{Context, UnsignedDecimal};
11
12impl<const N: usize> ToSql<Numeric, Mysql> for UnsignedDecimal<N>
13where
14 for<'a, 'b> Output<'a, 'b, Mysql>: Write,
15 UnsignedDecimal<N>: Debug + Display,
16{
17 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result {
18 write!(out, "{}", *self)
19 .map(|_| IsNull::No)
20 .map_err(Into::into)
21 }
22}
23
24impl<const N: usize> FromSql<Numeric, Mysql> for UnsignedDecimal<N> {
25 fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
26 let raw = value.as_bytes();
27
28 match value.value_type() {
29 MysqlType::UnsignedTiny => {
30 let i = raw[0];
31 Ok(i.into())
32 }
33 MysqlType::Tiny => {
34 let i = raw[0] as i8;
35 i.try_into()
36 .map_err(|_| format!("{i} is not valid decimal number").into())
37 }
38 MysqlType::UnsignedShort => {
39 let i = u16::from_ne_bytes((&raw[..2]).try_into()?);
40 Ok(i.into())
41 }
42 MysqlType::Short => {
43 let i = i16::from_ne_bytes((&raw[..2]).try_into()?);
44 i.try_into()
45 .map_err(|_| format!("{i} is not valid decimal number").into())
46 }
47 MysqlType::UnsignedLong => {
48 let i = u32::from_ne_bytes((&raw[..4]).try_into()?);
49 Ok(i.into())
50 }
51 MysqlType::Long => {
52 let i = i32::from_ne_bytes((&raw[..4]).try_into()?);
53 i.try_into()
54 .map_err(|_| format!("{i} is not valid decimal number").into())
55 }
56 MysqlType::UnsignedLongLong => {
57 let i = u64::from_ne_bytes(raw.try_into()?);
58 Ok(i.into())
59 }
60 MysqlType::LongLong => {
61 let i = i64::from_ne_bytes(raw.try_into()?);
62 i.try_into()
63 .map_err(|_| format!("{i} is not valid decimal number").into())
64 }
65 MysqlType::Float => {
66 let i = f32::from_ne_bytes(raw.try_into()?);
67 i.try_into()
68 .map_err(|_| format!("{i} is not valid decimal number").into())
69 }
70 MysqlType::Double => {
71 let i = f64::from_ne_bytes(raw.try_into()?);
72 i.try_into()
73 .map_err(|_| format!("{i} is not valid decimal number").into())
74 }
75 MysqlType::Numeric => {
76 let s = core::str::from_utf8(raw)?;
77 UnsignedDecimal::from_str(s, Context::default())
78 .map_err(|_| format!("{s} is not valid decimal number").into())
79 }
80 _ => Err(format!("{value:?} is not valid decimal number").into()),
81 }
82 }
83}