1pub mod errors;
2pub mod label_map;
3
4pub use binrw;
5pub use diff;
6
7mod algorithm;
8
9use errors::*;
10use label_map::LabelMap;
11
12use binrw::binrw as binrw_attr;
13use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
14use diff::Diff;
15use lazy_static::lazy_static;
16
17use std::fmt::{Display, Error as fmtError, Formatter};
18use std::io::{self, Read, Write};
19use std::ops::{Deref, DerefMut};
20use std::str::FromStr;
21use std::sync::{Arc, Mutex};
22
23#[cfg(feature = "serde")]
24use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
25
26lazy_static! {
27 static ref LABELS: Arc<Mutex<LabelMap>> = Arc::new(Mutex::new(LabelMap::default()));
29}
30
31#[binrw_attr]
34#[repr(transparent)]
35#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
36pub struct Hash40(pub u64);
37
38pub const fn hash40(string: &str) -> Hash40 {
40 Hash40::new(string)
41}
42
43pub trait ReadHash40: ReadBytesExt {
45 fn read_hash40<T: ByteOrder>(&mut self) -> Result<Hash40, io::Error>;
46
47 fn read_hash40_with_meta<T: ByteOrder>(&mut self) -> Result<(Hash40, u32), io::Error>;
48}
49
50pub trait WriteHash40: WriteBytesExt {
52 fn write_hash40<T: ByteOrder>(&mut self, hash: Hash40) -> Result<(), io::Error>;
53
54 fn write_hash40_with_meta<T: ByteOrder>(
55 &mut self,
56 hash: Hash40,
57 meta: u32,
58 ) -> Result<(), io::Error>;
59}
60
61impl Hash40 {
62 pub const fn new(string: &str) -> Self {
65 Self(algorithm::hash40(string))
66 }
67
68 pub fn from_hex_str(value: &str) -> Result<Self, ParseHashError> {
70 if let Some(stripped) = value.strip_prefix("0x") {
71 Ok(Hash40(u64::from_str_radix(stripped, 16)?))
72 } else {
73 Err(ParseHashError::MissingPrefix)
74 }
75 }
76
77 pub fn from_label(label: &str) -> Result<Self, FromLabelError> {
81 match Self::from_hex_str(label) {
82 Ok(hash) => Ok(hash),
83 Err(err) => match err {
84 ParseHashError::MissingPrefix => {
85 let lock = LABELS.lock();
86 let labels = match lock {
87 Ok(labels) => labels,
88 Err(err) => err.into_inner(),
89 };
90 labels
91 .hash_of(label)
92 .ok_or_else(|| FromLabelError::LabelNotFound(String::from(label)))
93 }
94 ParseHashError::ParseError(err) => Err(err.into()),
95 },
96 }
97 }
98
99 pub fn to_label(&self) -> String {
102 let lock = LABELS.lock();
103 let labels = match lock {
104 Ok(labels) => labels,
105 Err(err) => err.into_inner(),
106 };
107 labels
108 .label_of(*self)
109 .unwrap_or_else(|| format!("0x{:010x}", self.0))
110 }
111
112 pub const fn crc(self) -> u32 {
114 self.0 as u32
115 }
116
117 pub const fn str_len(self) -> u8 {
119 (self.0 >> 32) as u8
120 }
121
122 pub fn label_map() -> Arc<Mutex<LabelMap>> {
124 LABELS.clone()
125 }
126
127 pub const fn concat(self, other: Self) -> Self {
130 Self(algorithm::hash40_concat(self.0, other.0))
131 }
132
133 pub const fn concat_str(self, other: &str) -> Self {
135 self.concat(hash40(other))
136 }
137
138 pub const fn join_path(self, other: Self) -> Self {
140 self.concat_str("/").concat(other)
141 }
142}
143
144impl FromStr for Hash40 {
145 type Err = FromLabelError;
146
147 fn from_str(f: &str) -> Result<Self, FromLabelError> {
148 Hash40::from_label(f)
149 }
150}
151
152impl Display for Hash40 {
154 fn fmt(&self, f: &mut Formatter) -> Result<(), fmtError> {
155 write!(f, "{}", self.to_label())
156 }
157}
158
159impl Deref for Hash40 {
160 type Target = u64;
161
162 fn deref(&self) -> &Self::Target {
163 &self.0
164 }
165}
166
167impl DerefMut for Hash40 {
168 fn deref_mut(&mut self) -> &mut Self::Target {
169 &mut self.0
170 }
171}
172
173impl<R: Read> ReadHash40 for R {
174 fn read_hash40<T: ByteOrder>(&mut self) -> Result<Hash40, io::Error> {
175 Ok(Hash40(self.read_u64::<T>()? & 0xff_ffff_ffff))
176 }
177
178 fn read_hash40_with_meta<T: ByteOrder>(&mut self) -> Result<(Hash40, u32), io::Error> {
179 let long = self.read_u64::<T>()?;
180 Ok((Hash40(long & 0xff_ffff_ffff), (long >> 40) as u32))
181 }
182}
183
184impl<W: Write> WriteHash40 for W {
185 fn write_hash40<T: ByteOrder>(&mut self, hash: Hash40) -> Result<(), io::Error> {
186 self.write_u64::<T>(hash.0)
187 }
188
189 fn write_hash40_with_meta<T: ByteOrder>(
190 &mut self,
191 hash: Hash40,
192 meta: u32,
193 ) -> Result<(), io::Error> {
194 self.write_u64::<T>(hash.0 | (meta as u64) << 40)
195 }
196}
197
198impl Diff for Hash40 {
199 type Repr = Option<Hash40>;
200
201 fn diff(&self, other: &Self) -> Self::Repr {
202 if self == other {
203 None
204 } else {
205 Some(*other)
206 }
207 }
208
209 fn apply(&mut self, diff: &Self::Repr) {
210 if let Some(other) = diff {
211 *self = *other;
212 }
213 }
214
215 fn identity() -> Self {
216 Default::default()
217 }
218}
219
220#[cfg(feature = "serde")]
221impl<'de> de::Visitor<'de> for Hash40Visitor {
222 type Value = Hash40;
223
224 fn expecting(
225 &self,
226 formatter: &mut std::fmt::Formatter,
227 ) -> std::result::Result<(), std::fmt::Error> {
228 formatter.write_str(
229 "A hex-formatted integer hash value, or a string representing for its reversed form",
230 )
231 }
232
233 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
234 Hash40::from_label(&String::from(value)).map_err(de::Error::custom)
235 }
236}
237
238#[cfg(feature = "serde")]
239impl Serialize for Hash40 {
240 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
241 serializer.serialize_str(&self.to_label())
242 }
243}
244
245#[cfg(feature = "serde")]
246impl<'de> Deserialize<'de> for Hash40 {
247 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
248 deserializer.deserialize_str(Hash40Visitor)
249 }
250}
251
252#[cfg(feature = "serde")]
253struct Hash40Visitor;