@@ -79,26 +79,47 @@ macro_rules! match_encoder {
79
79
/// ```
80
80
///
81
81
pub fn encode ( hash : Hash , input : & [ u8 ] ) -> Result < Multihash , EncodeError > {
82
- let ( offset, mut output) = encode_hash ( hash) ;
83
- match_encoder ! ( hash for ( input, & mut output[ offset ..] ) {
84
- SHA1 => sha1:: Sha1 ,
85
- SHA2256 => sha2:: Sha256 ,
86
- SHA2512 => sha2:: Sha512 ,
87
- SHA3224 => tiny:: new_sha3_224,
88
- SHA3256 => tiny:: new_sha3_256,
89
- SHA3384 => tiny:: new_sha3_384,
90
- SHA3512 => tiny:: new_sha3_512,
91
- Keccak224 => tiny:: new_keccak224,
92
- Keccak256 => tiny:: new_keccak256,
93
- Keccak384 => tiny:: new_keccak384,
94
- Keccak512 => tiny:: new_keccak512,
95
- Blake2b512 => blake2:: blake2b,
96
- Blake2s256 => blake2:: blake2s,
97
- } ) ;
98
-
99
- Ok ( Multihash {
100
- bytes : output. freeze ( ) ,
101
- } )
82
+ // Custom length encoding for the identity multihash
83
+ if let Hash :: Identity = hash {
84
+ if u64:: from ( std:: u32:: MAX ) < as_u64 ( input. len ( ) ) {
85
+ return Err ( EncodeError :: UnsupportedInputLength ) ;
86
+ }
87
+ let mut buf = encode:: u16_buffer ( ) ;
88
+ let code = encode:: u16 ( hash. code ( ) , & mut buf) ;
89
+ let mut len_buf = encode:: u32_buffer ( ) ;
90
+ let size = encode:: u32 ( input. len ( ) as u32 , & mut len_buf) ;
91
+
92
+ let total_len = code. len ( ) + size. len ( ) + input. len ( ) ;
93
+
94
+ let mut output = BytesMut :: with_capacity ( total_len) ;
95
+ output. put_slice ( code) ;
96
+ output. put_slice ( size) ;
97
+ output. put_slice ( input) ;
98
+ Ok ( Multihash {
99
+ bytes : output. freeze ( ) ,
100
+ } )
101
+ } else {
102
+ let ( offset, mut output) = encode_hash ( hash) ;
103
+ match_encoder ! ( hash for ( input, & mut output[ offset ..] ) {
104
+ SHA1 => sha1:: Sha1 ,
105
+ SHA2256 => sha2:: Sha256 ,
106
+ SHA2512 => sha2:: Sha512 ,
107
+ SHA3224 => tiny:: new_sha3_224,
108
+ SHA3256 => tiny:: new_sha3_256,
109
+ SHA3384 => tiny:: new_sha3_384,
110
+ SHA3512 => tiny:: new_sha3_512,
111
+ Keccak224 => tiny:: new_keccak224,
112
+ Keccak256 => tiny:: new_keccak256,
113
+ Keccak384 => tiny:: new_keccak384,
114
+ Keccak512 => tiny:: new_keccak512,
115
+ Blake2b512 => blake2:: blake2b,
116
+ Blake2s256 => blake2:: blake2s,
117
+ } ) ;
118
+
119
+ Ok ( Multihash {
120
+ bytes : output. freeze ( ) ,
121
+ } )
122
+ }
102
123
}
103
124
104
125
// Encode the given [`Hash`] value and ensure the returned [`BytesMut`]
@@ -206,6 +227,16 @@ impl<'a> MultihashRef<'a> {
206
227
let ( code, bytes) = decode:: u16 ( & input) . map_err ( |_| DecodeError :: BadInputLength ) ?;
207
228
208
229
let alg = Hash :: from_code ( code) . ok_or ( DecodeError :: UnknownCode ) ?;
230
+
231
+ // handle the identity case
232
+ if alg == Hash :: Identity {
233
+ let ( hash_len, bytes) = decode:: u32 ( & bytes) . map_err ( |_| DecodeError :: BadInputLength ) ?;
234
+ if as_u64 ( bytes. len ( ) ) != u64:: from ( hash_len) {
235
+ return Err ( DecodeError :: BadInputLength ) ;
236
+ }
237
+ return Ok ( MultihashRef { bytes : input } ) ;
238
+ }
239
+
209
240
let hash_len = usize:: from ( alg. size ( ) ) ;
210
241
211
242
// Length of input after hash code should be exactly hash_len + 1
@@ -256,3 +287,8 @@ impl<'a> PartialEq<Multihash> for MultihashRef<'a> {
256
287
self . bytes == & * other. bytes
257
288
}
258
289
}
290
+
291
+ #[ cfg( any( target_pointer_width = "32" , target_pointer_width = "64" ) ) ]
292
+ fn as_u64 ( a : usize ) -> u64 {
293
+ a as u64
294
+ }
0 commit comments