1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 The `ToBytes` and `IterBytes` traits
18 use container::Container;
20 use option::{None, Option, Some};
22 use str::{Str, StrSlice};
23 use vec::{Vector, ImmutableVector};
25 pub type Cb<'a> = 'a |buf: &[u8]| -> bool;
28 /// A trait to implement in order to make a type hashable;
29 /// This works in combination with the trait `std::hash::Hash`, and
30 /// may in the future be merged with that trait or otherwise
31 /// modified when default methods and trait inheritance are
34 /// IterBytes should be implemented so that the extent of the
35 /// produced byte stream can be discovered, given the original
37 /// For example, the IterBytes implementation for vectors emits
38 /// its length first, and enums should emit their discriminant.
41 /// Call the provided callback `f` one or more times with
42 /// byte-slices that should be used when computing a hash
43 /// value or otherwise "flattening" the structure into
44 /// a sequence of bytes. The `lsb0` parameter conveys
45 /// whether the caller is asking for little-endian bytes
46 /// (`true`) or big-endian (`false`); this should only be
47 /// relevant in implementations that represent a single
48 /// multi-byte datum such as a 32 bit integer or 64 bit
49 /// floating-point value. It can be safely ignored for
50 /// larger structured types as they are usually processed
51 /// left-to-right in declaration order, regardless of
52 /// underlying memory endianness.
54 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool;
57 impl IterBytes for bool {
59 fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
66 impl IterBytes for u8 {
68 fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
75 impl IterBytes for u16 {
77 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
92 impl IterBytes for u32 {
94 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
113 impl IterBytes for u64 {
115 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
142 impl IterBytes for i8 {
144 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
145 (*self as u8).iter_bytes(lsb0, f)
149 impl IterBytes for i16 {
151 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
152 (*self as u16).iter_bytes(lsb0, f)
156 impl IterBytes for i32 {
158 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
159 (*self as u32).iter_bytes(lsb0, f)
163 impl IterBytes for i64 {
165 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
166 (*self as u64).iter_bytes(lsb0, f)
170 impl IterBytes for char {
172 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
173 (*self as u32).iter_bytes(lsb0, f)
177 #[cfg(target_word_size = "32")]
178 impl IterBytes for uint {
180 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
181 (*self as u32).iter_bytes(lsb0, f)
185 #[cfg(target_word_size = "64")]
186 impl IterBytes for uint {
188 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
189 (*self as u64).iter_bytes(lsb0, f)
193 impl IterBytes for int {
195 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
196 (*self as uint).iter_bytes(lsb0, f)
200 impl IterBytes for f32 {
202 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
203 let i: u32 = unsafe {
204 // 0.0 == -0.0 so they should also have the same hashcode
205 cast::transmute(if *self == -0.0 { 0.0 } else { *self })
207 i.iter_bytes(lsb0, f)
211 impl IterBytes for f64 {
213 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
214 let i: u64 = unsafe {
215 // 0.0 == -0.0 so they should also have the same hashcode
216 cast::transmute(if *self == -0.0 { 0.0 } else { *self })
218 i.iter_bytes(lsb0, f)
222 impl<'a,A:IterBytes> IterBytes for &'a [A] {
224 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
225 self.len().iter_bytes(lsb0, |b| f(b)) &&
226 self.iter().advance(|elt| elt.iter_bytes(lsb0, |b| f(b)))
230 impl<A: IterBytes> IterBytes for (A, ) {
231 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
233 (ref a, ) => a.iter_bytes(lsb0, |b| f(b))
238 macro_rules! iter_bytes_tuple(
240 impl<$($A: IterBytes),+> IterBytes for ($($A),+) {
241 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
245 $A .iter_bytes(lsb0, |b| f(b))
254 iter_bytes_tuple!(A, B)
255 iter_bytes_tuple!(A, B, C)
256 iter_bytes_tuple!(A, B, C, D)
257 iter_bytes_tuple!(A, B, C, D, E)
258 iter_bytes_tuple!(A, B, C, D, E, F)
259 iter_bytes_tuple!(A, B, C, D, E, F, G)
260 iter_bytes_tuple!(A, B, C, D, E, F, G, H)
262 impl<A:IterBytes> IterBytes for ~[A] {
264 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
265 self.as_slice().iter_bytes(lsb0, f)
269 impl<A:IterBytes> IterBytes for @[A] {
271 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
272 self.as_slice().iter_bytes(lsb0, f)
276 impl<'a> IterBytes for &'a str {
278 fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
279 // Terminate the string with a byte that does not appear in UTF-8
280 f(self.as_bytes()) && f([0xFF])
284 impl IterBytes for ~str {
286 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
287 self.as_slice().iter_bytes(lsb0, f)
291 impl IterBytes for @str {
293 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
294 self.as_slice().iter_bytes(lsb0, f)
298 impl<A:IterBytes> IterBytes for Option<A> {
300 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
302 Some(ref a) => 0u8.iter_bytes(lsb0, |b| f(b)) && a.iter_bytes(lsb0, |b| f(b)),
303 None => 1u8.iter_bytes(lsb0, f)
308 impl<'a,A:IterBytes> IterBytes for &'a A {
310 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
311 (**self).iter_bytes(lsb0, f)
315 impl<A:IterBytes> IterBytes for @A {
317 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
318 (**self).iter_bytes(lsb0, f)
322 impl<A:IterBytes> IterBytes for @mut A {
324 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
325 (**self).iter_bytes(lsb0, f)
329 impl<A:IterBytes> IterBytes for Rc<A> {
331 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
332 self.borrow().iter_bytes(lsb0, f)
336 impl<A:IterBytes> IterBytes for ~A {
338 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
339 (**self).iter_bytes(lsb0, f)
343 // NB: raw-pointer IterBytes does _not_ dereference
344 // to the target; it just gives you the pointer-bytes.
345 impl<A> IterBytes for *A {
347 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
348 (*self as uint).iter_bytes(lsb0, f)
352 impl<A> IterBytes for *mut A {
354 fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
355 (*self as uint).iter_bytes(lsb0, f)
359 /// A trait for converting a value to a list of bytes.
361 /// Converts the current value to a list of bytes. This is equivalent to
362 /// invoking iter_bytes on a type and collecting all yielded values in an
364 fn to_bytes(&self, lsb0: bool) -> ~[u8];
367 impl<A:IterBytes> ToBytes for A {
368 fn to_bytes(&self, lsb0: bool) -> ~[u8] {
372 mem::with_mem_writer(|wr| {
373 self.iter_bytes(lsb0, |bytes| {
384 // just test to see if it compiles:
385 #[test] fn iterbytes_compiles () {
386 takes_iterbytes((3,4,5,false));
388 fn takes_iterbytes<T : IterBytes>(_x : T) {}