1use std::marker::PhantomData;
10use std::ops::Deref;
11
12use digest::generic_array::{
13 typenum::{U20, U32, U64},
14 GenericArray,
15};
16use sha2::Digest as RDigest;
17
18pub struct Digest<T>(InnerDigest, PhantomData<T>);
20
21enum InnerDigest {
22 Sha256(GenericArray<u8, U32>),
23 Sha512(GenericArray<u8, U64>),
24 Ripemd160(GenericArray<u8, U20>),
25}
26
27impl<T> Deref for Digest<T> {
28 type Target = [u8];
29 fn deref(&self) -> &Self::Target {
30 match self.0 {
31 InnerDigest::Sha256(ref d) => &d[..],
32 InnerDigest::Sha512(ref d) => &d[..],
33 InnerDigest::Ripemd160(ref d) => &d[..],
34 }
35 }
36}
37
38pub fn sha256(data: &[u8]) -> Digest<Sha256> {
40 let mut hasher = Hasher::sha256();
41 hasher.update(data);
42 hasher.finish()
43}
44
45pub fn sha512(data: &[u8]) -> Digest<Sha512> {
47 let mut hasher = Hasher::sha512();
48 hasher.update(data);
49 hasher.finish()
50}
51
52pub fn ripemd160(data: &[u8]) -> Digest<Ripemd160> {
54 let mut hasher = Hasher::ripemd160();
55 hasher.update(data);
56 hasher.finish()
57}
58
59#[derive(Debug)]
60pub enum Sha256 {}
61#[derive(Debug)]
62pub enum Sha512 {}
63#[derive(Debug)]
64pub enum Ripemd160 {}
65
66pub struct Hasher<T>(Inner, PhantomData<T>);
68
69enum Inner {
70 Sha256(sha2::Sha256),
71 Sha512(sha2::Sha512),
72 Ripemd160(ripemd160::Ripemd160),
73}
74
75impl Hasher<Sha256> {
76 pub fn sha256() -> Hasher<Sha256> {
77 Hasher(Inner::Sha256(sha2::Sha256::default()), PhantomData)
78 }
79}
80
81impl Hasher<Sha512> {
82 pub fn sha512() -> Hasher<Sha512> {
83 Hasher(Inner::Sha512(sha2::Sha512::default()), PhantomData)
84 }
85}
86
87impl Hasher<Ripemd160> {
88 pub fn ripemd160() -> Hasher<Ripemd160> {
89 Hasher(Inner::Ripemd160(ripemd160::Ripemd160::default()), PhantomData)
90 }
91}
92
93impl<T> Hasher<T> {
94 pub fn update(&mut self, data: &[u8]) {
95 match self.0 {
96 Inner::Sha256(ref mut ctx) => ctx.update(data),
97 Inner::Sha512(ref mut ctx) => ctx.update(data),
98 Inner::Ripemd160(ref mut ctx) => ctx.update(data),
99 }
100 }
101
102 pub fn finish(self) -> Digest<T> {
103 match self.0 {
104 Inner::Sha256(ctx) => Digest(InnerDigest::Sha256(ctx.finalize()), PhantomData),
105 Inner::Sha512(ctx) => Digest(InnerDigest::Sha512(ctx.finalize()), PhantomData),
106 Inner::Ripemd160(ctx) => Digest(InnerDigest::Ripemd160(ctx.finalize()), PhantomData),
107 }
108 }
109}