cdbc_mysql/types/
float.rs

1use byteorder::{ByteOrder, LittleEndian};
2
3use cdbc::decode::Decode;
4use cdbc::encode::{Encode, IsNull};
5use cdbc::error::BoxDynError;
6use crate::protocol::text::ColumnType;
7use crate::{MySql, MySqlTypeInfo, MySqlValueFormat, MySqlValueRef};
8use cdbc::types::Type;
9
10fn real_compatible(ty: &MySqlTypeInfo) -> bool {
11    matches!(ty.r#type, ColumnType::Float | ColumnType::Double)
12}
13
14impl Type<MySql> for f32 {
15    fn type_info() -> MySqlTypeInfo {
16        MySqlTypeInfo::binary(ColumnType::Float)
17    }
18
19    fn compatible(ty: &MySqlTypeInfo) -> bool {
20        real_compatible(ty)
21    }
22}
23
24impl Type<MySql> for f64 {
25    fn type_info() -> MySqlTypeInfo {
26        MySqlTypeInfo::binary(ColumnType::Double)
27    }
28
29    fn compatible(ty: &MySqlTypeInfo) -> bool {
30        real_compatible(ty)
31    }
32}
33
34impl Encode<'_, MySql> for f32 {
35    fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
36        buf.extend(&self.to_le_bytes());
37
38        IsNull::No
39    }
40}
41
42impl Encode<'_, MySql> for f64 {
43    fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
44        buf.extend(&self.to_le_bytes());
45
46        IsNull::No
47    }
48}
49
50impl Decode<'_, MySql> for f32 {
51    fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
52        Ok(match value.format() {
53            MySqlValueFormat::Binary => {
54                let buf = value.as_bytes()?;
55
56                if buf.len() == 8 {
57                    // MySQL can return 8-byte DOUBLE values for a FLOAT
58                    // We take and truncate to f32 as that's the same behavior as *in* MySQL
59                    LittleEndian::read_f64(buf) as f32
60                } else {
61                    LittleEndian::read_f32(buf)
62                }
63            }
64
65            MySqlValueFormat::Text => value.as_str()?.parse()?,
66        })
67    }
68}
69
70impl Decode<'_, MySql> for f64 {
71    fn decode(value: MySqlValueRef<'_>) -> Result<Self, BoxDynError> {
72        Ok(match value.format() {
73            MySqlValueFormat::Binary => LittleEndian::read_f64(value.as_bytes()?),
74            MySqlValueFormat::Text => value.as_str()?.parse()?,
75        })
76    }
77}