<commit_before>const BASE: u128 = 62;

// How much to add to the least-significant five bits of a byte to get the digit's
// value.
//
// Index 1: decimal digits
// Index 2: uppercase letters
// Index 3: lowercase letters
const STANDARD_OFFSETS: u32 = u32::from_le_bytes([0, -16_i8 as u8, 9, 35]);
const ALTERNATIVE_OFFSETS: u32 = u32::from_le_bytes([0, -16_i8 as u8, 35, 9]);

#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum DecodeError {
    InvalidBase62Byte(u8, usize),
    ArithmeticOverflow,
}

impl core::fmt::Display for DecodeError {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        match *self {
            DecodeError::InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid byte b'")?;
                for char_in_escape in ::core::ascii::escape_default(ch).map(char::from) {
                    write!(f, "{}", char_in_escape)?;
                }
                write!(f, "' at position {}", idx)
            }
            DecodeError::ArithmeticOverflow => write!(f, "Decoded number is too large"),
        }
    }
}

// Finds out how many base62 digits a value encodes into.
pub(crate) fn digit_count(mut n: u128) -> usize {
    const BASE_TO_2: u128 = BASE.pow(2);
    const BASE_TO_3: u128 = BASE.pow(3);
    const BASE_TO_6: u128 = BASE.pow(6);
    const BASE_TO_11: u128 = BASE.pow(11);

    let mut result = 1;

    if n >= BASE_TO_11 {
        result += 11;
        n /= BASE_TO_11;
    }
    if n >= BASE_TO_6 {
        result += 6;
        n /= BASE_TO_6;
    }
    if n >= BASE_TO_3 {
        result += 3;
        n /= BASE_TO_3;
    }
    if n >= BASE_TO_2 {
        result += 2;
        n /= BASE_TO_2;
    }
    if n >= BASE {
        result += 1;
    }

    result
}

macro_rules! internal_encoder_fn {
    ($fn_name:ident, $numeric_offset:literal, $first_letters_offset:literal, $last_letters_offset:literal) => {
        // # Safety
        //
        // With this function, `buf` MUST ALREADY have its capacity extended
        // to hold all the new base62 characters that will be added
        unsafe fn $fn_name(mut num: u128, digits: usize, buf: &mut String) {
            let buf_vec = buf.as_mut_vec();
            let new_len = buf_vec.len().wrapping_add(digits);
            let mut ptr = buf_vec.as_mut_ptr().add(new_len.wrapping_sub(1));

            for _ in 0..digits {
                ::core::ptr::write(ptr, {
                    let digit = (num % $crate::BASE) as u8;
                    match digit {
                        0..=9 => digit.wrapping_add($numeric_offset),
                        10..=35 => digit.wrapping_add($first_letters_offset),
                        _ => digit.wrapping_add($last_letters_offset),
                    }
                });
                ptr = ptr.sub(1);

                num /= $crate::BASE;
            }

            buf_vec.set_len(new_len);
        }
    };
}

// # Safety
//
// With these functions, `buf` MUST ALREADY have its capacity extended
// to hold all the new base62 characters that will be added
internal_encoder_fn!(_encode_buf, 48, 55, 61);
internal_encoder_fn!(_encode_alternative_buf, 48, 87, 29);

/// Encodes a uint into base62, using the standard digit ordering
/// (0 to 9, then A to Z, then a to z), and returns the resulting `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337_u32);
///     assert_eq!(b62, "LZ");
/// }
/// ```
#[must_use = "this allocates a new `String`"]
pub fn encode<T: Into<u128>>(num: T) -> String {
    let num = num.into();
    let digits = digit_count(num);
    let mut buf = String::with_capacity(digits);
    unsafe {
        _encode_buf(num, digits, &mut buf);
    }
    buf
}

/// Appends a uint encoded into base62, using the standard digit ordering
/// (0 to 9, then A to Z, then a to z), onto the end of a `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_buf(1337_u32, &mut buf);
///     assert_eq!(buf, "LZ");
/// }
/// ```
pub fn encode_buf<T: Into<u128>>(num: T, buf: &mut String) {
    let num = num.into();
    let digits = digit_count(num);
    buf.reserve(digits);
    unsafe {
        _encode_buf(num, digits, buf);
    }
}

/// Encodes a uint into base62, using the alternative digit ordering
/// (0 to 9, then a to z, then A to Z) with lowercase letters before uppercase letters,
/// and returns the resulting `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337_u32);
///     assert_eq!(b62, "LZ");
/// }
/// ```
#[must_use = "this allocates a new `String`"]
pub fn encode_alternative<T: Into<u128>>(num: T) -> String {
    let num = num.into();
    let digits = digit_count(num);
    let mut buf = String::with_capacity(digits);
    unsafe {
        _encode_alternative_buf(num, digits, &mut buf);
    }
    buf
}

/// Appends a uint encoded into base62, using the alternative digit ordering
/// (0 to 9, then a to z, then A to Z) with lowercase letters before uppercase letters,
/// onto the end of a `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_alternative_buf(1337_u32, &mut buf);
///     assert_eq!(buf, "lz");
/// }
/// ```
pub fn encode_alternative_buf<T: Into<u128>>(num: T, buf: &mut String) {
    let num = num.into();
    let digits = digit_count(num);
    buf.reserve(digits);
    unsafe {
        _encode_alternative_buf(num, digits, buf);
    }
}

macro_rules! internal_decoder_fn {
    ($fn_name:ident, $offsets:ident) => {
        fn $fn_name(input: &[u8]) -> Result<u128, DecodeError> {
            let mut result = 0_u128;
            for (i, &ch) in input.iter().enumerate() {
                if ch.is_ascii_alphanumeric() {
                    result = result
                        .checked_mul(BASE)
                        .and_then(|x| {
                            x.checked_add((ch & 0b0001_1111).wrapping_add(
                                $offsets.wrapping_shr((ch.wrapping_shr(2) & 0b0001_1000) as u32)
                                    as u8,
                            ) as u128)
                        })
                        .ok_or($crate::DecodeError::ArithmeticOverflow)?
                } else {
                    return Err($crate::DecodeError::InvalidBase62Byte(ch, i));
                }
            }

            Ok(result)
        }
    };
}

internal_decoder_fn!(_decode, STANDARD_OFFSETS);
internal_decoder_fn!(_decode_alternative, ALTERNATIVE_OFFSETS);

/// Decodes a base62 byte slice or an equivalent like a `String` using the standard
/// digit ordering (0 to 9, then A to Z, then a to z).
///
/// Returns a Result containing a `u128`, which can be downcasted to any other uint.
///
/// # Examples
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let value = base62::decode("rustlang").unwrap();
///     assert_eq!(value, 189876682536016);
/// }
/// ```
#[must_use = "this returns the decoded result without modifying the original"]
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode(input.as_ref())
}

/// Decodes a base62 byte slice or an equivalent like a `String` using the alternative
/// digit ordering (0 to 9, then a to z, then A to Z) with lowercase letters before
/// uppercase letters.
///
/// Returns a Result containing a `u128`, which can be downcasted to any other uint.
///
/// # Examples
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let value = base62::decode_alternative("rustlang").unwrap();
///     assert_eq!(value, 96813686712946);
/// }
/// ```
#[must_use = "this returns the decoded result without modifying the original"]
pub fn decode_alternative<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode_alternative(input.as_ref())
}

#[cfg(test)]
mod tests {
    use super::*;
    use quickcheck::{quickcheck, TestResult};

    quickcheck! {
        fn encode_decode(xs: u128) -> bool {
            let encoded = encode(xs);
            xs == decode(&encoded).unwrap()
        }
    }

    quickcheck! {
        fn decode_good(xs: String) -> TestResult {
            if xs.chars().all(|ch| ch.is_ascii_alphanumeric()) && !xs.is_empty() {
                TestResult::from_bool(decode(&xs).is_ok())
            } else {
                TestResult::discard()
            }
        }
    }

    quickcheck! {
        fn decode_bad(xs: String) -> TestResult {
            if xs.chars().all(|ch| ch.is_ascii_alphanumeric()) {
                TestResult::discard()
            } else {
                TestResult::from_bool(decode(&xs).is_err())
            }
        }
    }

    #[test]
    fn test_encode() {
        assert_eq!(encode(u128::MAX), "7n42DGM5Tflk9n8mt7Fhc7");
        assert_eq!(encode(0_u8), "0");
    }

    #[test]
    fn test_encode_buf() {
        let mut buf = String::new();
        encode_buf(u128::MAX, &mut buf);
        assert_eq!(buf, "7n42DGM5Tflk9n8mt7Fhc7");
    }

    #[test]
    fn test_encode_alternative() {
        assert_eq!(encode_alternative(691337691337_u128), "caCOuUN");
        assert_eq!(encode_alternative(0_u8), "0");
    }

    #[test]
    fn test_encode_alternative_buf() {
        let mut buf = String::new();
        encode_alternative_buf(691337691337_u128, &mut buf);
        assert_eq!(buf, "caCOuUN");
    }

    #[test]
    fn test_decode() {
        assert_eq!(decode("7n42DGM5Tflk9n8mt7Fhc7").unwrap(), u128::MAX);
        assert_eq!(decode("").unwrap(), 0);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert_eq!(
            decode("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte(b'{', 2))
        );
    }

    #[test]
    fn test_decode_long_string() {
        assert_eq!(
            decode("7n42DGM5Tflk9n8mt7Fhc78"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }

    #[test]
    fn test_decode_alternative() {
        assert_eq!(
            decode_alternative("7N42dgm5tFLK9N8MT7fHC7").unwrap(),
            u128::MAX
        );
        assert_eq!(decode_alternative("").unwrap(), 0);
    }

    #[test]
    fn test_decode_alternative_invalid_char() {
        assert_eq!(
            decode_alternative("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte(b'{', 2))
        );
    }

    #[test]
    fn test_decode_alternative_long_string() {
        assert_eq!(
            decode_alternative("7N42dgm5tFLK9N8MT7fHC8"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }

    #[test]
    fn test_digit_count() {
        // The maximum length of a base62-encoded `u128`.
        let max_encoded_len: usize = core::iter::successors(Some(u128::MAX), |&n| Some(n / BASE))
            .take_while(|&n| n != 0)
            .count();

        // Assume that `digit_count` is a monotonically increasing function and
        // check that the boundaries have the right values.
        assert_eq!(digit_count(0), 1);
        assert_eq!(digit_count(BASE.pow(0)), 1);
        for pow in 1..max_encoded_len {
            let this_power = BASE.pow(pow as u32);

            assert_eq!(digit_count(this_power - 1), pow);
            assert_eq!(digit_count(this_power), pow + 1);
        }
        assert_eq!(digit_count(u128::MAX), 22);
    }
}
<commit_msg>Now use `write_str` and `write_char` in `Display` for `DecodeError`<commit_after>const BASE: u128 = 62;

// How much to add to the least-significant five bits of a byte to get the digit's
// value.
//
// Index 1: decimal digits
// Index 2: uppercase letters
// Index 3: lowercase letters
const STANDARD_OFFSETS: u32 = u32::from_le_bytes([0, -16_i8 as u8, 9, 35]);
const ALTERNATIVE_OFFSETS: u32 = u32::from_le_bytes([0, -16_i8 as u8, 35, 9]);

#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum DecodeError {
    InvalidBase62Byte(u8, usize),
    ArithmeticOverflow,
}

impl core::fmt::Display for DecodeError {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        match *self {
            DecodeError::InvalidBase62Byte(ch, idx) => {
                use core::fmt::Write;

                f.write_str("Invalid byte b'")?;
                for char_in_escape in core::ascii::escape_default(ch) {
                    f.write_char(char::from(char_in_escape))?;
                }
                write!(f, "' at position {}", idx)
            }
            DecodeError::ArithmeticOverflow => write!(f, "Decoded number is too large"),
        }
    }
}

// Finds out how many base62 digits a value encodes into.
pub(crate) fn digit_count(mut n: u128) -> usize {
    const BASE_TO_2: u128 = BASE.pow(2);
    const BASE_TO_3: u128 = BASE.pow(3);
    const BASE_TO_6: u128 = BASE.pow(6);
    const BASE_TO_11: u128 = BASE.pow(11);

    let mut result = 1;

    if n >= BASE_TO_11 {
        result += 11;
        n /= BASE_TO_11;
    }
    if n >= BASE_TO_6 {
        result += 6;
        n /= BASE_TO_6;
    }
    if n >= BASE_TO_3 {
        result += 3;
        n /= BASE_TO_3;
    }
    if n >= BASE_TO_2 {
        result += 2;
        n /= BASE_TO_2;
    }
    if n >= BASE {
        result += 1;
    }

    result
}

macro_rules! internal_encoder_fn {
    ($fn_name:ident, $numeric_offset:literal, $first_letters_offset:literal, $last_letters_offset:literal) => {
        // # Safety
        //
        // With this function, `buf` MUST ALREADY have its capacity extended
        // to hold all the new base62 characters that will be added
        unsafe fn $fn_name(mut num: u128, digits: usize, buf: &mut String) {
            let buf_vec = buf.as_mut_vec();
            let new_len = buf_vec.len().wrapping_add(digits);
            let mut ptr = buf_vec.as_mut_ptr().add(new_len.wrapping_sub(1));

            for _ in 0..digits {
                ::core::ptr::write(ptr, {
                    let digit = (num % $crate::BASE) as u8;
                    match digit {
                        0..=9 => digit.wrapping_add($numeric_offset),
                        10..=35 => digit.wrapping_add($first_letters_offset),
                        _ => digit.wrapping_add($last_letters_offset),
                    }
                });
                ptr = ptr.sub(1);

                num /= $crate::BASE;
            }

            buf_vec.set_len(new_len);
        }
    };
}

// # Safety
//
// With these functions, `buf` MUST ALREADY have its capacity extended
// to hold all the new base62 characters that will be added
internal_encoder_fn!(_encode_buf, 48, 55, 61);
internal_encoder_fn!(_encode_alternative_buf, 48, 87, 29);

/// Encodes a uint into base62, using the standard digit ordering
/// (0 to 9, then A to Z, then a to z), and returns the resulting `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337_u32);
///     assert_eq!(b62, "LZ");
/// }
/// ```
#[must_use = "this allocates a new `String`"]
pub fn encode<T: Into<u128>>(num: T) -> String {
    let num = num.into();
    let digits = digit_count(num);
    let mut buf = String::with_capacity(digits);
    unsafe {
        _encode_buf(num, digits, &mut buf);
    }
    buf
}

/// Appends a uint encoded into base62, using the standard digit ordering
/// (0 to 9, then A to Z, then a to z), onto the end of a `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_buf(1337_u32, &mut buf);
///     assert_eq!(buf, "LZ");
/// }
/// ```
pub fn encode_buf<T: Into<u128>>(num: T, buf: &mut String) {
    let num = num.into();
    let digits = digit_count(num);
    buf.reserve(digits);
    unsafe {
        _encode_buf(num, digits, buf);
    }
}

/// Encodes a uint into base62, using the alternative digit ordering
/// (0 to 9, then a to z, then A to Z) with lowercase letters before uppercase letters,
/// and returns the resulting `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337_u32);
///     assert_eq!(b62, "LZ");
/// }
/// ```
#[must_use = "this allocates a new `String`"]
pub fn encode_alternative<T: Into<u128>>(num: T) -> String {
    let num = num.into();
    let digits = digit_count(num);
    let mut buf = String::with_capacity(digits);
    unsafe {
        _encode_alternative_buf(num, digits, &mut buf);
    }
    buf
}

/// Appends a uint encoded into base62, using the alternative digit ordering
/// (0 to 9, then a to z, then A to Z) with lowercase letters before uppercase letters,
/// onto the end of a `String`.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_alternative_buf(1337_u32, &mut buf);
///     assert_eq!(buf, "lz");
/// }
/// ```
pub fn encode_alternative_buf<T: Into<u128>>(num: T, buf: &mut String) {
    let num = num.into();
    let digits = digit_count(num);
    buf.reserve(digits);
    unsafe {
        _encode_alternative_buf(num, digits, buf);
    }
}

macro_rules! internal_decoder_fn {
    ($fn_name:ident, $offsets:ident) => {
        fn $fn_name(input: &[u8]) -> Result<u128, DecodeError> {
            let mut result = 0_u128;
            for (i, &ch) in input.iter().enumerate() {
                if ch.is_ascii_alphanumeric() {
                    result = result
                        .checked_mul(BASE)
                        .and_then(|x| {
                            x.checked_add((ch & 0b0001_1111).wrapping_add(
                                $offsets.wrapping_shr((ch.wrapping_shr(2) & 0b0001_1000) as u32)
                                    as u8,
                            ) as u128)
                        })
                        .ok_or($crate::DecodeError::ArithmeticOverflow)?
                } else {
                    return Err($crate::DecodeError::InvalidBase62Byte(ch, i));
                }
            }

            Ok(result)
        }
    };
}

internal_decoder_fn!(_decode, STANDARD_OFFSETS);
internal_decoder_fn!(_decode_alternative, ALTERNATIVE_OFFSETS);

/// Decodes a base62 byte slice or an equivalent like a `String` using the standard
/// digit ordering (0 to 9, then A to Z, then a to z).
///
/// Returns a Result containing a `u128`, which can be downcasted to any other uint.
///
/// # Examples
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let value = base62::decode("rustlang").unwrap();
///     assert_eq!(value, 189876682536016);
/// }
/// ```
#[must_use = "this returns the decoded result without modifying the original"]
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode(input.as_ref())
}

/// Decodes a base62 byte slice or an equivalent like a `String` using the alternative
/// digit ordering (0 to 9, then a to z, then A to Z) with lowercase letters before
/// uppercase letters.
///
/// Returns a Result containing a `u128`, which can be downcasted to any other uint.
///
/// # Examples
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let value = base62::decode_alternative("rustlang").unwrap();
///     assert_eq!(value, 96813686712946);
/// }
/// ```
#[must_use = "this returns the decoded result without modifying the original"]
pub fn decode_alternative<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode_alternative(input.as_ref())
}

#[cfg(test)]
mod tests {
    use super::*;
    use quickcheck::{quickcheck, TestResult};

    quickcheck! {
        fn encode_decode(xs: u128) -> bool {
            let encoded = encode(xs);
            xs == decode(&encoded).unwrap()
        }
    }

    quickcheck! {
        fn decode_good(xs: String) -> TestResult {
            if xs.chars().all(|ch| ch.is_ascii_alphanumeric()) && !xs.is_empty() {
                TestResult::from_bool(decode(&xs).is_ok())
            } else {
                TestResult::discard()
            }
        }
    }

    quickcheck! {
        fn decode_bad(xs: String) -> TestResult {
            if xs.chars().all(|ch| ch.is_ascii_alphanumeric()) {
                TestResult::discard()
            } else {
                TestResult::from_bool(decode(&xs).is_err())
            }
        }
    }

    #[test]
    fn test_encode() {
        assert_eq!(encode(u128::MAX), "7n42DGM5Tflk9n8mt7Fhc7");
        assert_eq!(encode(0_u8), "0");
    }

    #[test]
    fn test_encode_buf() {
        let mut buf = String::new();
        encode_buf(u128::MAX, &mut buf);
        assert_eq!(buf, "7n42DGM5Tflk9n8mt7Fhc7");
    }

    #[test]
    fn test_encode_alternative() {
        assert_eq!(encode_alternative(691337691337_u128), "caCOuUN");
        assert_eq!(encode_alternative(0_u8), "0");
    }

    #[test]
    fn test_encode_alternative_buf() {
        let mut buf = String::new();
        encode_alternative_buf(691337691337_u128, &mut buf);
        assert_eq!(buf, "caCOuUN");
    }

    #[test]
    fn test_decode() {
        assert_eq!(decode("7n42DGM5Tflk9n8mt7Fhc7").unwrap(), u128::MAX);
        assert_eq!(decode("").unwrap(), 0);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert_eq!(
            decode("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte(b'{', 2))
        );
    }

    #[test]
    fn test_decode_long_string() {
        assert_eq!(
            decode("7n42DGM5Tflk9n8mt7Fhc78"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }

    #[test]
    fn test_decode_alternative() {
        assert_eq!(
            decode_alternative("7N42dgm5tFLK9N8MT7fHC7").unwrap(),
            u128::MAX
        );
        assert_eq!(decode_alternative("").unwrap(), 0);
    }

    #[test]
    fn test_decode_alternative_invalid_char() {
        assert_eq!(
            decode_alternative("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte(b'{', 2))
        );
    }

    #[test]
    fn test_decode_alternative_long_string() {
        assert_eq!(
            decode_alternative("7N42dgm5tFLK9N8MT7fHC8"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }

    #[test]
    fn test_digit_count() {
        // The maximum length of a base62-encoded `u128`.
        let max_encoded_len: usize = core::iter::successors(Some(u128::MAX), |&n| Some(n / BASE))
            .take_while(|&n| n != 0)
            .count();

        // Assume that `digit_count` is a monotonically increasing function and
        // check that the boundaries have the right values.
        assert_eq!(digit_count(0), 1);
        assert_eq!(digit_count(BASE.pow(0)), 1);
        for pow in 1..max_encoded_len {
            let this_power = BASE.pow(pow as u32);

            assert_eq!(digit_count(this_power - 1), pow);
            assert_eq!(digit_count(this_power), pow + 1);
        }
        assert_eq!(digit_count(u128::MAX), 22);
    }
}
<|endoftext|>


<commit_before>//! # `object`
//!
//! The `object` crate provides a unified interface to working with object files
//! across platforms.
//!
//! See the [`File` struct](./struct.File.html) for details.

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

extern crate goblin;

use std::fmt;
use std::io::Cursor;

mod elf;
pub use elf::*;

mod macho;
pub use macho::*;

/// An object file.
#[derive(Debug)]
pub struct File<'a> {
    kind: ObjectKind<'a>,
}

#[derive(Debug)]
enum ObjectKind<'a> {
    Elf(ElfFile<'a>),
    MachO(MachOFile<'a>),
}

/// The kind of a sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionKind {
    /// The section kind is unknown.
    Unknown,
    /// An executable code section.
    Text,
    /// A data section.
    Data,
    /// A read only data section.
    ReadOnlyData,
    /// An uninitialized data section.
    UninitializedData,
    /// Some other type of text or data section.
    Other,
}

/// A symbol table entry.
#[derive(Debug)]
pub struct Symbol<'a> {
    kind: SymbolKind,
    section: usize,
    section_kind: Option<SectionKind>,
    global: bool,
    name: &'a [u8],
    address: u64,
    size: u64,
}

/// The kind of a symbol.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymbolKind {
    /// The symbol kind is unknown.
    Unknown,
    /// The symbol is for executable code.
    Text,
    /// The symbol is for a data object.
    Data,
    /// The symbol is for a section.
    Section,
    /// The symbol is the name of a file. It precedes symbols within that file.
    File,
    /// The symbol is for an uninitialized common block.
    Common,
    /// The symbol is for a thread local storage entity.
    Tls,
}

/// An iterator of the sections of a `File`.
#[derive(Debug)]
pub struct SectionIterator<'a, 'b> {
    inner: SectionIteratorInternal<'a, 'b>,
}

// we wrap our enums in a struct so that they are kept private.
#[derive(Debug)]
enum SectionIteratorInternal<'a, 'b> {
    MachO(MachOSectionIterator<'a, 'b>),
    Elf(ElfSectionIterator<'a>),
}

enum SectionInternal<'a> {
    MachO(MachOSection<'a>),
    Elf(ElfSection<'a>),
}

/// A Section of a File
pub struct Section<'a> {
    inner: SectionInternal<'a>,
}

impl<'a> fmt::Debug for Section<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's painful to do much better than this
        f.debug_struct("Section")
            .field("name", &self.name().unwrap_or("<invalid name>"))
            .field("address", &self.address())
            .field("size", &self.data().len())
            .finish()
    }
}

impl<'a> Section<'a> {
    /// returns the address of the section
    pub fn address(&self) -> u64 {
        match &self.inner {
            &SectionInternal::MachO(ref macho) => macho.address(),
            &SectionInternal::Elf(ref elf) => elf.address(),
        }
    }

    /// returns a reference to contents of the section
    pub fn data(&self) -> &'a [u8] {
        match &self.inner {
            &SectionInternal::MachO(ref macho) => macho.data(),
            &SectionInternal::Elf(ref elf) => elf.data(),
        }
    }

    /// returns the name of the section
    pub fn name(&self) -> Option<&str> {
        match &self.inner {
            &SectionInternal::MachO(ref macho) => macho.name(),
            &SectionInternal::Elf(ref elf) => elf.name(),
        }
    }
}

impl<'a, 'b> Iterator for SectionIterator<'a, 'b> {
    type Item = Section<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        match &mut self.inner {
            &mut SectionIteratorInternal::MachO(ref mut macho) => macho.next().map(|x| {
                Section {
                    inner: SectionInternal::MachO(x),
                }
            }),
            &mut SectionIteratorInternal::Elf(ref mut elf) => elf.next().map(|x| {
                Section {
                    inner: SectionInternal::Elf(x),
                }
            }),
        }
    }
}

impl<'a> File<'a> {
    /// Parse the raw object file data.
    pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let mut cursor = Cursor::new(data);
        let kind = match goblin::peek(&mut cursor).map_err(|_| "Could not parse file magic")? {
            goblin::Hint::Elf(_) => ObjectKind::Elf(ElfFile::parse(data)?),
            goblin::Hint::Mach(_) => ObjectKind::MachO(MachOFile::parse(data)?),
            _ => return Err("Unknown file magic"),
        };
        Ok(File { kind })
    }

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    pub fn get_section(&self, section_name: &str) -> Option<&'a [u8]> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.get_section(section_name),
            ObjectKind::MachO(ref macho) => macho.get_section(section_name),
        }
    }

    /// Get an Iterator over the sections in the file.
    pub fn get_sections(&self) -> SectionIterator {
        match self.kind {
            ObjectKind::Elf(ref elf) => SectionIterator {
                inner: SectionIteratorInternal::Elf(elf.get_sections()),
            },
            ObjectKind::MachO(ref macho) => SectionIterator {
                inner: SectionIteratorInternal::MachO(macho.get_sections()),
            },
        }
    }

    /// Get a `Vec` of the symbols defined in the file.
    pub fn get_symbols(&self) -> Vec<Symbol<'a>> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.get_symbols(),
            ObjectKind::MachO(ref macho) => macho.get_symbols(),
        }
    }

    /// Return true if the file is little endian, false if it is big endian.
    pub fn is_little_endian(&self) -> bool {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.is_little_endian(),
            ObjectKind::MachO(ref macho) => macho.is_little_endian(),
        }
    }
}

impl<'a> Symbol<'a> {
    /// Return the kind of this symbol.
    #[inline]
    pub fn kind(&self) -> SymbolKind {
        self.kind
    }

    /// Returns the section kind for the symbol, or `None` if the symbol is undefnined.
    #[inline]
    pub fn section_kind(&self) -> Option<SectionKind> {
        self.section_kind
    }

    /// Return true if the symbol is undefined.
    #[inline]
    pub fn is_undefined(&self) -> bool {
        self.section_kind.is_none()
    }

    /// Return true if the symbol is global.
    #[inline]
    pub fn is_global(&self) -> bool {
        self.global
    }

    /// Return true if the symbol is local.
    #[inline]
    pub fn is_local(&self) -> bool {
        !self.global
    }

    /// The name of the symbol.
    #[inline]
    pub fn name(&self) -> &'a [u8] {
        self.name
    }

    /// The address of the symbol. May be zero if the address is unknown.
    #[inline]
    pub fn address(&self) -> u64 {
        self.address
    }

    /// The size of the symbol. May be zero if the size is unknown.
    #[inline]
    pub fn size(&self) -> u64 {
        self.size
    }
}

#[doc(hidden)]
#[deprecated]
pub trait Object {}
<commit_msg>Reorder lib.rs<commit_after>//! # `object`
//!
//! The `object` crate provides a unified interface to working with object files
//! across platforms.
//!
//! See the [`File` struct](./struct.File.html) for details.

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

extern crate goblin;

use std::fmt;
use std::io::Cursor;

mod elf;
pub use elf::*;

mod macho;
pub use macho::*;

/// An object file.
#[derive(Debug)]
pub struct File<'a> {
    kind: ObjectKind<'a>,
}

#[derive(Debug)]
enum ObjectKind<'a> {
    Elf(ElfFile<'a>),
    MachO(MachOFile<'a>),
}

/// An iterator of the sections of a `File`.
#[derive(Debug)]
pub struct SectionIterator<'a, 'b> {
    inner: SectionIteratorInternal<'a, 'b>,
}

// we wrap our enums in a struct so that they are kept private.
#[derive(Debug)]
enum SectionIteratorInternal<'a, 'b> {
    Elf(ElfSectionIterator<'a>),
    MachO(MachOSectionIterator<'a, 'b>),
}

/// A Section of a File
pub struct Section<'a> {
    inner: SectionInternal<'a>,
}

enum SectionInternal<'a> {
    Elf(ElfSection<'a>),
    MachO(MachOSection<'a>),
}

/// The kind of a sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionKind {
    /// The section kind is unknown.
    Unknown,
    /// An executable code section.
    Text,
    /// A data section.
    Data,
    /// A read only data section.
    ReadOnlyData,
    /// An uninitialized data section.
    UninitializedData,
    /// Some other type of text or data section.
    Other,
}

/// A symbol table entry.
#[derive(Debug)]
pub struct Symbol<'a> {
    kind: SymbolKind,
    section: usize,
    section_kind: Option<SectionKind>,
    global: bool,
    name: &'a [u8],
    address: u64,
    size: u64,
}

/// The kind of a symbol.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymbolKind {
    /// The symbol kind is unknown.
    Unknown,
    /// The symbol is for executable code.
    Text,
    /// The symbol is for a data object.
    Data,
    /// The symbol is for a section.
    Section,
    /// The symbol is the name of a file. It precedes symbols within that file.
    File,
    /// The symbol is for an uninitialized common block.
    Common,
    /// The symbol is for a thread local storage entity.
    Tls,
}

impl<'a> File<'a> {
    /// Parse the raw object file data.
    pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let mut cursor = Cursor::new(data);
        let kind = match goblin::peek(&mut cursor).map_err(|_| "Could not parse file magic")? {
            goblin::Hint::Elf(_) => ObjectKind::Elf(ElfFile::parse(data)?),
            goblin::Hint::Mach(_) => ObjectKind::MachO(MachOFile::parse(data)?),
            _ => return Err("Unknown file magic"),
        };
        Ok(File { kind })
    }

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    pub fn get_section(&self, section_name: &str) -> Option<&'a [u8]> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.get_section(section_name),
            ObjectKind::MachO(ref macho) => macho.get_section(section_name),
        }
    }

    /// Get an Iterator over the sections in the file.
    pub fn get_sections(&self) -> SectionIterator {
        match self.kind {
            ObjectKind::Elf(ref elf) => SectionIterator {
                inner: SectionIteratorInternal::Elf(elf.get_sections()),
            },
            ObjectKind::MachO(ref macho) => SectionIterator {
                inner: SectionIteratorInternal::MachO(macho.get_sections()),
            },
        }
    }

    /// Get a `Vec` of the symbols defined in the file.
    pub fn get_symbols(&self) -> Vec<Symbol<'a>> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.get_symbols(),
            ObjectKind::MachO(ref macho) => macho.get_symbols(),
        }
    }

    /// Return true if the file is little endian, false if it is big endian.
    pub fn is_little_endian(&self) -> bool {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.is_little_endian(),
            ObjectKind::MachO(ref macho) => macho.is_little_endian(),
        }
    }
}

impl<'a, 'b> Iterator for SectionIterator<'a, 'b> {
    type Item = Section<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        match &mut self.inner {
            &mut SectionIteratorInternal::Elf(ref mut elf) => elf.next().map(|x| {
                Section {
                    inner: SectionInternal::Elf(x),
                }
            }),
            &mut SectionIteratorInternal::MachO(ref mut macho) => macho.next().map(|x| {
                Section {
                    inner: SectionInternal::MachO(x),
                }
            }),
        }
    }
}

impl<'a> fmt::Debug for Section<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's painful to do much better than this
        f.debug_struct("Section")
            .field("name", &self.name().unwrap_or("<invalid name>"))
            .field("address", &self.address())
            .field("size", &self.data().len())
            .finish()
    }
}

impl<'a> Section<'a> {
    /// returns the address of the section
    pub fn address(&self) -> u64 {
        match &self.inner {
            &SectionInternal::Elf(ref elf) => elf.address(),
            &SectionInternal::MachO(ref macho) => macho.address(),
        }
    }

    /// returns a reference to contents of the section
    pub fn data(&self) -> &'a [u8] {
        match &self.inner {
            &SectionInternal::Elf(ref elf) => elf.data(),
            &SectionInternal::MachO(ref macho) => macho.data(),
        }
    }

    /// returns the name of the section
    pub fn name(&self) -> Option<&str> {
        match &self.inner {
            &SectionInternal::Elf(ref elf) => elf.name(),
            &SectionInternal::MachO(ref macho) => macho.name(),
        }
    }
}

impl<'a> Symbol<'a> {
    /// Return the kind of this symbol.
    #[inline]
    pub fn kind(&self) -> SymbolKind {
        self.kind
    }

    /// Returns the section kind for the symbol, or `None` if the symbol is undefnined.
    #[inline]
    pub fn section_kind(&self) -> Option<SectionKind> {
        self.section_kind
    }

    /// Return true if the symbol is undefined.
    #[inline]
    pub fn is_undefined(&self) -> bool {
        self.section_kind.is_none()
    }

    /// Return true if the symbol is global.
    #[inline]
    pub fn is_global(&self) -> bool {
        self.global
    }

    /// Return true if the symbol is local.
    #[inline]
    pub fn is_local(&self) -> bool {
        !self.global
    }

    /// The name of the symbol.
    #[inline]
    pub fn name(&self) -> &'a [u8] {
        self.name
    }

    /// The address of the symbol. May be zero if the address is unknown.
    #[inline]
    pub fn address(&self) -> u64 {
        self.address
    }

    /// The size of the symbol. May be zero if the size is unknown.
    #[inline]
    pub fn size(&self) -> u64 {
        self.size
    }
}

#[doc(hidden)]
#[deprecated]
pub trait Object {}
<|endoftext|>


<commit_before>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! The crate is called `redis` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.redis]
//! version = "*"
//! ```
//!
//! If you want to use the git version:
//!
//! ```ini
//! [dependencies.redis]
//! git = "https://github.com/mitsuhiko/redis-rs.git"
//! ```
//!
//! # Basic Operation
//!
//! redis-rs exposes to API levels: a low- and a high-level part.  The high-level
//! part does not expose all the functionality of redis and might take some
//! liberties in how it speaks the protocol.  The low-level part of the API
//! allows you to express any request on the redis level.  You can fluently
//! switch between both API levels at any point.
//!
//! ## Connection Handling
//!
//! For connecting to redis you can use a client object which then can produce
//! actual connections.  Connections and clients as well as results of
//! connections and clients are considered `ConnectionLike` objects and
//! can be used anywhere a request is made.
//!
//! The full canonical way to get a connection is to create a client and
//! to ask for a connection from it:
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn do_something() -> redis::RedisResult<()> {
//!     let client = try!(redis::Client::open("redis://127.0.0.1/"));
//!     let con = try!(client.get_connection());
//!
//!     /* do something here */
//!
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! ## Unix Sockets
//!
//! By default this library does not support unix sockets on older versions
//! of Rust but you can optionally compile it with unix sockets enabled by
//! enabling the `with-unix-sockets` feature flag.  On rust 1.10 or later
//! this is not needed.
//!
//! ```ini
//! [dependencies.redis]
//! version = "*"
//! features = ["with-unix-sockets"]
//! ```
//!
//! ## Connection Parameters
//!
//! redis-rs knows different ways to define where a connection should
//! go.  The parameter to `Client::open` needs to implement the
//! `IntoConnectionInfo` trait of which there are three implementations:
//!
//! * string slices in `redis://` URL format.
//! * URL objects from the redis-url crate.
//! * `ConnectionInfo` objects.
//!
//! The URL format is `redis://[:<passwd>@]<hostname>[:port][/<db>]`
//!
//! In case the create is compiled with Unix socket support you can also
//! use a unix URL in this format:
//!
//! `unix:///[:<passwd>@]<path>[?db=<db>]`
//!
//! ## Executing Low-Level Commands
//!
//! To execute low-level commands you can use the `cmd` function which allows
//! you to build redis requests.  Once you have configured a command object
//! to your liking you can send a query into any `ConnectionLike` object:
//!
//! ```rust,no_run
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(redis::cmd("SET").arg("my_key").arg(42).query(con));
//!     Ok(())
//! }
//! ```
//!
//! Upon querying the return value is a result object.  If you do not care
//! about the actual return value (other than that it is not a failure)
//! you can always type annotate it to the unit type `()`.
//!
//! ## Executing High-Level Commands
//!
//! The high-level interface is similar.  For it to become available you
//! need to use the `Commands` trait in which case all `ConnectionLike`
//! objects the library provides will also have high-level methods which
//! make working with the protocol easier:
//!
//! ```rust,no_run
//! extern crate redis;
//! use redis::Commands;
//!
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(con.set("my_key", 42));
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! Note that high-level commands are work in progress and many are still
//! missing!
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use redis::Commands;
//! # use std::collections::{HashMap, HashSet};
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = try!(con.get("my_counter"));
//! let count = con.get("my_counter").unwrap_or(0i32);
//! let k : Option<String> = try!(con.get("missing_key"));
//! let name : String = try!(con.get("my_name"));
//! let bin : Vec<u8> = try!(con.get("my_binary"));
//! let map : HashMap<String, i32> = try!(con.hgetall("my_hash"));
//! let keys : Vec<String> = try!(con.hkeys("my_hash"));
//! let mems : HashSet<i32> = try!(con.smembers("my_set"));
//! let (k1, k2) : (String, String) = try!(con.get(&["k1", "k2"]));
//! # Ok(())
//! # }
//! ```
//!
//! # Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut iter : redis::Iter<isize> = try!(redis::cmd("SSCAN").arg("my_set")
//!     .cursor_arg(0).iter(&con));
//! for x in iter {
//!     // do something with the item
//! }
//! # Ok(()) }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg`
//! instead of `arg` so that the library knows which argument needs updating
//! as the query is run for more items.
//!
//! # Pipelining
//!
//! In addition to simple queries you can also send command pipelines.  This
//! is provided through the `pipe` function.  It works very similar to sending
//! individual commands but you can send more than one in one go.  This also
//! allows you to ignore individual results so that matching on the end result
//! is easier:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .cmd("SET").arg("key_1").arg(42).ignore()
//!     .cmd("SET").arg("key_2").arg(43).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! If you want the pipeline to be wrapped in a `MULTI`/`EXEC` block you can
//! easily do that by switching the pipeline into `atomic` mode.  From the
//! caller's point of view nothing changes, the pipeline itself will take
//! care of the rest for you:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .cmd("SET").arg("key_1").arg(42).ignore()
//!     .cmd("SET").arg("key_2").arg(43).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! You can also use high-level commands on pipelines through the
//! `PipelineCommands` trait:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::PipelineCommands;
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .set("key_1", 42).ignore()
//!     .set("key_2", 43).ignore()
//!     .get("key_1")
//!     .get("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! # Transactions
//!
//! Transactions are available through atomic pipelines.  In order to use
//! them in a more simple way you can use the `transaction` function of a
//! connection:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::{Commands, PipelineCommands};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let key = "the_key";
//! let (new_val,) : (isize,) = try!(redis::transaction(&con, &[key], |pipe| {
//!     let old_val : isize = try!(con.get(key));
//!     pipe
//!         .set(key, old_val + 1).ignore()
//!         .get(key).query(&con)
//! }));
//! println!("The incremented number is: {}", new_val);
//! # Ok(()) }
//! ```
//!
//! For more information see the `transaction` function.
//!
//! # PubSub
//!
//! Pubsub is currently work in progress but provided through the `PubSub`
//! connection object.  Due to the fact that Rust does not have support
//! for async IO in libnative yet, the API does not provide a way to
//! read messages with any form of timeout yet.
//!
//! Example usage:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! let client = try!(redis::Client::open("redis://127.0.0.1/"));
//! let mut pubsub = try!(client.get_pubsub());
//! try!(pubsub.subscribe("channel_1"));
//! try!(pubsub.subscribe("channel_2"));
//!
//! loop {
//!     let msg = try!(pubsub.get_message());
//!     let payload : String = try!(msg.get_payload());
//!     println!("channel '{}': {}", msg.get_channel_name(), payload);
//! }
//! # }
//! ```
//!
//! # Scripts
//!
//! Lua scripts are supported through the `Script` type in a convenient
//! way (it does not support pipelining currently).  It will automatically
//! load the script if it does not exist and invoke it.
//!
//! Example:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let script = redis::Script::new(r"
//!     return tonumber(ARGV[1]) + tonumber(ARGV[2]);
//! ");
//! let result : isize = try!(script.arg(1).arg(2).invoke(&con));
//! assert_eq!(result, 3);
//! # Ok(()) }
//! ```
//!
//! ## Breaking Changes
//!
//! In Rust 0.5.0 the semi-internal `ConnectionInfo` struct had to be
//! changed because of the unix socket support.  You are generally
//! heavily encouraged to use the URL based configuration format which
//! is a lot more stable than the structs.

#![deny(non_camel_case_types)]

extern crate url;
extern crate sha1;

#[cfg(feature="with-rustc-json")]
pub extern crate rustc_serialize as serialize;
#[cfg(feature="with-unix-sockets")]
extern crate unix_socket;

#[doc(hidden)]
#[cfg(feature="with-rustc-json")]
pub use serialize::json::Json;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use script::{Script, ScriptInvocation};
pub use connection::{Connection, ConnectionLike, ConnectionInfo,
                     ConnectionAddr, IntoConnectionInfo, PubSub, Msg, transaction,
                     parse_redis_url};
pub use cmd::{cmd, Cmd, pipe, Pipeline, Iter, pack_command};
pub use commands::{
    Commands,
    PipelineCommands,
};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,

    /* error and result types */
    RedisError,
    RedisResult,

    /* error kinds */
    ErrorKind,

    /* utility types */
    InfoDict,
    NumericBehavior,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,

    /* utility functions */
    from_redis_value,
};

mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod script;
mod cmd;
mod commands;
<commit_msg>Added optional feature docs<commit_after>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! The crate is called `redis` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.redis]
//! version = "*"
//! ```
//!
//! If you want to use the git version:
//!
//! ```ini
//! [dependencies.redis]
//! git = "https://github.com/mitsuhiko/redis-rs.git"
//! ```
//!
//! # Basic Operation
//!
//! redis-rs exposes to API levels: a low- and a high-level part.  The high-level
//! part does not expose all the functionality of redis and might take some
//! liberties in how it speaks the protocol.  The low-level part of the API
//! allows you to express any request on the redis level.  You can fluently
//! switch between both API levels at any point.
//!
//! ## Connection Handling
//!
//! For connecting to redis you can use a client object which then can produce
//! actual connections.  Connections and clients as well as results of
//! connections and clients are considered `ConnectionLike` objects and
//! can be used anywhere a request is made.
//!
//! The full canonical way to get a connection is to create a client and
//! to ask for a connection from it:
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn do_something() -> redis::RedisResult<()> {
//!     let client = try!(redis::Client::open("redis://127.0.0.1/"));
//!     let con = try!(client.get_connection());
//!
//!     /* do something here */
//!
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! ## Optional Features
//!
//! There are currently two features defined that can enable additional
//! functionality if so desired.
//!
//! `with-unix-sockets`:
//!   By default this library does not support unix sockets on older versions
//!   of Rust but you can optionally compile it with unix sockets enabled by
//!   enabling the `with-unix-sockets` feature flag.  On rust 1.10 or later
//!   this is not needed.
//!
//! `with-rustc-json`:
//!   This feature flag enables the `rustc_serialize` JSON support.
//!
//! ## Connection Parameters
//!
//! redis-rs knows different ways to define where a connection should
//! go.  The parameter to `Client::open` needs to implement the
//! `IntoConnectionInfo` trait of which there are three implementations:
//!
//! * string slices in `redis://` URL format.
//! * URL objects from the redis-url crate.
//! * `ConnectionInfo` objects.
//!
//! The URL format is `redis://[:<passwd>@]<hostname>[:port][/<db>]`
//!
//! In case the create is compiled with Unix socket support you can also
//! use a unix URL in this format:
//!
//! `unix:///[:<passwd>@]<path>[?db=<db>]`
//!
//! ## Executing Low-Level Commands
//!
//! To execute low-level commands you can use the `cmd` function which allows
//! you to build redis requests.  Once you have configured a command object
//! to your liking you can send a query into any `ConnectionLike` object:
//!
//! ```rust,no_run
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(redis::cmd("SET").arg("my_key").arg(42).query(con));
//!     Ok(())
//! }
//! ```
//!
//! Upon querying the return value is a result object.  If you do not care
//! about the actual return value (other than that it is not a failure)
//! you can always type annotate it to the unit type `()`.
//!
//! ## Executing High-Level Commands
//!
//! The high-level interface is similar.  For it to become available you
//! need to use the `Commands` trait in which case all `ConnectionLike`
//! objects the library provides will also have high-level methods which
//! make working with the protocol easier:
//!
//! ```rust,no_run
//! extern crate redis;
//! use redis::Commands;
//!
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(con.set("my_key", 42));
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! Note that high-level commands are work in progress and many are still
//! missing!
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use redis::Commands;
//! # use std::collections::{HashMap, HashSet};
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = try!(con.get("my_counter"));
//! let count = con.get("my_counter").unwrap_or(0i32);
//! let k : Option<String> = try!(con.get("missing_key"));
//! let name : String = try!(con.get("my_name"));
//! let bin : Vec<u8> = try!(con.get("my_binary"));
//! let map : HashMap<String, i32> = try!(con.hgetall("my_hash"));
//! let keys : Vec<String> = try!(con.hkeys("my_hash"));
//! let mems : HashSet<i32> = try!(con.smembers("my_set"));
//! let (k1, k2) : (String, String) = try!(con.get(&["k1", "k2"]));
//! # Ok(())
//! # }
//! ```
//!
//! # Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut iter : redis::Iter<isize> = try!(redis::cmd("SSCAN").arg("my_set")
//!     .cursor_arg(0).iter(&con));
//! for x in iter {
//!     // do something with the item
//! }
//! # Ok(()) }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg`
//! instead of `arg` so that the library knows which argument needs updating
//! as the query is run for more items.
//!
//! # Pipelining
//!
//! In addition to simple queries you can also send command pipelines.  This
//! is provided through the `pipe` function.  It works very similar to sending
//! individual commands but you can send more than one in one go.  This also
//! allows you to ignore individual results so that matching on the end result
//! is easier:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .cmd("SET").arg("key_1").arg(42).ignore()
//!     .cmd("SET").arg("key_2").arg(43).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! If you want the pipeline to be wrapped in a `MULTI`/`EXEC` block you can
//! easily do that by switching the pipeline into `atomic` mode.  From the
//! caller's point of view nothing changes, the pipeline itself will take
//! care of the rest for you:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .cmd("SET").arg("key_1").arg(42).ignore()
//!     .cmd("SET").arg("key_2").arg(43).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! You can also use high-level commands on pipelines through the
//! `PipelineCommands` trait:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::PipelineCommands;
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .set("key_1", 42).ignore()
//!     .set("key_2", 43).ignore()
//!     .get("key_1")
//!     .get("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! # Transactions
//!
//! Transactions are available through atomic pipelines.  In order to use
//! them in a more simple way you can use the `transaction` function of a
//! connection:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::{Commands, PipelineCommands};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let key = "the_key";
//! let (new_val,) : (isize,) = try!(redis::transaction(&con, &[key], |pipe| {
//!     let old_val : isize = try!(con.get(key));
//!     pipe
//!         .set(key, old_val + 1).ignore()
//!         .get(key).query(&con)
//! }));
//! println!("The incremented number is: {}", new_val);
//! # Ok(()) }
//! ```
//!
//! For more information see the `transaction` function.
//!
//! # PubSub
//!
//! Pubsub is currently work in progress but provided through the `PubSub`
//! connection object.  Due to the fact that Rust does not have support
//! for async IO in libnative yet, the API does not provide a way to
//! read messages with any form of timeout yet.
//!
//! Example usage:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! let client = try!(redis::Client::open("redis://127.0.0.1/"));
//! let mut pubsub = try!(client.get_pubsub());
//! try!(pubsub.subscribe("channel_1"));
//! try!(pubsub.subscribe("channel_2"));
//!
//! loop {
//!     let msg = try!(pubsub.get_message());
//!     let payload : String = try!(msg.get_payload());
//!     println!("channel '{}': {}", msg.get_channel_name(), payload);
//! }
//! # }
//! ```
//!
//! # Scripts
//!
//! Lua scripts are supported through the `Script` type in a convenient
//! way (it does not support pipelining currently).  It will automatically
//! load the script if it does not exist and invoke it.
//!
//! Example:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let script = redis::Script::new(r"
//!     return tonumber(ARGV[1]) + tonumber(ARGV[2]);
//! ");
//! let result : isize = try!(script.arg(1).arg(2).invoke(&con));
//! assert_eq!(result, 3);
//! # Ok(()) }
//! ```
//!
//! ## Breaking Changes
//!
//! In Rust 0.5.0 the semi-internal `ConnectionInfo` struct had to be
//! changed because of the unix socket support.  You are generally
//! heavily encouraged to use the URL based configuration format which
//! is a lot more stable than the structs.

#![deny(non_camel_case_types)]

extern crate url;
extern crate sha1;

#[cfg(feature="with-rustc-json")]
pub extern crate rustc_serialize as serialize;
#[cfg(feature="with-unix-sockets")]
extern crate unix_socket;

#[doc(hidden)]
#[cfg(feature="with-rustc-json")]
pub use serialize::json::Json;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use script::{Script, ScriptInvocation};
pub use connection::{Connection, ConnectionLike, ConnectionInfo,
                     ConnectionAddr, IntoConnectionInfo, PubSub, Msg, transaction,
                     parse_redis_url};
pub use cmd::{cmd, Cmd, pipe, Pipeline, Iter, pack_command};
pub use commands::{
    Commands,
    PipelineCommands,
};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,

    /* error and result types */
    RedisError,
    RedisResult,

    /* error kinds */
    ErrorKind,

    /* utility types */
    InfoDict,
    NumericBehavior,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,

    /* utility functions */
    from_redis_value,
};

mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod script;
mod cmd;
mod commands;
<|endoftext|>


<commit_before>// use variable names from paper, namely registers M
#![allow(non_snake_case)]

#![crate_name = "basichll"]
#![crate_type = "lib"]

extern crate byteorder;

/* -------------------- std libs ------------------- */
use std::cmp;
use std::fmt;
use std::hash::{ Hash, Hasher, SipHasher };
use std::io::Cursor;
use std::iter::{ repeat, Iterator };
/* ------------------------------------------------- */

use byteorder::{ BigEndian, WriteBytesExt, ReadBytesExt };

/* -------------------- constants ------------------ */

const METADATA_LENGTH: usize = 21;

/* -------------------- helpers -------------------- */

fn alpha (m: usize) -> f64 {
    match m {
        16 => 0.673,
        32 => 0.697,
        64 => 0.709,
        _  => 0.7213/(1f64 + 1.079/(m as f64))
    }
}

fn leftmost_one_bit (v: u64) -> usize {
    let mut counter: usize = 0;
    let mut shiftable = v;

    while shiftable > 0 {
        shiftable >>= 1;
        counter += 1;
    }

    64 - counter
}

/* ------------------------------------------------- */

/* --------------- hyper log log ------------------- */

/// The `HLL` struct stores the underlying registers
/// of the HyperLogLog, with `m` many registers.
///
/// The value for `m` is derived from the desired error
/// of the estimation. The error is considered to be
/// 1.04 / sqrt(2 ^ bits). So, given a desired 1% error
/// rate, we result in around 12 bits per register,
/// producing an underlying M of 2^12 bits (i.e. 4kb).
#[derive(Clone, PartialEq)]
pub struct HLL {
    alpha: f64,
    b: u32,
    m: usize,
    M: Vec<u8>,
    // [!] this is pretty much a hack until I can think of something
    //     better to do for the monoid instance. Basically we need the
    //     zero value to always satisfy the left and right identity laws
    //     but because you need to have the number of registers be
    //     equivalent to do addition, it implies you need a distinct
    //     monoid instance per HLL configuration (i.e. an HLL of 4
    //     registers has a distinct zero from a HLL of 16).
    //
    //     Because I can't really do dependent types in rust, we instead
    //     have a distinguished zero element, that is allowed to bypass
    //     the assertions on the equivalent sizes...
    //
    //     For reference, Ed Kmett's haskell implementation actually does
    //     use higher kinded types and some tricky reflection to make the
    //     monoid instance be parameterised by a config type that is itself
    //     typed to a Peano natural encoded type. Twitter's algebird instance
    //     declares a separate class that encapsulates the notion of
    //     a "HyperLogLogMonoid" instance, and instances of that class are
    //     instantiated with the register size (i.e. the 'instance' for monoid
    //     is just an 'instance' of the class, for two interpretations of
    //     'instance').
    isZero: bool
}

impl std::cmp::Eq for HLL {}

impl HLL {
    /// Convenience function to produce a HLL with
    /// one hundred and twenty eight registers.
    pub fn one_hundred_twenty_eight () -> HLL {
        HLL::new(0.09192)
    }

    /// Create a new HLL with the desired standard error.
    /// Some examples might be:
    ///
    ///```ignore
    ///     bits    size    error
    ///     12      4096    0.0163
    ///     13      8192    0.0115
    ///     14      16384   0.0081
    ///```
    ///
    /// The error must be between 0.0 and 1.0. Beware using a stupidly
    /// small error size will grow beyond e.g. isize at less than 0.03
    /// (if you need something that isn't an estimate probably don't use
    /// a hyperloglog).
    pub fn new(error: f64) -> HLL {
        assert!(error > 0.0 && error < 1.0);
        // error = 1.04 / sqrt(m)
        let m = ((1.04/error) * (1.04/error)).floor() as usize;
        let b = (m as f64).log2() as u32;

        HLL {
            alpha: alpha(m),
            b: b,
            m: m,
            M: repeat(0u8).take(m).collect(),
            isZero: false
        }
    }

    /// Add an element into the hyperloglog estimate.
    /// We require the type of value to be able to be hashed.
    /// Returns whether the insertion altered the hyperloglog
    pub fn insert<T: Hash>(&mut self, val: &T) -> bool {
        let mut hasher = SipHasher::new();
        val.hash(&mut hasher);
        let hash = hasher.finish();

        // j is the first b many bits
        let j = (hash >> (64 - self.b)) as usize;
        // w is the remaining bits (i.e. b -> 64)
        let w = hash & (2u64.pow(64 - self.b) - 1) as u64;
        let rho = leftmost_one_bit(w) as u8;

        let prev = self.M[j];
        self.M[j] = cmp::max(self.M[j], rho);

        prev != self.M[j]
    }

    /// Return the estimated cardinality of the observed set
    /// of elements.
    pub fn count(&self) -> f64 {
        self.range_correction(self.raw_estimate())
    }

    fn raw_estimate(&self) -> f64 {
        let sum: f64 = self.M.iter().fold (0.0, |p, &r| p + 2.0f64.powi(-(r as i32)));

        self.alpha as f64 * ((self.m  * self.m) as f64) * (1.0 / sum)
    }

    fn empty_registers (&self) -> usize {
        self.M.iter().filter(|&r| *r == 0).count()
    }

    fn range_correction(&self, e: f64) -> f64 {
        let twoTo32: f64 = 2.0f64.powi(32) as f64;

        // small range correction
        if e <= (5.0*(self.m as f64))/2.0 {
            let v  = self.empty_registers() as f64;
            let fm = self.m as f64;

            return match v {
                0.0 => e,
                _   => fm * (fm / v).ln()
            }
        }

        // medium range (no) correction
        if e <= twoTo32/30.0 {
            return e;
        }

        -twoTo32 * (1.0 - e/twoTo32).ln()
    }

    /// Access a copy of the underlying registers (this is mainly
    /// here just for debugging/testing... its unlikely you'll need
    /// this access typically).
    pub fn registers(&self) -> Vec<u8> {
        self.M.clone()
    }

    /// A completely zeroed HLL. Not particularly useful
    /// except as an identity element in `Add`.
    pub fn empty () -> HLL {
        HLL {
            alpha: 0.0,
            m: 0,
            b: 0,
            M: Vec::new(),
            isZero: true
        }
    }

    pub fn into_vec(self) -> Vec<u8> {
        let mut data = self.M;
        data.reserve(METADATA_LENGTH);
        data.write_f64::<BigEndian>(self.alpha).unwrap();
        data.write_u32::<BigEndian>(self.b).unwrap();
        data.write_u64::<BigEndian>(self.m as u64).unwrap();
        data.write_u8(if self.isZero { 0 } else { 1 }).unwrap();
        data
    }

    pub fn from_vec(data: Vec<u8>) -> HLL {
        assert!(data.len() >= METADATA_LENGTH);
        let mut M = data;
        let metadata_offset = M.len() - METADATA_LENGTH;
        let metadata: Vec<u8> = M.drain(metadata_offset..).collect();

        let mut readable = Cursor::new(metadata);
        let alpha = readable.read_f64::<BigEndian>().unwrap();
        let b = readable.read_u32::<BigEndian>().unwrap();
        let m = readable.read_u64::<BigEndian>().unwrap() as usize;
        let isZero = readable.read_u8().unwrap() == 0;
        HLL {
            M: M,
            alpha: alpha,
            b: b,
            m: m,
            isZero: isZero,
        }
    }
}

/* ------------------------------------------------- */

/* --------------- trait instances ----------------- */

impl std::fmt::Display for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::fmt::Debug for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

fn zipWith<R, U: Iterator, C: Fn(U::Item, U::Item) -> R> (combo: C, left: U, right: U)
   -> Vec<R> {
    left.zip(right).map(| (l, r) | combo(l, r)).collect()
}

fn mergeRegisters (first: &Vec<u8>, second: &Vec<u8>) -> Vec<u8> {
    zipWith(|&l, &r| std::cmp::max(l, r), first.iter(), second.iter())
}

/// Adding together two HLLs produces a new HLL where
/// the larger value of each register has been selected.
impl<'a> std::ops::Add<&'a HLL> for &'a HLL {
    type Output = HLL;

    fn add(self, other: &'a HLL) -> HLL {
        // [!] gross...
        if self.isZero { return other.clone(); }
        if other.isZero { return self.clone(); }

        assert!(self.alpha == other.alpha);
        assert!(self.b == other.b);
        assert!(self.m == other.m);

        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: mergeRegisters(&self.M, &other.M),
            isZero: false
        }
    }
}

/* ------------------------------------------------- */
<commit_msg>:wrench: remove deprecated 'SipHasher' for 'std::collections::hash_map::DefaultHasher'<commit_after>// use variable names from paper, namely registers M
#![allow(non_snake_case)]

#![crate_name = "basichll"]
#![crate_type = "lib"]

extern crate byteorder;

/* -------------------- std libs ------------------- */
use std::cmp;
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{ Hash, Hasher };
use std::io::Cursor;
use std::iter::{ repeat, Iterator };
/* ------------------------------------------------- */

use byteorder::{ BigEndian, WriteBytesExt, ReadBytesExt };

/* -------------------- constants ------------------ */

const METADATA_LENGTH: usize = 21;

/* -------------------- helpers -------------------- */

fn alpha (m: usize) -> f64 {
    match m {
        16 => 0.673,
        32 => 0.697,
        64 => 0.709,
        _  => 0.7213/(1f64 + 1.079/(m as f64))
    }
}

fn leftmost_one_bit (v: u64) -> usize {
    let mut counter: usize = 0;
    let mut shiftable = v;

    while shiftable > 0 {
        shiftable >>= 1;
        counter += 1;
    }

    64 - counter
}

/* ------------------------------------------------- */

/* --------------- hyper log log ------------------- */

/// The `HLL` struct stores the underlying registers
/// of the HyperLogLog, with `m` many registers.
///
/// The value for `m` is derived from the desired error
/// of the estimation. The error is considered to be
/// 1.04 / sqrt(2 ^ bits). So, given a desired 1% error
/// rate, we result in around 12 bits per register,
/// producing an underlying M of 2^12 bits (i.e. 4kb).
#[derive(Clone, PartialEq)]
pub struct HLL {
    alpha: f64,
    b: u32,
    m: usize,
    M: Vec<u8>,
    // [!] this is pretty much a hack until I can think of something
    //     better to do for the monoid instance. Basically we need the
    //     zero value to always satisfy the left and right identity laws
    //     but because you need to have the number of registers be
    //     equivalent to do addition, it implies you need a distinct
    //     monoid instance per HLL configuration (i.e. an HLL of 4
    //     registers has a distinct zero from a HLL of 16).
    //
    //     Because I can't really do dependent types in rust, we instead
    //     have a distinguished zero element, that is allowed to bypass
    //     the assertions on the equivalent sizes...
    //
    //     For reference, Ed Kmett's haskell implementation actually does
    //     use higher kinded types and some tricky reflection to make the
    //     monoid instance be parameterised by a config type that is itself
    //     typed to a Peano natural encoded type. Twitter's algebird instance
    //     declares a separate class that encapsulates the notion of
    //     a "HyperLogLogMonoid" instance, and instances of that class are
    //     instantiated with the register size (i.e. the 'instance' for monoid
    //     is just an 'instance' of the class, for two interpretations of
    //     'instance').
    isZero: bool
}

impl std::cmp::Eq for HLL {}

impl HLL {
    /// Convenience function to produce a HLL with
    /// one hundred and twenty eight registers.
    pub fn one_hundred_twenty_eight () -> HLL {
        HLL::new(0.09192)
    }

    /// Create a new HLL with the desired standard error.
    /// Some examples might be:
    ///
    ///```ignore
    ///     bits    size    error
    ///     12      4096    0.0163
    ///     13      8192    0.0115
    ///     14      16384   0.0081
    ///```
    ///
    /// The error must be between 0.0 and 1.0. Beware using a stupidly
    /// small error size will grow beyond e.g. isize at less than 0.03
    /// (if you need something that isn't an estimate probably don't use
    /// a hyperloglog).
    pub fn new(error: f64) -> HLL {
        assert!(error > 0.0 && error < 1.0);
        // error = 1.04 / sqrt(m)
        let m = ((1.04/error) * (1.04/error)).floor() as usize;
        let b = (m as f64).log2() as u32;

        HLL {
            alpha: alpha(m),
            b: b,
            m: m,
            M: repeat(0u8).take(m).collect(),
            isZero: false
        }
    }

    /// Add an element into the hyperloglog estimate.
    /// We require the type of value to be able to be hashed.
    /// Returns whether the insertion altered the hyperloglog
    pub fn insert<T: Hash>(&mut self, val: &T) -> bool {
        let mut hasher = DefaultHasher::new();
        val.hash(&mut hasher);
        let hash = hasher.finish();

        // j is the first b many bits
        let j = (hash >> (64 - self.b)) as usize;
        // w is the remaining bits (i.e. b -> 64)
        let w = hash & (2u64.pow(64 - self.b) - 1) as u64;
        let rho = leftmost_one_bit(w) as u8;

        let prev = self.M[j];
        self.M[j] = cmp::max(self.M[j], rho);

        prev != self.M[j]
    }

    /// Return the estimated cardinality of the observed set
    /// of elements.
    pub fn count(&self) -> f64 {
        self.range_correction(self.raw_estimate())
    }

    fn raw_estimate(&self) -> f64 {
        let sum: f64 = self.M.iter().fold (0.0, |p, &r| p + 2.0f64.powi(-(r as i32)));

        self.alpha as f64 * ((self.m  * self.m) as f64) * (1.0 / sum)
    }

    fn empty_registers (&self) -> usize {
        self.M.iter().filter(|&r| *r == 0).count()
    }

    fn range_correction(&self, e: f64) -> f64 {
        let twoTo32: f64 = 2.0f64.powi(32) as f64;

        // small range correction
        if e <= (5.0*(self.m as f64))/2.0 {
            let v  = self.empty_registers() as f64;
            let fm = self.m as f64;

            return match v {
                0.0 => e,
                _   => fm * (fm / v).ln()
            }
        }

        // medium range (no) correction
        if e <= twoTo32/30.0 {
            return e;
        }

        -twoTo32 * (1.0 - e/twoTo32).ln()
    }

    /// Access a copy of the underlying registers (this is mainly
    /// here just for debugging/testing... its unlikely you'll need
    /// this access typically).
    pub fn registers(&self) -> Vec<u8> {
        self.M.clone()
    }

    /// A completely zeroed HLL. Not particularly useful
    /// except as an identity element in `Add`.
    pub fn empty () -> HLL {
        HLL {
            alpha: 0.0,
            m: 0,
            b: 0,
            M: Vec::new(),
            isZero: true
        }
    }

    pub fn into_vec(self) -> Vec<u8> {
        let mut data = self.M;
        data.reserve(METADATA_LENGTH);
        data.write_f64::<BigEndian>(self.alpha).unwrap();
        data.write_u32::<BigEndian>(self.b).unwrap();
        data.write_u64::<BigEndian>(self.m as u64).unwrap();
        data.write_u8(if self.isZero { 0 } else { 1 }).unwrap();
        data
    }

    pub fn from_vec(data: Vec<u8>) -> HLL {
        assert!(data.len() >= METADATA_LENGTH);
        let mut M = data;
        let metadata_offset = M.len() - METADATA_LENGTH;
        let metadata: Vec<u8> = M.drain(metadata_offset..).collect();

        let mut readable = Cursor::new(metadata);
        let alpha = readable.read_f64::<BigEndian>().unwrap();
        let b = readable.read_u32::<BigEndian>().unwrap();
        let m = readable.read_u64::<BigEndian>().unwrap() as usize;
        let isZero = readable.read_u8().unwrap() == 0;
        HLL {
            M: M,
            alpha: alpha,
            b: b,
            m: m,
            isZero: isZero,
        }
    }
}

/* ------------------------------------------------- */

/* --------------- trait instances ----------------- */

impl std::fmt::Display for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::fmt::Debug for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

fn zipWith<R, U: Iterator, C: Fn(U::Item, U::Item) -> R> (combo: C, left: U, right: U)
   -> Vec<R> {
    left.zip(right).map(| (l, r) | combo(l, r)).collect()
}

fn mergeRegisters (first: &Vec<u8>, second: &Vec<u8>) -> Vec<u8> {
    zipWith(|&l, &r| std::cmp::max(l, r), first.iter(), second.iter())
}

/// Adding together two HLLs produces a new HLL where
/// the larger value of each register has been selected.
impl<'a> std::ops::Add<&'a HLL> for &'a HLL {
    type Output = HLL;

    fn add(self, other: &'a HLL) -> HLL {
        // [!] gross...
        if self.isZero { return other.clone(); }
        if other.isZero { return self.clone(); }

        assert!(self.alpha == other.alpha);
        assert!(self.b == other.b);
        assert!(self.m == other.m);

        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: mergeRegisters(&self.M, &other.M),
            isZero: false
        }
    }
}

/* ------------------------------------------------- */
<|endoftext|>


<commit_before>#![feature(plugin_registrar, quote, rustc_private, custom_attribute)]

extern crate rustc_plugin;
extern crate syntax;

use rustc_plugin::registry::Registry;
use syntax::ast::{Attribute, Block, Expr, ExprKind, Ident, Item, ItemKind, Mac,
                  MetaItem, MetaItemKind};
use syntax::fold::{self, Folder};
use syntax::ptr::P;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
use syntax::ext::build::AstBuilder;
use syntax::feature_gate::AttributeType;
use syntax::symbol::Symbol;
use syntax::util::small_vector::SmallVector;

pub fn insert_flame_guard(cx: &mut ExtCtxt, _span: Span, _mi: &MetaItem,
                          a: Annotatable) -> Annotatable {
    match a {
        Annotatable::Item(i) => Annotatable::Item(
            Flamer { cx: cx, ident: i.ident }.fold_item(i).expect_one("expected exactly one item")),
        Annotatable::TraitItem(i) => Annotatable::TraitItem(
            i.map(|i| Flamer { cx: cx, ident: i.ident }.fold_trait_item(i).expect_one("expected exactly one item"))),
        Annotatable::ImplItem(i) => Annotatable::ImplItem(
            i.map(|i| Flamer { cx: cx, ident: i.ident }.fold_impl_item(i).expect_one("expected exactly one item"))),
    }
}

struct Flamer<'a, 'cx: 'a> {
    ident: Ident,
    cx: &'a mut ExtCtxt<'cx>,
}

impl<'a, 'cx> Folder for Flamer<'a, 'cx> {
    fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
        if let ItemKind::Mac(_) = item.node {
            let expanded = self.cx.expander().fold_item(item);
            expanded.into_iter()
                    .flat_map(|i| fold::noop_fold_item(i, self).into_iter())
                    .collect()
        } else {
            fold::noop_fold_item(item, self)
        }
    }

    fn fold_item_simple(&mut self, i: Item) -> Item {
        fn is_flame_annotation(attr: &Attribute) -> bool {
            if let MetaItemKind::Word(ref name) = attr.value.node {
                name == "flame" || name == "noflame"
            } else {
                false
            }
        }
        // don't double-flame nested annotations
        if i.attrs.iter().any(is_flame_annotation) { return i; }
        if let ItemKind::Mac(_) = i.node {
            return i;
        }else {
            self.ident = i.ident; // update in case of nested items
            fold::noop_fold_item_simple(i, self)
        }
    }

    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
        block.map(|block| {
            let name = self.cx.expr_str(DUMMY_SP, self.ident.name);
            quote_block!(self.cx, {
                let g = ::flame::start_guard($name);
                let r = $block;
                g.end();
                r
            }).unwrap()
        })
    }

    fn fold_expr(&mut self, expr: P<Expr>) -> P<Expr> {
        if let ExprKind::Mac(_) = expr.node {
            self.cx.expander().fold_expr(expr)
                              .map(|e| fold::noop_fold_expr(e, self))
        } else {
            expr
        }
    }

    fn fold_mac(&mut self, mac: Mac) -> Mac {
        mac
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(Symbol::intern("flame"),
        SyntaxExtension::MultiModifier(Box::new(insert_flame_guard)));
    reg.register_attribute(String::from("noflame"), AttributeType::Whitelisted);
}
<commit_msg>trying something else<commit_after>#![feature(plugin_registrar, quote, rustc_private, custom_attribute)]

extern crate rustc_plugin;
extern crate syntax;

use rustc_plugin::registry::Registry;
use syntax::ast::{Attribute, Block, Expr, ExprKind, Ident, Item, ItemKind, Mac,
                  MetaItem, MetaItemKind};
use syntax::fold::{self, Folder};
use syntax::ptr::P;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
use syntax::ext::build::AstBuilder;
use syntax::feature_gate::AttributeType;
use syntax::symbol::Symbol;
use syntax::util::small_vector::SmallVector;

pub fn insert_flame_guard(cx: &mut ExtCtxt, _span: Span, _mi: &MetaItem,
                          a: Annotatable) -> Annotatable {
    match a {
        Annotatable::Item(i) => Annotatable::Item(
            Flamer { cx: cx, ident: i.ident }.fold_item(i).expect_one("expected exactly one item")),
        Annotatable::TraitItem(i) => Annotatable::TraitItem(
            i.map(|i| Flamer { cx: cx, ident: i.ident }.fold_trait_item(i).expect_one("expected exactly one item"))),
        Annotatable::ImplItem(i) => Annotatable::ImplItem(
            i.map(|i| Flamer { cx: cx, ident: i.ident }.fold_impl_item(i).expect_one("expected exactly one item"))),
    }
}

struct Flamer<'a, 'cx: 'a> {
    ident: Ident,
    cx: &'a mut ExtCtxt<'cx>,
}

impl<'a, 'cx> Folder for Flamer<'a, 'cx> {
    fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
        if let ItemKind::Mac(_) = item.node {
            let expanded = self.cx.expander().fold_item(item);
            expanded.into_iter()
                    .flat_map(|i| fold::noop_fold_item(i, self).into_iter())
                    .collect()
        } else {
            fold::noop_fold_item(item, self)
        }
    }

    fn fold_item_simple(&mut self, i: Item) -> Item {
        fn is_flame_annotation(attr: &Attribute) -> bool {
            match attr.value.node {
                MetaItemKind::Word => {
                    attr.value.name.as_str() == "flame"
                },
                _ => false
            }
        }
        // don't double-flame nested annotations
        if i.attrs.iter().any(is_flame_annotation) { return i; }
        if let ItemKind::Mac(_) = i.node {
            return i;
        }else {
            self.ident = i.ident; // update in case of nested items
            fold::noop_fold_item_simple(i, self)
        }
    }

    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
        block.map(|block| {
            let name = self.cx.expr_str(DUMMY_SP, self.ident.name);
            quote_block!(self.cx, {
                let g = ::flame::start_guard($name);
                let r = $block;
                g.end();
                r
            }).unwrap()
        })
    }

    fn fold_expr(&mut self, expr: P<Expr>) -> P<Expr> {
        if let ExprKind::Mac(_) = expr.node {
            self.cx.expander().fold_expr(expr)
                              .map(|e| fold::noop_fold_expr(e, self))
        } else {
            expr
        }
    }

    fn fold_mac(&mut self, mac: Mac) -> Mac {
        mac
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(Symbol::intern("flame"),
        SyntaxExtension::MultiModifier(Box::new(insert_flame_guard)));
    reg.register_attribute(String::from("noflame"), AttributeType::Whitelisted);
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![no_std]

extern crate collections;

extern crate abs;
extern crate from_primitive;
extern crate max;
extern crate min;
extern crate one;
extern crate pi;
extern crate round;
extern crate signum;
extern crate sqrt;
extern crate trig;
extern crate zero;

use collections::string::ToString;
use core::ops::*;

pub use abs::Abs;
pub use from_primitive::FromPrimitive;
pub use max::Max;
pub use min::Min;
pub use one::One;
pub use pi::Pi;
pub use round::Round;
pub use signum::Signum;
pub use sqrt::Sqrt;
pub use trig::Trig;
pub use zero::Zero;

pub trait Num:
    Copy + One + Zero + Sqrt
    + Min + Max + Signum
    + Abs
    + FromPrimitive
    + Trig
    + Pi
    + PartialEq
    + PartialOrd
    + Round
    + ToString

    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>
    + Neg<Output = Self> {}

impl<T> Num for T where T:
    Copy + One + Zero + Sqrt
    + Min + Max + Signum
    + Abs
    + FromPrimitive
    + Trig
    + Pi
    + PartialEq
    + PartialOrd
    + Round
    + ToString

    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>
    + Neg<Output = T> {}
<commit_msg>updates<commit_after>#![feature(collections, reflect_marker)]
#![no_std]

extern crate collections;

extern crate abs;
extern crate from_primitive;
extern crate max;
extern crate min;
extern crate one;
extern crate pi;
extern crate round;
extern crate signum;
extern crate sqrt;
extern crate trig;
extern crate zero;

use collections::string::ToString;
use core::marker::Reflect;
use core::ops::*;

pub use abs::Abs;
pub use from_primitive::FromPrimitive;
pub use max::Max;
pub use min::Min;
pub use one::One;
pub use pi::Pi;
pub use round::Round;
pub use signum::Signum;
pub use sqrt::Sqrt;
pub use trig::Trig;
pub use zero::Zero;

pub trait Num:
    Copy + One + Zero + Sqrt
    + Min + Max + Signum
    + Abs
    + FromPrimitive
    + Trig
    + Pi
    + PartialEq
    + PartialOrd
    + Round
    + ToString
    + Reflect

    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>
    + Neg<Output = Self> {}

impl<T> Num for T where T:
    Copy + One + Zero + Sqrt
    + Min + Max + Signum
    + Abs
    + FromPrimitive
    + Trig
    + Pi
    + PartialEq
    + PartialOrd
    + Round
    + ToString
    + Reflect

    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>
    + Neg<Output = T> {}
<|endoftext|>