2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2012-09-19 18:52:32 -05:00
|
|
|
/*!
|
|
|
|
|
2013-12-24 10:08:28 -06:00
|
|
|
The `ToBytes` and `IterBytes` traits for converting to raw bytes
|
2012-09-19 18:52:32 -05:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2013-06-15 11:58:38 -05:00
|
|
|
use cast;
|
2013-08-14 22:23:33 -05:00
|
|
|
use container::Container;
|
2013-09-08 10:01:16 -05:00
|
|
|
use iter::Iterator;
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::{None, Option, Some};
|
2013-11-25 12:47:09 -06:00
|
|
|
use rc::Rc;
|
2013-08-14 22:23:33 -05:00
|
|
|
use str::{Str, StrSlice};
|
|
|
|
use vec::{Vector, ImmutableVector};
|
2012-08-30 13:10:01 -05:00
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
pub type Cb<'a> = 'a |buf: &[u8]| -> bool;
|
2012-08-30 13:10:01 -05:00
|
|
|
|
2013-08-14 22:23:33 -05:00
|
|
|
///
|
|
|
|
/// A trait to implement in order to make a type hashable;
|
|
|
|
/// This works in combination with the trait `std::hash::Hash`, and
|
|
|
|
/// may in the future be merged with that trait or otherwise
|
|
|
|
/// modified when default methods and trait inheritance are
|
|
|
|
/// completed.
|
|
|
|
///
|
|
|
|
/// IterBytes should be implemented so that the extent of the
|
|
|
|
/// produced byte stream can be discovered, given the original
|
|
|
|
/// type.
|
|
|
|
/// For example, the IterBytes implementation for vectors emits
|
|
|
|
/// its length first, and enums should emit their discriminant.
|
|
|
|
///
|
2012-09-28 19:41:45 -05:00
|
|
|
pub trait IterBytes {
|
2013-08-14 22:23:33 -05:00
|
|
|
/// 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.
|
|
|
|
///
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool;
|
2012-11-28 13:36:04 -06:00
|
|
|
}
|
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for bool {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
|
|
|
|
f([
|
|
|
|
*self as u8
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for u8 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
|
|
|
|
f([
|
|
|
|
*self
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for u16 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
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
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for u32 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
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
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for u64 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
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
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for i8 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u8).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for i16 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u16).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for i32 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u32).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for i64 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u64).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for char {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u32).iter_bytes(lsb0, f)
|
2012-09-07 19:24:02 -05:00
|
|
|
}
|
2012-08-30 13:10:01 -05:00
|
|
|
}
|
|
|
|
|
2013-05-19 21:46:54 -05:00
|
|
|
#[cfg(target_word_size = "32")]
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for uint {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u32).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2013-01-08 21:37:25 -06:00
|
|
|
|
2013-05-19 21:46:54 -05:00
|
|
|
#[cfg(target_word_size = "64")]
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for uint {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as u64).iter_bytes(lsb0, f)
|
2012-09-07 19:24:02 -05:00
|
|
|
}
|
2012-08-30 13:10:01 -05:00
|
|
|
}
|
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for int {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as uint).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-06-15 11:58:38 -05:00
|
|
|
impl IterBytes for f32 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-06-15 11:58:38 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
let i: u32 = unsafe {
|
|
|
|
// 0.0 == -0.0 so they should also have the same hashcode
|
|
|
|
cast::transmute(if *self == -0.0 { 0.0 } else { *self })
|
|
|
|
};
|
|
|
|
i.iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IterBytes for f64 {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-06-15 11:58:38 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
let i: u64 = unsafe {
|
|
|
|
// 0.0 == -0.0 so they should also have the same hashcode
|
|
|
|
cast::transmute(if *self == -0.0 { 0.0 } else { *self })
|
|
|
|
};
|
|
|
|
i.iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
impl<'a,A:IterBytes> IterBytes for &'a [A] {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
2013-08-14 22:23:33 -05:00
|
|
|
self.len().iter_bytes(lsb0, |b| f(b)) &&
|
2013-06-21 07:29:53 -05:00
|
|
|
self.iter().advance(|elt| elt.iter_bytes(lsb0, |b| f(b)))
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-08-15 16:51:39 -05:00
|
|
|
impl<A: IterBytes> IterBytes for (A, ) {
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
match *self {
|
|
|
|
(ref a, ) => a.iter_bytes(lsb0, |b| f(b))
|
|
|
|
}
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-08-15 16:51:39 -05:00
|
|
|
macro_rules! iter_bytes_tuple(
|
|
|
|
($($A:ident),+) => (
|
|
|
|
impl<$($A: IterBytes),+> IterBytes for ($($A),+) {
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
match *self {
|
|
|
|
($(ref $A),+) => {
|
|
|
|
$(
|
|
|
|
$A .iter_bytes(lsb0, |b| f(b))
|
|
|
|
)&&+
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
iter_bytes_tuple!(A, B)
|
|
|
|
iter_bytes_tuple!(A, B, C)
|
|
|
|
iter_bytes_tuple!(A, B, C, D)
|
|
|
|
iter_bytes_tuple!(A, B, C, D, E)
|
|
|
|
iter_bytes_tuple!(A, B, C, D, E, F)
|
|
|
|
iter_bytes_tuple!(A, B, C, D, E, F, G)
|
|
|
|
iter_bytes_tuple!(A, B, C, D, E, F, G, H)
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl<A:IterBytes> IterBytes for ~[A] {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
2013-08-14 22:23:33 -05:00
|
|
|
self.as_slice().iter_bytes(lsb0, f)
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
}
|
2012-09-07 19:24:02 -05:00
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
impl<'a> IterBytes for &'a str {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
|
2013-08-14 22:23:33 -05:00
|
|
|
// Terminate the string with a byte that does not appear in UTF-8
|
|
|
|
f(self.as_bytes()) && f([0xFF])
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl IterBytes for ~str {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-08-14 22:23:33 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
self.as_slice().iter_bytes(lsb0, f)
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl<A:IterBytes> IterBytes for Option<A> {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
match *self {
|
2013-06-21 19:08:35 -05:00
|
|
|
Some(ref a) => 0u8.iter_bytes(lsb0, |b| f(b)) && a.iter_bytes(lsb0, |b| f(b)),
|
2013-05-02 17:33:18 -05:00
|
|
|
None => 1u8.iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
impl<'a,A:IterBytes> IterBytes for &'a A {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(**self).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl<A:IterBytes> IterBytes for @A {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
2013-07-16 16:54:29 -05:00
|
|
|
(**self).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-25 12:47:09 -06:00
|
|
|
impl<A:IterBytes> IterBytes for Rc<A> {
|
|
|
|
#[inline]
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
self.borrow().iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
impl<A:IterBytes> IterBytes for ~A {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(**self).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
|
|
|
// NB: raw-pointer IterBytes does _not_ dereference
|
|
|
|
// to the target; it just gives you the pointer-bytes.
|
2013-08-02 23:41:06 -05:00
|
|
|
impl<A> IterBytes for *A {
|
|
|
|
#[inline]
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as uint).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<A> IterBytes for *mut A {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-02 17:33:18 -05:00
|
|
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
|
|
|
(*self as uint).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// A trait for converting a value to a list of bytes.
|
2013-05-03 04:25:02 -05:00
|
|
|
pub trait ToBytes {
|
2013-05-28 16:35:52 -05:00
|
|
|
/// Converts the current value to a list of bytes. This is equivalent to
|
|
|
|
/// invoking iter_bytes on a type and collecting all yielded values in an
|
|
|
|
/// array
|
2012-11-28 13:36:04 -06:00
|
|
|
fn to_bytes(&self, lsb0: bool) -> ~[u8];
|
2012-08-30 13:10:01 -05:00
|
|
|
}
|
|
|
|
|
2013-02-20 19:07:17 -06:00
|
|
|
impl<A:IterBytes> ToBytes for A {
|
2012-11-28 13:36:04 -06:00
|
|
|
fn to_bytes(&self, lsb0: bool) -> ~[u8] {
|
2013-11-11 00:46:32 -06:00
|
|
|
use io::Writer;
|
2013-10-22 01:06:12 -05:00
|
|
|
|
2014-01-15 15:25:09 -06:00
|
|
|
let mut m = ::io::MemWriter::new();
|
|
|
|
self.iter_bytes(lsb0, |bytes| {
|
|
|
|
m.write(bytes);
|
|
|
|
true
|
|
|
|
});
|
|
|
|
m.unwrap()
|
2012-08-30 13:10:01 -05:00
|
|
|
}
|
2012-07-03 23:30:09 -05:00
|
|
|
}
|
2013-06-27 18:00:18 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
// just test to see if it compiles:
|
|
|
|
#[test] fn iterbytes_compiles () {
|
|
|
|
takes_iterbytes((3,4,5,false));
|
|
|
|
}
|
2013-09-10 23:16:59 -05:00
|
|
|
fn takes_iterbytes<T : IterBytes>(_x : T) {}
|
2013-06-27 18:00:18 -05:00
|
|
|
}
|