8
8
9
9
mod errors;
10
10
mod hashes;
11
+ mod storage;
11
12
12
13
use std:: convert:: TryFrom ;
14
+ use std:: fmt:: Debug ;
15
+ use std:: hash;
13
16
14
17
use blake2b_simd:: { blake2b, Params as Blake2bVariable } ;
15
18
use blake2s_simd:: { blake2s, Params as Blake2sVariable } ;
16
- use bytes:: { BufMut , Bytes , BytesMut } ;
17
19
use sha2:: Digest ;
18
20
use tiny_keccak:: Keccak ;
19
21
use unsigned_varint:: { decode, encode} ;
20
22
21
23
pub use errors:: { DecodeError , DecodeOwnedError , EncodeError } ;
22
24
pub use hashes:: Hash ;
25
+ use std:: fmt;
26
+ use storage:: Storage ;
23
27
24
28
// Helper macro for encoding input into output using sha1, sha2, tiny_keccak, or blake2
25
29
macro_rules! encode {
@@ -107,12 +111,12 @@ pub fn encode(hash: Hash, input: &[u8]) -> Result<Multihash, EncodeError> {
107
111
108
112
let total_len = code. len ( ) + size. len ( ) + input. len ( ) ;
109
113
110
- let mut output = BytesMut :: with_capacity ( total_len) ;
111
- output. put_slice ( code) ;
112
- output. put_slice ( size) ;
113
- output. put_slice ( input) ;
114
+ let mut output = Vec :: with_capacity ( total_len) ;
115
+ output. extend_from_slice ( code) ;
116
+ output. extend_from_slice ( size) ;
117
+ output. extend_from_slice ( input) ;
114
118
Ok ( Multihash {
115
- bytes : output . freeze ( ) ,
119
+ storage : Storage :: copy_from_slice ( & output ) ,
116
120
} )
117
121
} else {
118
122
let ( offset, mut output) = encode_hash ( hash) ;
@@ -135,31 +139,51 @@ pub fn encode(hash: Hash, input: &[u8]) -> Result<Multihash, EncodeError> {
135
139
} ) ;
136
140
137
141
Ok ( Multihash {
138
- bytes : output . freeze ( ) ,
142
+ storage : Storage :: copy_from_slice ( & output ) ,
139
143
} )
140
144
}
141
145
}
142
146
143
- // Encode the given [`Hash`] value and ensure the returned [`BytesMut `]
147
+ // Encode the given [`Hash`] value and ensure the returned [`Vec<u8> `]
144
148
// has enough capacity to hold the actual digest.
145
- fn encode_hash ( hash : Hash ) -> ( usize , BytesMut ) {
149
+ fn encode_hash ( hash : Hash ) -> ( usize , Vec < u8 > ) {
146
150
let mut buf = encode:: u16_buffer ( ) ;
147
151
let code = encode:: u16 ( hash. code ( ) , & mut buf) ;
148
152
149
153
let len = code. len ( ) + 1 + usize:: from ( hash. size ( ) ) ;
150
154
151
- let mut output = BytesMut :: with_capacity ( len) ;
152
- output. put_slice ( code) ;
153
- output. put_u8 ( hash. size ( ) ) ;
155
+ let mut output = Vec :: with_capacity ( len) ;
156
+ output. extend_from_slice ( code) ;
157
+ output. push ( hash. size ( ) ) ;
154
158
output. resize ( len, 0 ) ;
155
159
156
160
( code. len ( ) + 1 , output)
157
161
}
158
162
159
163
/// Represents a valid multihash.
160
- #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
164
+ #[ derive( Clone ) ]
161
165
pub struct Multihash {
162
- bytes : Bytes ,
166
+ storage : Storage ,
167
+ }
168
+
169
+ impl Debug for Multihash {
170
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
171
+ write ! ( f, "Multihash" )
172
+ }
173
+ }
174
+
175
+ impl PartialEq for Multihash {
176
+ fn eq ( & self , other : & Self ) -> bool {
177
+ self . storage . bytes ( ) == other. storage . bytes ( )
178
+ }
179
+ }
180
+
181
+ impl Eq for Multihash { }
182
+
183
+ impl hash:: Hash for Multihash {
184
+ fn hash < H : hash:: Hasher > ( & self , state : & mut H ) {
185
+ self . storage . bytes ( ) . hash ( state) ;
186
+ }
163
187
}
164
188
165
189
impl Multihash {
@@ -172,7 +196,7 @@ impl Multihash {
172
196
} ) ;
173
197
}
174
198
Ok ( Multihash {
175
- bytes : Bytes :: from ( bytes) ,
199
+ storage : Storage :: copy_from_slice ( & bytes) ,
176
200
} )
177
201
}
178
202
@@ -183,17 +207,21 @@ impl Multihash {
183
207
184
208
/// Returns the bytes representation of the multihash.
185
209
pub fn to_vec ( & self ) -> Vec < u8 > {
186
- Vec :: from ( & self . bytes [ .. ] )
210
+ Vec :: from ( self . as_bytes ( ) )
187
211
}
188
212
189
213
/// Returns the bytes representation of this multihash.
190
214
pub fn as_bytes ( & self ) -> & [ u8 ] {
191
- & self . bytes
215
+ let bytes = self . storage . bytes ( ) ;
216
+ let size = multihash_size ( bytes) . expect ( "storage contains a valid multihash" ) ;
217
+ & bytes[ ..size]
192
218
}
193
219
194
220
/// Builds a `MultihashRef` corresponding to this `Multihash`.
195
221
pub fn as_ref ( & self ) -> MultihashRef {
196
- MultihashRef { bytes : & self . bytes }
222
+ MultihashRef {
223
+ bytes : self . as_bytes ( ) ,
224
+ }
197
225
}
198
226
199
227
/// Returns which hashing algorithm is used in this multihash.
@@ -215,7 +243,7 @@ impl AsRef<[u8]> for Multihash {
215
243
216
244
impl < ' a > PartialEq < MultihashRef < ' a > > for Multihash {
217
245
fn eq ( & self , other : & MultihashRef < ' a > ) -> bool {
218
- & * self . bytes == other. bytes
246
+ & * self . as_bytes ( ) == other. as_bytes ( )
219
247
}
220
248
}
221
249
@@ -233,6 +261,30 @@ pub struct MultihashRef<'a> {
233
261
bytes : & ' a [ u8 ] ,
234
262
}
235
263
264
+ /// Given a buffer starting with a valid multihash, returns the size of the multihash
265
+ fn multihash_size ( input : & [ u8 ] ) -> Result < usize , DecodeError > {
266
+ if input. is_empty ( ) {
267
+ return Err ( DecodeError :: BadInputLength ) ;
268
+ }
269
+ let mut res = 0usize ;
270
+
271
+ // Ensure `Hash::code` returns a `u16` so that our `decode::u16` here is correct.
272
+ std:: convert:: identity :: < fn ( Hash ) -> u16 > ( Hash :: code) ;
273
+ let ( code, bytes) = decode:: u16 ( & input) . map_err ( |_| DecodeError :: BadInputLength ) ?;
274
+
275
+ // Very convoluted way to get the size of the code
276
+ let mut tmp = [ 0u8 ; 3 ] ;
277
+ res += unsigned_varint:: encode:: u16 ( code, & mut tmp) . len ( ) ;
278
+
279
+ let ( hash_len, _) = decode:: u32 ( & bytes) . map_err ( |_| DecodeError :: BadInputLength ) ?;
280
+
281
+ // Very convoluted way to get the size of the hash_len
282
+ let mut tmp = [ 0u8 ; 5 ] ;
283
+ res += unsigned_varint:: encode:: u32 ( hash_len, & mut tmp) . len ( ) ;
284
+ res += hash_len as usize ;
285
+ Ok ( res)
286
+ }
287
+
236
288
impl < ' a > MultihashRef < ' a > {
237
289
/// Creates a `MultihashRef` from the given `input`.
238
290
pub fn from_slice ( input : & ' a [ u8 ] ) -> Result < Self , DecodeError > {
@@ -290,7 +342,7 @@ impl<'a> MultihashRef<'a> {
290
342
/// This operation allocates.
291
343
pub fn to_owned ( & self ) -> Multihash {
292
344
Multihash {
293
- bytes : Bytes :: copy_from_slice ( self . bytes ) ,
345
+ storage : Storage :: copy_from_slice ( self . bytes ) ,
294
346
}
295
347
}
296
348
@@ -302,7 +354,7 @@ impl<'a> MultihashRef<'a> {
302
354
303
355
impl < ' a > PartialEq < Multihash > for MultihashRef < ' a > {
304
356
fn eq ( & self , other : & Multihash ) -> bool {
305
- self . bytes == & * other. bytes
357
+ self . as_bytes ( ) == & * other. as_bytes ( )
306
358
}
307
359
}
308
360
0 commit comments