Skip to main content

diesel/mysql_like/connection/
url.rs

1extern crate percent_encoding;
2extern crate url;
3
4use self::percent_encoding::percent_decode;
5use self::url::{Host, Url};
6use alloc::ffi::CString;
7use core::ffi::CStr;
8use std::collections::HashMap;
9
10use crate::mysql_like::MysqlLikeBackend;
11use crate::result::{ConnectionError, ConnectionResult};
12
13use mysqlclient_sys::mysql_ssl_mode;
14
15bitflags::bitflags! {
16    #[derive(#[automatically_derived]
impl ::core::clone::Clone for CapabilityFlags {
    #[inline]
    fn clone(&self) -> CapabilityFlags {
        let _:
                ::core::clone::AssertParamIsClone<<CapabilityFlags as
                ::bitflags::__private::PublicFlags>::Internal>;
        *self
    }
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy :: min_ident_chars,
clippy :: assign_op_pattern, clippy :: indexing_slicing, clippy ::
same_name_method, clippy :: iter_without_into_iter,)]
const _: () =
    {
        #[repr(transparent)]
        pub struct InternalBitFlags(u32);
        #[automatically_derived]
        #[doc(hidden)]
        unsafe impl ::core::clone::TrivialClone for InternalBitFlags { }
        #[automatically_derived]
        impl ::core::clone::Clone for InternalBitFlags {
            #[inline]
            fn clone(&self) -> InternalBitFlags {
                let _: ::core::clone::AssertParamIsClone<u32>;
                *self
            }
        }
        #[automatically_derived]
        impl ::core::marker::Copy for InternalBitFlags { }
        #[automatically_derived]
        impl ::core::marker::StructuralPartialEq for InternalBitFlags { }
        #[automatically_derived]
        impl ::core::cmp::PartialEq for InternalBitFlags {
            #[inline]
            fn eq(&self, other: &InternalBitFlags) -> bool {
                self.0 == other.0
            }
        }
        #[automatically_derived]
        impl ::core::cmp::Eq for InternalBitFlags {
            #[inline]
            #[doc(hidden)]
            #[coverage(off)]
            fn assert_fields_are_eq(&self) {
                let _: ::core::cmp::AssertParamIsEq<u32>;
            }
        }
        #[automatically_derived]
        impl ::core::cmp::PartialOrd for InternalBitFlags {
            #[inline]
            fn partial_cmp(&self, other: &InternalBitFlags)
                -> ::core::option::Option<::core::cmp::Ordering> {
                ::core::option::Option::Some(::core::cmp::Ord::cmp(self,
                        other))
            }
        }
        #[automatically_derived]
        impl ::core::cmp::Ord for InternalBitFlags {
            #[inline]
            fn cmp(&self, other: &InternalBitFlags) -> ::core::cmp::Ordering {
                ::core::cmp::Ord::cmp(&self.0, &other.0)
            }
        }
        #[automatically_derived]
        impl ::core::hash::Hash for InternalBitFlags {
            #[inline]
            fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
                ::core::hash::Hash::hash(&self.0, state)
            }
        }
        impl CapabilityFlags {
            pub const CLIENT_LONG_PASSWORD: Self =
                Self::from_bits_retain(0x00000001);
            pub const CLIENT_FOUND_ROWS: Self =
                Self::from_bits_retain(0x00000002);
            pub const CLIENT_LONG_FLAG: Self =
                Self::from_bits_retain(0x00000004);
            pub const CLIENT_CONNECT_WITH_DB: Self =
                Self::from_bits_retain(0x00000008);
            pub const CLIENT_NO_SCHEMA: Self =
                Self::from_bits_retain(0x00000010);
            pub const CLIENT_COMPRESS: Self =
                Self::from_bits_retain(0x00000020);
            pub const CLIENT_ODBC: Self = Self::from_bits_retain(0x00000040);
            pub const CLIENT_LOCAL_FILES: Self =
                Self::from_bits_retain(0x00000080);
            pub const CLIENT_IGNORE_SPACE: Self =
                Self::from_bits_retain(0x00000100);
            pub const CLIENT_PROTOCOL_41: Self =
                Self::from_bits_retain(0x00000200);
            pub const CLIENT_INTERACTIVE: Self =
                Self::from_bits_retain(0x00000400);
            pub const CLIENT_SSL: Self = Self::from_bits_retain(0x00000800);
            pub const CLIENT_IGNORE_SIGPIPE: Self =
                Self::from_bits_retain(0x00001000);
            pub const CLIENT_TRANSACTIONS: Self =
                Self::from_bits_retain(0x00002000);
            pub const CLIENT_RESERVED: Self =
                Self::from_bits_retain(0x00004000);
            pub const CLIENT_SECURE_CONNECTION: Self =
                Self::from_bits_retain(0x00008000);
            pub const CLIENT_MULTI_STATEMENTS: Self =
                Self::from_bits_retain(0x00010000);
            pub const CLIENT_MULTI_RESULTS: Self =
                Self::from_bits_retain(0x00020000);
            pub const CLIENT_PS_MULTI_RESULTS: Self =
                Self::from_bits_retain(0x00040000);
            pub const CLIENT_PLUGIN_AUTH: Self =
                Self::from_bits_retain(0x00080000);
            pub const CLIENT_CONNECT_ATTRS: Self =
                Self::from_bits_retain(0x00100000);
            pub const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: Self =
                Self::from_bits_retain(0x00200000);
            pub const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: Self =
                Self::from_bits_retain(0x00400000);
            pub const CLIENT_SESSION_TRACK: Self =
                Self::from_bits_retain(0x00800000);
            pub const CLIENT_DEPRECATE_EOF: Self =
                Self::from_bits_retain(0x01000000);
        }
        impl ::bitflags::Flags for CapabilityFlags {
            const FLAGS: &'static [::bitflags::Flag<CapabilityFlags>] =
                {
                    mod __bitflags_flag_names {
                        use super::*;
                        pub(super) const CLIENT_LONG_PASSWORD: &'static str =
                            "CLIENT_LONG_PASSWORD";
                        pub(super) const CLIENT_FOUND_ROWS: &'static str =
                            "CLIENT_FOUND_ROWS";
                        pub(super) const CLIENT_LONG_FLAG: &'static str =
                            "CLIENT_LONG_FLAG";
                        pub(super) const CLIENT_CONNECT_WITH_DB: &'static str =
                            "CLIENT_CONNECT_WITH_DB";
                        pub(super) const CLIENT_NO_SCHEMA: &'static str =
                            "CLIENT_NO_SCHEMA";
                        pub(super) const CLIENT_COMPRESS: &'static str =
                            "CLIENT_COMPRESS";
                        pub(super) const CLIENT_ODBC: &'static str = "CLIENT_ODBC";
                        pub(super) const CLIENT_LOCAL_FILES: &'static str =
                            "CLIENT_LOCAL_FILES";
                        pub(super) const CLIENT_IGNORE_SPACE: &'static str =
                            "CLIENT_IGNORE_SPACE";
                        pub(super) const CLIENT_PROTOCOL_41: &'static str =
                            "CLIENT_PROTOCOL_41";
                        pub(super) const CLIENT_INTERACTIVE: &'static str =
                            "CLIENT_INTERACTIVE";
                        pub(super) const CLIENT_SSL: &'static str = "CLIENT_SSL";
                        pub(super) const CLIENT_IGNORE_SIGPIPE: &'static str =
                            "CLIENT_IGNORE_SIGPIPE";
                        pub(super) const CLIENT_TRANSACTIONS: &'static str =
                            "CLIENT_TRANSACTIONS";
                        pub(super) const CLIENT_RESERVED: &'static str =
                            "CLIENT_RESERVED";
                        pub(super) const CLIENT_SECURE_CONNECTION: &'static str =
                            "CLIENT_SECURE_CONNECTION";
                        pub(super) const CLIENT_MULTI_STATEMENTS: &'static str =
                            "CLIENT_MULTI_STATEMENTS";
                        pub(super) const CLIENT_MULTI_RESULTS: &'static str =
                            "CLIENT_MULTI_RESULTS";
                        pub(super) const CLIENT_PS_MULTI_RESULTS: &'static str =
                            "CLIENT_PS_MULTI_RESULTS";
                        pub(super) const CLIENT_PLUGIN_AUTH: &'static str =
                            "CLIENT_PLUGIN_AUTH";
                        pub(super) const CLIENT_CONNECT_ATTRS: &'static str =
                            "CLIENT_CONNECT_ATTRS";
                        pub(super) const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA:
                            &'static str =
                            "CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA";
                        pub(super) const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS:
                            &'static str =
                            "CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS";
                        pub(super) const CLIENT_SESSION_TRACK: &'static str =
                            "CLIENT_SESSION_TRACK";
                        pub(super) const CLIENT_DEPRECATE_EOF: &'static str =
                            "CLIENT_DEPRECATE_EOF";
                    }
                    &[{
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_LONG_PASSWORD,
                                        CapabilityFlags::CLIENT_LONG_PASSWORD)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_FOUND_ROWS,
                                        CapabilityFlags::CLIENT_FOUND_ROWS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_LONG_FLAG,
                                        CapabilityFlags::CLIENT_LONG_FLAG)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_CONNECT_WITH_DB,
                                        CapabilityFlags::CLIENT_CONNECT_WITH_DB)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_NO_SCHEMA,
                                        CapabilityFlags::CLIENT_NO_SCHEMA)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_COMPRESS,
                                        CapabilityFlags::CLIENT_COMPRESS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_ODBC,
                                        CapabilityFlags::CLIENT_ODBC)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_LOCAL_FILES,
                                        CapabilityFlags::CLIENT_LOCAL_FILES)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_IGNORE_SPACE,
                                        CapabilityFlags::CLIENT_IGNORE_SPACE)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_PROTOCOL_41,
                                        CapabilityFlags::CLIENT_PROTOCOL_41)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_INTERACTIVE,
                                        CapabilityFlags::CLIENT_INTERACTIVE)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_SSL,
                                        CapabilityFlags::CLIENT_SSL)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_IGNORE_SIGPIPE,
                                        CapabilityFlags::CLIENT_IGNORE_SIGPIPE)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_TRANSACTIONS,
                                        CapabilityFlags::CLIENT_TRANSACTIONS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_RESERVED,
                                        CapabilityFlags::CLIENT_RESERVED)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_SECURE_CONNECTION,
                                        CapabilityFlags::CLIENT_SECURE_CONNECTION)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_MULTI_STATEMENTS,
                                        CapabilityFlags::CLIENT_MULTI_STATEMENTS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_MULTI_RESULTS,
                                        CapabilityFlags::CLIENT_MULTI_RESULTS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_PS_MULTI_RESULTS,
                                        CapabilityFlags::CLIENT_PS_MULTI_RESULTS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_PLUGIN_AUTH,
                                        CapabilityFlags::CLIENT_PLUGIN_AUTH)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_CONNECT_ATTRS,
                                        CapabilityFlags::CLIENT_CONNECT_ATTRS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA,
                                        CapabilityFlags::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS,
                                        CapabilityFlags::CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_SESSION_TRACK,
                                        CapabilityFlags::CLIENT_SESSION_TRACK)
                                },
                                {
                                    ::bitflags::Flag::new(__bitflags_flag_names::CLIENT_DEPRECATE_EOF,
                                        CapabilityFlags::CLIENT_DEPRECATE_EOF)
                                }]
                };
            type Bits = u32;
            fn bits(&self) -> u32 { CapabilityFlags::bits(self) }
            fn from_bits_retain(bits: u32) -> CapabilityFlags {
                CapabilityFlags::from_bits_retain(bits)
            }
            fn all_named() -> CapabilityFlags {
                const ALL_NAMED: u32 =
                    {
                        let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
                        let mut i = 0;
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        {
                            {
                                let flag =
                                    &<CapabilityFlags as ::bitflags::Flags>::FLAGS[i];
                                if flag.is_named() {
                                    truncated = truncated | flag.value().bits();
                                }
                                i += 1;
                            }
                        };
                        let _ = i;
                        truncated
                    };
                CapabilityFlags::from_bits_retain(ALL_NAMED)
            }
        }
        impl ::bitflags::__private::PublicFlags for CapabilityFlags {
            type Primitive = u32;
            type Internal = InternalBitFlags;
        }
        impl ::bitflags::__private::core::default::Default for
            InternalBitFlags {
            #[inline]
            fn default() -> Self { InternalBitFlags::empty() }
        }
        impl ::bitflags::__private::core::fmt::Debug for InternalBitFlags {
            fn fmt(&self,
                f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
                -> ::bitflags::__private::core::fmt::Result {
                if self.is_empty() {
                    f.write_fmt(format_args!("{0:#x}",
                            <u32 as ::bitflags::Bits>::EMPTY))
                } else {
                    ::bitflags::__private::core::fmt::Display::fmt(self, f)
                }
            }
        }
        impl ::bitflags::__private::core::fmt::Display for InternalBitFlags {
            fn fmt(&self,
                f: &mut ::bitflags::__private::core::fmt::Formatter<'_>)
                -> ::bitflags::__private::core::fmt::Result {
                ::bitflags::parser::to_writer(&CapabilityFlags(*self), f)
            }
        }
        impl ::bitflags::__private::core::str::FromStr for InternalBitFlags {
            type Err = ::bitflags::parser::ParseError;
            fn from_str(s: &str)
                ->
                    ::bitflags::__private::core::result::Result<Self,
                    Self::Err> {
                ::bitflags::parser::from_str::<CapabilityFlags>(s).map(|flags|
                        flags.0)
            }
        }
        impl ::bitflags::__private::core::convert::AsRef<u32> for
            InternalBitFlags {
            fn as_ref(&self) -> &u32 { &self.0 }
        }
        impl ::bitflags::__private::core::convert::From<u32> for
            InternalBitFlags {
            fn from(bits: u32) -> Self { Self::from_bits_retain(bits) }
        }
        impl InternalBitFlags {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u32 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self {
                const ALL: InternalBitFlags =
                    {
                        let mut truncated = <u32 as ::bitflags::Bits>::EMPTY;
                        let mut _i = 0;
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        {
                            {
                                truncated |=
                                    <CapabilityFlags as
                                                    ::bitflags::Flags>::FLAGS[_i].value().bits();
                                _i += 1;
                            }
                        };
                        InternalBitFlags(truncated)
                    };
                ALL
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u32 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[inline]
            pub const fn from_bits(bits: u32)
                -> ::bitflags::__private::core::option::Option<Self> {
                let truncated = Self::from_bits_truncate(bits).0;
                if truncated == bits {
                    ::bitflags::__private::core::option::Option::Some(Self(bits))
                } else { ::bitflags::__private::core::option::Option::None }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u32) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u32) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[inline]
            pub fn from_name(name: &str)
                -> ::bitflags::__private::core::option::Option<Self> {
                mod __bitflags_flag_names {
                    use super::*;
                    pub(super) const CLIENT_LONG_PASSWORD: &'static str =
                        "CLIENT_LONG_PASSWORD";
                    pub(super) const CLIENT_FOUND_ROWS: &'static str =
                        "CLIENT_FOUND_ROWS";
                    pub(super) const CLIENT_LONG_FLAG: &'static str =
                        "CLIENT_LONG_FLAG";
                    pub(super) const CLIENT_CONNECT_WITH_DB: &'static str =
                        "CLIENT_CONNECT_WITH_DB";
                    pub(super) const CLIENT_NO_SCHEMA: &'static str =
                        "CLIENT_NO_SCHEMA";
                    pub(super) const CLIENT_COMPRESS: &'static str =
                        "CLIENT_COMPRESS";
                    pub(super) const CLIENT_ODBC: &'static str = "CLIENT_ODBC";
                    pub(super) const CLIENT_LOCAL_FILES: &'static str =
                        "CLIENT_LOCAL_FILES";
                    pub(super) const CLIENT_IGNORE_SPACE: &'static str =
                        "CLIENT_IGNORE_SPACE";
                    pub(super) const CLIENT_PROTOCOL_41: &'static str =
                        "CLIENT_PROTOCOL_41";
                    pub(super) const CLIENT_INTERACTIVE: &'static str =
                        "CLIENT_INTERACTIVE";
                    pub(super) const CLIENT_SSL: &'static str = "CLIENT_SSL";
                    pub(super) const CLIENT_IGNORE_SIGPIPE: &'static str =
                        "CLIENT_IGNORE_SIGPIPE";
                    pub(super) const CLIENT_TRANSACTIONS: &'static str =
                        "CLIENT_TRANSACTIONS";
                    pub(super) const CLIENT_RESERVED: &'static str =
                        "CLIENT_RESERVED";
                    pub(super) const CLIENT_SECURE_CONNECTION: &'static str =
                        "CLIENT_SECURE_CONNECTION";
                    pub(super) const CLIENT_MULTI_STATEMENTS: &'static str =
                        "CLIENT_MULTI_STATEMENTS";
                    pub(super) const CLIENT_MULTI_RESULTS: &'static str =
                        "CLIENT_MULTI_RESULTS";
                    pub(super) const CLIENT_PS_MULTI_RESULTS: &'static str =
                        "CLIENT_PS_MULTI_RESULTS";
                    pub(super) const CLIENT_PLUGIN_AUTH: &'static str =
                        "CLIENT_PLUGIN_AUTH";
                    pub(super) const CLIENT_CONNECT_ATTRS: &'static str =
                        "CLIENT_CONNECT_ATTRS";
                    pub(super) const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA:
                        &'static str =
                        "CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA";
                    pub(super) const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS:
                        &'static str =
                        "CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS";
                    pub(super) const CLIENT_SESSION_TRACK: &'static str =
                        "CLIENT_SESSION_TRACK";
                    pub(super) const CLIENT_DEPRECATE_EOF: &'static str =
                        "CLIENT_DEPRECATE_EOF";
                }
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_LONG_PASSWORD {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_LONG_PASSWORD.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_FOUND_ROWS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_FOUND_ROWS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_LONG_FLAG {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_LONG_FLAG.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_CONNECT_WITH_DB {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_CONNECT_WITH_DB.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_NO_SCHEMA {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_NO_SCHEMA.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_COMPRESS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_COMPRESS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_ODBC {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_ODBC.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_LOCAL_FILES {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_LOCAL_FILES.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_IGNORE_SPACE {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_IGNORE_SPACE.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_PROTOCOL_41 {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_PROTOCOL_41.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_INTERACTIVE {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_INTERACTIVE.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_SSL {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_SSL.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_IGNORE_SIGPIPE {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_IGNORE_SIGPIPE.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_TRANSACTIONS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_TRANSACTIONS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_RESERVED {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_RESERVED.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_SECURE_CONNECTION {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_SECURE_CONNECTION.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_MULTI_STATEMENTS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_MULTI_STATEMENTS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_MULTI_RESULTS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_MULTI_RESULTS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_PS_MULTI_RESULTS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_PS_MULTI_RESULTS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_PLUGIN_AUTH {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_PLUGIN_AUTH.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_CONNECT_ATTRS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_CONNECT_ATTRS.bits()));
                        }
                    };
                };
                {
                    {
                        if name ==
                                __bitflags_flag_names::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
                            {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA.bits()));
                        }
                    };
                };
                {
                    {
                        if name ==
                                __bitflags_flag_names::CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_SESSION_TRACK {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_SESSION_TRACK.bits()));
                        }
                    };
                };
                {
                    {
                        if name == __bitflags_flag_names::CLIENT_DEPRECATE_EOF {
                            return ::bitflags::__private::core::option::Option::Some(Self(CapabilityFlags::CLIENT_DEPRECATE_EOF.bits()));
                        }
                    };
                };
                let _ = name;
                ::bitflags::__private::core::option::Option::None
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u32 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u32 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            #[must_use]
            pub const fn complement(self) -> Self {
                Self::from_bits_truncate(!self.0)
            }
        }
        impl ::bitflags::__private::core::fmt::Binary for InternalBitFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::Octal for InternalBitFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::LowerHex for InternalBitFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::UpperHex for InternalBitFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::ops::BitOr for InternalBitFlags {
            type Output = Self;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: InternalBitFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for InternalBitFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            InternalBitFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for InternalBitFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            InternalBitFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand_assign(&mut self, other: Self) {
                *self =
                    Self::from_bits_retain(self.bits()).intersection(other);
            }
        }
        impl ::bitflags::__private::core::ops::Sub for InternalBitFlags {
            type Output = Self;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for InternalBitFlags
            {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for InternalBitFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<InternalBitFlags> for
            InternalBitFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(&mut self, iterator: T) {
                for item in iterator { self.insert(item) }
            }
        }
        impl ::bitflags::__private::core::iter::FromIterator<InternalBitFlags>
            for InternalBitFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(iterator: T) -> Self {
                use ::bitflags::__private::core::iter::Extend;
                let mut result = Self::empty();
                result.extend(iterator);
                result
            }
        }
        impl InternalBitFlags {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[inline]
            pub const fn iter(&self)
                -> ::bitflags::iter::Iter<CapabilityFlags> {
                ::bitflags::iter::Iter::__private_const_new(<CapabilityFlags
                        as ::bitflags::Flags>::FLAGS,
                    CapabilityFlags::from_bits_retain(self.bits()),
                    CapabilityFlags::from_bits_retain(self.bits()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[inline]
            pub const fn iter_names(&self)
                -> ::bitflags::iter::IterNames<CapabilityFlags> {
                ::bitflags::iter::IterNames::__private_const_new(<CapabilityFlags
                        as ::bitflags::Flags>::FLAGS,
                    CapabilityFlags::from_bits_retain(self.bits()),
                    CapabilityFlags::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for
            InternalBitFlags {
            type Item = CapabilityFlags;
            type IntoIter = ::bitflags::iter::Iter<CapabilityFlags>;
            fn into_iter(self) -> Self::IntoIter { self.iter() }
        }
        impl InternalBitFlags {
            /// Returns a mutable reference to the raw value of the flags currently stored.
            #[inline]
            pub fn bits_mut(&mut self) -> &mut u32 { &mut self.0 }
        }
        impl CapabilityFlags {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self { Self(InternalBitFlags::empty()) }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self { Self(InternalBitFlags::all()) }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u32 { self.0.bits() }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[inline]
            pub const fn from_bits(bits: u32)
                -> ::bitflags::__private::core::option::Option<Self> {
                match InternalBitFlags::from_bits(bits) {
                    ::bitflags::__private::core::option::Option::Some(bits) =>
                        ::bitflags::__private::core::option::Option::Some(Self(bits)),
                    ::bitflags::__private::core::option::Option::None =>
                        ::bitflags::__private::core::option::Option::None,
                }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u32) -> Self {
                Self(InternalBitFlags::from_bits_truncate(bits))
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u32) -> Self {
                Self(InternalBitFlags::from_bits_retain(bits))
            }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[inline]
            pub fn from_name(name: &str)
                -> ::bitflags::__private::core::option::Option<Self> {
                match InternalBitFlags::from_name(name) {
                    ::bitflags::__private::core::option::Option::Some(bits) =>
                        ::bitflags::__private::core::option::Option::Some(Self(bits)),
                    ::bitflags::__private::core::option::Option::None =>
                        ::bitflags::__private::core::option::Option::None,
                }
            }
            /// Whether all bits in `self` are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool { self.0.is_empty() }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool { self.0.is_all() }
            /// Whether any set bits in `other` are also set in `self`.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0.intersects(other.0)
            }
            /// Whether all set bits in `other` are also set in `self`.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0.contains(other.0)
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            pub fn insert(&mut self, other: Self) { self.0.insert(other.0) }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) { self.0.remove(other.0) }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            pub fn toggle(&mut self, other: Self) { self.0.toggle(other.0) }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                self.0.set(other.0, value)
            }
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0.intersection(other.0))
            }
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0.union(other.0))
            }
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0.difference(other.0))
            }
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0.symmetric_difference(other.0))
            }
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            #[must_use]
            pub const fn complement(self) -> Self {
                Self(self.0.complement())
            }
        }
        impl ::bitflags::__private::core::fmt::Binary for CapabilityFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::Octal for CapabilityFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::LowerHex for CapabilityFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::UpperHex for CapabilityFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::ops::BitOr for CapabilityFlags {
            type Output = Self;
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor(self, other: CapabilityFlags) -> Self {
                self.union(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for CapabilityFlags
            {
            /// The bitwise or (`|`) of the bits in `self` and `other`.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for CapabilityFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for
            CapabilityFlags {
            /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for CapabilityFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for
            CapabilityFlags {
            /// The bitwise and (`&`) of the bits in `self` and `other`.
            #[inline]
            fn bitand_assign(&mut self, other: Self) {
                *self =
                    Self::from_bits_retain(self.bits()).intersection(other);
            }
        }
        impl ::bitflags::__private::core::ops::Sub for CapabilityFlags {
            type Output = Self;
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for CapabilityFlags {
            /// The intersection of `self` with the complement of `other` (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for CapabilityFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in `self`, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<CapabilityFlags> for
            CapabilityFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(&mut self, iterator: T) {
                for item in iterator { self.insert(item) }
            }
        }
        impl ::bitflags::__private::core::iter::FromIterator<CapabilityFlags>
            for CapabilityFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(iterator: T) -> Self {
                use ::bitflags::__private::core::iter::Extend;
                let mut result = Self::empty();
                result.extend(iterator);
                result
            }
        }
        impl CapabilityFlags {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[inline]
            pub const fn iter(&self)
                -> ::bitflags::iter::Iter<CapabilityFlags> {
                ::bitflags::iter::Iter::__private_const_new(<CapabilityFlags
                        as ::bitflags::Flags>::FLAGS,
                    CapabilityFlags::from_bits_retain(self.bits()),
                    CapabilityFlags::from_bits_retain(self.bits()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[inline]
            pub const fn iter_names(&self)
                -> ::bitflags::iter::IterNames<CapabilityFlags> {
                ::bitflags::iter::IterNames::__private_const_new(<CapabilityFlags
                        as ::bitflags::Flags>::FLAGS,
                    CapabilityFlags::from_bits_retain(self.bits()),
                    CapabilityFlags::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for
            CapabilityFlags {
            type Item = CapabilityFlags;
            type IntoIter = ::bitflags::iter::Iter<CapabilityFlags>;
            fn into_iter(self) -> Self::IntoIter { self.iter() }
        }
    };Clone, #[automatically_derived]
impl ::core::marker::Copy for CapabilityFlags { }Copy)]
17    pub struct CapabilityFlags: u32 {
18        const CLIENT_LONG_PASSWORD = 0x00000001;
19        const CLIENT_FOUND_ROWS = 0x00000002;
20        const CLIENT_LONG_FLAG = 0x00000004;
21        const CLIENT_CONNECT_WITH_DB = 0x00000008;
22        const CLIENT_NO_SCHEMA = 0x00000010;
23        const CLIENT_COMPRESS = 0x00000020;
24        const CLIENT_ODBC = 0x00000040;
25        const CLIENT_LOCAL_FILES = 0x00000080;
26        const CLIENT_IGNORE_SPACE = 0x00000100;
27        const CLIENT_PROTOCOL_41 = 0x00000200;
28        const CLIENT_INTERACTIVE = 0x00000400;
29        const CLIENT_SSL = 0x00000800;
30        const CLIENT_IGNORE_SIGPIPE = 0x00001000;
31        const CLIENT_TRANSACTIONS = 0x00002000;
32        const CLIENT_RESERVED = 0x00004000;
33        const CLIENT_SECURE_CONNECTION = 0x00008000;
34        const CLIENT_MULTI_STATEMENTS = 0x00010000;
35        const CLIENT_MULTI_RESULTS = 0x00020000;
36        const CLIENT_PS_MULTI_RESULTS = 0x00040000;
37        const CLIENT_PLUGIN_AUTH = 0x00080000;
38        const CLIENT_CONNECT_ATTRS = 0x00100000;
39        const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000;
40        const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS = 0x00400000;
41        const CLIENT_SESSION_TRACK = 0x00800000;
42        const CLIENT_DEPRECATE_EOF = 0x01000000;
43    }
44}
45
46pub(super) struct ConnectionOptions {
47    host: Option<CString>,
48    user: CString,
49    password: Option<CString>,
50    database: Option<CString>,
51    port: Option<u16>,
52    unix_socket: Option<CString>,
53    client_flags: CapabilityFlags,
54    ssl_mode: Option<mysql_ssl_mode>,
55    ssl_ca: Option<CString>,
56    ssl_cert: Option<CString>,
57    ssl_key: Option<CString>,
58    local_infile: Option<bool>,
59}
60
61impl ConnectionOptions {
62    pub(super) fn parse<DB: MysqlLikeBackend>(database_url: &str) -> ConnectionResult<Self> {
63        let url = match Url::parse(database_url) {
64            Ok(url) => url,
65            Err(_) => return Err(connection_url_error()),
66        };
67
68        if url.scheme() != DB::SCHEME {
69            return Err(connection_url_error());
70        }
71
72        if url.path_segments().map(Iterator::count).unwrap_or(0) > 1 {
73            return Err(connection_url_error());
74        }
75
76        let query_pairs = url.query_pairs().into_owned().collect::<HashMap<_, _>>();
77        if query_pairs.contains_key("database") {
78            return Err(connection_url_error());
79        }
80
81        let unix_socket = match query_pairs.get("unix_socket") {
82            Some(v) => Some(CString::new(v.as_bytes())?),
83            _ => None,
84        };
85
86        let ssl_ca = match query_pairs.get("ssl_ca") {
87            Some(v) => Some(CString::new(v.as_bytes())?),
88            _ => None,
89        };
90
91        let ssl_cert = match query_pairs.get("ssl_cert") {
92            Some(v) => Some(CString::new(v.as_bytes())?),
93            _ => None,
94        };
95
96        let ssl_key = match query_pairs.get("ssl_key") {
97            Some(v) => Some(CString::new(v.as_bytes())?),
98            _ => None,
99        };
100
101        let ssl_mode = match query_pairs.get("ssl_mode") {
102            Some(v) => {
103                let ssl_mode = match v.to_lowercase().as_str() {
104                    "disabled" => mysql_ssl_mode::SSL_MODE_DISABLED,
105                    "preferred" => mysql_ssl_mode::SSL_MODE_PREFERRED,
106                    "required" => mysql_ssl_mode::SSL_MODE_REQUIRED,
107                    "verify_ca" => mysql_ssl_mode::SSL_MODE_VERIFY_CA,
108                    "verify_identity" => mysql_ssl_mode::SSL_MODE_VERIFY_IDENTITY,
109                    _ => {
110                        let msg = "unknown ssl_mode";
111                        return Err(ConnectionError::InvalidConnectionUrl(msg.into()));
112                    }
113                };
114                Some(ssl_mode)
115            }
116            _ => None,
117        };
118
119        let local_infile = match query_pairs.get("local_infile") {
120            Some(v) => match v.parse() {
121                Ok(v) => Some(v),
122                Err(_) => {
123                    let msg = "unknown local_infile";
124                    return Err(ConnectionError::InvalidConnectionUrl(msg.into()));
125                }
126            },
127            None => None,
128        };
129
130        let host = match url.host() {
131            Some(Host::Ipv6(host)) => Some(CString::new(host.to_string())?),
132            Some(host) if host.to_string() == "localhost" && unix_socket.is_some() => None,
133            Some(host) => Some(CString::new(host.to_string())?),
134            None => None,
135        };
136        let user = decode_into_cstring(url.username())?;
137        let password = match url.password() {
138            Some(password) => Some(decode_into_cstring(password)?),
139            None => None,
140        };
141
142        let database = match url.path_segments().and_then(|mut iter| iter.next()) {
143            Some("") | None => None,
144            Some(segment) => Some(CString::new(segment.as_bytes())?),
145        };
146
147        // this is not present in the database_url, using a default value
148        let client_flags = CapabilityFlags::CLIENT_FOUND_ROWS;
149
150        Ok(ConnectionOptions {
151            host,
152            user,
153            password,
154            database,
155            port: url.port(),
156            client_flags,
157            ssl_mode,
158            unix_socket,
159            ssl_ca,
160            ssl_cert,
161            ssl_key,
162            local_infile,
163        })
164    }
165
166    pub(super) fn host(&self) -> Option<&CStr> {
167        self.host.as_deref()
168    }
169
170    pub(super) fn user(&self) -> &CStr {
171        &self.user
172    }
173
174    pub(super) fn password(&self) -> Option<&CStr> {
175        self.password.as_deref()
176    }
177
178    pub(super) fn database(&self) -> Option<&CStr> {
179        self.database.as_deref()
180    }
181
182    pub(super) fn port(&self) -> Option<u16> {
183        self.port
184    }
185
186    pub(super) fn unix_socket(&self) -> Option<&CStr> {
187        self.unix_socket.as_deref()
188    }
189
190    pub(super) fn ssl_ca(&self) -> Option<&CStr> {
191        self.ssl_ca.as_deref()
192    }
193
194    pub(super) fn ssl_cert(&self) -> Option<&CStr> {
195        self.ssl_cert.as_deref()
196    }
197
198    pub(super) fn ssl_key(&self) -> Option<&CStr> {
199        self.ssl_key.as_deref()
200    }
201
202    pub(super) fn client_flags(&self) -> CapabilityFlags {
203        self.client_flags
204    }
205
206    pub(super) fn ssl_mode(&self) -> Option<mysql_ssl_mode> {
207        self.ssl_mode
208    }
209
210    pub(super) fn local_infile(&self) -> Option<bool> {
211        self.local_infile
212    }
213}
214
215fn decode_into_cstring(s: &str) -> ConnectionResult<CString> {
216    let decoded = percent_decode(s.as_bytes())
217        .decode_utf8()
218        .map_err(|_| connection_url_error())?;
219    CString::new(decoded.as_bytes()).map_err(Into::into)
220}
221
222fn connection_url_error() -> ConnectionError {
223    let msg = "MySQL connection URLs must be in the form \
224               `mysql://[[user]:[password]@]host[:port][/database][?unix_socket=socket-path]`";
225    ConnectionError::InvalidConnectionUrl(msg.into())
226}
227
228#[cfg(all(test, any(feature = "mysql", feature = "mariadb")))]
229mod tests {
230    use super::*;
231
232    #[cfg(feature = "mysql")]
233    type DB = crate::mysql::Mysql;
234    #[cfg(feature = "mariadb")]
235    type DB = crate::mariadb::Mariadb;
236
237    const SCHEME: &str = DB::SCHEME;
238
239    #[cfg(feature = "mysql")]
240    #[diesel_test_helper::test]
241    fn urls_with_schemes_other_than_mysql_are_errors() {
242        assert!(ConnectionOptions::parse::<DB>("postgres://localhost").is_err());
243        assert!(ConnectionOptions::parse::<DB>("http://localhost").is_err());
244        assert!(ConnectionOptions::parse::<DB>("file:///tmp/mysql.sock").is_err());
245        assert!(ConnectionOptions::parse::<DB>("socket:///tmp/mysql.sock").is_err());
246        assert!(ConnectionOptions::parse::<DB>("mariadb://localhost").is_err());
247        assert!(ConnectionOptions::parse::<DB>("mysql://localhost?database=somedb").is_err());
248        assert!(ConnectionOptions::parse::<DB>("mysql://localhost").is_ok());
249    }
250
251    #[cfg(feature = "mariadb")]
252    #[diesel_test_helper::test]
253    fn urls_with_schemes_other_than_mariadb_are_errors() {
254        assert!(ConnectionOptions::parse::<DB>("postgres://localhost").is_err());
255        assert!(ConnectionOptions::parse::<DB>("http://localhost").is_err());
256        assert!(ConnectionOptions::parse::<DB>("file:///tmp/mysql.sock").is_err());
257        assert!(ConnectionOptions::parse::<DB>("socket:///tmp/mysql.sock").is_err());
258        assert!(ConnectionOptions::parse::<DB>("mysql://localhost").is_err());
259        assert!(ConnectionOptions::parse::<DB>("mariadb://localhost?database=somedb").is_err());
260        assert!(ConnectionOptions::parse::<DB>("mariadb://localhost").is_ok());
261    }
262
263    #[diesel_test_helper::test]
264    fn urls_must_have_zero_or_one_path_segments() {
265        assert!(ConnectionOptions::parse::<DB>(&format!("{SCHEME}://localhost/foo/bar")).is_err());
266        assert!(ConnectionOptions::parse::<DB>(&format!("{SCHEME}://localhost/foo")).is_ok());
267    }
268
269    #[diesel_test_helper::test]
270    fn first_path_segment_is_treated_as_database() {
271        let foo_cstr = CString::new("foo").unwrap();
272        let bar_cstr = CString::new("bar").unwrap();
273        assert_eq!(
274            Some(&*foo_cstr),
275            ConnectionOptions::parse::<DB>(&format!("{SCHEME}://localhost/foo"))
276                .unwrap()
277                .database()
278        );
279        assert_eq!(
280            Some(&*bar_cstr),
281            ConnectionOptions::parse::<DB>(&format!("{SCHEME}://localhost/bar"))
282                .unwrap()
283                .database()
284        );
285        assert_eq!(
286            None,
287            ConnectionOptions::parse::<DB>(&format!("{SCHEME}://localhost"))
288                .unwrap()
289                .database()
290        );
291    }
292
293    #[diesel_test_helper::test]
294    fn userinfo_should_be_percent_decode() {
295        use self::percent_encoding::{AsciiSet, CONTROLS, utf8_percent_encode};
296        const USERINFO_ENCODE_SET: &AsciiSet = &CONTROLS
297            .add(b' ')
298            .add(b'"')
299            .add(b'<')
300            .add(b'>')
301            .add(b'`')
302            .add(b'#')
303            .add(b'?')
304            .add(b'{')
305            .add(b'}')
306            .add(b'/')
307            .add(b':')
308            .add(b';')
309            .add(b'=')
310            .add(b'@')
311            .add(b'[')
312            .add(b'\\')
313            .add(b']')
314            .add(b'^')
315            .add(b'|');
316
317        let username = "x#gfuL?4Zuj{n73m}eeJt0";
318        let encoded_username = utf8_percent_encode(username, USERINFO_ENCODE_SET);
319
320        let password = "x/gfuL?4Zuj{n73m}eeJt1";
321        let encoded_password = utf8_percent_encode(password, USERINFO_ENCODE_SET);
322
323        let db_url = format!("{SCHEME}://{encoded_username}:{encoded_password}@localhost/bar",);
324        let db_url = Url::parse(&db_url).unwrap();
325
326        let conn_opts = ConnectionOptions::parse::<DB>(db_url.as_str()).unwrap();
327        let username = CString::new(username.as_bytes()).unwrap();
328        let password = CString::new(password.as_bytes()).unwrap();
329        assert_eq!(username, conn_opts.user);
330        assert_eq!(password, conn_opts.password.unwrap());
331    }
332
333    #[diesel_test_helper::test]
334    fn ipv6_host_not_wrapped_in_brackets() {
335        let host1 = CString::new("::1").unwrap();
336        let host2 = CString::new("2001:db8:85a3::8a2e:370:7334").unwrap();
337
338        assert_eq!(
339            Some(&*host1),
340            ConnectionOptions::parse::<DB>(&format!("{SCHEME}://[::1]"))
341                .unwrap()
342                .host()
343        );
344        assert_eq!(
345            Some(&*host2),
346            ConnectionOptions::parse::<DB>(&format!("{SCHEME}://[2001:db8:85a3::8a2e:370:7334]"))
347                .unwrap()
348                .host()
349        );
350    }
351
352    #[diesel_test_helper::test]
353    fn unix_socket_tests() {
354        let unix_socket = "/var/run/mysqld.sock";
355        let username = "foo";
356        let password = "bar";
357        let db_url =
358            format!("{SCHEME}://{username}:{password}@localhost?unix_socket={unix_socket}",);
359        let conn_opts = ConnectionOptions::parse::<DB>(db_url.as_str()).unwrap();
360        let cstring = |s| CString::new(s).unwrap();
361        assert_eq!(None, conn_opts.host);
362        assert_eq!(None, conn_opts.port);
363        assert_eq!(cstring(username), conn_opts.user);
364        assert_eq!(cstring(password), conn_opts.password.unwrap());
365        assert_eq!(
366            CString::new(unix_socket).unwrap(),
367            conn_opts.unix_socket.unwrap()
368        );
369    }
370
371    #[diesel_test_helper::test]
372    #[cfg(feature = "mysql")]
373    fn ssl_ca_tests() {
374        let ssl_ca = "/etc/ssl/certs/ca-certificates.crt";
375        let username = "foo";
376        let password = "bar";
377        let db_url = format!("mysql://{username}:{password}@localhost?ssl_ca={ssl_ca}",);
378        let conn_opts = ConnectionOptions::parse::<DB>(db_url.as_str()).unwrap();
379        let cstring = |s| CString::new(s).unwrap();
380        assert_eq!(Some(cstring("localhost")), conn_opts.host);
381        assert_eq!(None, conn_opts.port);
382        assert_eq!(cstring(username), conn_opts.user);
383        assert_eq!(cstring(password), conn_opts.password.unwrap());
384        assert_eq!(CString::new(ssl_ca).unwrap(), conn_opts.ssl_ca.unwrap());
385
386        let url_with_unix_str_and_ssl_ca = format!(
387            "mysql://{username}:{password}@localhost?unix_socket=/var/run/mysqld.sock&ssl_ca={ssl_ca}"
388        );
389
390        let conn_opts2 =
391            ConnectionOptions::parse::<DB>(url_with_unix_str_and_ssl_ca.as_str()).unwrap();
392        assert_eq!(None, conn_opts2.host);
393        assert_eq!(None, conn_opts2.port);
394        assert_eq!(CString::new(ssl_ca).unwrap(), conn_opts2.ssl_ca.unwrap());
395    }
396
397    #[diesel_test_helper::test]
398    #[cfg(feature = "mysql")]
399    fn ssl_cert_tests() {
400        let ssl_cert = "/etc/ssl/certs/client-cert.crt";
401        let username = "foo";
402        let password = "bar";
403        let db_url = format!("mysql://{username}:{password}@localhost?ssl_cert={ssl_cert}");
404        let conn_opts = ConnectionOptions::parse::<DB>(db_url.as_str()).unwrap();
405        let cstring = |s| CString::new(s).unwrap();
406        assert_eq!(Some(cstring("localhost")), conn_opts.host);
407        assert_eq!(None, conn_opts.port);
408        assert_eq!(cstring(username), conn_opts.user);
409        assert_eq!(cstring(password), conn_opts.password.unwrap());
410        assert_eq!(CString::new(ssl_cert).unwrap(), conn_opts.ssl_cert.unwrap());
411
412        let url_with_unix_str_and_ssl_cert = format!(
413            "mysql://{username}:{password}@localhost?unix_socket=/var/run/mysqld.sock&ssl_cert={ssl_cert}"
414        );
415
416        let conn_opts2 =
417            ConnectionOptions::parse::<DB>(url_with_unix_str_and_ssl_cert.as_str()).unwrap();
418        assert_eq!(None, conn_opts2.host);
419        assert_eq!(None, conn_opts2.port);
420        assert_eq!(
421            CString::new(ssl_cert).unwrap(),
422            conn_opts2.ssl_cert.unwrap()
423        );
424    }
425
426    #[diesel_test_helper::test]
427    #[cfg(feature = "mysql")]
428    fn ssl_key_tests() {
429        let ssl_key = "/etc/ssl/certs/client-key.crt";
430        let username = "foo";
431        let password = "bar";
432        let db_url = format!("mysql://{username}:{password}@localhost?ssl_key={ssl_key}");
433        let conn_opts = ConnectionOptions::parse::<DB>(db_url.as_str()).unwrap();
434        let cstring = |s| CString::new(s).unwrap();
435        assert_eq!(Some(cstring("localhost")), conn_opts.host);
436        assert_eq!(None, conn_opts.port);
437        assert_eq!(cstring(username), conn_opts.user);
438        assert_eq!(cstring(password), conn_opts.password.unwrap());
439        assert_eq!(CString::new(ssl_key).unwrap(), conn_opts.ssl_key.unwrap());
440
441        let url_with_unix_str_and_ssl_key = format!(
442            "mysql://{username}:{password}@localhost?unix_socket=/var/run/mysqld.sock&ssl_key={ssl_key}"
443        );
444
445        let conn_opts2 =
446            ConnectionOptions::parse::<DB>(url_with_unix_str_and_ssl_key.as_str()).unwrap();
447        assert_eq!(None, conn_opts2.host);
448        assert_eq!(None, conn_opts2.port);
449        assert_eq!(CString::new(ssl_key).unwrap(), conn_opts2.ssl_key.unwrap());
450    }
451
452    #[diesel_test_helper::test]
453    #[cfg(feature = "mysql")]
454    fn ssl_mode() {
455        let ssl_mode = |url| ConnectionOptions::parse::<DB>(url).unwrap().ssl_mode();
456        assert_eq!(ssl_mode("mysql://localhost"), None);
457        assert_eq!(
458            ssl_mode("mysql://localhost?ssl_mode=disabled"),
459            Some(mysql_ssl_mode::SSL_MODE_DISABLED)
460        );
461        assert_eq!(
462            ssl_mode("mysql://localhost?ssl_mode=PREFERRED"),
463            Some(mysql_ssl_mode::SSL_MODE_PREFERRED)
464        );
465        assert_eq!(
466            ssl_mode("mysql://localhost?ssl_mode=required"),
467            Some(mysql_ssl_mode::SSL_MODE_REQUIRED)
468        );
469        assert_eq!(
470            ssl_mode("mysql://localhost?ssl_mode=VERIFY_CA"),
471            Some(mysql_ssl_mode::SSL_MODE_VERIFY_CA)
472        );
473        assert_eq!(
474            ssl_mode("mysql://localhost?ssl_mode=verify_identity"),
475            Some(mysql_ssl_mode::SSL_MODE_VERIFY_IDENTITY)
476        );
477    }
478
479    #[diesel_test_helper::test]
480    fn local_infile() {
481        let url = |url| ConnectionOptions::parse::<DB>(url).map(|v| v.local_infile());
482        let url_str = format!("{SCHEME}://localhost");
483        assert_eq!(url(&url_str), Ok(None));
484        let url_str = format!("{SCHEME}://localhost?local_infile=true");
485        assert_eq!(url(&url_str), Ok(Some(true)));
486        let url_str = format!("{SCHEME}://localhost?local_infile=false");
487        assert_eq!(url(&url_str), Ok(Some(false)));
488        let url_str = format!("{SCHEME}://localhost?local_infile=1");
489        url(&url_str).unwrap_err();
490    }
491}