use std::fmt::Display;
use combined_id::CombinedId;
use prefix::IdPrefix;
use serde::{Deserialize, Serialize};
pub mod combined_id;
pub mod entity_id;
pub mod prefix;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
pub struct Id {
sha256_value: [u8; 32],
}
impl Display for Id {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut buf = [0; 64];
write!(f, "{}", self.hex_to_buf(&mut buf))
}
}
impl std::fmt::Debug for Id {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Sha256(")?;
for b in self.as_bytes() {
write!(f, "{b:02x}")?;
}
f.write_str(")")
}
}
#[allow(missing_docs)]
pub mod decode {
use std::str::FromStr;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Your hex input buffer was not 64 bytes long, but: {0}")]
InvalidLen(usize),
#[error("Your hex input contained an invalid char. The buffer is: '{0:?}'")]
InvalidChar(Vec<u8>),
}
impl FromStr for super::Id {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_hex(s.as_bytes())
}
}
impl TryFrom<&str> for super::Id {
type Error = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
<Self as FromStr>::from_str(value)
}
}
impl TryFrom<String> for super::Id {
type Error = Error;
fn try_from(value: String) -> Result<Self, Self::Error> {
<Self as FromStr>::from_str(&value)
}
}
}
impl From<Id> for String {
fn from(value: Id) -> Self {
value.to_string()
}
}
impl Id {
pub fn from_hex(buffer: &[u8]) -> Result<Self, decode::Error> {
if buffer.len() != 64 {
return Err(decode::Error::InvalidLen(buffer.len()));
}
let mut buf = [0; 32];
faster_hex::hex_decode(buffer, &mut buf).map_err(|err| match err {
faster_hex::Error::InvalidChar => decode::Error::InvalidChar(buffer.to_owned()),
faster_hex::Error::InvalidLength(len) => {
unreachable!("Bug: Id Length is invalid but was checked: {len}")
}
faster_hex::Error::Overflow => unreachable!("We allocated enough"),
})?;
Ok(Self { sha256_value: buf })
}
pub(crate) fn from_sha256_hash(input: &[u8]) -> Self {
let mut buffer = [0; 32];
buffer.copy_from_slice(input);
Self {
sha256_value: buffer,
}
}
fn as_bytes(&self) -> &[u8] {
&self.sha256_value
}
#[must_use]
pub fn as_slice(&self) -> &[u8] {
&self.sha256_value
}
pub fn hex_to_buf<'a>(&self, buf: &'a mut [u8]) -> &'a mut str {
let num_hex_bytes = self.sha256_value.len() * 2;
faster_hex::hex_encode(self.as_bytes(), &mut buf[..num_hex_bytes]).expect("We can count")
}
#[must_use]
pub fn shorten(&self) -> IdPrefix {
(*self).into()
}
#[must_use]
pub fn combine_with(self, other: Id) -> CombinedId {
CombinedId {
primary_id: self,
secondary_id: other,
}
}
}