1use std::fmt;
12use tag::Tag;
13use uvar::Uvar;
14
15#[cfg(feature = "sha-1")]
16mod sha1;
17#[cfg(feature = "sha-1")]
18pub use self::sha1::Sha1;
19
20#[cfg(feature = "sha2")]
21mod sha2;
22#[cfg(feature = "sha2")]
23pub use self::sha2::{Sha2256, Sha2512};
24
25#[cfg(feature = "sha3")]
26mod sha3;
27#[cfg(feature = "sha3")]
28pub use self::sha3::{Sha3224, Sha3256, Sha3384, Sha3512};
29
30#[cfg(feature = "blake2")]
31mod blake2;
32#[cfg(feature = "blake2")]
33pub use self::blake2::{Blake2b512, Blake2s256};
34
35pub trait Multihash: Default + PartialEq {
50 type Digester: Default;
51
52 fn length(&self) -> u8;
53 fn code(&self) -> Uvar;
54 fn name(&self) -> &str;
55 fn digester(&self) -> Self::Digester {
56 Self::Digester::default()
57 }
58
59 fn digest_primitive(&self, tag: Tag, bytes: &[u8]) -> Harvest;
60 fn digest_collection(&self, tag: Tag, list: Vec<Vec<u8>>) -> Harvest;
61}
62
63#[derive(Debug)]
64pub enum MultihashError {
65 Unknown,
66}
67
68#[derive(Debug, PartialEq, Eq, Hash)]
70pub struct Harvest(Box<[u8]>);
71
72impl AsRef<[u8]> for Harvest {
73 fn as_ref(&self) -> &[u8] {
74 self.0.as_ref()
75 }
76}
77
78impl fmt::Display for Harvest {
79 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
80 for byte in self.0.as_ref() {
81 write!(formatter, "{:02x}", byte)?;
82 }
83
84 Ok(())
85 }
86}
87
88impl Harvest {
89 pub fn as_slice(&self) -> &[u8] {
90 &self.0
91 }
92}
93
94impl From<Vec<u8>> for Harvest {
95 fn from(vec: Vec<u8>) -> Self {
96 Harvest(vec.into_boxed_slice())
97 }
98}
99
100impl From<Box<[u8]>> for Harvest {
101 fn from(b: Box<[u8]>) -> Self {
102 Harvest(b)
103 }
104}
105
106#[derive(Debug, PartialEq, Eq, Hash)]
108pub struct Hash<T: Multihash> {
109 tag: T,
110 digest: Harvest,
111}
112
113impl<T: Multihash> Hash<T> {
114 pub fn new<D: Into<Harvest>>(tag: T, digest: D) -> Hash<T> {
115 Hash {
116 tag,
117 digest: digest.into(),
118 }
119 }
120
121 pub fn digest(&self) -> &Harvest {
122 &self.digest
123 }
124
125 pub fn tag(&self) -> &T {
126 &self.tag
127 }
128}
129
130impl<T: Multihash> fmt::Display for Hash<T> {
131 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
132 write!(formatter, "{:02x}", &self.tag.code())?;
133 write!(formatter, "{:02x}", &self.tag.length())?;
134 write!(formatter, "{}", &self.digest)?;
135
136 Ok(())
137 }
138}