<commit_before>// Copyright 2012-2013 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.

//! Base64 binary-to-text encoding
use std::str;
use std::fmt;

/// Available encoding character sets
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe
}

/// Contains configuration parameters for `to_base64`.
pub struct Config {
    /// Character set to use
    pub char_set: CharacterSet,
    /// True to pad output with `=` characters
    pub pad: bool,
    /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
    pub line_length: Option<uint>
}

/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
    Config {char_set: Standard, pad: true, line_length: None};

/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
    Config {char_set: UrlSafe, pad: false, line_length: None};

/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
    Config {char_set: Standard, pad: true, line_length: Some(76)};

static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                                        abcdefghijklmnopqrstuvwxyz\
                                        0123456789+/";

static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                                       abcdefghijklmnopqrstuvwxyz\
                                       0123456789-_";

/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
    /// Converts the value of `self` to a base64 value following the specified
    /// format configuration, returning the owned string.
    fn to_base64(&self, config: Config) -> String;
}

impl<'a> ToBase64 for &'a [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ```rust
     * extern crate serialize;
     * use serialize::base64::{ToBase64, STANDARD};
     *
     * fn main () {
     *     let str = [52,32].to_base64(STANDARD);
     *     println!("base 64 output: {}", str);
     * }
     * ```
     */
    fn to_base64(&self, config: Config) -> String {
        let bytes = match config.char_set {
            Standard => STANDARD_CHARS,
            UrlSafe => URLSAFE_CHARS
        };

        let mut v = Vec::new();
        let mut i = 0;
        let mut cur_length = 0;
        let len = self.len();
        while i < len - (len % 3) {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                        cur_length = 0;
                    },
                None => ()
            }

            let n = (self[i] as u32) << 16 |
                    (self[i + 1] as u32) << 8 |
                    (self[i + 2] as u32);

            // This 24-bit number gets separated into four 6-bit numbers.
            v.push(bytes[((n >> 18) & 63) as uint]);
            v.push(bytes[((n >> 12) & 63) as uint]);
            v.push(bytes[((n >> 6 ) & 63) as uint]);
            v.push(bytes[(n & 63) as uint]);

            cur_length += 4;
            i += 3;
        }

        if len % 3 != 0 {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                    },
                None => ()
            }
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
            0 => (),
            1 => {
                let n = (self[i] as u32) << 16;
                v.push(bytes[((n >> 18) & 63) as uint]);
                v.push(bytes[((n >> 12) & 63) as uint]);
                if config.pad {
                    v.push('=' as u8);
                    v.push('=' as u8);
                }
            }
            2 => {
                let n = (self[i] as u32) << 16 |
                    (self[i + 1u] as u32) << 8;
                v.push(bytes[((n >> 18) & 63) as uint]);
                v.push(bytes[((n >> 12) & 63) as uint]);
                v.push(bytes[((n >> 6 ) & 63) as uint]);
                if config.pad {
                    v.push('=' as u8);
                }
            }
            _ => fail!("Algebra is broken, please alert the math police")
        }

        unsafe {
            str::raw::from_utf8_owned(v)
        }
    }
}

/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
    /// Converts the value of `self`, interpreted as base64 encoded data, into
    /// an owned vector of bytes, returning the vector.
    fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error>;
}

/// Errors that can occur when decoding a base64 encoded string
pub enum FromBase64Error {
    /// The input contained a character not part of the base64 format
    InvalidBase64Character(char, uint),
    /// The input had an invalid length
    InvalidBase64Length,
}

impl fmt::Show for FromBase64Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase64Character(ch, idx) =>
                write!(f, "Invalid character '{}' at position {}", ch, idx),
            InvalidBase64Length => write!(f, "Invalid length"),
        }
    }
}

impl<'a> FromBase64 for &'a str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `String::from_utf8` function in `std::string` to turn a
     * `Vec<u8>` into a string with characters corresponding to those values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ```rust
     * extern crate serialize;
     * use serialize::base64::{ToBase64, FromBase64, STANDARD};
     *
     * fn main () {
     *     let hello_str = b"Hello, World".to_base64(STANDARD);
     *     println!("base64 output: {}", hello_str);
     *     let res = hello_str.as_slice().from_base64();
     *     if res.is_ok() {
     *       let opt_bytes = String::from_utf8(res.unwrap());
     *       if opt_bytes.is_ok() {
     *         println!("decoded from base64: {}", opt_bytes.unwrap());
     *       }
     *     }
     * }
     * ```
     */
    fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
        let mut r = Vec::new();
        let mut buf: u32 = 0;
        let mut modulus = 0i;

        let mut it = self.bytes().enumerate();
        for (idx, byte) in it {
            let val = byte as u32;

            match byte as char {
                'A'..'Z' => buf |= val - 0x41,
                'a'..'z' => buf |= val - 0x47,
                '0'..'9' => buf |= val + 0x04,
                '+'|'-' => buf |= 0x3E,
                '/'|'_' => buf |= 0x3F,
                '\r'|'\n' => continue,
                '=' => break,
                _ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
            }

            buf <<= 6;
            modulus += 1;
            if modulus == 4 {
                modulus = 0;
                r.push((buf >> 22) as u8);
                r.push((buf >> 14) as u8);
                r.push((buf >> 6 ) as u8);
            }
        }

        for (idx, byte) in it {
            match byte as char {
                '='|'\r'|'\n' => continue,
                _ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
            }
        }

        match modulus {
            2 => {
                r.push((buf >> 10) as u8);
            }
            3 => {
                r.push((buf >> 16) as u8);
                r.push((buf >> 8 ) as u8);
            }
            0 => (),
            _ => return Err(InvalidBase64Length),
        }

        Ok(r)
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;
    use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE};

    #[test]
    fn test_to_base64_basic() {
        assert_eq!("".as_bytes().to_base64(STANDARD), "".to_string());
        assert_eq!("f".as_bytes().to_base64(STANDARD), "Zg==".to_string());
        assert_eq!("fo".as_bytes().to_base64(STANDARD), "Zm8=".to_string());
        assert_eq!("foo".as_bytes().to_base64(STANDARD), "Zm9v".to_string());
        assert_eq!("foob".as_bytes().to_base64(STANDARD), "Zm9vYg==".to_string());
        assert_eq!("fooba".as_bytes().to_base64(STANDARD), "Zm9vYmE=".to_string());
        assert_eq!("foobar".as_bytes().to_base64(STANDARD), "Zm9vYmFy".to_string());
    }

    #[test]
    fn test_to_base64_line_break() {
        assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD})
                              .as_slice()
                              .contains("\r\n"));
        assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
                                                         ..STANDARD}),
                   "Zm9v\r\nYmFy".to_string());
    }

    #[test]
    fn test_to_base64_padding() {
        assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zg".to_string());
        assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zm8".to_string());
    }

    #[test]
    fn test_to_base64_url_safe() {
        assert_eq!([251, 255].to_base64(URL_SAFE), "-_8".to_string());
        assert_eq!([251, 255].to_base64(STANDARD), "+/8=".to_string());
    }

    #[test]
    fn test_from_base64_basic() {
        assert_eq!("".from_base64().unwrap().as_slice(), "".as_bytes());
        assert_eq!("Zg==".from_base64().unwrap().as_slice(), "f".as_bytes());
        assert_eq!("Zm8=".from_base64().unwrap().as_slice(), "fo".as_bytes());
        assert_eq!("Zm9v".from_base64().unwrap().as_slice(), "foo".as_bytes());
        assert_eq!("Zm9vYg==".from_base64().unwrap().as_slice(), "foob".as_bytes());
        assert_eq!("Zm9vYmE=".from_base64().unwrap().as_slice(), "fooba".as_bytes());
        assert_eq!("Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
    }

    #[test]
    fn test_from_base64_newlines() {
        assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap().as_slice(),
                   "foobar".as_bytes());
        assert_eq!("Zm9vYg==\r\n".from_base64().unwrap().as_slice(),
                   "foob".as_bytes());
    }

    #[test]
    fn test_from_base64_urlsafe() {
        assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
    }

    #[test]
    fn test_from_base64_invalid_char() {
        assert!("Zm$=".from_base64().is_err())
        assert!("Zg==$".from_base64().is_err());
    }

    #[test]
    fn test_from_base64_invalid_padding() {
        assert!("Z===".from_base64().is_err());
    }

    #[test]
    fn test_base64_random() {
        use std::rand::{task_rng, random, Rng};

        for _ in range(0u, 1000) {
            let times = task_rng().gen_range(1u, 100);
            let v = Vec::from_fn(times, |_| random::<u8>());
            assert_eq!(v.as_slice()
                        .to_base64(STANDARD)
                        .as_slice()
                        .from_base64()
                        .unwrap()
                        .as_slice(),
                       v.as_slice());
        }
    }

    #[bench]
    pub fn bench_to_base64(b: &mut Bencher) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        b.iter(|| {
            s.as_bytes().to_base64(STANDARD);
        });
        b.bytes = s.len() as u64;
    }

    #[bench]
    pub fn bench_from_base64(b: &mut Bencher) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        let sb = s.as_bytes().to_base64(STANDARD);
        b.iter(|| {
            sb.as_slice().from_base64().unwrap();
        });
        b.bytes = sb.len() as u64;
    }

}
<commit_msg>auto merge of #15810 : SimonSapin/rust/base64-from-bytes, r=alexcrichton<commit_after>// Copyright 2012-2013 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.

//! Base64 binary-to-text encoding
use std::str;
use std::fmt;

/// Available encoding character sets
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe
}

/// Contains configuration parameters for `to_base64`.
pub struct Config {
    /// Character set to use
    pub char_set: CharacterSet,
    /// True to pad output with `=` characters
    pub pad: bool,
    /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
    pub line_length: Option<uint>
}

/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
    Config {char_set: Standard, pad: true, line_length: None};

/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
    Config {char_set: UrlSafe, pad: false, line_length: None};

/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
    Config {char_set: Standard, pad: true, line_length: Some(76)};

static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                                        abcdefghijklmnopqrstuvwxyz\
                                        0123456789+/";

static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                                       abcdefghijklmnopqrstuvwxyz\
                                       0123456789-_";

/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
    /// Converts the value of `self` to a base64 value following the specified
    /// format configuration, returning the owned string.
    fn to_base64(&self, config: Config) -> String;
}

impl<'a> ToBase64 for &'a [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ```rust
     * extern crate serialize;
     * use serialize::base64::{ToBase64, STANDARD};
     *
     * fn main () {
     *     let str = [52,32].to_base64(STANDARD);
     *     println!("base 64 output: {}", str);
     * }
     * ```
     */
    fn to_base64(&self, config: Config) -> String {
        let bytes = match config.char_set {
            Standard => STANDARD_CHARS,
            UrlSafe => URLSAFE_CHARS
        };

        let mut v = Vec::new();
        let mut i = 0;
        let mut cur_length = 0;
        let len = self.len();
        while i < len - (len % 3) {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                        cur_length = 0;
                    },
                None => ()
            }

            let n = (self[i] as u32) << 16 |
                    (self[i + 1] as u32) << 8 |
                    (self[i + 2] as u32);

            // This 24-bit number gets separated into four 6-bit numbers.
            v.push(bytes[((n >> 18) & 63) as uint]);
            v.push(bytes[((n >> 12) & 63) as uint]);
            v.push(bytes[((n >> 6 ) & 63) as uint]);
            v.push(bytes[(n & 63) as uint]);

            cur_length += 4;
            i += 3;
        }

        if len % 3 != 0 {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                    },
                None => ()
            }
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
            0 => (),
            1 => {
                let n = (self[i] as u32) << 16;
                v.push(bytes[((n >> 18) & 63) as uint]);
                v.push(bytes[((n >> 12) & 63) as uint]);
                if config.pad {
                    v.push('=' as u8);
                    v.push('=' as u8);
                }
            }
            2 => {
                let n = (self[i] as u32) << 16 |
                    (self[i + 1u] as u32) << 8;
                v.push(bytes[((n >> 18) & 63) as uint]);
                v.push(bytes[((n >> 12) & 63) as uint]);
                v.push(bytes[((n >> 6 ) & 63) as uint]);
                if config.pad {
                    v.push('=' as u8);
                }
            }
            _ => fail!("Algebra is broken, please alert the math police")
        }

        unsafe {
            str::raw::from_utf8_owned(v)
        }
    }
}

/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
    /// Converts the value of `self`, interpreted as base64 encoded data, into
    /// an owned vector of bytes, returning the vector.
    fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error>;
}

/// Errors that can occur when decoding a base64 encoded string
pub enum FromBase64Error {
    /// The input contained a character not part of the base64 format
    InvalidBase64Byte(u8, uint),
    /// The input had an invalid length
    InvalidBase64Length,
}

impl fmt::Show for FromBase64Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase64Byte(ch, idx) =>
                write!(f, "Invalid character '{}' at position {}", ch, idx),
            InvalidBase64Length => write!(f, "Invalid length"),
        }
    }
}

impl<'a> FromBase64 for &'a str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `String::from_utf8` function in `std::string` to turn a
     * `Vec<u8>` into a string with characters corresponding to those values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ```rust
     * extern crate serialize;
     * use serialize::base64::{ToBase64, FromBase64, STANDARD};
     *
     * fn main () {
     *     let hello_str = b"Hello, World".to_base64(STANDARD);
     *     println!("base64 output: {}", hello_str);
     *     let res = hello_str.as_slice().from_base64();
     *     if res.is_ok() {
     *       let opt_bytes = String::from_utf8(res.unwrap());
     *       if opt_bytes.is_ok() {
     *         println!("decoded from base64: {}", opt_bytes.unwrap());
     *       }
     *     }
     * }
     * ```
     */
    #[inline]
    fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
        self.as_bytes().from_base64()
    }
}

impl<'a> FromBase64 for &'a [u8] {
    fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
        let mut r = Vec::new();
        let mut buf: u32 = 0;
        let mut modulus = 0i;

        let mut it = self.iter().enumerate();
        for (idx, &byte) in it {
            let val = byte as u32;

            match byte {
                b'A'..b'Z' => buf |= val - 0x41,
                b'a'..b'z' => buf |= val - 0x47,
                b'0'..b'9' => buf |= val + 0x04,
                b'+' | b'-' => buf |= 0x3E,
                b'/' | b'_' => buf |= 0x3F,
                b'\r' | b'\n' => continue,
                b'=' => break,
                _ => return Err(InvalidBase64Byte(self[idx], idx)),
            }

            buf <<= 6;
            modulus += 1;
            if modulus == 4 {
                modulus = 0;
                r.push((buf >> 22) as u8);
                r.push((buf >> 14) as u8);
                r.push((buf >> 6 ) as u8);
            }
        }

        for (idx, &byte) in it {
            match byte {
                b'=' | b'\r' | b'\n' => continue,
                _ => return Err(InvalidBase64Byte(self[idx], idx)),
            }
        }

        match modulus {
            2 => {
                r.push((buf >> 10) as u8);
            }
            3 => {
                r.push((buf >> 16) as u8);
                r.push((buf >> 8 ) as u8);
            }
            0 => (),
            _ => return Err(InvalidBase64Length),
        }

        Ok(r)
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;
    use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE};

    #[test]
    fn test_to_base64_basic() {
        assert_eq!("".as_bytes().to_base64(STANDARD), "".to_string());
        assert_eq!("f".as_bytes().to_base64(STANDARD), "Zg==".to_string());
        assert_eq!("fo".as_bytes().to_base64(STANDARD), "Zm8=".to_string());
        assert_eq!("foo".as_bytes().to_base64(STANDARD), "Zm9v".to_string());
        assert_eq!("foob".as_bytes().to_base64(STANDARD), "Zm9vYg==".to_string());
        assert_eq!("fooba".as_bytes().to_base64(STANDARD), "Zm9vYmE=".to_string());
        assert_eq!("foobar".as_bytes().to_base64(STANDARD), "Zm9vYmFy".to_string());
    }

    #[test]
    fn test_to_base64_line_break() {
        assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD})
                              .as_slice()
                              .contains("\r\n"));
        assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
                                                         ..STANDARD}),
                   "Zm9v\r\nYmFy".to_string());
    }

    #[test]
    fn test_to_base64_padding() {
        assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zg".to_string());
        assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zm8".to_string());
    }

    #[test]
    fn test_to_base64_url_safe() {
        assert_eq!([251, 255].to_base64(URL_SAFE), "-_8".to_string());
        assert_eq!([251, 255].to_base64(STANDARD), "+/8=".to_string());
    }

    #[test]
    fn test_from_base64_basic() {
        assert_eq!("".from_base64().unwrap().as_slice(), "".as_bytes());
        assert_eq!("Zg==".from_base64().unwrap().as_slice(), "f".as_bytes());
        assert_eq!("Zm8=".from_base64().unwrap().as_slice(), "fo".as_bytes());
        assert_eq!("Zm9v".from_base64().unwrap().as_slice(), "foo".as_bytes());
        assert_eq!("Zm9vYg==".from_base64().unwrap().as_slice(), "foob".as_bytes());
        assert_eq!("Zm9vYmE=".from_base64().unwrap().as_slice(), "fooba".as_bytes());
        assert_eq!("Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
    }

    #[test]
    fn test_from_base64_bytes() {
        assert_eq!(b"Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
    }

    #[test]
    fn test_from_base64_newlines() {
        assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap().as_slice(),
                   "foobar".as_bytes());
        assert_eq!("Zm9vYg==\r\n".from_base64().unwrap().as_slice(),
                   "foob".as_bytes());
    }

    #[test]
    fn test_from_base64_urlsafe() {
        assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
    }

    #[test]
    fn test_from_base64_invalid_char() {
        assert!("Zm$=".from_base64().is_err())
        assert!("Zg==$".from_base64().is_err());
    }

    #[test]
    fn test_from_base64_invalid_padding() {
        assert!("Z===".from_base64().is_err());
    }

    #[test]
    fn test_base64_random() {
        use std::rand::{task_rng, random, Rng};

        for _ in range(0u, 1000) {
            let times = task_rng().gen_range(1u, 100);
            let v = Vec::from_fn(times, |_| random::<u8>());
            assert_eq!(v.as_slice()
                        .to_base64(STANDARD)
                        .as_slice()
                        .from_base64()
                        .unwrap()
                        .as_slice(),
                       v.as_slice());
        }
    }

    #[bench]
    pub fn bench_to_base64(b: &mut Bencher) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        b.iter(|| {
            s.as_bytes().to_base64(STANDARD);
        });
        b.bytes = s.len() as u64;
    }

    #[bench]
    pub fn bench_from_base64(b: &mut Bencher) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        let sb = s.as_bytes().to_base64(STANDARD);
        b.iter(|| {
            sb.as_slice().from_base64().unwrap();
        });
        b.bytes = sb.len() as u64;
    }

}
<|endoftext|>


<commit_before>extern crate serialize;
extern crate toml = "github.com/mneumann/rust-toml#toml:0.1";

use std::os;

#[deriving(ToStr,Decodable)]
struct Config {
    host: ~str,
    port: Option<uint>,
    ids: ~[uint],
    products: ~[Product]
}

#[deriving(ToStr,Decodable)]
struct Product {
    id: uint,
    name: ~str
}

fn main() {
    let toml = r###"
        host = "localhost"
        ids = [1, 10, 20]
          [[products]]
          id = 1
          name = "Product 1"
          [[products]]
          id = 2
          name = "Product 2"
    "###;

    let value = match toml::parse_from_bytes(toml.as_bytes()) {
        Ok(v) => v,
        Err(toml::ParseError) => {
            println!("parse error");
            os::set_exit_status(1);
            return;
        }
        Err(toml::IOError(e)) => {
            println!("I/O error: {}", e);
            os::set_exit_status(1);
            return;
        }
    };
    println!("{:?}", value);

    let cfg: Config = toml::from_toml(value);
    println!("{:s}", cfg.to_str());
}
<commit_msg>Change ToStr to Show in examples<commit_after>extern crate serialize;
extern crate toml = "github.com/mneumann/rust-toml#toml:0.1";

use std::os;

#[deriving(Show,Decodable)]
struct Config {
    host: ~str,
    port: Option<uint>,
    ids: ~[uint],
    products: ~[Product]
}

#[deriving(Show,Decodable)]
struct Product {
    id: uint,
    name: ~str
}

fn main() {
    let toml = r###"
        host = "localhost"
        ids = [1, 10, 20]
          [[products]]
          id = 1
          name = "Product 1"
          [[products]]
          id = 2
          name = "Product 2"
    "###;

    let value = match toml::parse_from_bytes(toml.as_bytes()) {
        Ok(v) => v,
        Err(toml::ParseError) => {
            println!("parse error");
            os::set_exit_status(1);
            return;
        }
        Err(toml::IOError(e)) => {
            println!("I/O error: {}", e);
            os::set_exit_status(1);
            return;
        }
    };
    println!("{:?}", value);

    let cfg: Config = toml::from_toml(value);
    println!("{:s}", cfg.to_str());
}
<|endoftext|>


<commit_before>//!CDRS support traffic decompression as it is described in [Apache
//!Cassandra protocol](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L790)
//!
//!Before being used, client and server must agree on a compression algorithm to
//!use, which is done in the STARTUP message. As a consequence, a STARTUP message
//!must never be compressed.  However, once the STARTUP frame has been received
//!by the server, messages can be compressed (including the response to the STARTUP
//!request).
//!
//!CDRS provides generic trait [`Compressor`][compressor].
//!Enum [`Compression`][compression] contains implementation
//!for `Compressor`.
//!
//!```no_run
//!use cdrs::client::CDRS;
//!use cdrs::query::QueryBuilder;
//!use cdrs::authenticators::NoneAuthenticator;
//!use cdrs::compression::Compression;
//!
//!let addr = "127.0.0.1:9042";
//!let tcp_transport = TransportTcp::new(addr).unwrap();
//!
//!// pass authenticator into CDRS' constructor
//!let client = CDRS::new(tcp_transport, NoneAuthenticator);
//!let session = client.start(Compression::None);
//!//let session = client.start(Compression::Lz4)
//!//let session = client.start(Compression::Snappy)
//!```
//![compression]:enum.Compression.html
//![compressor]:trait.Compressor.html

use std::convert::From;
use std::error::Error;
use std::result;
use std::fmt;
use std::io;

use snap;
use lz4_compress as lz4;

type Result<T> = result::Result<T, CompressionError>;

pub const LZ4: &'static str = "lz4";
pub const SNAPPY: &'static str = "snappy";

/// It's an error which may occure during encoding or deconding
/// frame body. As there are only two types of compressors it
/// contains two related enum options.
#[derive(Debug)]
pub enum CompressionError {
    /// Snappy error.
    Snappy(snap::Error),
    /// Lz4 error.
    Lz4(io::Error),
}

impl fmt::Display for CompressionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CompressionError::Snappy(ref err) => write!(f, "Snappy Error: {:?}", err),
            &CompressionError::Lz4(ref err) => write!(f, "Lz4 Error: {:?}", err),
        }
    }
}

impl Error for CompressionError {
    fn description(&self) -> &str {
        match self {
            &CompressionError::Snappy(ref err) => err.description(),
            &CompressionError::Lz4(ref err) => err.description(),
        }
    }
}

/// Compressor trait that defines functionality
/// which should be provided by typical compressor.
pub trait Compressor {
    /// Encodes given bytes and returns `Result` that contains either
    /// encoded data or an error which occures during the transformation.
    fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Encodes given encoded data and returns `Result` that contains either
    /// encoded bytes or an error which occures during the transformation.
    fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Returns a string which is a name of a compressor. This name should be
    /// exactly the same as one which returns a server in a response to
    /// `Options` request.
    fn into_string(&self) -> Option<String>;
}

/// Enum which represents a type of compression. Only non-startup frame's body can be compressen.
#[derive(Debug, PartialEq, Clone, Copy, Eq, Ord, PartialOrd)]
pub enum Compression {
    /// [lz4](https://code.google.com/p/lz4/) compression
    Lz4,
    /// [snappy](https://code.google.com/p/snappy/) compression
    Snappy,
    /// Non compression
    None,
}

impl Compression {
    /// It encodes `bytes` basing on type of `Compression`..
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///
    ///   let snappy_compression = Compression::Snappy;
    ///   let bytes = String::from("Hello World").into_bytes().to_vec();
    ///   let encoded = snappy_compression.encode(bytes.clone()).unwrap();
    ///   assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    ///
    /// ```
    pub fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::encode_lz4(bytes),
            &Compression::Snappy => Compression::encode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It decodes `bytes` basing on type of compression.
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///     let lz4_compression = Compression::Lz4;
    ///     let bytes = String::from("Hello World").into_bytes().to_vec();
    ///     let encoded = lz4_compression.encode(bytes.clone()).unwrap();
    ///     let len = encoded.len() as u8;
    ///     let mut input = vec![0, 0, 0, len];
    ///     input.extend_from_slice(encoded.as_slice());
    ///     assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    /// ```
    pub fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::decode_lz4(bytes),
            &Compression::Snappy => Compression::decode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It transforms compression method into a `&str`.
    pub fn as_str(&self) -> Option<&'static str> {
        match self {
            &Compression::Lz4 => Some(LZ4),
            &Compression::Snappy => Some(SNAPPY),
            &Compression::None => None,
        }
    }

    fn encode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut encoder = snap::Encoder::new();
        encoder.compress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn decode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = snap::Decoder::new();
        decoder.decompress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn encode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        return Ok(lz4::compress(bytes.as_slice()));
    }

    fn decode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        // skip first 4 bytes in accordance to
        // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L805
        lz4::decompress(&bytes[4..]).map_err(CompressionError::Lz4)
    }
}

impl From<String> for Compression {
    /// It converts `String` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_string: String) -> Compression {
        return Compression::from(compression_string.as_str());
    }
}

impl<'a> From<&'a str> for Compression {
    /// It converts `str` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_str: &'a str) -> Compression {
        match compression_str {
            LZ4 => Compression::Lz4,
            SNAPPY => Compression::Snappy,
            _ => Compression::None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_compression_from_str() {
        let lz4 = "lz4";
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy";
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x";
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_from_string() {
        let lz4 = "lz4".to_string();
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy".to_string();
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x".to_string();
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_encode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression.encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = snappy_compression.encode(bytes.clone()).unwrap();
        assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4() {
        let snappy_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression.encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_lz4() {
        let lz4_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let len = encoded.len() as u8;
        let mut input = vec![0, 0, 0, len];
        input.extend_from_slice(encoded.as_slice());
        assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        none_compression.encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = none_compression.encode(bytes.clone()).unwrap();
        assert_eq!(none_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4_with_invalid_input() {
        let lz4_compression = Compression::Lz4;
        let bytes: Vec<u8> = vec![0x7f, 0x7f, 0x7f, 0x7f, 0x7f];
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let decode = lz4_compression.decode(encoded);
        assert_eq!(decode.is_err(), true);
    }

    #[test]
    fn test_compression_encode_snappy_with_non_utf8() {
        let snappy_compression = Compression::Snappy;
        let v = vec![0xff, 0xff];
        let encoded = snappy_compression.encode(v.clone())
            .expect("Should work without exceptions");
        assert_eq!(snappy_compression.decode(encoded).unwrap(), v);
    }

}
<commit_msg>Fix code formatting<commit_after>//!CDRS support traffic decompression as it is described in [Apache
//!Cassandra protocol](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L790)
//!
//!Before being used, client and server must agree on a compression algorithm to
//!use, which is done in the STARTUP message. As a consequence, a STARTUP message
//!must never be compressed.  However, once the STARTUP frame has been received
//!by the server, messages can be compressed (including the response to the STARTUP
//!request).
//!
//!CDRS provides generic trait [`Compressor`][compressor].
//!Enum [`Compression`][compression] contains implementation
//!for `Compressor`.
//!
//!```no_run
//!use cdrs::client::CDRS;
//!use cdrs::query::QueryBuilder;
//!use cdrs::authenticators::NoneAuthenticator;
//!use cdrs::compression::Compression;
//!
//!let addr = "127.0.0.1:9042";
//!let tcp_transport = TransportTcp::new(addr).unwrap();
//!
//!// pass authenticator into CDRS' constructor
//!let client = CDRS::new(tcp_transport, NoneAuthenticator);
//!let session = client.start(Compression::None);
//!//let session = client.start(Compression::Lz4)
//!//let session = client.start(Compression::Snappy)
//!```
//![compression]:enum.Compression.html
//![compressor]:trait.Compressor.html

use std::convert::From;
use std::error::Error;
use std::result;
use std::fmt;
use std::io;

use snap;
use lz4_compress as lz4;

type Result<T> = result::Result<T, CompressionError>;

pub const LZ4: &'static str = "lz4";
pub const SNAPPY: &'static str = "snappy";

/// It's an error which may occure during encoding or deconding
/// frame body. As there are only two types of compressors it
/// contains two related enum options.
#[derive(Debug)]
pub enum CompressionError {
    /// Snappy error.
    Snappy(snap::Error),
    /// Lz4 error.
    Lz4(io::Error),
}

impl fmt::Display for CompressionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CompressionError::Snappy(ref err) => write!(f, "Snappy Error: {:?}", err),
            &CompressionError::Lz4(ref err) => write!(f, "Lz4 Error: {:?}", err),
        }
    }
}

impl Error for CompressionError {
    fn description(&self) -> &str {
        match self {
            &CompressionError::Snappy(ref err) => err.description(),
            &CompressionError::Lz4(ref err) => err.description(),
        }
    }
}

/// Compressor trait that defines functionality
/// which should be provided by typical compressor.
pub trait Compressor {
    /// Encodes given bytes and returns `Result` that contains either
    /// encoded data or an error which occures during the transformation.
    fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Encodes given encoded data and returns `Result` that contains either
    /// encoded bytes or an error which occures during the transformation.
    fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Returns a string which is a name of a compressor. This name should be
    /// exactly the same as one which returns a server in a response to
    /// `Options` request.
    fn into_string(&self) -> Option<String>;
}

/// Enum which represents a type of compression. Only non-startup frame's body can be compressen.
#[derive(Debug, PartialEq, Clone, Copy, Eq, Ord, PartialOrd)]
pub enum Compression {
    /// [lz4](https://code.google.com/p/lz4/) compression
    Lz4,
    /// [snappy](https://code.google.com/p/snappy/) compression
    Snappy,
    /// Non compression
    None,
}

impl Compression {
    /// It encodes `bytes` basing on type of `Compression`..
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///
    ///   let snappy_compression = Compression::Snappy;
    ///   let bytes = String::from("Hello World").into_bytes().to_vec();
    ///   let encoded = snappy_compression.encode(bytes.clone()).unwrap();
    ///   assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    ///
    /// ```
    pub fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::encode_lz4(bytes),
            &Compression::Snappy => Compression::encode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It decodes `bytes` basing on type of compression.
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///     let lz4_compression = Compression::Lz4;
    ///     let bytes = String::from("Hello World").into_bytes().to_vec();
    ///     let encoded = lz4_compression.encode(bytes.clone()).unwrap();
    ///     let len = encoded.len() as u8;
    ///     let mut input = vec![0, 0, 0, len];
    ///     input.extend_from_slice(encoded.as_slice());
    ///     assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    /// ```
    pub fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::decode_lz4(bytes),
            &Compression::Snappy => Compression::decode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It transforms compression method into a `&str`.
    pub fn as_str(&self) -> Option<&'static str> {
        match self {
            &Compression::Lz4 => Some(LZ4),
            &Compression::Snappy => Some(SNAPPY),
            &Compression::None => None,
        }
    }

    fn encode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut encoder = snap::Encoder::new();
        encoder
            .compress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn decode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = snap::Decoder::new();
        decoder
            .decompress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn encode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        return Ok(lz4::compress(bytes.as_slice()));
    }

    fn decode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        // skip first 4 bytes in accordance to
        // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L805
        lz4::decompress(&bytes[4..]).map_err(CompressionError::Lz4)
    }
}

impl From<String> for Compression {
    /// It converts `String` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_string: String) -> Compression {
        return Compression::from(compression_string.as_str());
    }
}

impl<'a> From<&'a str> for Compression {
    /// It converts `str` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_str: &'a str) -> Compression {
        match compression_str {
            LZ4 => Compression::Lz4,
            SNAPPY => Compression::Snappy,
            _ => Compression::None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_compression_from_str() {
        let lz4 = "lz4";
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy";
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x";
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_from_string() {
        let lz4 = "lz4".to_string();
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy".to_string();
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x".to_string();
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_encode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = snappy_compression.encode(bytes.clone()).unwrap();
        assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4() {
        let snappy_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_lz4() {
        let lz4_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let len = encoded.len() as u8;
        let mut input = vec![0, 0, 0, len];
        input.extend_from_slice(encoded.as_slice());
        assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        none_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = none_compression.encode(bytes.clone()).unwrap();
        assert_eq!(none_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4_with_invalid_input() {
        let lz4_compression = Compression::Lz4;
        let bytes: Vec<u8> = vec![0x7f, 0x7f, 0x7f, 0x7f, 0x7f];
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let decode = lz4_compression.decode(encoded);
        assert_eq!(decode.is_err(), true);
    }

    #[test]
    fn test_compression_encode_snappy_with_non_utf8() {
        let snappy_compression = Compression::Snappy;
        let v = vec![0xff, 0xff];
        let encoded = snappy_compression
            .encode(v.clone())
            .expect("Should work without exceptions");
        assert_eq!(snappy_compression.decode(encoded).unwrap(), v);
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 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.

use schema::*;

use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
use std::io::{Cursor, Write};
use std::slice;
use std::u32;

/// While we are generating the metadata, we also track the position
/// of each DefIndex. It is not required that all definitions appear
/// in the metadata, nor that they are serialized in order, and
/// therefore we first allocate the vector here and fill it with
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
pub struct Index {
    positions: [Vec<u32>; 2]
}

impl Index {
    pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index {
        Index {
            positions: [vec![u32::MAX; max_index_lo],
                        vec![u32::MAX; max_index_hi]],
        }
    }

    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
        assert!(def_id.is_local());
        self.record_index(def_id.index, entry);
    }

    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
        assert!(entry.position < (u32::MAX as usize));
        let position = entry.position as u32;
        let space_index = item.address_space().index();
        let array_index = item.as_array_index();

        assert!(self.positions[space_index][array_index] == u32::MAX,
                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
                item,
                self.positions[space_index][array_index],
                position);

        self.positions[space_index][array_index] = position.to_le();
    }

    pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
        let pos = buf.position();

        // First we write the length of the lower range ...
        buf.write_all(words_to_bytes(&[self.positions[0].len() as u32])).unwrap();
        // ... then the values in the lower range ...
        buf.write_all(words_to_bytes(&self.positions[0][..])).unwrap();
        // ... then the values in the higher range.
        buf.write_all(words_to_bytes(&self.positions[1][..])).unwrap();
        LazySeq::with_position_and_length(pos as usize,
            self.positions[0].len() + self.positions[1].len() + 1)
    }
}

impl<'tcx> LazySeq<Index> {
    /// Given the metadata, extract out the offset of a particular
    /// DefIndex (if any).
    #[inline(never)]
    pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        let index = def_index.as_usize();

        debug!("Index::lookup: index={:?} words.len={:?}",
               index,
               words.len());

        let positions = match def_index.address_space() {
            DefIndexAddressSpace::Low => &words[1..],
            DefIndexAddressSpace::High => {
                // This is a DefIndex in the higher range, so find out where
                // that starts:
                let lo_count = u32::from_le(words[0].get()) as usize;
                &words[lo_count + 1 .. ]
            }
        };

        let array_index = def_index.as_array_index();
        let position = u32::from_le(positions[array_index].get());
        if position == u32::MAX {
            debug!("Index::lookup: position=u32::MAX");
            None
        } else {
            debug!("Index::lookup: position={:?}", position);
            Some(Lazy::with_position(position as usize))
        }
    }

    pub fn iter_enumerated<'a>(&self,
                               bytes: &'a [u8])
                               -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        let lo_count = u32::from_le(words[0].get()) as usize;
        let lo = &words[1 .. lo_count + 1];
        let hi = &words[1 + lo_count ..];

        lo.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
            if pos == u32::MAX {
                None
            } else {
                let pos = u32::from_le(pos) as usize;
                Some((DefIndex::new(index), Lazy::with_position(pos)))
            }
        }).chain(hi.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
            if pos == u32::MAX {
                None
            } else {
                let pos = u32::from_le(pos) as usize;
                Some((DefIndex::new(index + DefIndexAddressSpace::High.start()),
                                    Lazy::with_position(pos)))
            }
        }))
    }
}

#[repr(packed)]
#[derive(Copy)]
struct Unaligned<T>(T);

// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
// the field to `T::clone`, but this reference may not be properly aligned.
impl<T: Copy> Clone for Unaligned<T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Unaligned<T> {
    fn get(self) -> T { self.0 }
}

fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
    unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
}

fn words_to_bytes(w: &[u32]) -> &[u8] {
    unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
}
<commit_msg>Auto merge of #41666 - nagisa:try-poking-bigendian-again, r=arielb1<commit_after>// Copyright 2015 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.

use schema::*;

use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
use std::io::{Cursor, Write};
use std::slice;
use std::u32;

/// While we are generating the metadata, we also track the position
/// of each DefIndex. It is not required that all definitions appear
/// in the metadata, nor that they are serialized in order, and
/// therefore we first allocate the vector here and fill it with
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
pub struct Index {
    positions: [Vec<u32>; 2]
}

impl Index {
    pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index {
        Index {
            positions: [vec![u32::MAX; max_index_lo],
                        vec![u32::MAX; max_index_hi]],
        }
    }

    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
        assert!(def_id.is_local());
        self.record_index(def_id.index, entry);
    }

    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
        assert!(entry.position < (u32::MAX as usize));
        let position = entry.position as u32;
        let space_index = item.address_space().index();
        let array_index = item.as_array_index();

        assert!(self.positions[space_index][array_index] == u32::MAX,
                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
                item,
                self.positions[space_index][array_index],
                position);

        self.positions[space_index][array_index] = position.to_le();
    }

    pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
        let pos = buf.position();

        // First we write the length of the lower range ...
        buf.write_all(words_to_bytes(&[(self.positions[0].len() as u32).to_le()])).unwrap();
        // ... then the values in the lower range ...
        buf.write_all(words_to_bytes(&self.positions[0][..])).unwrap();
        // ... then the values in the higher range.
        buf.write_all(words_to_bytes(&self.positions[1][..])).unwrap();
        LazySeq::with_position_and_length(pos as usize,
            self.positions[0].len() + self.positions[1].len() + 1)
    }
}

impl<'tcx> LazySeq<Index> {
    /// Given the metadata, extract out the offset of a particular
    /// DefIndex (if any).
    #[inline(never)]
    pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        let index = def_index.as_usize();

        debug!("Index::lookup: index={:?} words.len={:?}",
               index,
               words.len());

        let positions = match def_index.address_space() {
            DefIndexAddressSpace::Low => &words[1..],
            DefIndexAddressSpace::High => {
                // This is a DefIndex in the higher range, so find out where
                // that starts:
                let lo_count = u32::from_le(words[0].get()) as usize;
                &words[lo_count + 1 .. ]
            }
        };

        let array_index = def_index.as_array_index();
        let position = u32::from_le(positions[array_index].get());
        if position == u32::MAX {
            debug!("Index::lookup: position=u32::MAX");
            None
        } else {
            debug!("Index::lookup: position={:?}", position);
            Some(Lazy::with_position(position as usize))
        }
    }

    pub fn iter_enumerated<'a>(&self,
                               bytes: &'a [u8])
                               -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
        let lo_count = u32::from_le(words[0].get()) as usize;
        let lo = &words[1 .. lo_count + 1];
        let hi = &words[1 + lo_count ..];

        lo.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
            if pos == u32::MAX {
                None
            } else {
                let pos = u32::from_le(pos) as usize;
                Some((DefIndex::new(index), Lazy::with_position(pos)))
            }
        }).chain(hi.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
            if pos == u32::MAX {
                None
            } else {
                let pos = u32::from_le(pos) as usize;
                Some((DefIndex::new(index + DefIndexAddressSpace::High.start()),
                                    Lazy::with_position(pos)))
            }
        }))
    }
}

#[repr(packed)]
#[derive(Copy)]
struct Unaligned<T>(T);

// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
// the field to `T::clone`, but this reference may not be properly aligned.
impl<T: Copy> Clone for Unaligned<T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Unaligned<T> {
    fn get(self) -> T { self.0 }
}

fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
    unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
}

fn words_to_bytes(w: &[u32]) -> &[u8] {
    unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
}
<|endoftext|>


<commit_before>use crate::ffi::OsStr;
use crate::mem;
use crate::path::Prefix;

fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
    unsafe { mem::transmute(s) }
}
unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
    mem::transmute(s)
}

#[inline]
pub fn is_sep_byte(b: u8) -> bool {
    b == b'/' || b == b'\\'
}

#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
    b == b'\\'
}

pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
    use crate::path::Prefix::*;
    unsafe {
        // The unsafety here stems from converting between &OsStr and &[u8]
        // and back. This is safe to do because (1) we only look at ASCII
        // contents of the encoding and (2) new &OsStr values are produced
        // only from ASCII-bounded slices of existing &OsStr values.
        let mut path = os_str_as_u8_slice(path);

        if path.starts_with(br"\\") {
            // \\
            path = &path[2..];
            if path.starts_with(br"?\") {
                // \\?\
                path = &path[2..];
                if path.starts_with(br"UNC\") {
                    // \\?\UNC\server\share
                    path = &path[4..];
                    let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
                        Some((server, share)) => {
                            (u8_slice_as_os_str(server), u8_slice_as_os_str(share))
                        }
                        None => (u8_slice_as_os_str(path), u8_slice_as_os_str(&[])),
                    };
                    return Some(VerbatimUNC(server, share));
                } else {
                    // \\?\path
                    let idx = path.iter().position(|&b| b == b'\\');
                    if idx == Some(2) && path[1] == b':' {
                        let c = path[0];
                        if c.is_ascii() && (c as char).is_alphabetic() {
                            // \\?\C:\ path
                            return Some(VerbatimDisk(c.to_ascii_uppercase()));
                        }
                    }
                    let slice = &path[..idx.unwrap_or(path.len())];
                    return Some(Verbatim(u8_slice_as_os_str(slice)));
                }
            } else if path.starts_with(b".\\") {
                // \\.\path
                path = &path[2..];
                let pos = path.iter().position(|&b| b == b'\\');
                let slice = &path[..pos.unwrap_or(path.len())];
                return Some(DeviceNS(u8_slice_as_os_str(slice)));
            }
            match parse_two_comps(path, is_sep_byte) {
                Some((server, share)) if !server.is_empty() && !share.is_empty() => {
                    // \\server\share
                    return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
                }
                _ => (),
            }
        } else if path.get(1) == Some(&b':') {
            // C:
            let c = path[0];
            if c.is_ascii() && (c as char).is_alphabetic() {
                return Some(Disk(c.to_ascii_uppercase()));
            }
        }
        return None;
    }

    fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
        let first = &path[..path.iter().position(|x| f(*x))?];
        path = &path[(first.len() + 1)..];
        let idx = path.iter().position(|x| f(*x));
        let second = &path[..idx.unwrap_or(path.len())];
        Some((first, second))
    }
}

pub const MAIN_SEP_STR: &str = "\\";
pub const MAIN_SEP: char = '\\';
<commit_msg>Move constants to top file<commit_after>use crate::ffi::OsStr;
use crate::mem;
use crate::path::Prefix;

pub const MAIN_SEP_STR: &str = "\\";
pub const MAIN_SEP: char = '\\';

fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
    unsafe { mem::transmute(s) }
}
unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
    mem::transmute(s)
}

#[inline]
pub fn is_sep_byte(b: u8) -> bool {
    b == b'/' || b == b'\\'
}

#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
    b == b'\\'
}

pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
    use crate::path::Prefix::*;
    unsafe {
        // The unsafety here stems from converting between &OsStr and &[u8]
        // and back. This is safe to do because (1) we only look at ASCII
        // contents of the encoding and (2) new &OsStr values are produced
        // only from ASCII-bounded slices of existing &OsStr values.
        let mut path = os_str_as_u8_slice(path);

        if path.starts_with(br"\\") {
            // \\
            path = &path[2..];
            if path.starts_with(br"?\") {
                // \\?\
                path = &path[2..];
                if path.starts_with(br"UNC\") {
                    // \\?\UNC\server\share
                    path = &path[4..];
                    let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
                        Some((server, share)) => {
                            (u8_slice_as_os_str(server), u8_slice_as_os_str(share))
                        }
                        None => (u8_slice_as_os_str(path), u8_slice_as_os_str(&[])),
                    };
                    return Some(VerbatimUNC(server, share));
                } else {
                    // \\?\path
                    let idx = path.iter().position(|&b| b == b'\\');
                    if idx == Some(2) && path[1] == b':' {
                        let c = path[0];
                        if c.is_ascii() && (c as char).is_alphabetic() {
                            // \\?\C:\ path
                            return Some(VerbatimDisk(c.to_ascii_uppercase()));
                        }
                    }
                    let slice = &path[..idx.unwrap_or(path.len())];
                    return Some(Verbatim(u8_slice_as_os_str(slice)));
                }
            } else if path.starts_with(b".\\") {
                // \\.\path
                path = &path[2..];
                let pos = path.iter().position(|&b| b == b'\\');
                let slice = &path[..pos.unwrap_or(path.len())];
                return Some(DeviceNS(u8_slice_as_os_str(slice)));
            }
            match parse_two_comps(path, is_sep_byte) {
                Some((server, share)) if !server.is_empty() && !share.is_empty() => {
                    // \\server\share
                    return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
                }
                _ => (),
            }
        } else if path.get(1) == Some(&b':') {
            // C:
            let c = path[0];
            if c.is_ascii() && (c as char).is_alphabetic() {
                return Some(Disk(c.to_ascii_uppercase()));
            }
        }
        return None;
    }

    fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
        let first = &path[..path.iter().position(|x| f(*x))?];
        path = &path[(first.len() + 1)..];
        let idx = path.iter().position(|x| f(*x));
        let second = &path[..idx.unwrap_or(path.len())];
        Some((first, second))
    }
}

<|endoftext|>


<commit_before>use std::time::SystemTime;
use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};
use bincode;

use exonum::storage::StorageValue;
use exonum::crypto::{self, hash, CryptoHash, Hash, PublicKey, SecretKey, Signature};

#[derive(Debug, Serialize, Deserialize)]
pub struct Message {
    signature: Signature,
    payload: AuthorizedPayload,
}

#[derive(Debug, Serialize, Deserialize)]
struct AuthorizedPayload {
    from: PublicKey,
    payload: Vec<u8>,
}

#[derive(Debug, Serialize, Deserialize)]
struct Transaction {
    service_id: u32,
    payload: Vec<u8>,
}

#[derive(Debug, Serialize, Deserialize)]
enum Consensus {
    Connect { time: SystemTime },
    Block { state_hash: Hash },
    Transaction(Transaction),
}

#[derive(Debug, Serialize, Deserialize)]
enum CryptoCurrencyTransactions {
    Issue {
        amount: u64,
        seed: u32,
    },
    Transfer {
        to: PublicKey,
        amount: u64,
        seed: u32,
    },
}

impl AuthorizedPayload {
    fn new<T: Into<Consensus>>(from: PublicKey, msg: T) -> AuthorizedPayload {
        AuthorizedPayload {
            from,
            payload: bincode::serialize(&msg.into()).unwrap(),
        }
    }

    fn sign(&self, secret_key: &SecretKey) -> Signature {
        let bytes = bincode::serialize(self).unwrap();
        crypto::sign(&bytes, secret_key)
    }

    fn verify(&self, signature: &Signature) -> bool {
        let bytes = bincode::serialize(self).unwrap();
        crypto::verify(signature, &bytes, &self.from)
    }
}

impl Message {
    fn from_payload(payload: AuthorizedPayload, key: &SecretKey) -> Message {
        Message {
            signature: payload.sign(key),
            payload,
        }
    }

    fn verify(&self) -> bool {
        self.payload.verify(&self.signature)
    }

    fn decode(self) -> Consensus {
        let bytes = self.payload.payload;
        bincode::deserialize(&bytes).unwrap()
    }
}

impl From<CryptoCurrencyTransactions> for Transaction {
    fn from(value: CryptoCurrencyTransactions) -> Transaction {
        Transaction {
            service_id: 10,
            payload: bincode::serialize(&value).unwrap(),
        }
    }
}

impl<T: Into<Transaction>> From<T> for Consensus {
    fn from(tx: T) -> Consensus {
        Consensus::Transaction(tx.into())
    }
}

#[test]
fn test_serialize_verify() {
    let tx = CryptoCurrencyTransactions::Issue {
        amount: 1000,
        seed: 10,
    };
    let keypair = crypto::gen_keypair();
    let msg = Message::from_payload(AuthorizedPayload::new(keypair.0, tx), &keypair.1);
    assert!(msg.verify());

    let consensus = msg.decode();
    if let Consensus::Transaction(tx) = consensus {
        let tx: CryptoCurrencyTransactions = bincode::deserialize(&tx.payload).unwrap();
        println!("{:?}", tx);
    } else {
        panic!("Ooops");
    }
}
<commit_msg>Add Cow<commit_after>use std::borrow::Cow;
use std::time::SystemTime;
use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};
use bincode;

use exonum::storage::StorageValue;
use exonum::crypto::{self, hash, CryptoHash, Hash, PublicKey, SecretKey, Signature};

#[derive(Debug, Serialize, Deserialize)]
pub struct Message<'a> {
    signature: Signature,
    payload: AuthorizedPayload<'a>,
}

#[derive(Debug, Serialize, Deserialize)]
struct AuthorizedPayload<'a> {
    from: PublicKey,
    payload: Cow<'a, [u8]>,
}

#[derive(Debug, Serialize, Deserialize)]
struct Transaction<'a> {
    service_id: u32,
    payload: Cow<'a, [u8]>,
}

#[derive(Debug, Serialize, Deserialize)]
enum Consensus<'a> {
    Connect { time: SystemTime },
    Block { state_hash: Hash },
    Transaction(Transaction<'a>),
}

#[derive(Debug, Serialize, Deserialize)]
enum CryptoCurrencyTransactions {
    Issue {
        amount: u64,
        seed: u32,
    },
    Transfer {
        to: PublicKey,
        amount: u64,
        seed: u32,
    },
}

impl<'a> AuthorizedPayload<'a> {
    fn new<'b, T: Into<Consensus<'b>>>(from: PublicKey, msg: T) -> AuthorizedPayload<'a> {
        AuthorizedPayload {
            from,
            payload: bincode::serialize(&msg.into()).unwrap().into(),
        }
    }

    fn sign(&self, secret_key: &SecretKey) -> Signature {
        let bytes = bincode::serialize(self).unwrap();
        crypto::sign(&bytes, secret_key)
    }

    fn verify(&self, signature: &Signature) -> bool {
        let bytes = bincode::serialize(self).unwrap();
        crypto::verify(signature, &bytes, &self.from)
    }
}

impl<'a> Message<'a> {
    fn from_payload(payload: AuthorizedPayload<'a>, key: &SecretKey) -> Message<'a> {
        Message {
            signature: payload.sign(key),
            payload,
        }
    }

    fn verify(&self) -> bool {
        self.payload.verify(&self.signature)
    }

    fn decode<'b>(self) -> Consensus<'b> {
        let bytes = self.payload.payload;
        bincode::deserialize(&bytes).unwrap()
    }
}

impl<'a> From<CryptoCurrencyTransactions> for Transaction<'a> {
    fn from(value: CryptoCurrencyTransactions) -> Transaction<'a> {
        Transaction {
            service_id: 10,
            payload: bincode::serialize(&value).unwrap().into(),
        }
    }
}

impl<'a, T: Into<Transaction<'a>>> From<T> for Consensus<'a> {
    fn from(tx: T) -> Consensus<'a> {
        Consensus::Transaction(tx.into())
    }
}

#[test]
fn test_serialize_verify() {
    let tx = CryptoCurrencyTransactions::Issue {
        amount: 1000,
        seed: 10,
    };
    let keypair = crypto::gen_keypair();
    let msg = Message::from_payload(AuthorizedPayload::new(keypair.0, tx), &keypair.1);
    assert!(msg.verify());

    let consensus = msg.decode();
    if let Consensus::Transaction(tx) = consensus {
        let tx: CryptoCurrencyTransactions = bincode::deserialize(&tx.payload).unwrap();
        println!("{:?}", tx);
    } else {
        panic!("Ooops");
    }
}
<|endoftext|>


<commit_before>use euclid::{Vector2D, vec2};
use num::Integer;
use rand::{Rand, Rng};
use std::cmp::max;
use std::f32::consts::PI;
use std::ops::{Add, Sub};
use std::slice;

/// Hex grid geometry for vectors.
pub trait HexGeom {
    /// Hex distance represented by a vector.
    fn hex_dist(&self) -> i32;
}

impl HexGeom for Vector2D<i32> {
    fn hex_dist(&self) -> i32 {
        if self.x.signum() == self.y.signum() {
            max(self.x.abs(), self.y.abs())
        } else {
            self.x.abs() + self.y.abs()
        }
    }
}

// TODO return impl
// No need to muck with custom return iter type then...
/// Return offsets to neighboring hexes.
pub fn hex_neighbors() -> HexNeighborIter { HexNeighborIter(0) }

pub struct HexNeighborIter(i32);

impl Iterator for HexNeighborIter {
    type Item = Vector2D<i32>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.0 >= 6 {
            None
        } else {
            let ret = Some(Dir6::from_int(self.0).to_v2());
            self.0 += 1;
            ret
        }
    }
}

/// Return an iterator for all the points in the hex disc with the given radius.
pub fn hex_disc(radius: i32) -> HexDiscIterator { HexDiscIterator { radius, i: 0, r: 0 } }

pub struct HexDiscIterator {
    radius: i32,
    i: i32,
    r: i32,
}

impl Iterator for HexDiscIterator {
    type Item = Vector2D<i32>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.r > self.radius {
            return None;
        }

        if self.r == 0 {
            self.r += 1;
            self.i = 0;
            return Some(vec2(0, 0));
        }

        let sector = self.i / self.r;
        let offset = self.i % self.r;
        let rod = Dir6::from_int(sector);
        let tangent = Dir6::from_int(sector + 2);

        let ret = rod.to_v2() * self.r + tangent.to_v2() * offset;

        self.i += 1;
        if self.i >= 6 * self.r {
            self.i = 0;
            self.r += 1;
        }

        Some(ret)
    }
}

/// Hex grid directions.
#[derive(Copy, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Dir6 {
    North = 0,
    Northeast,
    Southeast,
    South,
    Southwest,
    Northwest,
}

impl Dir6 {
    /// Convert a vector into the closest hex direction.
    ///
    /// ```notrust
    ///        *0*       *1*
    ///           \ 14 15 | 00 01
    ///           13\     |      02
    ///               \   |
    ///         12      \ |        03
    ///     *5* ----------O-X------- *2*
    ///         11        Y \      04
    ///                   |   \
    ///           10      |     \05
    ///             09 08 | 07 06 \
    ///                  *4*       *3*
    ///
    /// The hexadecants (00 to 15) and the hex
    /// directions (*0* to *5*) around the origin.
    /// ```
    ///
    /// Vectors that are in a space between two hex direction vectors are
    /// rounded to a hexadecant, then assigned the hex direction whose vector
    /// is nearest to that hexadecant.
    pub fn from_v2(v: Vector2D<i32>) -> Dir6 {
        let hexadecant = {
            let width = PI / 8.0;
            let mut radian = (v.x as f32).atan2(-v.y as f32);
            if radian < 0.0 {
                radian += 2.0 * PI
            }
            (radian / width).floor() as i32
        };

        Dir6::from_int(match hexadecant {
            13 | 14 => 0,
            15 | 0 | 1 => 1,
            2 | 3 | 4 => 2,
            5 | 6 => 3,
            7 | 8 | 9 => 4,
            10 | 11 | 12 => 5,
            _ => panic!("Bad hexadecant"),
        })
    }

    /// Convert an integer to a hex dir using modular arithmetic.
    pub fn from_int(i: i32) -> Dir6 { DIRS[i.mod_floor(&6) as usize] }

    /// Convert a hex dir into the corresponding unit vector.
    pub fn to_v2(&self) -> Vector2D<i32> { Vector2D::from(*self) }

    /// Iterate through the six hex dirs in the standard order.
    pub fn iter() -> slice::Iter<'static, Dir6> { DIRS.iter() }
}

impl Add<i32> for Dir6 {
    type Output = Dir6;
    fn add(self, other: i32) -> Dir6 { Dir6::from_int(self as i32 + other) }
}

impl Sub<i32> for Dir6 {
    type Output = Dir6;
    fn sub(self, other: i32) -> Dir6 { Dir6::from_int(self as i32 - other) }
}

impl Rand for Dir6 {
    fn rand<R: Rng>(rng: &mut R) -> Dir6 { Dir6::from_int(rng.gen_range(0, 6)) }
}

impl From<Dir6> for Vector2D<i32> {
    fn from(d: Dir6) -> Self {
        const DIRS: [(i32, i32); 6] = [(-1, -1), (0, -1), (1, 0), (1, 1), (0, 1), (-1, 0)];

        let (x, y) = DIRS[d as usize];
        vec2(x, y)
    }
}

static DIRS: [Dir6; 6] = [
    Dir6::North,
    Dir6::Northeast,
    Dir6::Southeast,
    Dir6::South,
    Dir6::Southwest,
    Dir6::Northwest,
];

/// Hex grid directions with transitional directions.
#[derive(Copy, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Dir12 {
    North = 0,
    NorthNortheast,
    Northeast,
    East,
    Southeast,
    SouthSoutheast,
    South,
    SouthSouthwest,
    Southwest,
    West,
    Northwest,
    NorthNorthwest,
}

impl Dir12 {
    /// If there is exactly one cluster of neighbors in the neighbor mask,
    /// return a direction pointing away from that cluster.
    pub fn away_from(neighbors: &[bool; 6]) -> Option<Dir12> {
        use std::mem;

        let (begin, end) = match find_cluster(neighbors) {
            Some((a, b)) => (a, b),
            None => return None,
        };

        if !is_single_cluster(neighbors, begin, end) {
            return None;
        }

        let cluster_size = if end < begin {
            end + 6 - begin
        } else {
            end - begin
        };
        debug_assert!(cluster_size > 0);

        // Dir12 in use from here on.
        let center_dir = begin * 2 + (cluster_size - 1);
        let away_dir: u8 = ((center_dir + 6) % 12) as u8;
        debug_assert!(away_dir < 12);

        // XXX: Unsafe because I'm too lazy to do int conversion func by hand.
        return Some(unsafe { mem::transmute(away_dir) });

        fn find_cluster(neighbors: &[bool; 6]) -> Option<(usize, usize)> {
            // Start of the active cluster, inclusive.
            let mut cluster_start = None;
            // End of the active cluster, exclusive.
            let mut cluster_end = None;

            for i in 0..6 {
                if cluster_start.is_none() && neighbors[i] && !neighbors[(i + 5) % 6] {
                    cluster_start = Some(i);
                }

                if cluster_end.is_none() && !neighbors[i] && neighbors[(i + 5) % 6] {
                    cluster_end = Some(i);
                }
            }

            if cluster_start.is_none() {
                return None;
            }

            debug_assert!(cluster_end.is_some()); // Must be some if start is some.

            Some((cluster_start.unwrap(), cluster_end.unwrap()))
        }

        fn is_single_cluster(neighbors: &[bool; 6], start: usize, end: usize) -> bool {
            let mut in_cluster = true;

            for i in 0..6 {
                if (start + i) % 6 == end {
                    in_cluster = false;
                }

                if neighbors[(start + i) % 6] != in_cluster {
                    return false;
                }
            }

            true
        }
    }
}

#[cfg(test)]
mod test {
    use super::Dir12;
    use super::Dir6;
    use super::Dir6::*;
    use super::hex_disc;
    use euclid::vec2;

    #[test]
    fn test_dir6() {
        assert_eq!(North, Dir6::from_int(0));
        assert_eq!(Northwest, Dir6::from_int(-1));
        assert_eq!(Northwest, Dir6::from_int(5));
        assert_eq!(Northeast, Dir6::from_int(1));

        assert_eq!(Northeast, Dir6::from_v2(vec2(20i32, -21i32)));
        assert_eq!(Southeast, Dir6::from_v2(vec2(20, -10)));
        assert_eq!(North, Dir6::from_v2(vec2(-10, -10)));
        assert_eq!(South, Dir6::from_v2(vec2(1, 1)));

        for i in 0..6 {
            let d = Dir6::from_int(i);
            let v = d.to_v2();
            let v1 = Dir6::from_int(i - 1).to_v2();
            let v2 = Dir6::from_int(i + 1).to_v2();

            // Test static iter
            assert_eq!(Some(d), Dir6::iter().nth(i as usize).map(|&x| x));

            // Test vector mapping.
            assert_eq!(d, Dir6::from_v2(v));

            // Test opposite dir vector mapping.
            assert_eq!(Dir6::from_int(i + 3), Dir6::from_v2(vec2(-v.x, -v.y)));

            // Test approximation of longer vectors.
            assert_eq!(d, Dir6::from_v2(vec2(v.x * 3, v.y * 3)));
            assert_eq!(d, Dir6::from_v2(vec2(v.x * 3 + v1.x, v.y * 3 + v1.y)));
            assert_eq!(d, Dir6::from_v2(vec2(v.x * 3 + v2.x, v.y * 3 + v2.y)));
        }
    }

    #[test]
    fn test_dir12() {
        assert_eq!(
            None,
            Dir12::away_from(&[false, false, false, false, false, false])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[true, true, true, true, true, true])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[false, true, false, false, true, false])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[true, true, false, true, false, false])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[true, false, true, false, true, false])
        );
        assert_eq!(
            Some(Dir12::South),
            Dir12::away_from(&[true, false, false, false, false, false])
        );
        assert_eq!(
            Some(Dir12::East),
            Dir12::away_from(&[true, false, false, true, true, true])
        );
        assert_eq!(
            Some(Dir12::SouthSouthwest),
            Dir12::away_from(&[true, true, false, false, false, false])
        );
        assert_eq!(
            Some(Dir12::Southwest),
            Dir12::away_from(&[true, true, true, false, false, false])
        );
        assert_eq!(
            Some(Dir12::SouthSoutheast),
            Dir12::away_from(&[true, true, false, false, true, true])
        );
    }

    #[test]
    fn test_hex_disc() {
        use euclid::vec2;
        use super::HexGeom;

        for y in -8i32..8 {
            for x in -8i32..8 {
                let vec = vec2(x, y);

                for r in 0..8 {
                    assert_eq!(
                        vec.hex_dist() <= r,
                        hex_disc(r).find(|&v| vec == v).is_some()
                    );
                }
            }
        }
    }
}
<commit_msg>The hex neighbor helpers take an origin<commit_after>use euclid::{Vector2D, vec2};
use num::Integer;
use rand::{Rand, Rng};
use std::cmp::max;
use std::f32::consts::PI;
use std::ops::{Add, Sub};
use std::slice;

/// Hex grid geometry for vectors.
pub trait HexGeom {
    /// Hex distance represented by a vector.
    fn hex_dist(&self) -> i32;
}

impl HexGeom for Vector2D<i32> {
    fn hex_dist(&self) -> i32 {
        if self.x.signum() == self.y.signum() {
            max(self.x.abs(), self.y.abs())
        } else {
            self.x.abs() + self.y.abs()
        }
    }
}

// TODO return impl
// No need to muck with custom return iter type then...
/// Return offsets to neighboring hexes.
pub fn hex_neighbors
(origin: P) -> HexNeighborIter

where
    P: Clone + Add<Vector2D<i32>, Output = R>,
{
    HexNeighborIter { origin, i: 0 }
}

pub struct HexNeighborIter
 {
    origin: P,
    i: i32,
}

impl
 Iterator for HexNeighborIter

where
    P: Clone + Add<Vector2D<i32>, Output = R>,
{
    type Item = R;

    fn next(&mut self) -> Option<Self::Item> {
        if self.i >= 6 {
            None
        } else {
            let ret = Some(self.origin.clone() + Dir6::from_int(self.i).to_v2());
            self.i += 1;
            ret
        }
    }
}

/// Return an iterator for all the points in the hex disc with the given radius.
pub fn hex_disc
(origin: P, radius: i32) -> HexDiscIterator

where
    P: Clone + Add<Vector2D<i32>, Output = R>,
{
    HexDiscIterator {
        origin,
        radius,
        i: 0,
        r: 0,
    }
}

pub struct HexDiscIterator
 {
    origin: P,
    radius: i32,
    i: i32,
    r: i32,
}

impl
 Iterator for HexDiscIterator

where
    P: Clone + Add<Vector2D<i32>, Output = R>,
{
    type Item = R;

    fn next(&mut self) -> Option<Self::Item> {
        if self.r > self.radius {
            return None;
        }

        if self.r == 0 {
            self.r += 1;
            self.i = 0;
            return Some(self.origin.clone() + vec2(0, 0));
        }

        let sector = self.i / self.r;
        let offset = self.i % self.r;
        let rod = Dir6::from_int(sector);
        let tangent = Dir6::from_int(sector + 2);

        let ret = rod.to_v2() * self.r + tangent.to_v2() * offset;

        self.i += 1;
        if self.i >= 6 * self.r {
            self.i = 0;
            self.r += 1;
        }

        Some(self.origin.clone() + ret)
    }
}

/// Hex grid directions.
#[derive(Copy, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Dir6 {
    North = 0,
    Northeast,
    Southeast,
    South,
    Southwest,
    Northwest,
}

impl Dir6 {
    /// Convert a vector into the closest hex direction.
    ///
    /// ```notrust
    ///        *0*       *1*
    ///           \ 14 15 | 00 01
    ///           13\     |      02
    ///               \   |
    ///         12      \ |        03
    ///     *5* ----------O-X------- *2*
    ///         11        Y \      04
    ///                   |   \
    ///           10      |     \05
    ///             09 08 | 07 06 \
    ///                  *4*       *3*
    ///
    /// The hexadecants (00 to 15) and the hex
    /// directions (*0* to *5*) around the origin.
    /// ```
    ///
    /// Vectors that are in a space between two hex direction vectors are
    /// rounded to a hexadecant, then assigned the hex direction whose vector
    /// is nearest to that hexadecant.
    pub fn from_v2(v: Vector2D<i32>) -> Dir6 {
        let hexadecant = {
            let width = PI / 8.0;
            let mut radian = (v.x as f32).atan2(-v.y as f32);
            if radian < 0.0 {
                radian += 2.0 * PI
            }
            (radian / width).floor() as i32
        };

        Dir6::from_int(match hexadecant {
            13 | 14 => 0,
            15 | 0 | 1 => 1,
            2 | 3 | 4 => 2,
            5 | 6 => 3,
            7 | 8 | 9 => 4,
            10 | 11 | 12 => 5,
            _ => panic!("Bad hexadecant"),
        })
    }

    /// Convert an integer to a hex dir using modular arithmetic.
    pub fn from_int(i: i32) -> Dir6 { DIRS[i.mod_floor(&6) as usize] }

    /// Convert a hex dir into the corresponding unit vector.
    pub fn to_v2(&self) -> Vector2D<i32> { Vector2D::from(*self) }

    /// Iterate through the six hex dirs in the standard order.
    pub fn iter() -> slice::Iter<'static, Dir6> { DIRS.iter() }
}

impl Add<i32> for Dir6 {
    type Output = Dir6;
    fn add(self, other: i32) -> Dir6 { Dir6::from_int(self as i32 + other) }
}

impl Sub<i32> for Dir6 {
    type Output = Dir6;
    fn sub(self, other: i32) -> Dir6 { Dir6::from_int(self as i32 - other) }
}

impl Rand for Dir6 {
    fn rand<R: Rng>(rng: &mut R) -> Dir6 { Dir6::from_int(rng.gen_range(0, 6)) }
}

impl From<Dir6> for Vector2D<i32> {
    fn from(d: Dir6) -> Self {
        const DIRS: [(i32, i32); 6] = [(-1, -1), (0, -1), (1, 0), (1, 1), (0, 1), (-1, 0)];

        let (x, y) = DIRS[d as usize];
        vec2(x, y)
    }
}

static DIRS: [Dir6; 6] = [
    Dir6::North,
    Dir6::Northeast,
    Dir6::Southeast,
    Dir6::South,
    Dir6::Southwest,
    Dir6::Northwest,
];

/// Hex grid directions with transitional directions.
#[derive(Copy, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum Dir12 {
    North = 0,
    NorthNortheast,
    Northeast,
    East,
    Southeast,
    SouthSoutheast,
    South,
    SouthSouthwest,
    Southwest,
    West,
    Northwest,
    NorthNorthwest,
}

impl Dir12 {
    /// If there is exactly one cluster of neighbors in the neighbor mask,
    /// return a direction pointing away from that cluster.
    pub fn away_from(neighbors: &[bool; 6]) -> Option<Dir12> {
        use std::mem;

        let (begin, end) = match find_cluster(neighbors) {
            Some((a, b)) => (a, b),
            None => return None,
        };

        if !is_single_cluster(neighbors, begin, end) {
            return None;
        }

        let cluster_size = if end < begin {
            end + 6 - begin
        } else {
            end - begin
        };
        debug_assert!(cluster_size > 0);

        // Dir12 in use from here on.
        let center_dir = begin * 2 + (cluster_size - 1);
        let away_dir: u8 = ((center_dir + 6) % 12) as u8;
        debug_assert!(away_dir < 12);

        // XXX: Unsafe because I'm too lazy to do int conversion func by hand.
        return Some(unsafe { mem::transmute(away_dir) });

        fn find_cluster(neighbors: &[bool; 6]) -> Option<(usize, usize)> {
            // Start of the active cluster, inclusive.
            let mut cluster_start = None;
            // End of the active cluster, exclusive.
            let mut cluster_end = None;

            for i in 0..6 {
                if cluster_start.is_none() && neighbors[i] && !neighbors[(i + 5) % 6] {
                    cluster_start = Some(i);
                }

                if cluster_end.is_none() && !neighbors[i] && neighbors[(i + 5) % 6] {
                    cluster_end = Some(i);
                }
            }

            if cluster_start.is_none() {
                return None;
            }

            debug_assert!(cluster_end.is_some()); // Must be some if start is some.

            Some((cluster_start.unwrap(), cluster_end.unwrap()))
        }

        fn is_single_cluster(neighbors: &[bool; 6], start: usize, end: usize) -> bool {
            let mut in_cluster = true;

            for i in 0..6 {
                if (start + i) % 6 == end {
                    in_cluster = false;
                }

                if neighbors[(start + i) % 6] != in_cluster {
                    return false;
                }
            }

            true
        }
    }
}

#[cfg(test)]
mod test {
    use super::Dir12;
    use super::Dir6;
    use super::Dir6::*;
    use super::hex_disc;
    use euclid::vec2;

    #[test]
    fn test_dir6() {
        assert_eq!(North, Dir6::from_int(0));
        assert_eq!(Northwest, Dir6::from_int(-1));
        assert_eq!(Northwest, Dir6::from_int(5));
        assert_eq!(Northeast, Dir6::from_int(1));

        assert_eq!(Northeast, Dir6::from_v2(vec2(20i32, -21i32)));
        assert_eq!(Southeast, Dir6::from_v2(vec2(20, -10)));
        assert_eq!(North, Dir6::from_v2(vec2(-10, -10)));
        assert_eq!(South, Dir6::from_v2(vec2(1, 1)));

        for i in 0..6 {
            let d = Dir6::from_int(i);
            let v = d.to_v2();
            let v1 = Dir6::from_int(i - 1).to_v2();
            let v2 = Dir6::from_int(i + 1).to_v2();

            // Test static iter
            assert_eq!(Some(d), Dir6::iter().nth(i as usize).map(|&x| x));

            // Test vector mapping.
            assert_eq!(d, Dir6::from_v2(v));

            // Test opposite dir vector mapping.
            assert_eq!(Dir6::from_int(i + 3), Dir6::from_v2(vec2(-v.x, -v.y)));

            // Test approximation of longer vectors.
            assert_eq!(d, Dir6::from_v2(vec2(v.x * 3, v.y * 3)));
            assert_eq!(d, Dir6::from_v2(vec2(v.x * 3 + v1.x, v.y * 3 + v1.y)));
            assert_eq!(d, Dir6::from_v2(vec2(v.x * 3 + v2.x, v.y * 3 + v2.y)));
        }
    }

    #[test]
    fn test_dir12() {
        assert_eq!(
            None,
            Dir12::away_from(&[false, false, false, false, false, false])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[true, true, true, true, true, true])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[false, true, false, false, true, false])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[true, true, false, true, false, false])
        );
        assert_eq!(
            None,
            Dir12::away_from(&[true, false, true, false, true, false])
        );
        assert_eq!(
            Some(Dir12::South),
            Dir12::away_from(&[true, false, false, false, false, false])
        );
        assert_eq!(
            Some(Dir12::East),
            Dir12::away_from(&[true, false, false, true, true, true])
        );
        assert_eq!(
            Some(Dir12::SouthSouthwest),
            Dir12::away_from(&[true, true, false, false, false, false])
        );
        assert_eq!(
            Some(Dir12::Southwest),
            Dir12::away_from(&[true, true, true, false, false, false])
        );
        assert_eq!(
            Some(Dir12::SouthSoutheast),
            Dir12::away_from(&[true, true, false, false, true, true])
        );
    }

    #[test]
    fn test_hex_disc() {
        use euclid::vec2;
        use super::HexGeom;

        for y in -8i32..8 {
            for x in -8i32..8 {
                let vec = vec2(x, y);

                for r in 0..8 {
                    assert_eq!(
                        vec.hex_dist() <= r,
                        hex_disc(vec2(0, 0), r).find(|&v| vec == v).is_some()
                    );
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::{RefCell};

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

pub struct DoubleLink<T> {
    head: Link<T>,
    tail: Link<T>,
}

pub struct Node<T> {
    prev: Link<T>,
    next: Link<T>,
    elem: T,
}

impl<T> Node<T> {
    fn new(elem: T) -> Rc<RefCell<Self>> {
        Rc::new(RefCell::new(Node {
            prev: None,
            next: None,
            elem: elem,
        }))
    }
}

impl<T> DoubleLink<T> {
    fn new() -> Self {
        DoubleLink {
            head: None,
            tail: None,
        }
    }

    fn push_head(&mut self, elem: T) -> &mut Self {
        let new_node = Node::new(elem);
        match self.head.take() {
            Some(prev_head) => {
                // set new_node's next prop to prev head
                new_node.borrow_mut().next = Some(prev_head);
                // set prev head's prev prop to new node
                new_node.borrow_mut().prev = Some(new_node.clone());
                // set self's head to new node
                self.head = Some(new_node);
            },
            None => {
                self.head = Some(new_node.clone());
                self.tail = Some(new_node);
            }
        };
        self
    }

    fn push_tail(&mut self, elem: T) -> &mut Self {
        let new_node = Node::new(elem);
        match self.tail.take() {
            Some(prev_tail) => {
                prev_tail.borrow_mut().next = Some(new_node.clone());
                new_node.borrow_mut().prev = Some(prev_tail);
                self.tail = Some(new_node);
            },
            None => {
                self.head = Some(new_node.clone());
                self.tail = Some(new_node);
            }
        };
        self
    }
}
<commit_msg>implements push head/tail and pop head for double linked list<commit_after>use std::rc::Rc;
use std::cell::{RefCell};

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

pub struct DoubleLink<T> {
    head: Link<T>,
    tail: Link<T>,
}

pub struct Node<T> {
    prev: Link<T>,
    next: Link<T>,
    elem: T,
}

impl<T> Node<T> {
    fn new(elem: T) -> Rc<RefCell<Self>> {
        Rc::new(RefCell::new(Node {
            prev: None,
            next: None,
            elem: elem,
        }))
    }
}

impl<T> DoubleLink<T> {
    fn new() -> Self {
        DoubleLink {
            head: None,
            tail: None,
        }
    }

    fn push_head(&mut self, elem: T) -> &mut Self {
        let new_node = Node::new(elem);
        match self.head.take() {
            Some(prev_head) => {
                // set prev head's prev prop to new node
                prev_head.borrow_mut().prev = Some(new_node.clone());
                // set new_node's next prop to prev head
                new_node.borrow_mut().next = Some(prev_head);
                // set self's head to new node
                self.head = Some(new_node);
            },
            None => {
                self.head = Some(new_node.clone());
                self.tail = Some(new_node);
            }
        };
        self
    }

    fn push_tail(&mut self, elem: T) -> &mut Self {
        let new_node = Node::new(elem);
        match self.tail.take() {
            Some(prev_tail) => {
                prev_tail.borrow_mut().next = Some(new_node.clone());
                new_node.borrow_mut().prev = Some(prev_tail);
                self.tail = Some(new_node);
            },
            None => {
                self.head = Some(new_node.clone());
                self.tail = Some(new_node);
            }
        };
        self
    }

    fn pop_head(&mut self) -> Option<T> {
        self.head.take().map(|old_head| {
            match old_head.borrow_mut().next.take() {
                Some(new_head) => {
                    // remove the reference to the previous head.
                    new_head.borrow_mut().prev.take();
                    self.head = Some(new_head);
                },
                None => {
                    // If we've consumed the end of the list, we need to update the tail property. head has already been set to none via the 'take' call earlier.
                    self.tail.take();
                }
            };
            Rc::try_unwrap(old_head).ok().unwrap().into_inner().elem
        })
    }
}

#[cfg(test)]
mod test {
    use super::DoubleLink;

    #[test]
    fn basics() {
        let mut list = DoubleLink::new();

        // Check empty list behaves right
        assert_eq!(list.pop_head(), None);

        // // Populate list
        list.push_head(1);
        list.push_head(2);
        list.push_head(3);

        // // Check normal removal
        assert_eq!(list.pop_head(), Some(3));
        assert_eq!(list.pop_head(), Some(2));

        // Push some more just to make sure nothing's corrupted
        list.push_head(4);
        list.push_head(5);

        // Check normal removal
        assert_eq!(list.pop_head(), Some(5));
        assert_eq!(list.pop_head(), Some(4));

        // Check exhaustion
        assert_eq!(list.pop_head(), Some(1));
        assert_eq!(list.pop_head(), None);
    }
}
<|endoftext|>