<commit_before>/*
 * The MIT License
 *
 * Copyright 2016 Ahseya.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

extern crate log;
extern crate byteorder;

use std::io;
use std::io::{Error, ErrorKind};
use std::io::Write;

use byteorder::{ BigEndian, LittleEndian, ByteOrder };

pub struct Cookies{
    http_only: bool,
}

impl Cookies {
    pub fn new(http_only: bool) -> Cookies {
        Cookies{ http_only: http_only }
    }

    pub fn parse_content(&self, bs: &[u8]) -> io::Result<()> {
        // Magic bytes: "COOK" = 0x636F6F6B
        if slice(bs, 0, 4)? != [0x63, 0x6F, 0x6F, 0x6B] {
                return Err(Error::new(ErrorKind::InvalidData, ("not a cookie file")))
            }

        println!("# Netscape HTTP Cookie File");
        println!("# This file was generated by Horrorho's Burnt Cookie.");
        println!("# http://github.com/horrorho/burnt-cookie");

        let count = slice(bs, 4, 4).map(BigEndian::read_u32)? as usize;
        parse_table::<BigEndian>(&bs[8..], count)?
            .iter()
            .fold(count * 4 + 8, |off, &len| {
                slice(&bs, off, len)
                    .and_then(|u| self.parse_page(u))
                    .unwrap_or_else(|err| warn!("page parse failure: {}", err));
                off + len});
        Ok(())
    }

    fn parse_page(&self, bs: &[u8]) -> io::Result<()> {
        if slice(bs, 0, 4)? != [0x00, 0x00, 0x01, 0x00] {
                return Err(Error::new(ErrorKind::InvalidData, ("bad page header")))
            }

        let count = slice(bs, 4, 4).map(LittleEndian::read_u32)? as usize;
        parse_table::<LittleEndian>(&bs[8..], count)?
            .iter()
            .fold((), |_, &off|
                slice(bs, off, 4)
                    .map(LittleEndian::read_u32)
                    .and_then(|len| slice(bs, off, len as usize))
                    .and_then(|u| self.parse_cookie::<LittleEndian>(u))
                    .unwrap_or_else(|err| warn!("cookie parse failure: {}", err)));

        if slice(bs, count * 4 + 8, 4)? != [0x00, 0x00, 0x00, 0x00] {
                return Err(Error::new(ErrorKind::InvalidData, ("bad page trailer")))
            }
        Ok(())
    }

    fn parse_cookie<T: ByteOrder>(&self, bs: &[u8]) -> io::Result<()> {
        if bs.len() < 0x30 {
            return Err(Error::new(ErrorKind::InvalidData, ("cookie data underflow")))
        }
        let flags     = T::read_u32(&bs[0x08..0x0C]);

        let url_off   = T::read_u32(&bs[0x10..0x14]) as usize;
        let name_off  = T::read_u32(&bs[0x14..0x18]) as usize;
        let path_off  = T::read_u32(&bs[0x18..0x1C]) as usize;
        let value_off = T::read_u32(&bs[0x1C..0x20]) as usize;

        // i/OS/X to Unix timestamp +(1 Jan 2001 epoch seconds).
        let expiry = T::read_f64(&bs[0x28..0x30]) + 978307200f64;

        let url   = slice_to(bs, url_off,   name_off ).and_then(&c_str)?;
        let name  = slice_to(bs, name_off,  path_off ).and_then(&c_str)?;
        let path  = slice_to(bs, path_off,  value_off).and_then(&c_str)?;
        let value = slice_to(bs, value_off, bs.len() ).and_then(&c_str)?;

        let is_raw = url.starts_with(".");

        let is_secure    = flags & 0x01 == 0x01;
        let is_http_only = flags & 0x04 == 0x04;

        let prefix = if is_http_only && self.http_only { "#HttpOnly_" } else { "" };

        // Non-efficient workaround for println! broken pipes with | head.
        writeln!(&mut io::stdout(), "{}{}\t{}\t{}\t{}\t{}\t{}\t{}",
            prefix, url, bool_str(is_raw), path, bool_str(is_secure), expiry, name, value)
            .or(Ok(()))
    }
}

fn slice(bs: &[u8], off: usize, len: usize) -> io::Result<&[u8]> {
    if off + len > bs.len() {
        Err(Error::new(ErrorKind::InvalidData,
            format!("data underflow: {}", off + len - bs.len())))
    } else {
        Ok(&bs[off..off + len])
    }
}

fn parse_table<T: ByteOrder>(bs: &[u8], count: usize) -> io::Result<Vec<usize>> {
    let end = count * 4;
    if end  > bs.len() {
        return Err(Error::new(ErrorKind::InvalidData, ("table data underflow")))
    }
    let data = (&bs[..end])
        .chunks(4)
        .map(|u| T::read_u32(u) as usize)
        .collect();
    Ok(data)
}

fn slice_to(bs: &[u8], off: usize, to: usize) -> io::Result<&[u8]> {
    if to < off {
        Err(Error::new(ErrorKind::InvalidData, format!("negative data length: {}", to - off)))
    } else {
        slice(bs, off, to - off)
    }
}

fn c_str(bs: &[u8]) -> io::Result<String> {
    bs.split_last()
        .ok_or(Error::new(ErrorKind::InvalidData, "null c string"))
        .and_then(|(&last, elements)|
            if last == 0x00 {
                Ok(elements)
            } else {
                Err(Error::new(ErrorKind::InvalidData, "c string non null terminator"))
            })
        .and_then(|elements|
            String::from_utf8(elements.to_vec())
                .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())))
}

fn bool_str(b: bool) -> &'static str { if b { "TRUE" } else { "FALSE" } }
<commit_msg>Minor formatting.<commit_after>/*
 * The MIT License
 *
 * Copyright 2016 Ahseya.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

extern crate log;
extern crate byteorder;

use std::io;
use std::io::{Error, ErrorKind};
use std::io::Write;

use byteorder::{ BigEndian, LittleEndian, ByteOrder };

pub struct Cookies{
    http_only: bool,
}

impl Cookies {
    pub fn new(http_only: bool) -> Cookies {
        Cookies{ http_only: http_only }
    }

    pub fn parse_content(&self, bs: &[u8]) -> io::Result<()> {
        // Magic bytes: "COOK" = 0x636F6F6B
        if slice(bs, 0, 4)? != [0x63, 0x6F, 0x6F, 0x6B] {
                return Err(Error::new(ErrorKind::InvalidData, ("not a cookie file")))
            }
        println!("# Netscape HTTP Cookie File");
        println!("# This file was generated by Horrorho's Burnt Cookie.");
        println!("# http://github.com/horrorho/burnt-cookie");

        let count = slice(bs, 4, 4).map(BigEndian::read_u32)? as usize;
        parse_table::<BigEndian>(&bs[8..], count)?
            .iter()
            .fold(count * 4 + 8, |off, &len| {
                slice(&bs, off, len)
                    .and_then(|u| self.parse_page(u))
                    .unwrap_or_else(|err| warn!("page parse failure: {}", err));
                off + len});
        Ok(())
    }

    fn parse_page(&self, bs: &[u8]) -> io::Result<()> {
        if slice(bs, 0, 4)? != [0x00, 0x00, 0x01, 0x00] {
                return Err(Error::new(ErrorKind::InvalidData, ("bad page header")))
            }

        let count = slice(bs, 4, 4).map(LittleEndian::read_u32)? as usize;
        parse_table::<LittleEndian>(&bs[8..], count)?
            .iter()
            .fold((), |_, &off|
                slice(bs, off, 4)
                    .map(LittleEndian::read_u32)
                    .and_then(|len| slice(bs, off, len as usize))
                    .and_then(|u| self.parse_cookie::<LittleEndian>(u))
                    .unwrap_or_else(|err| warn!("cookie parse failure: {}", err)));

        if slice(bs, count * 4 + 8, 4)? != [0x00, 0x00, 0x00, 0x00] {
                return Err(Error::new(ErrorKind::InvalidData, ("bad page trailer")))
            }
        Ok(())
    }

    fn parse_cookie<T: ByteOrder>(&self, bs: &[u8]) -> io::Result<()> {
        if bs.len() < 0x30 {
            return Err(Error::new(ErrorKind::InvalidData, ("cookie data underflow")))
        }
        let flags     = T::read_u32(&bs[0x08..0x0C]);

        let url_off   = T::read_u32(&bs[0x10..0x14]) as usize;
        let name_off  = T::read_u32(&bs[0x14..0x18]) as usize;
        let path_off  = T::read_u32(&bs[0x18..0x1C]) as usize;
        let value_off = T::read_u32(&bs[0x1C..0x20]) as usize;

        // i/OS/X to Unix timestamp +(1 Jan 2001 epoch seconds).
        let expiry = T::read_f64(&bs[0x28..0x30]) + 978307200f64;

        let url   = slice_to(bs, url_off,   name_off ).and_then(&c_str)?;
        let name  = slice_to(bs, name_off,  path_off ).and_then(&c_str)?;
        let path  = slice_to(bs, path_off,  value_off).and_then(&c_str)?;
        let value = slice_to(bs, value_off, bs.len() ).and_then(&c_str)?;

        let is_raw = url.starts_with(".");

        let is_secure    = flags & 0x01 == 0x01;
        let is_http_only = flags & 0x04 == 0x04;

        let prefix = if is_http_only && self.http_only { "#HttpOnly_" } else { "" };

        // Non-efficient workaround for println! broken pipes with | head.
        writeln!(&mut io::stdout(), "{}{}\t{}\t{}\t{}\t{}\t{}\t{}",
            prefix, url, bool_str(is_raw), path, bool_str(is_secure), expiry, name, value)
            .or(Ok(()))
    }
}

fn slice(bs: &[u8], off: usize, len: usize) -> io::Result<&[u8]> {
    if off + len > bs.len() {
        Err(Error::new(ErrorKind::InvalidData,
            format!("data underflow: {}", off + len - bs.len())))
    } else {
        Ok(&bs[off..off + len])
    }
}

fn parse_table<T: ByteOrder>(bs: &[u8], count: usize) -> io::Result<Vec<usize>> {
    let end = count * 4;
    if end  > bs.len() {
        return Err(Error::new(ErrorKind::InvalidData, ("table data underflow")))
    }
    let data = (&bs[..end])
        .chunks(4)
        .map(|u| T::read_u32(u) as usize)
        .collect();
    Ok(data)
}

fn slice_to(bs: &[u8], off: usize, to: usize) -> io::Result<&[u8]> {
    if to < off {
        Err(Error::new(ErrorKind::InvalidData, format!("negative data length: {}", to - off)))
    } else {
        slice(bs, off, to - off)
    }
}

fn c_str(bs: &[u8]) -> io::Result<String> {
    bs.split_last()
        .ok_or(Error::new(ErrorKind::InvalidData, "null c string"))
        .and_then(|(&last, elements)|
            if last == 0x00 {
                Ok(elements)
            } else {
                Err(Error::new(ErrorKind::InvalidData, "c string non null terminator"))
            })
        .and_then(|elements|
            String::from_utf8(elements.to_vec())
                .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())))
}

fn bool_str(b: bool) -> &'static str { if b { "TRUE" } else { "FALSE" } }
<|endoftext|>


<commit_before>extern crate pink_spider;
extern crate feed_rs;
extern crate hyper;
extern crate chrono;
extern crate serde_json;

use pink_spider::model::{Model, Feed};

pub fn main() {
    println!("Start crawling...");

    let mut page  = 0;
    let per_page  = 10;
    let mut feeds = Feed::find(0, 0, None);
    let total = feeds.total;
    println!("{} feeds", total);
    while feeds.page * feeds.per_page < total {
        feeds = Feed::find(page, per_page, None);
        for mut feed in feeds.items {
            println!("Crawl {} ", feed.url);
            match feed.crawl() {
                Ok(entries) => {
                    println!("Found {} entries", entries.len());
                    println!("Found {} tracks",
                             entries.iter().fold(0, |sum, e| sum + e.tracks.len()));
                    println!("Found {} albums",
                             entries.iter().fold(0, |sum, e| sum + e.albums.len()));
                    println!("Found {} playlists",
                             entries.iter().fold(0, |sum, e| sum + e.playlists.len()));
                },
                Err(e) => {
                    println!("Failed to crawl {}: {:?}", feed.url, e);
                },
            }
        }
        page += 1;
    }
    println!("Complete crawling...");
}
<commit_msg>Better logging for crawler<commit_after>extern crate pink_spider;
extern crate feed_rs;
extern crate hyper;
extern crate chrono;
extern crate serde_json;

use std::time::Instant;
use chrono::Duration;
use pink_spider::model::{Model, Feed};

pub fn main() {
    println!("Start crawling...");
    let now = Instant::now();
    let mut page  = 0;
    let per_page  = 10;
    let mut feeds = Feed::find(0, 0, None);
    let total = feeds.total;
    let mut index = 0;
    println!("{} feeds", total);
    while feeds.page * feeds.per_page < total {
        feeds = Feed::find(page, per_page, None);
        for mut feed in feeds.items {
            println!("[{}/{}] Crawl {} ", index, total, feed.url);
            match feed.crawl() {
                Ok(entries) => {
                    println!("Found {} entries", entries.len());
                    println!("Found {} tracks",
                             entries.iter().fold(0, |sum, e| sum + e.tracks.len()));
                    println!("Found {} albums",
                             entries.iter().fold(0, |sum, e| sum + e.albums.len()));
                    println!("Found {} playlists",
                             entries.iter().fold(0, |sum, e| sum + e.playlists.len()));
                },
                Err(e) => {
                    println!("Failed to crawl {}: {:?}", feed.url, e);
                },
            }
            index += 1;
        }
        page += 1;
    }
    println!("Complete crawling... total {} ms",
             Duration::from_std(now.elapsed()).unwrap().num_milliseconds());
}
<|endoftext|>


<commit_before>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::{File,fs};
//use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
use libc::funcs::c95::stdlib::system;
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
        create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path)
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template. Attempt to open the
/// users default editor to make changes.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
    //let methods = parse_bytes(format!("$EDITOR {}", path.display()).as_bytes(), 1).unwrap();
    //system("vim ~/.muxed/muxed");
}

/// Create the muxed directory and return the path if creation is successful.
fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return a boolean if the ~/.muxed/ dir exists.
fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

/// Return the users current homedir as a string.
fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<commit_msg>Successfully open the new project file.<commit_after>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::{File,fs};
//use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
use libc::funcs::c95::stdlib::system;
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
        create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path)
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template. Attempt to open the
/// users default editor to make changes.
fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    let method = format!("$EDITOR {}", path.display()).to_c_str();
    unsafe { system(method.unwrap()); };
}

/// Create the muxed directory and return the path if creation is successful.
fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return a boolean if the ~/.muxed/ dir exists.
fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

/// Return the users current homedir as a string.
fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

/// Test helper to standardize how random files and directories are generated.
#[cfg(test)]
fn random_name() -> String {
    format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<|endoftext|>


<commit_before>use coefs::Coefficients;
use consts::SAMPLES;
use descramble::{descramble, Bootstrap};
use enhance::{self, EnhancedSpectrals, FrameEnergy};
use errors::Errors;
use gain::Gains;
use params::BaseParams;
use prev::PrevFrame;
use spectral::Spectrals;
use unvoiced::{UnvoicedParts, Unvoiced};
use voiced::{Phase, PhaseBase, Voiced};

pub struct CAIFrame {
    chunks: [u32; 8],
    errors: [usize; 7],
}

impl CAIFrame {
    pub fn new(chunks: [u32; 8], errors: [usize; 7]) -> CAIFrame {
        CAIFrame {
            chunks: chunks,
            errors: errors,
        }
    }
}

pub struct IMBEDecoder {
    prev: PrevFrame,
}

impl IMBEDecoder {
    pub fn new() -> IMBEDecoder {
        IMBEDecoder {
            prev: PrevFrame::default(),
        }
    }

    pub fn decode<F: FnMut(f32)>(&mut self, frame: CAIFrame, mut cb: F) {
        let period = match Bootstrap::new(&frame.chunks) {
            Bootstrap::Period(p) => p,
            Bootstrap::Invalid => {
                self.repeat(cb);
                return;
            },
            Bootstrap::Silence => {
                self.silence(cb);
                return;
            },
        };

        let errors = Errors::new(&frame.errors, self.prev.err_rate);

        if enhance::should_repeat(&errors) {
            self.repeat(cb);
            return;
        }

        if enhance::should_mute(&errors) {
            self.silence(cb);
            return;
        }

        let params = BaseParams::new(period);
        let (amps, mut voice, gain_idx) = descramble(&frame.chunks, &params);
        let gains = Gains::new(gain_idx, &amps, &params);
        let coefs = Coefficients::new(&gains, &amps, &params);
        let spectrals = Spectrals::new(&coefs, &params, &self.prev);
        let energy = FrameEnergy::new(&spectrals, &self.prev.energy, &params);

        let mut enhanced = EnhancedSpectrals::new(&spectrals, &energy, &params);
        let amp_thresh = enhance::amp_thresh(&errors, self.prev.amp_thresh);
        enhance::smooth(&mut enhanced, &mut voice, &errors, &energy, amp_thresh);

        let uparts = UnvoicedParts::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        {
            let unvoiced = Unvoiced::new(&uparts, &self.prev.unvoiced);
            let voiced = Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice);

            for n in 0..SAMPLES {
                cb(unvoiced.get(n) + voiced.get(n));
            }
        }

        self.prev = PrevFrame {
            params: params,
            spectrals: spectrals,
            enhanced: enhanced,
            voice: voice,
            err_rate: errors.rate,
            energy: energy,
            amp_thresh: amp_thresh,
            unvoiced: uparts,
            phase_base: vbase,
            phase: vphase,
        };
    }

    fn silence<F: FnMut(f32)>(&self, mut cb: F) {
        for _ in 0..SAMPLES {
            cb(0.0);
        }
    }

    fn repeat<F: FnMut(f32)>(&self, mut cb: F) {
        let params = self.prev.params.clone();
        let voice = self.prev.voice.clone();
        let enhanced = self.prev.enhanced.clone();

        let uparts = UnvoicedParts::new(&params, &voice, &enhanced);

        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        let unvoiced = Unvoiced::new(&uparts, &self.prev.unvoiced);
        let voiced = Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice);

        for n in 0..SAMPLES {
            cb(unvoiced.get(n) + voiced.get(n));
        }
    }
}
<commit_msg>Remove a newline<commit_after>use coefs::Coefficients;
use consts::SAMPLES;
use descramble::{descramble, Bootstrap};
use enhance::{self, EnhancedSpectrals, FrameEnergy};
use errors::Errors;
use gain::Gains;
use params::BaseParams;
use prev::PrevFrame;
use spectral::Spectrals;
use unvoiced::{UnvoicedParts, Unvoiced};
use voiced::{Phase, PhaseBase, Voiced};

pub struct CAIFrame {
    chunks: [u32; 8],
    errors: [usize; 7],
}

impl CAIFrame {
    pub fn new(chunks: [u32; 8], errors: [usize; 7]) -> CAIFrame {
        CAIFrame {
            chunks: chunks,
            errors: errors,
        }
    }
}

pub struct IMBEDecoder {
    prev: PrevFrame,
}

impl IMBEDecoder {
    pub fn new() -> IMBEDecoder {
        IMBEDecoder {
            prev: PrevFrame::default(),
        }
    }

    pub fn decode<F: FnMut(f32)>(&mut self, frame: CAIFrame, mut cb: F) {
        let period = match Bootstrap::new(&frame.chunks) {
            Bootstrap::Period(p) => p,
            Bootstrap::Invalid => {
                self.repeat(cb);
                return;
            },
            Bootstrap::Silence => {
                self.silence(cb);
                return;
            },
        };

        let errors = Errors::new(&frame.errors, self.prev.err_rate);

        if enhance::should_repeat(&errors) {
            self.repeat(cb);
            return;
        }

        if enhance::should_mute(&errors) {
            self.silence(cb);
            return;
        }

        let params = BaseParams::new(period);
        let (amps, mut voice, gain_idx) = descramble(&frame.chunks, &params);
        let gains = Gains::new(gain_idx, &amps, &params);
        let coefs = Coefficients::new(&gains, &amps, &params);
        let spectrals = Spectrals::new(&coefs, &params, &self.prev);
        let energy = FrameEnergy::new(&spectrals, &self.prev.energy, &params);

        let mut enhanced = EnhancedSpectrals::new(&spectrals, &energy, &params);
        let amp_thresh = enhance::amp_thresh(&errors, self.prev.amp_thresh);
        enhance::smooth(&mut enhanced, &mut voice, &errors, &energy, amp_thresh);

        let uparts = UnvoicedParts::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        {
            let unvoiced = Unvoiced::new(&uparts, &self.prev.unvoiced);
            let voiced = Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice);

            for n in 0..SAMPLES {
                cb(unvoiced.get(n) + voiced.get(n));
            }
        }

        self.prev = PrevFrame {
            params: params,
            spectrals: spectrals,
            enhanced: enhanced,
            voice: voice,
            err_rate: errors.rate,
            energy: energy,
            amp_thresh: amp_thresh,
            unvoiced: uparts,
            phase_base: vbase,
            phase: vphase,
        };
    }

    fn silence<F: FnMut(f32)>(&self, mut cb: F) {
        for _ in 0..SAMPLES {
            cb(0.0);
        }
    }

    fn repeat<F: FnMut(f32)>(&self, mut cb: F) {
        let params = self.prev.params.clone();
        let voice = self.prev.voice.clone();
        let enhanced = self.prev.enhanced.clone();

        let uparts = UnvoicedParts::new(&params, &voice, &enhanced);
        let vbase = PhaseBase::new(&params, &self.prev);
        let vphase = Phase::new(&params, &voice, &vbase);

        let unvoiced = Unvoiced::new(&uparts, &self.prev.unvoiced);
        let voiced = Voiced::new(&params, &self.prev, &vphase, &enhanced, &voice);

        for n in 0..SAMPLES {
            cb(unvoiced.get(n) + voiced.get(n));
        }
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use byteorder::{LittleEndian, ReadBytesExt};

use std::convert::{From, AsRef};
use std::error::Error;
use std::fmt;
use std::io::{self, Cursor, Read, Write, SeekFrom, Seek};

use {BmpHeader, BmpDibHeader, CompressionType, Image, Pixel};
use BmpVersion::*;

use self::BmpErrorKind::*;

/// A result type, either containing an `Image` or a `BmpError`.
pub type BmpResult<T> = Result<T, BmpError>;

/// The different kinds of possible BMP errors.
#[derive(Debug)]
pub enum BmpErrorKind {
    WrongMagicNumbers,
    UnsupportedBitsPerPixel,
    UnsupportedCompressionType,
    UnsupportedBmpVersion,
    Other,
    BmpIoError(io::Error),
    BmpByteorderError(byteorder::Error),
}

/// The error type returned if the decoding of an image from disk fails.
#[derive(Debug)]
pub struct BmpError {
    pub kind: BmpErrorKind,
    pub details: String,
}

impl BmpError {
    fn new<T: AsRef<str>>(kind: BmpErrorKind, details: T) -> BmpError {
        let description = match kind {
            WrongMagicNumbers => "Wrong magic numbers",
            UnsupportedBitsPerPixel => "Unsupported bits per pixel",
            UnsupportedCompressionType => "Unsupported compression type",
            UnsupportedBmpVersion => "Unsupported BMP version",
            _ => "BMP Error",
        };

        BmpError {
            kind: kind,
            details: format!("{}: {}", description, details.as_ref())
        }
    }
}

impl fmt::Display for BmpError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            BmpIoError(ref error) => return error.fmt(fmt),
            _ => write!(fmt, "{}", self.description())
        }
    }
}

impl From<io::Error> for BmpError {
    fn from(err: io::Error) -> BmpError {
        BmpError::new(BmpIoError(err), "Io Error")
    }
}

impl From<byteorder::Error> for BmpError {
    fn from(err: byteorder::Error) -> BmpError {
        BmpError::new(BmpByteorderError(err), "Byteorder Error")
    }
}

impl Error for BmpError {
    fn description(&self) -> &str {
        match self.kind {
            BmpIoError(ref e) => Error::description(e),
            BmpByteorderError(ref e) => Error::description(e),
            _ => &self.details
        }
    }
}

pub fn decode_image(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<Image> {
    try!(read_bmp_id(bmp_data));
    let header = try!(read_bmp_header(bmp_data));
    let dib_header = try!(read_bmp_dib_header(bmp_data));

    let color_palette = try!(read_color_palette(bmp_data, &dib_header));

    let width = dib_header.width.abs() as u32;
    let height = dib_header.height.abs() as u32;
    let padding = width % 4;

    let data = match color_palette {
        Some(ref palette) => try!(
            read_indexes(bmp_data.get_mut(), &palette, width as usize, height as usize,
                         dib_header.bits_per_pixel, header.pixel_offset as usize)
        ),
        None => try!(
            read_pixels(bmp_data, width, height, header.pixel_offset, padding as i64)
        )
    };

    let image = Image {
        header: header,
        dib_header: dib_header,
        color_palette: color_palette,
        width: width,
        height: height,
        padding: padding,
        data: data
    };

    Ok(image)
}

fn read_bmp_id(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<()> {
    let mut bm = [0, 0];
    try!(bmp_data.read(&mut bm));

    if bm == b"BM"[..] {
        Ok(())
    } else {
        Err(BmpError::new(WrongMagicNumbers, format!("Expected [66, 77], but was {:?}", bm)))
    }
}

fn read_bmp_header(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<BmpHeader> {
    let header = BmpHeader {
        file_size:    try!(bmp_data.read_u32::<LittleEndian>()),
        creator1:     try!(bmp_data.read_u16::<LittleEndian>()),
        creator2:     try!(bmp_data.read_u16::<LittleEndian>()),
        pixel_offset: try!(bmp_data.read_u32::<LittleEndian>()),
    };

    Ok(header)
}

fn read_bmp_dib_header(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<BmpDibHeader> {
    let dib_header = BmpDibHeader {
        header_size:    try!(bmp_data.read_u32::<LittleEndian>()),
        width:          try!(bmp_data.read_i32::<LittleEndian>()),
        height:         try!(bmp_data.read_i32::<LittleEndian>()),
        num_planes:     try!(bmp_data.read_u16::<LittleEndian>()),
        bits_per_pixel: try!(bmp_data.read_u16::<LittleEndian>()),
        compress_type:  try!(bmp_data.read_u32::<LittleEndian>()),
        data_size:      try!(bmp_data.read_u32::<LittleEndian>()),
        hres:           try!(bmp_data.read_i32::<LittleEndian>()),
        vres:           try!(bmp_data.read_i32::<LittleEndian>()),
        num_colors:     try!(bmp_data.read_u32::<LittleEndian>()),
        num_imp_colors: try!(bmp_data.read_u32::<LittleEndian>()),
    };

    match dib_header.header_size {
        // BMPv2 has a header size of 12 bytes
        12 => return Err(BmpError::new(UnsupportedBmpVersion, Version2)),
        // BMPv3 has a header size of 40 bytes, it is NT if the compression type is 3
        40 if dib_header.compress_type == 3 =>
            return Err(BmpError::new(UnsupportedBmpVersion, Version3NT)),
        // BMPv4 has more data in its header, it is currently ignored but we still try to parse it
        108 | _ => ()
    }

    match dib_header.bits_per_pixel {
        // Currently supported
        1 | 4 | 8 | 24 => (),
        other => return Err(
            BmpError::new(UnsupportedBitsPerPixel, format!("{}", other))
        )
    }

    match CompressionType::from_u32(dib_header.compress_type) {
        CompressionType::Uncompressed => (),
        other => return Err(BmpError::new(UnsupportedCompressionType, other)),
    }

    Ok(dib_header)
}

fn read_color_palette(bmp_data: &mut Cursor<Vec<u8>>, dh: &BmpDibHeader) ->
                      BmpResult<Option<Vec<Pixel>>> {
    let num_entries = match dh.bits_per_pixel {
        // We have a color_palette if there if num_colors in the dib header is not zero
        _ if dh.num_colors != 0 => dh.num_colors as usize,
        // Or if there are 8 or less bits per pixel
        bpp @ 1 | bpp @ 4 | bpp @ 8 => 1 << bpp,
        _ => return Ok(None)
    };

    let num_bytes = match dh.header_size {
        // Each entry in the color_palette is four bytes for Version 3 or 4
        40 | 108 => 4,
        // Three bytes for Version two. Though, this is currently not supported
        _ => return Err(BmpError::new(UnsupportedBmpVersion, Version2))
    };

    let mut px = &mut [0; 4][0 .. num_bytes as usize];
    let mut color_palette = Vec::with_capacity(num_entries);
    for _ in 0 .. num_entries {
        try!(bmp_data.read(&mut px));
        color_palette.push(px!(px[2], px[1], px[0]));
    }

    Ok(Some(color_palette))
}

fn read_indexes(bmp_data: &mut Vec<u8>, palette: &Vec<Pixel>,
                width: usize, height: usize, bpp: u16, offset: usize) -> BmpResult<Vec<Pixel>> {
    let mut data = Vec::with_capacity(height * width);
    // Number of bytes to read from each row, varies based on bits_per_pixel
    let bytes_per_row = (width as f64 / (8.0 / bpp as f64)).ceil() as usize;
    for y in 0 .. height {
        let padding = match bytes_per_row % 4 {
            0 => 0,
            other => 4 - other
        };
        let start = offset + (bytes_per_row + padding) * y;
        let bytes = &bmp_data[start .. start + bytes_per_row];

        // determine how to parse each row, depending on bits_per_pixel
        match bpp {
            1 => {
                for b in 0 .. width as usize {
                    let i = index(&bytes, b);
                    data.push(palette[i as usize]);
                }
            },
            4 => {
                let mut index = Vec::with_capacity(data.len() + 1);
                for b in bytes {
                    index.push((b >> 4));
                    index.push((b & 0x0f));
                }
                for i in 0 .. width as usize {
                    data.push(palette[index[i] as usize]);
                }
            },
            8 => {
                for index in bytes {
                    data.push(palette[*index as usize]);
                }
            },
            other => return Err(BmpError::new(Other,
                format!("BMP does not support color palettes for {} bits per pixel", other)))
        }
    }
    Ok(data)
}

const BITS: usize = 8;

fn index(bytes: &[u8], i: usize) -> u8 {
    let w = i / BITS;
    let b = i % BITS;

    (bytes[w] & (0x1 << (7 - b) as u8)) >> (7 - b)
}

fn read_pixels(bmp_data: &mut Cursor<Vec<u8>>, width: u32, height: u32,
               offset: u32, padding: i64) -> BmpResult<Vec<Pixel>> {
    let mut data = Vec::with_capacity((height * width) as usize);
    // seek until data
    try!(bmp_data.seek(SeekFrom::Start(offset as u64)));
    // read pixels until padding
    let mut px = [0; 3];
    for _ in 0 .. height {
        for _ in 0 .. width {
            try!(bmp_data.read(&mut px));
            data.push(px!(px[2], px[1], px[0]));
        }
        // seek padding
        try!(bmp_data.seek(SeekFrom::Current(padding)));
    }
    Ok(data)
}

#[test]
fn test_calculate_bit_index() {
    let bytes = vec![0b1000_0001, 0b1111_0001];

    assert_eq!(index(&bytes, 0), 1);
    assert_eq!(index(&bytes, 1), 0);
    assert_eq!(index(&bytes, 2), 0);
    assert_eq!(index(&bytes, 3), 0);
    assert_eq!(index(&bytes, 4), 0);
    assert_eq!(index(&bytes, 5), 0);
    assert_eq!(index(&bytes, 6), 0);
    assert_eq!(index(&bytes, 7), 1);

    assert_eq!(index(&bytes, 8), 1);
    assert_eq!(index(&bytes, 9), 1);
    assert_eq!(index(&bytes, 10), 1);
    assert_eq!(index(&bytes, 11), 1);
    assert_eq!(index(&bytes, 12), 0);
    assert_eq!(index(&bytes, 13), 0);
    assert_eq!(index(&bytes, 14), 0);
    assert_eq!(index(&bytes, 15), 1);
}
<commit_msg>Implement a bit_index iterator that parses indexes for 1, 4 and 8 bits per pixel when given a block of bytes<commit_after>extern crate byteorder;

use byteorder::{LittleEndian, ReadBytesExt};

use std::convert::{From, AsRef};
use std::error::Error;
use std::fmt;
use std::io::{self, Cursor, Read, Write, SeekFrom, Seek};

use {BmpHeader, BmpDibHeader, CompressionType, Image, Pixel};
use BmpVersion::*;

use self::BmpErrorKind::*;

/// A result type, either containing an `Image` or a `BmpError`.
pub type BmpResult<T> = Result<T, BmpError>;

/// The different kinds of possible BMP errors.
#[derive(Debug)]
pub enum BmpErrorKind {
    WrongMagicNumbers,
    UnsupportedBitsPerPixel,
    UnsupportedCompressionType,
    UnsupportedBmpVersion,
    Other,
    BmpIoError(io::Error),
    BmpByteorderError(byteorder::Error),
}

/// The error type returned if the decoding of an image from disk fails.
#[derive(Debug)]
pub struct BmpError {
    pub kind: BmpErrorKind,
    pub details: String,
}

impl BmpError {
    fn new<T: AsRef<str>>(kind: BmpErrorKind, details: T) -> BmpError {
        let description = match kind {
            WrongMagicNumbers => "Wrong magic numbers",
            UnsupportedBitsPerPixel => "Unsupported bits per pixel",
            UnsupportedCompressionType => "Unsupported compression type",
            UnsupportedBmpVersion => "Unsupported BMP version",
            _ => "BMP Error",
        };

        BmpError {
            kind: kind,
            details: format!("{}: {}", description, details.as_ref())
        }
    }
}

impl fmt::Display for BmpError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            BmpIoError(ref error) => return error.fmt(fmt),
            _ => write!(fmt, "{}", self.description())
        }
    }
}

impl From<io::Error> for BmpError {
    fn from(err: io::Error) -> BmpError {
        BmpError::new(BmpIoError(err), "Io Error")
    }
}

impl From<byteorder::Error> for BmpError {
    fn from(err: byteorder::Error) -> BmpError {
        BmpError::new(BmpByteorderError(err), "Byteorder Error")
    }
}

impl Error for BmpError {
    fn description(&self) -> &str {
        match self.kind {
            BmpIoError(ref e) => Error::description(e),
            BmpByteorderError(ref e) => Error::description(e),
            _ => &self.details
        }
    }
}

pub fn decode_image(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<Image> {
    try!(read_bmp_id(bmp_data));
    let header = try!(read_bmp_header(bmp_data));
    let dib_header = try!(read_bmp_dib_header(bmp_data));

    let color_palette = try!(read_color_palette(bmp_data, &dib_header));

    let width = dib_header.width.abs() as u32;
    let height = dib_header.height.abs() as u32;
    let padding = width % 4;

    let data = match color_palette {
        Some(ref palette) => try!(
            read_indexes(bmp_data.get_mut(), &palette, width as usize, height as usize,
                         dib_header.bits_per_pixel, header.pixel_offset as usize)
        ),
        None => try!(
            read_pixels(bmp_data, width, height, header.pixel_offset, padding as i64)
        )
    };

    let image = Image {
        header: header,
        dib_header: dib_header,
        color_palette: color_palette,
        width: width,
        height: height,
        padding: padding,
        data: data
    };

    Ok(image)
}

fn read_bmp_id(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<()> {
    let mut bm = [0, 0];
    try!(bmp_data.read(&mut bm));

    if bm == b"BM"[..] {
        Ok(())
    } else {
        Err(BmpError::new(WrongMagicNumbers, format!("Expected [66, 77], but was {:?}", bm)))
    }
}

fn read_bmp_header(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<BmpHeader> {
    let header = BmpHeader {
        file_size:    try!(bmp_data.read_u32::<LittleEndian>()),
        creator1:     try!(bmp_data.read_u16::<LittleEndian>()),
        creator2:     try!(bmp_data.read_u16::<LittleEndian>()),
        pixel_offset: try!(bmp_data.read_u32::<LittleEndian>()),
    };

    Ok(header)
}

fn read_bmp_dib_header(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<BmpDibHeader> {
    let dib_header = BmpDibHeader {
        header_size:    try!(bmp_data.read_u32::<LittleEndian>()),
        width:          try!(bmp_data.read_i32::<LittleEndian>()),
        height:         try!(bmp_data.read_i32::<LittleEndian>()),
        num_planes:     try!(bmp_data.read_u16::<LittleEndian>()),
        bits_per_pixel: try!(bmp_data.read_u16::<LittleEndian>()),
        compress_type:  try!(bmp_data.read_u32::<LittleEndian>()),
        data_size:      try!(bmp_data.read_u32::<LittleEndian>()),
        hres:           try!(bmp_data.read_i32::<LittleEndian>()),
        vres:           try!(bmp_data.read_i32::<LittleEndian>()),
        num_colors:     try!(bmp_data.read_u32::<LittleEndian>()),
        num_imp_colors: try!(bmp_data.read_u32::<LittleEndian>()),
    };

    match dib_header.header_size {
        // BMPv2 has a header size of 12 bytes
        12 => return Err(BmpError::new(UnsupportedBmpVersion, Version2)),
        // BMPv3 has a header size of 40 bytes, it is NT if the compression type is 3
        40 if dib_header.compress_type == 3 =>
            return Err(BmpError::new(UnsupportedBmpVersion, Version3NT)),
        // BMPv4 has more data in its header, it is currently ignored but we still try to parse it
        108 | _ => ()
    }

    match dib_header.bits_per_pixel {
        // Currently supported
        1 | 4 | 8 | 24 => (),
        other => return Err(
            BmpError::new(UnsupportedBitsPerPixel, format!("{}", other))
        )
    }

    match CompressionType::from_u32(dib_header.compress_type) {
        CompressionType::Uncompressed => (),
        other => return Err(BmpError::new(UnsupportedCompressionType, other)),
    }

    Ok(dib_header)
}

fn read_color_palette(bmp_data: &mut Cursor<Vec<u8>>, dh: &BmpDibHeader) ->
                      BmpResult<Option<Vec<Pixel>>> {
    let num_entries = match dh.bits_per_pixel {
        // We have a color_palette if there if num_colors in the dib header is not zero
        _ if dh.num_colors != 0 => dh.num_colors as usize,
        // Or if there are 8 or less bits per pixel
        bpp @ 1 | bpp @ 4 | bpp @ 8 => 1 << bpp,
        _ => return Ok(None)
    };

    let num_bytes = match dh.header_size {
        // Each entry in the color_palette is four bytes for Version 3 or 4
        40 | 108 => 4,
        // Three bytes for Version two. Though, this is currently not supported
        _ => return Err(BmpError::new(UnsupportedBmpVersion, Version2))
    };

    let mut px = &mut [0; 4][0 .. num_bytes as usize];
    let mut color_palette = Vec::with_capacity(num_entries);
    for _ in 0 .. num_entries {
        try!(bmp_data.read(&mut px));
        color_palette.push(px!(px[2], px[1], px[0]));
    }

    Ok(Some(color_palette))
}

fn read_indexes(bmp_data: &mut Vec<u8>, palette: &Vec<Pixel>,
                width: usize, height: usize, bpp: u16, offset: usize) -> BmpResult<Vec<Pixel>> {
    let mut data = Vec::with_capacity(height * width);
    // Number of bytes to read from each row, varies based on bits_per_pixel
    let bytes_per_row = (width as f64 / (8.0 / bpp as f64)).ceil() as usize;
    for y in 0 .. height {
        let padding = match bytes_per_row % 4 {
            0 => 0,
            other => 4 - other
        };
        let start = offset + (bytes_per_row + padding) * y;
        let bytes = &bmp_data[start .. start + bytes_per_row];

        for i in bit_index(&bytes, bpp as usize, width as usize) {
            data.push(palette[i]);
        }
    }
    Ok(data)
}

fn read_pixels(bmp_data: &mut Cursor<Vec<u8>>, width: u32, height: u32,
               offset: u32, padding: i64) -> BmpResult<Vec<Pixel>> {
    let mut data = Vec::with_capacity((height * width) as usize);
    // seek until data
    try!(bmp_data.seek(SeekFrom::Start(offset as u64)));
    // read pixels until padding
    let mut px = [0; 3];
    for _ in 0 .. height {
        for _ in 0 .. width {
            try!(bmp_data.read(&mut px));
            data.push(px!(px[2], px[1], px[0]));
        }
        // seek padding
        try!(bmp_data.seek(SeekFrom::Current(padding)));
    }
    Ok(data)
}

const BITS: usize = 8;

#[derive(Debug)]
struct BitIndex<'a> {
    size: usize,
    nbits: usize,
    bits_left: usize,
    mask: u8,
    bytes: &'a [u8],
    index: usize,
}

fn bit_index<'a>(bytes: &'a [u8], nbits: usize, size: usize) -> BitIndex {
    let bits_left = BITS - nbits;
    BitIndex {
        size: size,
        nbits: nbits,
        bits_left: bits_left,
        mask: (!0 as u8 >> bits_left),
        bytes: bytes,
        index: 0,
    }
}

impl<'a> Iterator for BitIndex<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        let n = self.index / BITS;
        let offset = self.bits_left - self.index % BITS;

        self.index += self.nbits;

        if self.size == 0 {
            None
        } else {
            self.size -= 1;
            self.bytes.get(n).map(|&block|
                ((block & self.mask << offset) >> offset) as usize
            )
        }
    }
}

#[test]
fn test_calculate_bit_index() {
    let bytes = vec![0b1000_0001, 0b1111_0001];

    let mut bi = bit_index(&bytes, 1, 15);
    assert_eq!(bi.next(), Some(1));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(1));
    assert_eq!(bi.next(), Some(1));
    assert_eq!(bi.next(), Some(1));
    assert_eq!(bi.next(), Some(1));
    assert_eq!(bi.next(), Some(1));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), Some(0));
    assert_eq!(bi.next(), None);
    assert_eq!(bi.next(), None);

    let mut bi = bit_index(&bytes, 4, 4);
    assert_eq!(bi.next(), Some(0b1000));
    assert_eq!(bi.next(), Some(0b0001));
    assert_eq!(bi.next(), Some(0b1111));
    assert_eq!(bi.next(), Some(0b0001));
    assert_eq!(bi.next(), None);

    let mut bi = bit_index(&bytes, 8, 2);
    assert_eq!(bi.next(), Some(0b1000_0001));
    assert_eq!(bi.next(), Some(0b1111_0001));
    assert_eq!(bi.next(), None);
}
<|endoftext|>


<commit_before>use std::mem;

macro_rules! boxed {
    [$($x:expr),*] => (Box::new([$($x),*]));
}

macro_rules! collect {
    ($x:expr, $y:ty) => ($x.collect::<Vec<$y>>().into_boxed_slice());
}

type Element = Box<[usize]>;

#[derive(Debug)]
pub struct Polytope<V> {
    dimensions: usize,
    vertices: Box<[V]>,
    elements: Box<[Box<[Element]>]>,
}

impl<V: Default> Polytope<V> {
    pub fn new() -> Self {
        Polytope::<V> {
            dimensions: 0,
            vertices: boxed![V::default()],
            elements: boxed![],
        }
    }
}

impl<V> Polytope<V> {
    pub fn extrude<F1, F2>(&self, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Vertices are a special case: Create a promoted pair of each and linked the pairs.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage element.
            new_edges.push(boxed![i, j]);
        }

        // For the rest of the dimensions, create a pair of each element and linked them via a
        // higher dimensional element.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage element.
                new_elems_next.push(collect!(e.iter().chain([i, j].iter()).cloned(), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }

    pub fn cone<F1, F2>(&self, tip: V, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Create a promoted pair of each vertex and linked all of them to the tip.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        let tip_index = self.vertices.len() * 2;
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage elements.
            new_edges.push(boxed![i, tip_index]);
            new_edges.push(boxed![j, tip_index]);
        }
        new_vertices.push(tip);

        // For the rest of the dimensions, create a pair of each element and linked them to the tip.
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| b * 2 + 1), usize));

                // Linkage elements.
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 0).chain([i].iter().cloned()), usize));
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 1).chain([j].iter().cloned()), usize));
            }
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }
}

#[cfg(test)]
mod tests {
    use element::*;

    #[derive(Debug)]
    struct MyVertex {
        coords: Box<[f64]>,
    }

    impl Default for MyVertex {
        fn default() -> Self {
            MyVertex {
                coords: Box::new([]),
            }
        }
    }

    impl MyVertex {
        fn promote(&self, h: f64) -> Self {
            MyVertex {
                coords: collect!(self.coords.iter().chain([h].iter()).map(|&x| x), f64),
            }
        }
    }

    #[test]
    fn polytope_new() {
        let p = Polytope::<MyVertex>::new();
        assert_eq!(p.dimensions, 0);
        assert_eq!(p.vertices.len(), 1);
        assert_eq!(p.elements.len(), 0);
    }

    #[test]
    fn extrude_point() {
        let p = Polytope::<MyVertex>::new();
        let q = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        assert_eq!(q.dimensions, 1);
        assert_eq!(q.vertices.len(), 2);
        assert!(q.vertices[0].coords == Box::new([-1.0]));
        assert!(q.vertices[1].coords == Box::new([ 1.0]));
        assert_eq!(q.elements.len(), 1);
        assert!(q.elements[0] == Box::new([Box::new([0, 1])]));
    }

    #[test]
    fn extrude_line() {
        let p = Polytope::<MyVertex>::new();
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.extrude(|v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 4);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 1]),
            Box::new([2, 3]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([Box::new([0, 1, 2, 3])]));
    }

    #[test]
    fn cone_line() {
        let p = Polytope::<MyVertex>::new();
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.cone(MyVertex { coords: boxed![0.0, 0.0] },
                       |v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 5);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert!(q.vertices[4].coords == Box::new([ 0.0,  0.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 4]),
            Box::new([1, 4]),
            Box::new([2, 4]),
            Box::new([3, 4]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([
            Box::new([0, 2, 4]),
            Box::new([1, 3, 5]),
        ]));

        let r = q.extrude(|v| v.promote(-3.0), |v| v.promote(3.0));
    }
}
<commit_msg>Add linkage_offset to cone too.<commit_after>use std::mem;

macro_rules! boxed {
    [$($x:expr),*] => (Box::new([$($x),*]));
}

macro_rules! collect {
    ($x:expr, $y:ty) => ($x.collect::<Vec<$y>>().into_boxed_slice());
}

type Element = Box<[usize]>;

#[derive(Debug)]
pub struct Polytope<V> {
    dimensions: usize,
    vertices: Box<[V]>,
    elements: Box<[Box<[Element]>]>,
}

impl<V: Default> Polytope<V> {
    pub fn new() -> Self {
        Polytope::<V> {
            dimensions: 0,
            vertices: boxed![V::default()],
            elements: boxed![],
        }
    }
}

impl<V> Polytope<V> {
    pub fn extrude<F1, F2>(&self, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Vertices are a special case: Create a promoted pair of each and linked the pairs.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage element.
            new_edges.push(boxed![i, j]);
        }

        // For the rest of the dimensions, create a pair of each element and linked them via a
        // higher dimensional element.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage element.
                new_elems_next.push(collect!(e.iter().chain([i, j].iter()).cloned(), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }

    pub fn cone<F1, F2>(&self, tip: V, pull_in: F1, push_out: F2) -> Self
            where F1: Fn(&V) -> V,
                  F2: Fn(&V) -> V {
        // Create a promoted pair of each vertex and linked all of them to the tip.
        let mut new_vertices = Vec::<V>::new();
        let mut new_edges = Vec::<Element>::new();
        let tip_index = self.vertices.len() * 2;
        for v in self.vertices.iter() {
            // Pulled in and pushed out copies.
            let i = new_vertices.len();
            new_vertices.push(pull_in(v));
            let j = new_vertices.len();
            new_vertices.push(push_out(v));

            // Linkage elements.
            new_edges.push(boxed![i, tip_index]);
            new_edges.push(boxed![j, tip_index]);
        }
        new_vertices.push(tip);

        // For the rest of the dimensions, create a pair of each element and linked them to the tip.
        let mut linkage_offset = 0;
        let mut new_elements = Vec::<Vec<Element>>::new();
        let mut new_elems_this = new_edges;
        let mut new_elems_next = Vec::<Element>::new();
        for elems_this in self.elements.iter() {
            let next_linkage_offset = new_elems_this.len();
            for e in elems_this.iter() {
                // Pulled in and pushed out copies.
                let i = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 0), usize));
                let j = new_elems_this.len();
                new_elems_this.push(collect!(e.iter().map(|b| linkage_offset + b * 2 + 1), usize));

                // Linkage elements.
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 0).chain([i].iter().cloned()), usize));
                new_elems_next.push(collect!(
                    e.iter().map(|b| b * 2 + 1).chain([j].iter().cloned()), usize));
            }
            linkage_offset = next_linkage_offset;
            // Reference-safe way of doing
            //   new_elements.push(new_elems_this);
            //   new_elems_this = new_elems_next;
            //   new_elems_next = vec![];
            new_elements.push(
                mem::replace(&mut new_elems_this,
                             mem::replace(&mut new_elems_next, vec![])));
        }
        // Don't forget the final dimension.
        new_elements.push(new_elems_this);

        let new_vertices = new_vertices.into_boxed_slice();
        let new_elements = collect!(new_elements.drain(..).map(
            |mut elements_of_this_dimension|
            collect!(elements_of_this_dimension.drain(..), Element)
        ), Box<[Element]>);
        Polytope::<V> {
            dimensions: self.dimensions + 1,
            vertices: new_vertices,
            elements: new_elements,
        }
    }
}

#[cfg(test)]
mod tests {
    use element::*;

    #[derive(Debug)]
    struct MyVertex {
        coords: Box<[f64]>,
    }

    impl Default for MyVertex {
        fn default() -> Self {
            MyVertex {
                coords: Box::new([]),
            }
        }
    }

    impl MyVertex {
        fn promote(&self, h: f64) -> Self {
            MyVertex {
                coords: collect!(self.coords.iter().chain([h].iter()).map(|&x| x), f64),
            }
        }
    }

    #[test]
    fn polytope_new() {
        let p = Polytope::<MyVertex>::new();
        assert_eq!(p.dimensions, 0);
        assert_eq!(p.vertices.len(), 1);
        assert_eq!(p.elements.len(), 0);
    }

    #[test]
    fn extrude_point() {
        let p = Polytope::<MyVertex>::new();
        let q = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        assert_eq!(q.dimensions, 1);
        assert_eq!(q.vertices.len(), 2);
        assert!(q.vertices[0].coords == Box::new([-1.0]));
        assert!(q.vertices[1].coords == Box::new([ 1.0]));
        assert_eq!(q.elements.len(), 1);
        assert!(q.elements[0] == Box::new([Box::new([0, 1])]));
    }

    #[test]
    fn extrude_line() {
        let p = Polytope::<MyVertex>::new();
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.extrude(|v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 4);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 1]),
            Box::new([2, 3]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([Box::new([0, 1, 2, 3])]));
    }

    #[test]
    fn cone_line() {
        let p = Polytope::<MyVertex>::new();
        let p = p.extrude(|v| v.promote(-1.0), |v| v.promote(1.0));
        let q = p.cone(MyVertex { coords: boxed![0.0, 0.0] },
                       |v| v.promote(-2.0), |v| v.promote(2.0));
        assert_eq!(q.dimensions, 2);
        assert_eq!(q.vertices.len(), 5);
        assert!(q.vertices[0].coords == Box::new([-1.0, -2.0]));
        assert!(q.vertices[1].coords == Box::new([-1.0,  2.0]));
        assert!(q.vertices[2].coords == Box::new([ 1.0, -2.0]));
        assert!(q.vertices[3].coords == Box::new([ 1.0,  2.0]));
        assert!(q.vertices[4].coords == Box::new([ 0.0,  0.0]));
        assert_eq!(q.elements.len(), 2);
        assert!(q.elements[0] == Box::new([
            Box::new([0, 4]),
            Box::new([1, 4]),
            Box::new([2, 4]),
            Box::new([3, 4]),
            Box::new([0, 2]),
            Box::new([1, 3]),
        ]));
        assert!(q.elements[1] == Box::new([
            Box::new([0, 2, 4]),
            Box::new([1, 3, 5]),
        ]));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;
use std::error;
use rustc_serialize;

use super::{Data, StrVal, Bool, VecVal, Map, OptVal};
pub use self::Error::*;

#[derive(Default)]
pub struct Encoder {
    pub data: Vec<Data>,
}

impl Encoder {
    pub fn new() -> Encoder {
        Encoder::default()
    }
}

/// Error type to represent encoding failure.
///
/// This type is not intended to be matched exhaustively as new variants
/// may be added in future without a version bump.
#[derive(Debug)]
pub enum Error {
    NestedOptions,
    UnsupportedType,
    MissingElements,
    KeyIsNotString,
    NoDataToEncode,
    MultipleRootsFound,

    #[doc(hidden)]
    __Nonexhaustive,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        self.description().fmt(f)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            NestedOptions => "nested Option types are not supported",
            UnsupportedType => "unsupported type",
            MissingElements => "no elements in value",
            KeyIsNotString => "key is not a string",
            NoDataToEncode => "the encodable type created no data",
            MultipleRootsFound => {
                "the encodable type emitted data that was not tree-like in structure"
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

pub type EncoderResult = Result<(), Error>;

impl Encoder {
    fn push(&mut self, data: Data) {
        self.data.push(data);
    }

    fn push_ok(&mut self, data: Data) -> EncoderResult {
        self.push(data);
        Ok(())
    }

    fn push_str_ok<T: ToString>(&mut self, data: T) -> EncoderResult {
        self.push(StrVal(data.to_string()));
        Ok(())
    }
}

impl rustc_serialize::Encoder for Encoder {
    type Error = Error;

    fn emit_nil(&mut self) -> EncoderResult {
        Err(UnsupportedType)
    }

    fn emit_isize(&mut self, v: isize) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_usize(&mut self, v: usize) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u64(&mut self, v: u64) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u32(&mut self, v: u32) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u16(&mut self, v: u16) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u8(&mut self, v: u8) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_i64(&mut self, v: i64) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_i32(&mut self, v: i32) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_i16(&mut self, v: i16) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_i8(&mut self, v: i8) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_bool(&mut self, v: bool) -> EncoderResult {
        self.push_ok(Bool(v))
    }

    fn emit_f64(&mut self, v: f64) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_f32(&mut self, v: f32) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_char(&mut self, v: char) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_str(&mut self, v: &str) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_enum<F>(&mut self, _name: &str, _f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_variant<F>(&mut self, _name: &str, _id: usize, _len: usize, _f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, _f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_struct_variant<F>(&mut self,
                                   _v_name: &str,
                                   _v_id: usize,
                                   _len: usize,
                                   _f: F)
                                   -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_struct_variant_field<F>(&mut self,
                                         _f_name: &str,
                                         _f_idx: usize,
                                         _f: F)
                                         -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.push(Map(HashMap::new()));
        f(self)
    }

    fn emit_struct_field<F>(&mut self, name: &str, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        let mut m = match self.data.pop() {
            Some(Map(m)) => m,
            _ => {
                return Err(UnsupportedType);
            }
        };
        try!(f(self));
        let data = match self.data.pop() {
            Some(d) => d,
            _ => {
                return Err(UnsupportedType);
            }
        };
        m.insert(name.to_string(), data);
        self.push_ok(Map(m))
    }

    fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq(len, f)
    }

    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq_elt(idx, f)
    }

    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq(len, f)
    }

    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq_elt(idx, f)
    }

    // Specialized types:
    fn emit_option<F>(&mut self, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        f(self)
    }

    fn emit_option_none(&mut self) -> EncoderResult {
        self.push_ok(OptVal(None))
    }

    fn emit_option_some<F>(&mut self, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        try!(f(self));
        let val = match self.data.pop() {
            Some(OptVal(_)) => return Err(NestedOptions),
            Some(d) => d,
            _ => {
                return Err(UnsupportedType);
            }
        };
        self.push_ok(OptVal(Some(Box::new(val))))
    }

    fn emit_seq<F>(&mut self, _len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.push(VecVal(Vec::new()));
        f(self)
    }

    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        let mut v = match self.data.pop() {
            Some(VecVal(v)) => v,
            _ => {
                return Err(UnsupportedType);
            }
        };
        try!(f(self));
        let data = match self.data.pop() {
            Some(d) => d,
            _ => {
                return Err(UnsupportedType);
            }
        };
        v.push(data);
        self.push_ok(VecVal(v))
    }

    fn emit_map<F>(&mut self, _len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.push(Map(HashMap::new()));
        f(self)
    }

    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        try!(f(self));
        let last = match self.data.last() {
            Some(d) => d,
            None => {
                return Err(MissingElements);
            }
        };
        match *last {
            StrVal(_) => Ok(()),
            _ => Err(KeyIsNotString),
        }
    }

    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        let k = match self.data.pop() {
            Some(StrVal(s)) => s,
            _ => {
                return Err(KeyIsNotString);
            }
        };
        let mut m = match self.data.pop() {
            Some(Map(m)) => m,
            _ => bug!("Expected a map"),
        };
        try!(f(self));
        let popped = match self.data.pop() {
            Some(p) => p,
            None => bug!("Nothing to pop!"),
        };
        m.insert(k, popped);
        self.push(Map(m));
        Ok(())
    }
}

pub fn encode<T: rustc_serialize::Encodable>(data: &T) -> Result<Data, Error> {
    let mut encoder = Encoder::new();
    try!(data.encode(&mut encoder));
    match encoder.data.len() {
        1 => Ok(encoder.data.pop().unwrap()),
        // These two errors are really down to either the type implementing Encodable wrong
        // or using some data which is incompatible with the way mustache *currently* works.
        // It does feel like `bug!` more than Error but maybe it covers some usecases so
        // lets not panic here.
        0 => Err(NoDataToEncode),
        _ => Err(MultipleRootsFound),
    }
}

#[cfg(test)]
mod tests {
    use super::{encode, Error};
    use rustc_serialize::{Encodable, Encoder};

    struct NoData;

    impl Encodable for NoData {
        fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
            Ok(())
        }
    }

    struct Multiroot;

    impl Encodable for Multiroot {
        fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
            try!(s.emit_u32(4));
            s.emit_u32(1)
        }
    }

    #[test]
    fn encodable_with_no_data() {
        assert_let!(Err(Error::NoDataToEncode) = encode(&NoData));
    }

    #[test]
    fn encodable_with_multiple_roots() {
        assert_let!(Err(Error::MultipleRootsFound) = encode(&Multiroot));
    }
}
<commit_msg>refactor(encoder): stop exporting all the Error variants<commit_after>use std::collections::HashMap;
use std::fmt;
use std::error;
use rustc_serialize;

use super::{Data, StrVal, Bool, VecVal, Map, OptVal};
use self::Error::*;

#[derive(Default)]
pub struct Encoder {
    pub data: Vec<Data>,
}

impl Encoder {
    pub fn new() -> Encoder {
        Encoder::default()
    }
}

/// Error type to represent encoding failure.
///
/// This type is not intended to be matched exhaustively as new variants
/// may be added in future without a version bump.
#[derive(Debug)]
pub enum Error {
    NestedOptions,
    UnsupportedType,
    MissingElements,
    KeyIsNotString,
    NoDataToEncode,
    MultipleRootsFound,

    #[doc(hidden)]
    __Nonexhaustive,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        self.description().fmt(f)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            NestedOptions => "nested Option types are not supported",
            UnsupportedType => "unsupported type",
            MissingElements => "no elements in value",
            KeyIsNotString => "key is not a string",
            NoDataToEncode => "the encodable type created no data",
            MultipleRootsFound => {
                "the encodable type emitted data that was not tree-like in structure"
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

pub type EncoderResult = Result<(), Error>;

impl Encoder {
    fn push(&mut self, data: Data) {
        self.data.push(data);
    }

    fn push_ok(&mut self, data: Data) -> EncoderResult {
        self.push(data);
        Ok(())
    }

    fn push_str_ok<T: ToString>(&mut self, data: T) -> EncoderResult {
        self.push(StrVal(data.to_string()));
        Ok(())
    }
}

impl rustc_serialize::Encoder for Encoder {
    type Error = Error;

    fn emit_nil(&mut self) -> EncoderResult {
        Err(UnsupportedType)
    }

    fn emit_isize(&mut self, v: isize) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_usize(&mut self, v: usize) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u64(&mut self, v: u64) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u32(&mut self, v: u32) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u16(&mut self, v: u16) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_u8(&mut self, v: u8) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_i64(&mut self, v: i64) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_i32(&mut self, v: i32) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_i16(&mut self, v: i16) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_i8(&mut self, v: i8) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_bool(&mut self, v: bool) -> EncoderResult {
        self.push_ok(Bool(v))
    }

    fn emit_f64(&mut self, v: f64) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_f32(&mut self, v: f32) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_char(&mut self, v: char) -> EncoderResult {
        self.push_str_ok(v)
    }
    fn emit_str(&mut self, v: &str) -> EncoderResult {
        self.push_str_ok(v)
    }

    fn emit_enum<F>(&mut self, _name: &str, _f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_variant<F>(&mut self, _name: &str, _id: usize, _len: usize, _f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, _f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_struct_variant<F>(&mut self,
                                   _v_name: &str,
                                   _v_id: usize,
                                   _len: usize,
                                   _f: F)
                                   -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_enum_struct_variant_field<F>(&mut self,
                                         _f_name: &str,
                                         _f_idx: usize,
                                         _f: F)
                                         -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        Err(UnsupportedType)
    }

    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.push(Map(HashMap::new()));
        f(self)
    }

    fn emit_struct_field<F>(&mut self, name: &str, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        let mut m = match self.data.pop() {
            Some(Map(m)) => m,
            _ => {
                return Err(UnsupportedType);
            }
        };
        try!(f(self));
        let data = match self.data.pop() {
            Some(d) => d,
            _ => {
                return Err(UnsupportedType);
            }
        };
        m.insert(name.to_string(), data);
        self.push_ok(Map(m))
    }

    fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq(len, f)
    }

    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq_elt(idx, f)
    }

    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq(len, f)
    }

    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.emit_seq_elt(idx, f)
    }

    // Specialized types:
    fn emit_option<F>(&mut self, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        f(self)
    }

    fn emit_option_none(&mut self) -> EncoderResult {
        self.push_ok(OptVal(None))
    }

    fn emit_option_some<F>(&mut self, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        try!(f(self));
        let val = match self.data.pop() {
            Some(OptVal(_)) => return Err(NestedOptions),
            Some(d) => d,
            _ => {
                return Err(UnsupportedType);
            }
        };
        self.push_ok(OptVal(Some(Box::new(val))))
    }

    fn emit_seq<F>(&mut self, _len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.push(VecVal(Vec::new()));
        f(self)
    }

    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        let mut v = match self.data.pop() {
            Some(VecVal(v)) => v,
            _ => {
                return Err(UnsupportedType);
            }
        };
        try!(f(self));
        let data = match self.data.pop() {
            Some(d) => d,
            _ => {
                return Err(UnsupportedType);
            }
        };
        v.push(data);
        self.push_ok(VecVal(v))
    }

    fn emit_map<F>(&mut self, _len: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        self.push(Map(HashMap::new()));
        f(self)
    }

    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        try!(f(self));
        let last = match self.data.last() {
            Some(d) => d,
            None => {
                return Err(MissingElements);
            }
        };
        match *last {
            StrVal(_) => Ok(()),
            _ => Err(KeyIsNotString),
        }
    }

    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncoderResult
    where F: FnOnce(&mut Encoder) -> EncoderResult
    {
        let k = match self.data.pop() {
            Some(StrVal(s)) => s,
            _ => {
                return Err(KeyIsNotString);
            }
        };
        let mut m = match self.data.pop() {
            Some(Map(m)) => m,
            _ => bug!("Expected a map"),
        };
        try!(f(self));
        let popped = match self.data.pop() {
            Some(p) => p,
            None => bug!("Nothing to pop!"),
        };
        m.insert(k, popped);
        self.push(Map(m));
        Ok(())
    }
}

pub fn encode<T: rustc_serialize::Encodable>(data: &T) -> Result<Data, Error> {
    let mut encoder = Encoder::new();
    try!(data.encode(&mut encoder));
    match encoder.data.len() {
        1 => Ok(encoder.data.pop().unwrap()),
        // These two errors are really down to either the type implementing Encodable wrong
        // or using some data which is incompatible with the way mustache *currently* works.
        // It does feel like `bug!` more than Error but maybe it covers some usecases so
        // lets not panic here.
        0 => Err(NoDataToEncode),
        _ => Err(MultipleRootsFound),
    }
}

#[cfg(test)]
mod tests {
    use super::{encode, Error};
    use rustc_serialize::{Encodable, Encoder};

    struct NoData;

    impl Encodable for NoData {
        fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
            Ok(())
        }
    }

    struct Multiroot;

    impl Encodable for Multiroot {
        fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
            try!(s.emit_u32(4));
            s.emit_u32(1)
        }
    }

    #[test]
    fn encodable_with_no_data() {
        assert_let!(Err(Error::NoDataToEncode) = encode(&NoData));
    }

    #[test]
    fn encodable_with_multiple_roots() {
        assert_let!(Err(Error::MultipleRootsFound) = encode(&Multiroot));
    }
}
<|endoftext|>


<commit_before>use lalafell::commands::MentionOrId;

use serenity::model::guild::{Member, Role};

use std::borrow::Borrow;

pub enum Filter {
  Include(FilterKind),
  Exclude(FilterKind)
}

impl Filter {
  fn find_all_filters(input: &str) -> Option<Vec<String>> {
    let mut roles = Vec::new();
    let mut last_index = 0;
    loop {
      let index = input[last_index..].find("role:").or_else(|| input[last_index..].find("user:"));
      let mut i = some_or!(index, break);
      if i + last_index != 0 && &input[i + last_index - 1..i + last_index] == "!" {
        i -= 1;
      }
      if !input[last_index..last_index + i].trim().is_empty() {
        return None;
      }
      if let Some((bytes, role)) = Filter::lexical_parse(&input[last_index + i..]) {
        last_index += bytes;
        roles.push(role);
      }
      last_index += i;
    }
    if input.len() - last_index != 0 {
      None
    } else {
      Some(roles)
    }
  }

  fn lexical_parse(input: &str) -> Option<(usize, String)> {
    let mut consumed_bytes = 0;
    let mut acc = String::new();
    let mut escaped = false;
    let mut take_whitespace = false;
    for c in input.chars() {
      if c == '`' {
        consumed_bytes += c.len_utf8();
        if take_whitespace {
          break;
        } else {
          take_whitespace = true;
          continue;
        }
      }
      if c == '\\' && !escaped {
        consumed_bytes += c.len_utf8();
        escaped = true;
        continue;
      }
      if escaped {
        acc.push(c);
        consumed_bytes += c.len_utf8();
        escaped = false;
        continue;
      }
      if !take_whitespace && c == ' ' {
        break;
      }
      acc.push(c);
      consumed_bytes += c.len_utf8();
    }
    if acc.is_empty() {
      None
    } else {
      Some((consumed_bytes, acc))
    }
  }

  pub fn all_filters(s: &str) -> Option<Vec<Filter>> {
    Filter::find_all_filters(s)?
      .into_iter()
      .map(|x| Filter::parse(&x))
      .collect()
  }

  pub fn parse(s: &str) -> Option<Filter> {
    if s.starts_with('!') {
      FilterKind::parse(&s[1..]).map(Filter::Exclude)
    } else {
      FilterKind::parse(s).map(Filter::Include)
    }
  }

  pub fn matches<I: Borrow<Role>>(&self, member: &Member, roles: &[I]) -> bool {
    let (include, fk) = match *self {
      Filter::Include(ref fk) => (true, fk),
      Filter::Exclude(ref fk) => (false, fk)
    };
    let roles: Vec<&Role> = roles.iter().map(|x| x.borrow()).collect();
    match *fk {
      FilterKind::Role(ref role_name) => {
        let role_name = role_name.to_lowercase();
        let role = match roles.iter().find(|r| r.name.to_lowercase() == role_name) {
          Some(r) => r,
          None => return !include
        };
        member.roles.iter().any(|r| *r == role.id) == include
      }
      FilterKind::User(id) => (member.user.read().id.0 == id) == include
    }
  }
}

impl ToString for Filter {
  fn to_string(&self) -> String {
    match *self {
      Filter::Include(ref fk) => fk.to_string(),
      Filter::Exclude(ref fk) => format!("!{}", fk.to_string())
    }
  }
}

pub enum FilterKind {
  Role(String),
  User(u64)
}

impl FilterKind {
  pub fn parse(s: &str) -> Option<FilterKind> {
    let parts: Vec<&str> = s.splitn(2, ':').collect();
    if parts.len() != 2 {
      return None;
    }
    let (kind, value) = (&parts[0], &parts[1]);
    match kind.to_lowercase().as_str() {
      "role" => Some(FilterKind::Role(value.to_string())),
      "user" | "member" => {
        let id = MentionOrId::parse(value).ok()?;
        Some(FilterKind::User(id.0))
      }
      _ => None
    }
  }
}

impl ToString for FilterKind {
  fn to_string(&self) -> String {
    match *self {
      FilterKind::Role(ref role) => format!("role:{}", role),
      FilterKind::User(id) => format!("user:{}", id)
    }
  }
}
<commit_msg>fix: properly escape roles in FilterKind<commit_after>use lalafell::commands::MentionOrId;

use serenity::model::guild::{Member, Role};

use std::borrow::Borrow;

pub enum Filter {
  Include(FilterKind),
  Exclude(FilterKind)
}

impl Filter {
  fn find_all_filters(input: &str) -> Option<Vec<String>> {
    let mut roles = Vec::new();
    let mut last_index = 0;
    loop {
      let index = input[last_index..].find("role:").or_else(|| input[last_index..].find("user:"));
      let mut i = some_or!(index, break);
      if i + last_index != 0 && &input[i + last_index - 1..i + last_index] == "!" {
        i -= 1;
      }
      if !input[last_index..last_index + i].trim().is_empty() {
        return None;
      }
      if let Some((bytes, role)) = Filter::lexical_parse(&input[last_index + i..]) {
        last_index += bytes;
        roles.push(role);
      }
      last_index += i;
    }
    if input.len() - last_index != 0 {
      None
    } else {
      Some(roles)
    }
  }

  fn lexical_parse(input: &str) -> Option<(usize, String)> {
    let mut consumed_bytes = 0;
    let mut acc = String::new();
    let mut escaped = false;
    let mut take_whitespace = false;
    for c in input.chars() {
      if c == '`' {
        consumed_bytes += c.len_utf8();
        if take_whitespace {
          break;
        } else {
          take_whitespace = true;
          continue;
        }
      }
      if c == '\\' && !escaped {
        consumed_bytes += c.len_utf8();
        escaped = true;
        continue;
      }
      if escaped {
        acc.push(c);
        consumed_bytes += c.len_utf8();
        escaped = false;
        continue;
      }
      if !take_whitespace && c == ' ' {
        break;
      }
      acc.push(c);
      consumed_bytes += c.len_utf8();
    }
    if acc.is_empty() {
      None
    } else {
      Some((consumed_bytes, acc))
    }
  }

  pub fn all_filters(s: &str) -> Option<Vec<Filter>> {
    Filter::find_all_filters(s)?
      .into_iter()
      .map(|x| Filter::parse(&x))
      .collect()
  }

  pub fn parse(s: &str) -> Option<Filter> {
    if s.starts_with('!') {
      FilterKind::parse(&s[1..]).map(Filter::Exclude)
    } else {
      FilterKind::parse(s).map(Filter::Include)
    }
  }

  pub fn matches<I: Borrow<Role>>(&self, member: &Member, roles: &[I]) -> bool {
    let (include, fk) = match *self {
      Filter::Include(ref fk) => (true, fk),
      Filter::Exclude(ref fk) => (false, fk)
    };
    let roles: Vec<&Role> = roles.iter().map(|x| x.borrow()).collect();
    match *fk {
      FilterKind::Role(ref role_name) => {
        let role_name = role_name.to_lowercase();
        let role = match roles.iter().find(|r| r.name.to_lowercase() == role_name) {
          Some(r) => r,
          None => return !include
        };
        member.roles.iter().any(|r| *r == role.id) == include
      }
      FilterKind::User(id) => (member.user.read().id.0 == id) == include
    }
  }
}

impl ToString for Filter {
  fn to_string(&self) -> String {
    match *self {
      Filter::Include(ref fk) => fk.to_string(),
      Filter::Exclude(ref fk) => format!("!{}", fk.to_string())
    }
  }
}

pub enum FilterKind {
  Role(String),
  User(u64)
}

impl FilterKind {
  pub fn parse(s: &str) -> Option<FilterKind> {
    let parts: Vec<&str> = s.splitn(2, ':').collect();
    if parts.len() != 2 {
      return None;
    }
    let (kind, value) = (&parts[0], &parts[1]);
    match kind.to_lowercase().as_str() {
      "role" => Some(FilterKind::Role(value.to_string())),
      "user" | "member" => {
        let id = MentionOrId::parse(value).ok()?;
        Some(FilterKind::User(id.0))
      }
      _ => None
    }
  }
}

impl ToString for FilterKind {
  fn to_string(&self) -> String {
    match *self {
      FilterKind::Role(ref role) if role.contains(' ') => format!("role:`{}`", role),
      FilterKind::Role(ref role) => format!("role:{}", role),
      FilterKind::User(id) => format!("user:{}", id)
    }
  }
}
<|endoftext|>