use std::fmt::Debug;
use async_trait::async_trait;
use tracing::instrument;
use crate::{Connection, Error, Result};
use super::Command;
#[derive(Debug, Clone)]
pub struct Hello<U, P> {
pub username: Option<U>,
pub password: Option<P>,
}
#[async_trait]
impl<U, P> Command for Hello<U, P>
where
U: AsRef<[u8]> + Send + Sync + Debug,
P: AsRef<[u8]> + Send + Sync + Debug,
{
type Response = ();
#[instrument(level = "debug")]
async fn run(self, connection: &mut Connection) -> Result<Self::Response> {
let handshake_res = match self.password {
Some(ref password) => {
connection
.cmd([
&b"hello"[..],
b"2",
b"auth",
self.username
.as_ref()
.map(|u| u.as_ref())
.unwrap_or(b"default"),
password.as_ref(),
])
.await
}
None => connection.cmd(["hello", "2"]).await,
};
match handshake_res {
Ok(_) => Ok(()),
Err(Error::Redis(msg)) if msg == "ERR unknown command 'HELLO'" => {
if let Some(password) = self.password {
match self.username {
Some(username) => {
connection
.cmd([b"auth", username.as_ref(), password.as_ref()])
.await?
}
None => connection.cmd([b"auth", password.as_ref()]).await?,
};
}
Ok(())
}
Err(e) => Err(e),
}
}
}