use base64::Engine;
use crate::error::{Error, Result};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Signature(Vec<u8>);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Encoding {
Base64,
Base64UrlNoPad,
HexLower,
}
impl Signature {
pub fn from_bytes(bytes: impl Into<Vec<u8>>) -> Self {
Self(bytes.into())
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
pub fn to_base64(&self) -> String {
base64::prelude::BASE64_STANDARD.encode(&self.0)
}
pub fn to_base64_url_nopad(&self) -> String {
base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(&self.0)
}
pub fn to_hex_lower(&self) -> String {
hex::encode(&self.0)
}
pub fn encode(&self, enc: Encoding) -> String {
match enc {
Encoding::Base64 => self.to_base64(),
Encoding::Base64UrlNoPad => self.to_base64_url_nopad(),
Encoding::HexLower => self.to_hex_lower(),
}
}
pub fn from_base64(s: impl AsRef<str>) -> Result<Self> {
base64::prelude::BASE64_STANDARD
.decode(s.as_ref())
.map(Self)
.map_err(|e| Error::SignatureDecode { encoding: Encoding::Base64, reason: e.to_string() })
}
pub fn from_base64_url_nopad(s: impl AsRef<str>) -> Result<Self> {
base64::prelude::BASE64_URL_SAFE_NO_PAD
.decode(s.as_ref())
.map(Self)
.map_err(|e| Error::SignatureDecode { encoding: Encoding::Base64UrlNoPad, reason: e.to_string() })
}
pub fn from_hex(s: impl AsRef<str>) -> Result<Self> {
hex::decode(s.as_ref())
.map(Self)
.map_err(|e| Error::SignatureDecode { encoding: Encoding::HexLower, reason: e.to_string() })
}
pub fn decode(s: impl AsRef<str>, enc: Encoding) -> Result<Self> {
match enc {
Encoding::Base64 => Self::from_base64(s),
Encoding::Base64UrlNoPad => Self::from_base64_url_nopad(s),
Encoding::HexLower => Self::from_hex(s),
}
}
}