use core::fmt::{self, Display};
#[cfg(feature = "phc")]
use password_hash::phc::Ident;
#[cfg(feature = "password-hash")]
use {core::str::FromStr, password_hash::Error};
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum Algorithm {
#[cfg(feature = "sha2")]
Pbkdf2Sha256,
#[cfg(feature = "sha2")]
Pbkdf2Sha512,
}
impl Algorithm {
#[cfg(feature = "sha2")]
pub const PBKDF2_SHA256_ID: &'static str = "pbkdf2-sha256";
#[cfg(feature = "sha2")]
pub const PBKDF2_SHA512_ID: &'static str = "pbkdf2-sha512";
#[cfg(feature = "phc")]
pub(crate) const PBKDF2_SHA256_IDENT: Ident = Ident::new_unwrap(Self::PBKDF2_SHA256_ID);
#[cfg(feature = "phc")]
pub(crate) const PBKDF2_SHA512_IDENT: Ident = Ident::new_unwrap(Self::PBKDF2_SHA512_ID);
#[cfg(feature = "sha2")]
pub const RECOMMENDED: Self = Self::Pbkdf2Sha256;
#[cfg(feature = "password-hash")]
pub fn new(id: impl AsRef<str>) -> password_hash::Result<Self> {
id.as_ref().parse()
}
#[must_use]
pub const fn to_str(self) -> &'static str {
match self {
#[cfg(feature = "sha2")]
Algorithm::Pbkdf2Sha256 => Self::PBKDF2_SHA256_ID,
#[cfg(feature = "sha2")]
Algorithm::Pbkdf2Sha512 => Self::PBKDF2_SHA512_ID,
}
}
}
impl AsRef<str> for Algorithm {
fn as_ref(&self) -> &str {
self.to_str()
}
}
#[cfg(feature = "sha2")]
impl Default for Algorithm {
fn default() -> Self {
Self::RECOMMENDED
}
}
impl Display for Algorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.to_str())
}
}
#[cfg(feature = "password-hash")]
impl FromStr for Algorithm {
type Err = Error;
fn from_str(s: &str) -> password_hash::Result<Algorithm> {
s.try_into()
}
}
#[cfg(feature = "phc")]
impl From<Algorithm> for Ident {
fn from(alg: Algorithm) -> Ident {
match alg {
Algorithm::Pbkdf2Sha256 => Algorithm::PBKDF2_SHA256_IDENT,
Algorithm::Pbkdf2Sha512 => Algorithm::PBKDF2_SHA512_IDENT,
}
}
}
#[cfg(feature = "password-hash")]
impl<'a> TryFrom<&'a str> for Algorithm {
type Error = Error;
fn try_from(name: &'a str) -> password_hash::Result<Algorithm> {
match name {
#[cfg(feature = "sha2")]
Self::PBKDF2_SHA256_ID => Ok(Algorithm::Pbkdf2Sha256),
#[cfg(feature = "sha2")]
Self::PBKDF2_SHA512_ID => Ok(Algorithm::Pbkdf2Sha512),
_ => Err(Error::Algorithm),
}
}
}