trine_kv/content/identity/
content_id.rs1use super::{CONTENT_ID_SHA256_TAG, Digest, Error, Result, Sha256, fmt, write_hex};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[non_exhaustive]
6pub enum ContentHashAlgorithm {
7 Sha256,
9}
10
11impl ContentHashAlgorithm {
12 pub(in crate::content) const fn tag(self) -> u8 {
13 match self {
14 Self::Sha256 => CONTENT_ID_SHA256_TAG,
15 }
16 }
17
18 pub(in crate::content) fn from_tag(tag: u8) -> Result<Self> {
19 match tag {
20 CONTENT_ID_SHA256_TAG => Ok(Self::Sha256),
21 _ => Err(Error::UnsupportedFormat {
22 message: format!("unsupported content hash algorithm tag {tag}"),
23 }),
24 }
25 }
26}
27
28#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub struct ContentId {
34 pub(in crate::content) algorithm: ContentHashAlgorithm,
35 pub(in crate::content) digest: [u8; 32],
36}
37
38impl ContentId {
39 pub fn from_bytes(bytes: [u8; 33]) -> Result<Self> {
50 let algorithm = ContentHashAlgorithm::from_tag(bytes[0])?;
51 let mut digest = [0_u8; 32];
52 digest.copy_from_slice(&bytes[1..]);
53 Ok(Self { algorithm, digest })
54 }
55
56 #[must_use]
58 pub fn to_bytes(self) -> [u8; 33] {
59 let mut bytes = [0_u8; 33];
60 bytes[0] = self.algorithm.tag();
61 bytes[1..].copy_from_slice(&self.digest);
62 bytes
63 }
64
65 #[must_use]
71 pub fn for_bytes(bytes: &[u8]) -> Self {
72 let digest: [u8; 32] = Sha256::digest(bytes).into();
73 Self {
74 algorithm: ContentHashAlgorithm::Sha256,
75 digest,
76 }
77 }
78
79 #[must_use]
81 pub const fn algorithm(self) -> ContentHashAlgorithm {
82 self.algorithm
83 }
84
85 #[must_use]
87 pub const fn digest(self) -> [u8; 32] {
88 self.digest
89 }
90
91 pub(crate) fn from_sha256(digest: [u8; 32]) -> Self {
92 Self {
93 algorithm: ContentHashAlgorithm::Sha256,
94 digest,
95 }
96 }
97
98 pub(in crate::content) fn encode_into(self, bytes: &mut Vec<u8>) {
99 bytes.push(self.algorithm.tag());
100 bytes.extend_from_slice(&self.digest);
101 }
102}
103
104impl fmt::Debug for ContentId {
105 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(formatter, "ContentId({self})")
107 }
108}
109
110impl fmt::Display for ContentId {
111 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
112 formatter.write_str("sha256:")?;
113 write_hex(formatter, &self.digest)
114 }
115}