git_bug/replica/entity/id/
mod.rs1use std::fmt::Display;
17
18use combined_id::CombinedId;
19use prefix::IdPrefix;
20use serde::{Deserialize, Serialize};
21
22pub mod combined_id;
23pub mod entity_id;
24pub mod prefix;
25
26#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
28pub struct Id {
29 sha256_value: [u8; 32],
31}
32
33impl Display for Id {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 let mut buf = [0; 64];
36 write!(f, "{}", self.hex_to_buf(&mut buf))
37 }
38}
39
40impl std::fmt::Debug for Id {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 f.write_str("Sha256(")?;
43 for b in self.as_bytes() {
44 write!(f, "{b:02x}")?;
45 }
46 f.write_str(")")
47 }
48}
49
50#[allow(missing_docs)]
51pub mod decode {
52 use std::str::FromStr;
53
54 #[derive(Debug, thiserror::Error)]
55 pub enum Error {
56 #[error("Your hex input buffer was not 64 bytes long, but: {0}")]
57 InvalidLen(usize),
58
59 #[error("Your hex input contained an invalid char. The buffer is: '{0:?}'")]
60 InvalidChar(Vec<u8>),
61 }
62
63 impl FromStr for super::Id {
64 type Err = Error;
65
66 fn from_str(s: &str) -> Result<Self, Self::Err> {
67 Self::from_hex(s.as_bytes())
68 }
69 }
70
71 impl TryFrom<&str> for super::Id {
72 type Error = Error;
73
74 fn try_from(value: &str) -> Result<Self, Self::Error> {
75 <Self as FromStr>::from_str(value)
76 }
77 }
78 impl TryFrom<String> for super::Id {
79 type Error = Error;
80
81 fn try_from(value: String) -> Result<Self, Self::Error> {
82 <Self as FromStr>::from_str(&value)
83 }
84 }
85}
86
87impl From<Id> for String {
88 fn from(value: Id) -> Self {
89 value.to_string()
90 }
91}
92
93impl Id {
94 pub fn from_hex(buffer: &[u8]) -> Result<Self, decode::Error> {
103 if buffer.len() != 64 {
104 return Err(decode::Error::InvalidLen(buffer.len()));
105 }
106
107 let mut buf = [0; 32];
108 faster_hex::hex_decode(buffer, &mut buf).map_err(|err| match err {
109 faster_hex::Error::InvalidChar => decode::Error::InvalidChar(buffer.to_owned()),
110 faster_hex::Error::InvalidLength(len) => {
111 unreachable!("Bug: Id Length is invalid but was checked: {len}")
112 }
113 faster_hex::Error::Overflow => unreachable!("We allocated enough"),
114 })?;
115
116 Ok(Self { sha256_value: buf })
117 }
118
119 pub(crate) fn from_sha256_hash(input: &[u8]) -> Self {
126 let mut buffer = [0; 32];
127 buffer.copy_from_slice(input);
128 Self {
129 sha256_value: buffer,
130 }
131 }
132
133 fn as_bytes(&self) -> &[u8] {
134 &self.sha256_value
135 }
136
137 #[must_use]
139 pub fn as_slice(&self) -> &[u8] {
140 &self.sha256_value
141 }
142
143 pub fn hex_to_buf<'a>(&self, buf: &'a mut [u8]) -> &'a mut str {
150 let num_hex_bytes = self.sha256_value.len() * 2;
151 faster_hex::hex_encode(self.as_bytes(), &mut buf[..num_hex_bytes]).expect("We can count")
152 }
153
154 #[must_use]
157 pub fn shorten(&self) -> IdPrefix {
158 (*self).into()
159 }
160
161 #[must_use]
170 pub fn combine_with(self, other: Id) -> CombinedId {
171 CombinedId {
172 primary_id: self,
173 secondary_id: other,
174 }
175 }
176}