use std::fmt::Display;
use std::str::FromStr;
use anyhow::anyhow;
use identity_core::convert::Base;
use identity_core::convert::BaseEncoding;
use serde::Deserialize;
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(try_from = "String")]
pub struct IntegrityMetadata(String);
impl IntegrityMetadata {
pub fn parse(s: &str) -> Result<Self, anyhow::Error> {
s.parse()
}
pub fn alg(&self) -> &str {
self.0.split_once('-').unwrap().0
}
pub fn digest(&self) -> &str {
self.0.split('-').nth(1).unwrap()
}
pub fn digest_bytes(&self) -> Vec<u8> {
BaseEncoding::decode(self.digest(), Base::Base64).unwrap()
}
pub fn options(&self) -> Option<&str> {
self.0.splitn(3, '-').nth(2)
}
}
impl AsRef<str> for IntegrityMetadata {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl Display for IntegrityMetadata {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.0)
}
}
impl FromStr for IntegrityMetadata {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(s.to_owned())
}
}
impl TryFrom<String> for IntegrityMetadata {
type Error = anyhow::Error;
fn try_from(value: String) -> Result<Self, Self::Error> {
let mut metadata_parts = value.splitn(3, '-');
let _alg = metadata_parts
.next()
.ok_or_else(|| anyhow!("invalid integrity metadata"))?;
let _digest = metadata_parts
.next()
.and_then(|digest| BaseEncoding::decode(digest, Base::Base64).ok())
.ok_or_else(|| anyhow!("invalid integrity metadata"))?;
let _options = metadata_parts.next();
Ok(Self(value))
}
}