summaryrefslogtreecommitdiffstats
path: root/src/util.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.rs')
-rw-r--r--src/util.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/util.rs b/src/util.rs
new file mode 100644
index 0000000..428990c
--- /dev/null
+++ b/src/util.rs
@@ -0,0 +1,68 @@
+use std::fmt::{Debug, Display, Formatter, Pointer};
+use std::ops::Deref;
+use crypto::digest::Digest;
+use crypto::sha1::Sha1;
+use serde::{Deserialize, Deserializer};
+use serde::de::{Error, Visitor};
+use hex::{FromHex, ToHex};
+
+// sha1 digests are 20 bytes long
+pub const SHA1_DIGEST_BYTES: usize = 20;
+pub type Sha1DigestBytes = [u8; SHA1_DIGEST_BYTES];
+
+#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
+pub struct Sha1Digest(pub Sha1DigestBytes);
+
+impl Debug for Sha1Digest {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "Sha1Digest {{{}}}", self.0.encode_hex::<String>())
+ }
+}
+
+impl Display for Sha1Digest {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.write_str(&self.0.encode_hex::<String>())
+ }
+}
+
+impl Sha1Digest {
+ pub fn verify(&self, s: &str) -> Result<(), Sha1Digest> {
+ let mut st = Sha1::new();
+ let mut dig = [0u8; SHA1_DIGEST_BYTES];
+
+ st.input_str(s);
+ st.result(&mut dig);
+
+ if self.0 == dig {
+ return Ok(());
+ }
+
+ Err(Sha1Digest(dig))
+ }
+}
+
+struct Sha1DigestVisitor;
+
+impl <'a> Visitor<'a> for Sha1DigestVisitor {
+ type Value = Sha1Digest;
+
+ fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
+ write!(formatter, "a valid SHA-1 digest (40-character hex string)")
+ }
+
+ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ Sha1DigestBytes::from_hex(v).map_err(|e| E::custom(e)).map(Sha1Digest)
+ }
+}
+
+impl<'a> Deserialize<'a> for Sha1Digest {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'a>,
+ {
+ deserializer.deserialize_any(Sha1DigestVisitor)
+ }
+} \ No newline at end of file