diesel_async/mysql/
serialize.rs

1use diesel::mysql::data_types::MysqlTime;
2use diesel::mysql::MysqlType;
3use diesel::mysql::MysqlValue;
4use diesel::QueryResult;
5use mysql_async::{Params, Value};
6use std::convert::TryInto;
7
8pub(super) struct ToSqlHelper {
9    pub(super) metadata: Vec<MysqlType>,
10    pub(super) binds: Vec<Option<Vec<u8>>>,
11}
12
13fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> QueryResult<Value> {
14    let cast_helper = |e| diesel::result::Error::SerializationError(Box::new(e));
15    let v = match bind {
16        Some(bind) => match metadata {
17            MysqlType::Tiny => Value::Int(i8::from_be_bytes([bind[0]]) as i64),
18            MysqlType::Short => Value::Int(i16::from_ne_bytes(bind.try_into().unwrap()) as _),
19            MysqlType::Long => Value::Int(i32::from_ne_bytes(bind.try_into().unwrap()) as _),
20            MysqlType::LongLong => Value::Int(i64::from_ne_bytes(bind.try_into().unwrap())),
21
22            MysqlType::UnsignedTiny => Value::UInt(bind[0] as _),
23            MysqlType::UnsignedShort => {
24                Value::UInt(u16::from_ne_bytes(bind.try_into().unwrap()) as _)
25            }
26            MysqlType::UnsignedLong => {
27                Value::UInt(u32::from_ne_bytes(bind.try_into().unwrap()) as _)
28            }
29            MysqlType::UnsignedLongLong => {
30                Value::UInt(u64::from_ne_bytes(bind.try_into().unwrap()))
31            }
32            MysqlType::Float => Value::Float(f32::from_ne_bytes(bind.try_into().unwrap())),
33            MysqlType::Double => Value::Double(f64::from_ne_bytes(bind.try_into().unwrap())),
34
35            MysqlType::Time => {
36                let time: MysqlTime = diesel::deserialize::FromSql::<
37                    diesel::sql_types::Time,
38                    diesel::mysql::Mysql,
39                >::from_sql(MysqlValue::new(&bind, metadata))
40                .expect("This does not fail");
41                Value::Time(
42                    time.neg,
43                    time.day,
44                    time.hour.try_into().map_err(cast_helper)?,
45                    time.minute.try_into().map_err(cast_helper)?,
46                    time.second.try_into().map_err(cast_helper)?,
47                    time.second_part.try_into().expect("Cast does not fail"),
48                )
49            }
50            MysqlType::Date | MysqlType::DateTime | MysqlType::Timestamp => {
51                let time: MysqlTime = diesel::deserialize::FromSql::<
52                    diesel::sql_types::Timestamp,
53                    diesel::mysql::Mysql,
54                >::from_sql(MysqlValue::new(&bind, metadata))
55                .expect("This does not fail");
56                Value::Date(
57                    time.year.try_into().map_err(cast_helper)?,
58                    time.month.try_into().map_err(cast_helper)?,
59                    time.day.try_into().map_err(cast_helper)?,
60                    time.hour.try_into().map_err(cast_helper)?,
61                    time.minute.try_into().map_err(cast_helper)?,
62                    time.second.try_into().map_err(cast_helper)?,
63                    time.second_part.try_into().expect("Cast does not fail"),
64                )
65            }
66            MysqlType::Numeric
67            | MysqlType::Set
68            | MysqlType::Enum
69            | MysqlType::String
70            | MysqlType::Blob => Value::Bytes(bind),
71            MysqlType::Bit => unimplemented!(),
72            _ => unreachable!(),
73        },
74        None => Value::NULL,
75    };
76    Ok(v)
77}
78
79impl TryFrom<ToSqlHelper> for Params {
80    type Error = diesel::result::Error;
81
82    fn try_from(ToSqlHelper { metadata, binds }: ToSqlHelper) -> Result<Self, Self::Error> {
83        let values = metadata
84            .into_iter()
85            .zip(binds)
86            .map(to_value)
87            .collect::<Result<Vec<_>, Self::Error>>()?;
88        Ok(Params::Positional(values))
89    }
90}