use std::{
borrow::Cow,
fmt::{Display, Formatter},
};
#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;
#[cfg(feature = "bounded-static")]
use bounded_static::ToStatic;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
core::{impl_try_from, Atom},
secret::Secret,
};
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct AuthMechanism<'a>(Inner<'a>);
impl<'a> AuthMechanism<'a> {
pub const PLAIN: AuthMechanism<'static> = AuthMechanism(Inner::Plain);
pub const LOGIN: AuthMechanism<'static> = AuthMechanism(Inner::Login);
pub const XOAUTH2: AuthMechanism<'static> = AuthMechanism(Inner::XOAuth2);
}
impl_try_from!(Atom<'a>, 'a, &'a [u8], AuthMechanism<'a>);
impl_try_from!(Atom<'a>, 'a, Vec<u8>, AuthMechanism<'a>);
impl_try_from!(Atom<'a>, 'a, &'a str, AuthMechanism<'a>);
impl_try_from!(Atom<'a>, 'a, String, AuthMechanism<'a>);
impl_try_from!(Atom<'a>, 'a, Cow<'a, str>, AuthMechanism<'a>);
impl<'a> From<Atom<'a>> for AuthMechanism<'a> {
fn from(atom: Atom<'a>) -> Self {
match atom.as_ref().to_ascii_uppercase().as_str() {
"PLAIN" => Self::PLAIN,
"LOGIN" => Self::LOGIN,
"XOAUTH2" => Self::XOAUTH2,
_ => Self(Inner::Other(atom)),
}
}
}
impl<'a> Display for AuthMechanism<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(match &self.0 {
Inner::Plain => "PLAIN",
Inner::Login => "LOGIN",
Inner::XOAuth2 => "XOAUTH2",
Inner::Other(other) => other.as_ref(),
})
}
}
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Inner<'a> {
Plain,
Login,
XOAuth2,
Other(Atom<'a>),
}
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct AuthenticateData(pub Secret<Vec<u8>>);