]> git.lizzy.rs Git - rust.git/blob - src/libstd/to_bytes.rs
auto merge of #10977 : brson/rust/androidtest, r=brson
[rust.git] / src / libstd / to_bytes.rs
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.
4 //
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.
10
11 /*!
12
13 The `ToBytes` and `IterBytes` traits
14
15 */
16
17 use cast;
18 use container::Container;
19 use iter::Iterator;
20 use option::{None, Option, Some};
21 use rc::Rc;
22 use str::{Str, StrSlice};
23 use vec::{Vector, ImmutableVector};
24
25 pub type Cb<'a> = 'a |buf: &[u8]| -> bool;
26
27 ///
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
32 /// completed.
33 ///
34 /// IterBytes should be implemented so that the extent of the
35 /// produced byte stream can be discovered, given the original
36 /// type.
37 /// For example, the IterBytes implementation for vectors emits
38 /// its length first, and enums should emit their discriminant.
39 ///
40 pub trait IterBytes {
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.
53     ///
54     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool;
55 }
56
57 impl IterBytes for bool {
58     #[inline]
59     fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
60         f([
61             *self as u8
62         ])
63     }
64 }
65
66 impl IterBytes for u8 {
67     #[inline]
68     fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
69         f([
70             *self
71         ])
72     }
73 }
74
75 impl IterBytes for u16 {
76     #[inline]
77     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
78         if lsb0 {
79             f([
80                 *self as u8,
81                 (*self >> 8) as u8
82             ])
83         } else {
84             f([
85                 (*self >> 8) as u8,
86                 *self as u8
87             ])
88         }
89     }
90 }
91
92 impl IterBytes for u32 {
93     #[inline]
94     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
95         if lsb0 {
96             f([
97                 *self as u8,
98                 (*self >> 8) as u8,
99                 (*self >> 16) as u8,
100                 (*self >> 24) as u8,
101             ])
102         } else {
103             f([
104                 (*self >> 24) as u8,
105                 (*self >> 16) as u8,
106                 (*self >> 8) as u8,
107                 *self as u8
108             ])
109         }
110     }
111 }
112
113 impl IterBytes for u64 {
114     #[inline]
115     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
116         if lsb0 {
117             f([
118                 *self as u8,
119                 (*self >> 8) as u8,
120                 (*self >> 16) as u8,
121                 (*self >> 24) as u8,
122                 (*self >> 32) as u8,
123                 (*self >> 40) as u8,
124                 (*self >> 48) as u8,
125                 (*self >> 56) as u8
126             ])
127         } else {
128             f([
129                 (*self >> 56) as u8,
130                 (*self >> 48) as u8,
131                 (*self >> 40) as u8,
132                 (*self >> 32) as u8,
133                 (*self >> 24) as u8,
134                 (*self >> 16) as u8,
135                 (*self >> 8) as u8,
136                 *self as u8
137             ])
138         }
139     }
140 }
141
142 impl IterBytes for i8 {
143     #[inline]
144     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
145         (*self as u8).iter_bytes(lsb0, f)
146     }
147 }
148
149 impl IterBytes for i16 {
150     #[inline]
151     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
152         (*self as u16).iter_bytes(lsb0, f)
153     }
154 }
155
156 impl IterBytes for i32 {
157     #[inline]
158     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
159         (*self as u32).iter_bytes(lsb0, f)
160     }
161 }
162
163 impl IterBytes for i64 {
164     #[inline]
165     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
166         (*self as u64).iter_bytes(lsb0, f)
167     }
168 }
169
170 impl IterBytes for char {
171     #[inline]
172     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
173         (*self as u32).iter_bytes(lsb0, f)
174     }
175 }
176
177 #[cfg(target_word_size = "32")]
178 impl IterBytes for uint {
179     #[inline]
180     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
181         (*self as u32).iter_bytes(lsb0, f)
182     }
183 }
184
185 #[cfg(target_word_size = "64")]
186 impl IterBytes for uint {
187     #[inline]
188     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
189         (*self as u64).iter_bytes(lsb0, f)
190     }
191 }
192
193 impl IterBytes for int {
194     #[inline]
195     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
196         (*self as uint).iter_bytes(lsb0, f)
197     }
198 }
199
200 impl IterBytes for f32 {
201     #[inline]
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 })
206         };
207         i.iter_bytes(lsb0, f)
208     }
209 }
210
211 impl IterBytes for f64 {
212     #[inline]
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 })
217         };
218         i.iter_bytes(lsb0, f)
219     }
220 }
221
222 impl<'a,A:IterBytes> IterBytes for &'a [A] {
223     #[inline]
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)))
227     }
228 }
229
230 impl<A: IterBytes> IterBytes for (A, ) {
231     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
232         match *self {
233             (ref a, ) => a.iter_bytes(lsb0, |b| f(b))
234         }
235     }
236 }
237
238 macro_rules! iter_bytes_tuple(
239     ($($A:ident),+) => (
240         impl<$($A: IterBytes),+> IterBytes for ($($A),+) {
241             fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
242                 match *self {
243                     ($(ref $A),+) => {
244                         $(
245                             $A .iter_bytes(lsb0, |b| f(b))
246                         )&&+
247                     }
248                 }
249             }
250         }
251     )
252 )
253
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)
261
262 impl<A:IterBytes> IterBytes for ~[A] {
263     #[inline]
264     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
265         self.as_slice().iter_bytes(lsb0, f)
266     }
267 }
268
269 impl<A:IterBytes> IterBytes for @[A] {
270     #[inline]
271     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
272         self.as_slice().iter_bytes(lsb0, f)
273     }
274 }
275
276 impl<'a> IterBytes for &'a str {
277     #[inline]
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])
281     }
282 }
283
284 impl IterBytes for ~str {
285     #[inline]
286     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
287         self.as_slice().iter_bytes(lsb0, f)
288     }
289 }
290
291 impl IterBytes for @str {
292     #[inline]
293     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
294         self.as_slice().iter_bytes(lsb0, f)
295     }
296 }
297
298 impl<A:IterBytes> IterBytes for Option<A> {
299     #[inline]
300     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
301         match *self {
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)
304         }
305     }
306 }
307
308 impl<'a,A:IterBytes> IterBytes for &'a A {
309     #[inline]
310     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
311         (**self).iter_bytes(lsb0, f)
312     }
313 }
314
315 impl<A:IterBytes> IterBytes for @A {
316     #[inline]
317     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
318         (**self).iter_bytes(lsb0, f)
319     }
320 }
321
322 impl<A:IterBytes> IterBytes for @mut A {
323     #[inline]
324     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
325         (**self).iter_bytes(lsb0, f)
326     }
327 }
328
329 impl<A:IterBytes> IterBytes for Rc<A> {
330     #[inline]
331     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
332         self.borrow().iter_bytes(lsb0, f)
333     }
334 }
335
336 impl<A:IterBytes> IterBytes for ~A {
337     #[inline]
338     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
339         (**self).iter_bytes(lsb0, f)
340     }
341 }
342
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 {
346     #[inline]
347     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
348         (*self as uint).iter_bytes(lsb0, f)
349     }
350 }
351
352 impl<A> IterBytes for *mut A {
353     #[inline]
354     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
355         (*self as uint).iter_bytes(lsb0, f)
356     }
357 }
358
359 /// A trait for converting a value to a list of bytes.
360 pub trait ToBytes {
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
363     /// array
364     fn to_bytes(&self, lsb0: bool) -> ~[u8];
365 }
366
367 impl<A:IterBytes> ToBytes for A {
368     fn to_bytes(&self, lsb0: bool) -> ~[u8] {
369         use io::mem;
370         use io::Writer;
371
372         mem::with_mem_writer(|wr| {
373             self.iter_bytes(lsb0, |bytes| {
374                 wr.write(bytes);
375                 true
376             });
377         })
378     }
379 }
380
381 #[cfg(test)]
382 mod test {
383     use super::*;
384     // just test to see if it compiles:
385     #[test] fn iterbytes_compiles () {
386         takes_iterbytes((3,4,5,false));
387     }
388     fn takes_iterbytes<T : IterBytes>(_x : T) {}
389 }