@@ -13,6 +13,7 @@ use std::convert::TryFrom;
13
13
14
14
use blake2b_simd:: blake2b;
15
15
use blake2s_simd:: blake2s;
16
+ use bytes:: { BufMut , Bytes , BytesMut } ;
16
17
use sha2:: Digest ;
17
18
use tiny_keccak:: Keccak ;
18
19
use unsigned_varint:: { decode, encode} ;
@@ -71,25 +72,15 @@ macro_rules! match_encoder {
71
72
/// use multihash::{encode, Hash};
72
73
///
73
74
/// assert_eq!(
74
- /// encode(Hash::SHA2256, b"hello world").unwrap().into_bytes (),
75
+ /// encode(Hash::SHA2256, b"hello world").unwrap().to_vec (),
75
76
/// vec![18, 32, 185, 77, 39, 185, 147, 77, 62, 8, 165, 46, 82, 215, 218, 125, 171, 250, 196,
76
77
/// 132, 239, 227, 122, 83, 128, 238, 144, 136, 247, 172, 226, 239, 205, 233]
77
78
/// );
78
79
/// ```
79
80
///
80
81
pub fn encode ( hash : Hash , input : & [ u8 ] ) -> Result < Multihash , EncodeError > {
81
- let mut buf = encode:: u16_buffer ( ) ;
82
- let code = encode:: u16 ( hash. code ( ) , & mut buf) ;
83
-
84
- let header_len = code. len ( ) + 1 ;
85
- let size = hash. size ( ) ;
86
-
87
- let mut output = Vec :: new ( ) ;
88
- output. resize ( header_len + size as usize , 0 ) ;
89
- output[ ..code. len ( ) ] . copy_from_slice ( code) ;
90
- output[ code. len ( ) ] = size;
91
-
92
- match_encoder ! ( hash for ( input, & mut output[ header_len..] ) {
82
+ let ( offset, mut output) = encode_hash ( hash) ;
83
+ match_encoder ! ( hash for ( input, & mut output[ offset ..] ) {
93
84
SHA1 => sha1:: Sha1 ,
94
85
SHA2256 => sha2:: Sha256 ,
95
86
SHA2512 => sha2:: Sha512 ,
@@ -105,55 +96,73 @@ pub fn encode(hash: Hash, input: &[u8]) -> Result<Multihash, EncodeError> {
105
96
Blake2s256 => blake2:: blake2s,
106
97
} ) ;
107
98
108
- Ok ( Multihash { bytes : output } )
99
+ Ok ( Multihash {
100
+ bytes : output. freeze ( ) ,
101
+ } )
102
+ }
103
+
104
+ // Encode the given [`Hash`] value and ensure the returned [`BytesMut`]
105
+ // has enough capacity to hold the actual digest.
106
+ fn encode_hash ( hash : Hash ) -> ( usize , BytesMut ) {
107
+ let mut buf = encode:: u16_buffer ( ) ;
108
+ let code = encode:: u16 ( hash. code ( ) , & mut buf) ;
109
+
110
+ let len = code. len ( ) + 1 + usize:: from ( hash. size ( ) ) ;
111
+
112
+ let mut output = BytesMut :: with_capacity ( len) ;
113
+ output. put_slice ( code) ;
114
+ output. put_u8 ( hash. size ( ) ) ;
115
+ output. resize ( len, 0 ) ;
116
+
117
+ ( code. len ( ) + 1 , output)
109
118
}
110
119
111
120
/// Represents a valid multihash.
112
121
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
113
122
pub struct Multihash {
114
- bytes : Vec < u8 > ,
123
+ bytes : Bytes ,
115
124
}
116
125
117
126
impl Multihash {
118
127
/// Verifies whether `bytes` contains a valid multihash, and if so returns a `Multihash`.
119
- #[ inline]
120
128
pub fn from_bytes ( bytes : Vec < u8 > ) -> Result < Multihash , DecodeOwnedError > {
121
129
if let Err ( err) = MultihashRef :: from_slice ( & bytes) {
122
130
return Err ( DecodeOwnedError {
123
131
error : err,
124
132
data : bytes,
125
133
} ) ;
126
134
}
127
-
128
- Ok ( Multihash { bytes } )
135
+ Ok ( Multihash {
136
+ bytes : Bytes :: from ( bytes) ,
137
+ } )
129
138
}
130
139
131
140
/// Returns the bytes representation of the multihash.
132
- #[ inline]
133
141
pub fn into_bytes ( self ) -> Vec < u8 > {
134
- self . bytes
142
+ self . to_vec ( )
143
+ }
144
+
145
+ /// Returns the bytes representation of the multihash.
146
+ pub fn to_vec ( & self ) -> Vec < u8 > {
147
+ Vec :: from ( & self . bytes [ ..] )
135
148
}
136
149
137
150
/// Returns the bytes representation of this multihash.
138
- #[ inline]
139
151
pub fn as_bytes ( & self ) -> & [ u8 ] {
140
152
& self . bytes
141
153
}
142
154
143
155
/// Builds a `MultihashRef` corresponding to this `Multihash`.
144
- #[ inline]
145
156
pub fn as_ref ( & self ) -> MultihashRef {
146
157
MultihashRef { bytes : & self . bytes }
147
158
}
148
159
149
160
/// Returns which hashing algorithm is used in this multihash.
150
- #[ inline]
151
161
pub fn algorithm ( & self ) -> Hash {
152
162
self . as_ref ( ) . algorithm ( )
153
163
}
154
164
155
165
/// Returns the hashed data.
156
- #[ inline]
157
166
pub fn digest ( & self ) -> & [ u8 ] {
158
167
self . as_ref ( ) . digest ( )
159
168
}
@@ -166,7 +175,6 @@ impl AsRef<[u8]> for Multihash {
166
175
}
167
176
168
177
impl < ' a > PartialEq < MultihashRef < ' a > > for Multihash {
169
- #[ inline]
170
178
fn eq ( & self , other : & MultihashRef < ' a > ) -> bool {
171
179
& * self . bytes == other. bytes
172
180
}
@@ -187,64 +195,63 @@ pub struct MultihashRef<'a> {
187
195
}
188
196
189
197
impl < ' a > MultihashRef < ' a > {
190
- /// Verifies whether `bytes` contains a valid multihash, and if so returns a `MultihashRef `.
191
- pub fn from_slice ( input : & ' a [ u8 ] ) -> Result < MultihashRef < ' a > , DecodeError > {
198
+ /// Creates a `MultihashRef` from the given `input `.
199
+ pub fn from_slice ( input : & ' a [ u8 ] ) -> Result < Self , DecodeError > {
192
200
if input. is_empty ( ) {
193
201
return Err ( DecodeError :: BadInputLength ) ;
194
202
}
195
203
196
- // NOTE: We choose u16 here because there is no hashing algorithm implemented in this crate
197
- // whose length exceeds 2^16 - 1.
204
+ // Ensure `Hash::code` returns a ` u16` so that our `decode::u16` here is correct.
205
+ std :: convert :: identity :: < fn ( Hash ) -> u16 > ( Hash :: code ) ;
198
206
let ( code, bytes) = decode:: u16 ( & input) . map_err ( |_| DecodeError :: BadInputLength ) ?;
199
207
200
208
let alg = Hash :: from_code ( code) . ok_or ( DecodeError :: UnknownCode ) ?;
201
- let hash_len = alg. size ( ) as usize ;
209
+ let hash_len = usize :: from ( alg. size ( ) ) ;
202
210
203
211
// Length of input after hash code should be exactly hash_len + 1
204
212
if bytes. len ( ) != hash_len + 1 {
205
213
return Err ( DecodeError :: BadInputLength ) ;
206
214
}
207
215
208
- if bytes[ 0 ] as usize != hash_len {
216
+ if usize :: from ( bytes[ 0 ] ) != hash_len {
209
217
return Err ( DecodeError :: BadInputLength ) ;
210
218
}
211
219
212
220
Ok ( MultihashRef { bytes : input } )
213
221
}
214
222
215
223
/// Returns which hashing algorithm is used in this multihash.
216
- #[ inline]
217
224
pub fn algorithm ( & self ) -> Hash {
218
- let ( code, _) = decode:: u16 ( & self . bytes ) . expect ( "multihash is known to be valid algorithm" ) ;
225
+ let code = decode:: u16 ( & self . bytes )
226
+ . expect ( "multihash is known to be valid algorithm" )
227
+ . 0 ;
219
228
Hash :: from_code ( code) . expect ( "multihash is known to be valid" )
220
229
}
221
230
222
231
/// Returns the hashed data.
223
- #[ inline]
224
232
pub fn digest ( & self ) -> & ' a [ u8 ] {
225
- let ( _, bytes) = decode:: u16 ( & self . bytes ) . expect ( "multihash is known to be valid digest" ) ;
233
+ let bytes = decode:: u16 ( & self . bytes )
234
+ . expect ( "multihash is known to be valid digest" )
235
+ . 1 ;
226
236
& bytes[ 1 ..]
227
237
}
228
238
229
239
/// Builds a `Multihash` that owns the data.
230
240
///
231
241
/// This operation allocates.
232
- #[ inline]
233
242
pub fn to_owned ( & self ) -> Multihash {
234
243
Multihash {
235
- bytes : self . bytes . to_owned ( ) ,
244
+ bytes : Bytes :: copy_from_slice ( self . bytes ) ,
236
245
}
237
246
}
238
247
239
248
/// Returns the bytes representation of this multihash.
240
- #[ inline]
241
249
pub fn as_bytes ( & self ) -> & ' a [ u8 ] {
242
250
& self . bytes
243
251
}
244
252
}
245
253
246
254
impl < ' a > PartialEq < Multihash > for MultihashRef < ' a > {
247
- #[ inline]
248
255
fn eq ( & self , other : & Multihash ) -> bool {
249
256
self . bytes == & * other. bytes
250
257
}
0 commit comments