use crate::Sha256;
use base64::Engine as _;
use base64::engine::general_purpose::STANDARD;
use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Sha256Base64Error {
#[non_exhaustive]
InvalidBase64,
#[non_exhaustive]
WrongLength {
got: u32,
},
}
impl fmt::Display for Sha256Base64Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidBase64 => f.write_str("SHA-256 digest is not canonical padded base64"),
Self::WrongLength { got } => {
write!(
f,
"base64 SHA-256 digest must decode to 32 bytes (got {got})"
)
}
}
}
}
impl std::error::Error for Sha256Base64Error {}
impl Sha256 {
pub fn to_base64(&self) -> String {
STANDARD.encode(self.to_bytes())
}
pub fn from_base64(s: &str) -> Result<Self, Sha256Base64Error> {
let bytes = STANDARD
.decode(s)
.map_err(|_| Sha256Base64Error::InvalidBase64)?;
let digest: [u8; 32] =
bytes
.as_slice()
.try_into()
.map_err(|_| Sha256Base64Error::WrongLength {
got: u32::try_from(bytes.len()).unwrap_or(u32::MAX),
})?;
Ok(Self::from(digest))
}
}