orcinus 0.3.0

async-ready mysql protocol implementation / wrapper libraries
Documentation
use std::io::{Read, Write};

use futures_util::{future::BoxFuture, FutureExt};
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};

use crate::{
    protos::{write_packet, write_packet_sync, AsyncReceivePacket, GenericOKErrPacket, OKPacket, ReceivePacket},
    CommunicationError,
};

/// ClearText Authentication(`"mysql_clear_password"`)
pub struct ClearText;
impl super::Authentication for ClearText {
    const NAME: &'static str = "mysql_clear_password";

    fn run_sync(
        &self,
        mut stream: impl Read + Write,
        con_info: &super::ConnectionInfo,
        first_sequence_id: u8,
    ) -> Result<(OKPacket, u8), CommunicationError> {
        let mut buf = Vec::with_capacity(con_info.password.as_bytes().len() + 1);
        buf.extend(con_info.password.bytes());
        buf.push(0);

        write_packet_sync(
            &mut stream,
            con_info.make_handshake_response(&buf, Some(Self::NAME)),
            first_sequence_id,
        )?;
        stream.flush()?;
        let (resp, sequence_id) =
            GenericOKErrPacket::read_packet(stream, con_info.client_capabilities)?.into_result()?;

        Ok((resp, sequence_id))
    }
}
impl<'s, S> super::AsyncAuthentication<'s, S> for ClearText
where
    S: AsyncRead + AsyncWrite + Send + Sync + Unpin + 's,
{
    type OperationF = BoxFuture<'s, Result<(OKPacket, u8), CommunicationError>>;

    fn run(&'s self, mut stream: S, con_info: &'s super::ConnectionInfo, first_sequence_id: u8) -> Self::OperationF {
        async move {
            let mut buf = Vec::with_capacity(con_info.password.as_bytes().len() + 1);
            buf.extend(con_info.password.bytes());
            buf.push(0);

            write_packet(
                &mut stream,
                con_info.make_handshake_response(&buf, Some(<Self as super::Authentication>::NAME)),
                first_sequence_id,
            )
            .await?;
            stream.flush().await?;
            let (resp, sequence_id) = GenericOKErrPacket::read_packet_async(stream, con_info.client_capabilities)
                .await?
                .into_result()?;

            Ok((resp, sequence_id))
        }
        .boxed()
    }
}