1use core::ops::Index;
7use core::slice::SliceIndex;
8use core::str;
9
10use crate::{sha256, FromSliceError};
11
12crate::internal_macros::hash_type! {
13 256,
14 true,
15 "Output of the SHA256d hash function."
16}
17
18type HashEngine = sha256::HashEngine;
19
20fn from_engine(e: sha256::HashEngine) -> Hash {
21 use crate::Hash as _;
22
23 let sha2 = sha256::Hash::from_engine(e);
24 let sha2d = sha256::Hash::hash(&sha2[..]);
25
26 let mut ret = [0; 32];
27 ret.copy_from_slice(&sha2d[..]);
28 Hash(ret)
29}
30
31#[cfg(test)]
32mod tests {
33 use crate::{sha256d, Hash as _};
34
35 #[test]
36 #[cfg(feature = "alloc")]
37 fn test() {
38 use crate::{sha256, HashEngine};
39
40 #[derive(Clone)]
41 struct Test {
42 input: &'static str,
43 output: Vec<u8>,
44 output_str: &'static str,
45 }
46
47 #[rustfmt::skip]
48 let tests = vec![
49 Test {
51 input: "",
52 output: vec![
53 0x5d, 0xf6, 0xe0, 0xe2, 0x76, 0x13, 0x59, 0xd3,
54 0x0a, 0x82, 0x75, 0x05, 0x8e, 0x29, 0x9f, 0xcc,
55 0x03, 0x81, 0x53, 0x45, 0x45, 0xf5, 0x5c, 0xf4,
56 0x3e, 0x41, 0x98, 0x3f, 0x5d, 0x4c, 0x94, 0x56,
57 ],
58 output_str: "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d",
59 },
60 ];
61
62 for test in tests {
63 let hash = sha256d::Hash::hash(test.input.as_bytes());
65 assert_eq!(hash, test.output_str.parse::<sha256d::Hash>().expect("parse hex"));
66 assert_eq!(&hash[..], &test.output[..]);
67 assert_eq!(&hash.to_string(), &test.output_str);
68
69 let mut engine = sha256d::Hash::engine();
71 for ch in test.input.as_bytes() {
72 engine.input(&[*ch]);
73 }
74 let manual_hash = sha256d::Hash::from_engine(engine);
75 assert_eq!(hash, manual_hash);
76
77 let sha2_hash = sha256::Hash::hash(test.input.as_bytes());
79 let sha2d_hash = sha2_hash.hash_again();
80 assert_eq!(hash, sha2d_hash);
81
82 assert_eq!(hash.to_byte_array()[..].as_ref(), test.output.as_slice());
83 }
84 }
85
86 #[test]
87 fn fmt_roundtrips() {
88 let hash = sha256d::Hash::hash(b"some arbitrary bytes");
89 let hex = format!("{}", hash);
90 let rinsed = hex.parse::<sha256d::Hash>().expect("failed to parse hex");
91 assert_eq!(rinsed, hash)
92 }
93
94 #[cfg(feature = "serde")]
95 #[test]
96 fn sha256_serde() {
97 use serde_test::{assert_tokens, Configure, Token};
98
99 #[rustfmt::skip]
100 static HASH_BYTES: [u8; 32] = [
101 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
102 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
103 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
104 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
105 ];
106
107 let hash = sha256d::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
108 assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
109 assert_tokens(
110 &hash.readable(),
111 &[Token::Str("6cfb35868c4465b7c289d7d5641563aa973db6a929655282a7bf95c8257f53ef")],
112 );
113 }
114}
115
116#[cfg(bench)]
117mod benches {
118 use test::Bencher;
119
120 use crate::{sha256d, Hash, HashEngine};
121
122 #[bench]
123 pub fn sha256d_10(bh: &mut Bencher) {
124 let mut engine = sha256d::Hash::engine();
125 let bytes = [1u8; 10];
126 bh.iter(|| {
127 engine.input(&bytes);
128 });
129 bh.bytes = bytes.len() as u64;
130 }
131
132 #[bench]
133 pub fn sha256d_1k(bh: &mut Bencher) {
134 let mut engine = sha256d::Hash::engine();
135 let bytes = [1u8; 1024];
136 bh.iter(|| {
137 engine.input(&bytes);
138 });
139 bh.bytes = bytes.len() as u64;
140 }
141
142 #[bench]
143 pub fn sha256d_64k(bh: &mut Bencher) {
144 let mut engine = sha256d::Hash::engine();
145 let bytes = [1u8; 65536];
146 bh.iter(|| {
147 engine.input(&bytes);
148 });
149 bh.bytes = bytes.len() as u64;
150 }
151}