use std::fmt::{self, Display};
use bh_jws_utils::base64_url_encode;
use serde_json::Value;
use crate::{Hasher, JsonObject, RESERVED_CLAIM_NAMES};
#[derive(Debug, PartialEq, Clone)]
pub struct VecDisplayWrapper<T>(pub Vec<T>);
impl<T: Display> Display for VecDisplayWrapper<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some((last, without_last)) = self.0.split_last() {
for element in without_last {
write!(f, "{}, ", element)?;
}
write!(f, "{}", last)?;
}
Ok(())
}
}
pub(crate) const SD_ALG_FIELD_NAME: &str = "_sd_alg";
pub fn base64_url_digest(input: &[u8], hasher: impl Hasher) -> String {
let digest = hasher.digest(input);
base64_url_encode(digest)
}
pub(crate) fn is_reserved_key_name(key: &str) -> Option<&'static str> {
RESERVED_CLAIM_NAMES
.iter()
.find(|&name| key.eq(*name))
.copied()
}
pub(crate) fn check_claim_names_object(
object: &JsonObject,
reserved_predicate: &impl Fn(&str) -> Option<&'static str>,
recurse: bool,
) -> Option<&'static str> {
for (claim_name, claim_value) in object {
if let Some(name) = reserved_predicate(claim_name.as_str()) {
return Some(name);
}
if !recurse {
continue;
}
if let Some(name) = check_claim_names(claim_value, reserved_predicate) {
return Some(name);
}
}
None
}
fn check_claim_names(
value: &Value,
reserved_predicate: &impl Fn(&str) -> Option<&'static str>,
) -> Option<&'static str> {
match value {
Value::Object(object) => check_claim_names_object(object, reserved_predicate, true),
Value::Array(array) => {
for element in array {
if let Some(name) = check_claim_names(element, reserved_predicate) {
return Some(name);
}
}
None
}
_ => None,
}
}