@@ -15,37 +15,43 @@ The `ToBytes` and `IterBytes` traits
15
15
*/
16
16
17
17
use cast;
18
+ use container:: Container ;
18
19
use io;
19
20
use io:: Writer ;
20
21
use iterator:: Iterator ;
21
22
use option:: { None , Option , Some } ;
22
- use str:: StrSlice ;
23
- use vec:: ImmutableVector ;
23
+ use str:: { Str , StrSlice } ;
24
+ use vec:: { Vector , ImmutableVector } ;
24
25
25
26
pub type Cb < ' self > = & ' self fn ( buf : & [ u8 ] ) -> bool ;
26
27
27
- /**
28
- * A trait to implement in order to make a type hashable;
29
- * This works in combination with the trait `Hash::Hash`, and
30
- * may in the future be merged with that trait or otherwise
31
- * modified when default methods and trait inheritance are
32
- * completed.
33
- */
28
+ ///
29
+ /// A trait to implement in order to make a type hashable;
30
+ /// This works in combination with the trait `std::hash::Hash`, and
31
+ /// may in the future be merged with that trait or otherwise
32
+ /// modified when default methods and trait inheritance are
33
+ /// completed.
34
+ ///
35
+ /// IterBytes should be implemented so that the extent of the
36
+ /// produced byte stream can be discovered, given the original
37
+ /// type.
38
+ /// For example, the IterBytes implementation for vectors emits
39
+ /// its length first, and enums should emit their discriminant.
40
+ ///
34
41
pub trait IterBytes {
35
- /**
36
- * Call the provided callback `f` one or more times with
37
- * byte-slices that should be used when computing a hash
38
- * value or otherwise "flattening" the structure into
39
- * a sequence of bytes. The `lsb0` parameter conveys
40
- * whether the caller is asking for little-endian bytes
41
- * (`true`) or big-endian (`false`); this should only be
42
- * relevant in implementations that represent a single
43
- * multi-byte datum such as a 32 bit integer or 64 bit
44
- * floating-point value. It can be safely ignored for
45
- * larger structured types as they are usually processed
46
- * left-to-right in declaration order, regardless of
47
- * underlying memory endianness.
48
- */
42
+ /// Call the provided callback `f` one or more times with
43
+ /// byte-slices that should be used when computing a hash
44
+ /// value or otherwise "flattening" the structure into
45
+ /// a sequence of bytes. The `lsb0` parameter conveys
46
+ /// whether the caller is asking for little-endian bytes
47
+ /// (`true`) or big-endian (`false`); this should only be
48
+ /// relevant in implementations that represent a single
49
+ /// multi-byte datum such as a 32 bit integer or 64 bit
50
+ /// floating-point value. It can be safely ignored for
51
+ /// larger structured types as they are usually processed
52
+ /// left-to-right in declaration order, regardless of
53
+ /// underlying memory endianness.
54
+ ///
49
55
fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool ;
50
56
}
51
57
@@ -224,74 +230,76 @@ impl IterBytes for f64 {
224
230
impl < ' self , A : IterBytes > IterBytes for & ' self [ A ] {
225
231
#[ inline]
226
232
fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
233
+ self . len ( ) . iter_bytes ( lsb0, |b| f ( b) ) &&
227
234
self . iter ( ) . advance ( |elt| elt. iter_bytes ( lsb0, |b| f ( b) ) )
228
235
}
229
236
}
230
237
231
- impl < A : IterBytes , B : IterBytes > IterBytes for ( A , B ) {
232
- #[ inline]
233
- fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
234
- match * self {
235
- ( ref a, ref b) => { a. iter_bytes ( lsb0, |b| f ( b) ) &&
236
- b. iter_bytes ( lsb0, |b| f ( b) ) }
237
- }
238
- }
239
- }
240
-
241
- impl < A : IterBytes , B : IterBytes , C : IterBytes > IterBytes for ( A , B , C ) {
242
- #[ inline]
243
- fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
244
- match * self {
245
- ( ref a, ref b, ref c) => {
246
- a. iter_bytes ( lsb0, |b| f ( b) ) &&
247
- b. iter_bytes ( lsb0, |b| f ( b) ) &&
248
- c. iter_bytes ( lsb0, |b| f ( b) )
249
- }
238
+ impl < A : IterBytes > IterBytes for ( A , ) {
239
+ fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
240
+ match * self {
241
+ ( ref a, ) => a. iter_bytes ( lsb0, |b| f ( b) )
242
+ }
250
243
}
251
- }
252
244
}
253
245
254
- // Move this to vec, probably.
255
- fn borrow < ' x , A > ( a : & ' x [ A ] ) -> & ' x [ A ] {
256
- a
257
- }
246
+ macro_rules! iter_bytes_tuple(
247
+ ( $( $A: ident) ,+) => (
248
+ impl <$( $A: IterBytes ) ,+> IterBytes for ( $( $A) ,+) {
249
+ fn iter_bytes( & self , lsb0: bool , f: Cb ) -> bool {
250
+ match * self {
251
+ ( $( ref $A) ,+) => {
252
+ $(
253
+ $A . iter_bytes( lsb0, |b| f( b) )
254
+ ) &&+
255
+ }
256
+ }
257
+ }
258
+ }
259
+ )
260
+ )
261
+
262
+ iter_bytes_tuple ! ( A , B )
263
+ iter_bytes_tuple ! ( A , B , C )
264
+ iter_bytes_tuple ! ( A , B , C , D )
265
+ iter_bytes_tuple ! ( A , B , C , D , E )
266
+ iter_bytes_tuple ! ( A , B , C , D , E , F )
267
+ iter_bytes_tuple ! ( A , B , C , D , E , F , G )
268
+ iter_bytes_tuple ! ( A , B , C , D , E , F , G , H )
258
269
259
270
impl < A : IterBytes > IterBytes for ~[ A ] {
260
271
#[ inline]
261
272
fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
262
- borrow ( * self ) . iter_bytes ( lsb0, f)
273
+ self . as_slice ( ) . iter_bytes ( lsb0, f)
263
274
}
264
275
}
265
276
266
277
impl < A : IterBytes > IterBytes for @[ A ] {
267
278
#[ inline]
268
279
fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
269
- borrow ( * self ) . iter_bytes ( lsb0, f)
280
+ self . as_slice ( ) . iter_bytes ( lsb0, f)
270
281
}
271
282
}
272
283
273
284
impl < ' self > IterBytes for & ' self str {
274
285
#[ inline]
275
286
fn iter_bytes ( & self , _lsb0 : bool , f : Cb ) -> bool {
276
- f ( self . as_bytes ( ) )
287
+ // Terminate the string with a byte that does not appear in UTF-8
288
+ f ( self . as_bytes ( ) ) && f ( [ 0xFF ] )
277
289
}
278
290
}
279
291
280
292
impl IterBytes for ~str {
281
293
#[ inline]
282
- fn iter_bytes ( & self , _lsb0 : bool , f : Cb ) -> bool {
283
- // this should possibly include the null terminator, but that
284
- // breaks .find_equiv on hashmaps.
285
- f ( self . as_bytes ( ) )
294
+ fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
295
+ self . as_slice ( ) . iter_bytes ( lsb0, f)
286
296
}
287
297
}
288
298
289
299
impl IterBytes for @str {
290
300
#[ inline]
291
- fn iter_bytes ( & self , _lsb0 : bool , f : Cb ) -> bool {
292
- // this should possibly include the null terminator, but that
293
- // breaks .find_equiv on hashmaps.
294
- f ( self . as_bytes ( ) )
301
+ fn iter_bytes ( & self , lsb0 : bool , f : Cb ) -> bool {
302
+ self . as_slice ( ) . iter_bytes ( lsb0, f)
295
303
}
296
304
}
297
305
0 commit comments