Skip to main content

diesel/mariadb/types/
uuid.rs

1use std::io::prelude::Write;
2
3use crate::deserialize::FromSql;
4use crate::mariadb::Mariadb;
5use crate::serialize::{IsNull, ToSql};
6use crate::sql_types::Uuid;
7
8impl FromSql<Uuid, Mariadb> for uuid::Uuid {
9    fn from_sql(
10        bytes: <Mariadb as crate::backend::Backend>::RawValue<'_>,
11    ) -> crate::deserialize::Result<Self> {
12        let uuid_rfc = core::str::from_utf8(bytes.as_bytes())?;
13        uuid::Uuid::parse_str(uuid_rfc).map_err(Into::into)
14    }
15}
16
17impl ToSql<Uuid, Mariadb> for uuid::Uuid {
18    fn to_sql<'b>(
19        &'b self,
20        out: &mut crate::serialize::Output<'b, '_, Mariadb>,
21    ) -> crate::serialize::Result {
22        out.write_fmt(format_args!("{0}", self))write!(out, "{}", self)
23            .map(|_| IsNull::No)
24            .map_err(Into::into)
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use core::str::FromStr;
31
32    use super::*;
33    use crate::mariadb::MariadbValue;
34    use crate::mysql_like::MysqlType;
35    use crate::serialize::Output;
36    use crate::test_helpers::format_error;
37
38    #[diesel_test_helper::test]
39    fn uuid_to_sql() {
40        use crate::query_builder::bind_collector::ByteWrapper;
41
42        let mut buffer = Vec::new();
43
44        let hyphenated = "ffffffff-ffff-ffff-6162-636465663132";
45
46        let test_uuid = uuid::Uuid::from_str(hyphenated).unwrap();
47        let mut bytes = Output::test(ByteWrapper(&mut buffer));
48        ToSql::<Uuid, Mariadb>::to_sql(&test_uuid, &mut bytes).unwrap();
49        assert_eq!(&buffer, hyphenated.as_bytes());
50    }
51
52    #[diesel_test_helper::test]
53    fn some_uuid_from_sql() {
54        let bytes = [
55            0xFF_u8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
56            0x31, 0x32,
57        ];
58        let input_uuid = uuid::Uuid::from_slice(&bytes).unwrap();
59        let output_uuid =
60            <uuid::Uuid as FromSql<Uuid, Mariadb>>::from_sql(MariadbValue::new_internal(
61                input_uuid.hyphenated().to_string().as_bytes(),
62                MysqlType::String,
63            ))
64            .unwrap();
65        assert_eq!(input_uuid, output_uuid);
66    }
67
68    #[diesel_test_helper::test]
69    fn bad_uuid_from_sql() {
70        let uuid = uuid::Uuid::from_sql(MariadbValue::new_internal(b"boom", MysqlType::String));
71        assert!(uuid.is_err());
72        // The error message changes slightly between different
73        // uuid versions, so we just check on the relevant parts
74        // The exact error messages are either:
75        // "invalid character: found `o` at 1"
76        // or
77        // "invalid length: expected 16 bytes, found 4"
78        let error_message = format_error(&*uuid.unwrap_err());
79        assert!(error_message.starts_with("invalid"));
80        assert!(error_message.contains("character"));
81        assert!(error_message.contains("o"));
82        assert!(error_message.ends_with("at 1"));
83    }
84
85    #[diesel_test_helper::test]
86    fn no_uuid_from_sql() {
87        let uuid = uuid::Uuid::from_nullable_sql(None);
88        assert_eq!(
89            format_error(&*uuid.unwrap_err()),
90            "Unexpected null for non-null column"
91        );
92    }
93}