use serde::{Deserialize, Serialize};
use sha256::{digest, Sha256Digest};
use std::{fmt::Debug, ops::Deref};
#[derive(Clone, Eq, Default)]
pub struct Hashed<T: Sha256Digest> {
hash: String,
_marker: std::marker::PhantomData<T>,
}
impl<T: Sha256Digest> Hashed<T> {
pub fn new(value: T) -> Self {
Self {
hash: digest(value),
_marker: std::marker::PhantomData,
}
}
}
impl<T: Sha256Digest> Deref for Hashed<T> {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.hash
}
}
impl<T: Sha256Digest> From<T> for Hashed<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: Sha256Digest> From<Hashed<T>> for String {
fn from(val: Hashed<T>) -> Self {
val.hash
}
}
impl<T: Sha256Digest> Debug for Hashed<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.hash.fmt(f)
}
}
impl<T: Sha256Digest> PartialEq for Hashed<T> {
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}
impl<T: Sha256Digest> PartialEq<String> for Hashed<T> {
fn eq(&self, other: &String) -> bool {
self.hash == digest(other)
}
}
impl<T: Sha256Digest> PartialEq<&str> for Hashed<T> {
fn eq(&self, other: &&str) -> bool {
self.hash == digest(*other)
}
}
impl<T: Sha256Digest> Serialize for Hashed<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.hash.serialize(serializer)
}
}
impl<'de, T: Sha256Digest> Deserialize<'de> for Hashed<T> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(Self {
_marker: std::marker::PhantomData,
hash: String::deserialize(deserializer)?,
})
}
}
#[cfg(feature = "schema")]
impl<T: Sha256Digest> schemars::JsonSchema for Hashed<T> {
fn schema_name() -> String {
String::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
gen.subschema_for::<String>()
}
}