diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2013-05-17 10:45:09 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2013-05-22 21:57:05 -0700 |
| commit | 0c820d4123c754522b0655e9e74f692c55685bfa (patch) | |
| tree | 7dbb86c30b451217b4e8f75173043744fe3255ff /src/libstd/to_bytes.rs | |
| parent | 565942b145efbf6c1d1f66db46423d721b55d32c (diff) | |
| download | rust-0c820d4123c754522b0655e9e74f692c55685bfa.tar.gz rust-0c820d4123c754522b0655e9e74f692c55685bfa.zip | |
libstd: Rename libcore to libstd and libstd to libextra; update makefiles.
This only changes the directory names; it does not change the "real" metadata names.
Diffstat (limited to 'src/libstd/to_bytes.rs')
| -rw-r--r-- | src/libstd/to_bytes.rs | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs new file mode 100644 index 00000000000..5b66e94c1b4 --- /dev/null +++ b/src/libstd/to_bytes.rs @@ -0,0 +1,354 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +The `ToBytes` and `IterBytes` traits + +*/ + +use io; +use io::Writer; +use option::{None, Option, Some}; +use old_iter::BaseIter; +use str; + +pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool; + +/** + * A trait to implement in order to make a type hashable; + * This works in combination with the trait `Hash::Hash`, and + * may in the future be merged with that trait or otherwise + * modified when default methods and trait inheritence are + * completed. + */ +pub trait IterBytes { + /** + * Call the provided callback `f` one or more times with + * byte-slices that should be used when computing a hash + * value or otherwise "flattening" the structure into + * a sequence of bytes. The `lsb0` parameter conveys + * whether the caller is asking for little-endian bytes + * (`true`) or big-endian (`false`); this should only be + * relevant in implementations that represent a single + * multi-byte datum such as a 32 bit integer or 64 bit + * floating-point value. It can be safely ignored for + * larger structured types as they are usually processed + * left-to-right in declaration order, regardless of + * underlying memory endianness. + */ + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool; +} + +impl IterBytes for bool { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + f([ + *self as u8 + ]) + } +} + +impl IterBytes for u8 { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + f([ + *self + ]) + } +} + +impl IterBytes for u16 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + if lsb0 { + f([ + *self as u8, + (*self >> 8) as u8 + ]) + } else { + f([ + (*self >> 8) as u8, + *self as u8 + ]) + } + } +} + +impl IterBytes for u32 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + if lsb0 { + f([ + *self as u8, + (*self >> 8) as u8, + (*self >> 16) as u8, + (*self >> 24) as u8, + ]) + } else { + f([ + (*self >> 24) as u8, + (*self >> 16) as u8, + (*self >> 8) as u8, + *self as u8 + ]) + } + } +} + +impl IterBytes for u64 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + if lsb0 { + f([ + *self as u8, + (*self >> 8) as u8, + (*self >> 16) as u8, + (*self >> 24) as u8, + (*self >> 32) as u8, + (*self >> 40) as u8, + (*self >> 48) as u8, + (*self >> 56) as u8 + ]) + } else { + f([ + (*self >> 56) as u8, + (*self >> 48) as u8, + (*self >> 40) as u8, + (*self >> 32) as u8, + (*self >> 24) as u8, + (*self >> 16) as u8, + (*self >> 8) as u8, + *self as u8 + ]) + } + } +} + +impl IterBytes for i8 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u8).iter_bytes(lsb0, f) + } +} + +impl IterBytes for i16 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u16).iter_bytes(lsb0, f) + } +} + +impl IterBytes for i32 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u32).iter_bytes(lsb0, f) + } +} + +impl IterBytes for i64 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u64).iter_bytes(lsb0, f) + } +} + +impl IterBytes for char { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u32).iter_bytes(lsb0, f) + } +} + +#[cfg(target_word_size = "32")] +impl IterBytes for uint { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u32).iter_bytes(lsb0, f) + } +} + +#[cfg(target_word_size = "64")] +impl IterBytes for uint { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u64).iter_bytes(lsb0, f) + } +} + +impl IterBytes for int { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as uint).iter_bytes(lsb0, f) + } +} + +impl<'self,A:IterBytes> IterBytes for &'self [A] { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + self.each(|elt| elt.iter_bytes(lsb0, |b| f(b))) + } +} + +impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + match *self { + (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) } + } + } +} + +impl<A:IterBytes,B:IterBytes,C:IterBytes> IterBytes for (A,B,C) { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + match *self { + (ref a, ref b, ref c) => { + a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f) + } + } + } +} + +// Move this to vec, probably. +fn borrow<'x,A>(a: &'x [A]) -> &'x [A] { + a +} + +impl<A:IterBytes> IterBytes for ~[A] { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + borrow(*self).iter_bytes(lsb0, f) + } +} + +impl<A:IterBytes> IterBytes for @[A] { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + borrow(*self).iter_bytes(lsb0, f) + } +} + +// NOTE: remove all of these after a snapshot, the new for-loop iteration +// protocol makes these unnecessary. + +#[inline(always)] +pub fn iter_bytes_2<A:IterBytes,B:IterBytes>(a: &A, b: &B, + lsb0: bool, z: Cb) -> bool { + a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) +} + +pub fn iter_bytes_3<A: IterBytes, + B: IterBytes, + C: IterBytes>(a: &A, b: &B, c: &C, lsb0: bool, z: Cb) -> bool { + a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) +} + +pub fn iter_bytes_4<A: IterBytes, + B: IterBytes, + C: IterBytes, + D: IterBytes>(a: &A, b: &B, c: &C, + d: &D, + lsb0: bool, z: Cb) -> bool { + a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) && + d.iter_bytes(lsb0, z) +} + +pub fn iter_bytes_5<A: IterBytes, + B: IterBytes, + C: IterBytes, + D: IterBytes, + E: IterBytes>(a: &A, b: &B, c: &C, + d: &D, e: &E, + lsb0: bool, z: Cb) -> bool { + a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) && + d.iter_bytes(lsb0, z) && e.iter_bytes(lsb0, z) +} + +impl<'self> IterBytes for &'self str { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + do str::byte_slice(*self) |bytes| { + f(bytes) + } + } +} + +impl IterBytes for ~str { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + do str::byte_slice(*self) |bytes| { + f(bytes) + } + } +} + +impl IterBytes for @str { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + do str::byte_slice(*self) |bytes| { + f(bytes) + } + } +} + +impl<A:IterBytes> IterBytes for Option<A> { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + match *self { + Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f), + None => 1u8.iter_bytes(lsb0, f) + } + } +} + +impl<'self,A:IterBytes> IterBytes for &'self A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (**self).iter_bytes(lsb0, f) + } +} + +impl<A:IterBytes> IterBytes for @A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (**self).iter_bytes(lsb0, f) + } +} + +impl<A:IterBytes> IterBytes for ~A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (**self).iter_bytes(lsb0, f) + } +} + +// NB: raw-pointer IterBytes does _not_ dereference +// to the target; it just gives you the pointer-bytes. +impl<A> IterBytes for *const A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as uint).iter_bytes(lsb0, f) + } +} + +pub trait ToBytes { + fn to_bytes(&self, lsb0: bool) -> ~[u8]; +} + +impl<A:IterBytes> ToBytes for A { + fn to_bytes(&self, lsb0: bool) -> ~[u8] { + do io::with_bytes_writer |wr| { + for self.iter_bytes(lsb0) |bytes| { + wr.write(bytes) + } + } + } +} |
