<commit_before>
use rusqlite::Connection;
use rusqlite;

use folders::{Folders,Folder,RootFolder};
use fromdb::FromDb;
use images::Image;
use keyword::Keyword;
use libraryfile::LibraryFile;

const LR3_VERSION: &str = "0300025";
const LR4_VERSION: &str = "0400020";

/// Catalog version.
#[derive(Debug,PartialEq)]
pub enum CatalogVersion {
    Unknown,
    Lr3,
    Lr4
}

pub struct Catalog {
    /// catalog path
    path: String,
    pub version: String,
    pub catalog_version: CatalogVersion,
    pub root_keyword_id: f64,

    keywords: Vec<Keyword>,
    folders: Folders,
    images: Vec<Image>,
    libfiles: Vec<LibraryFile>,

    dbconn: Option<Connection>,
}

impl Catalog {

    pub fn new(path: &str) -> Catalog {
        Catalog {
            path: String::from(path),
            version: String::from(""),
            catalog_version: CatalogVersion::Unknown,
            root_keyword_id: 0.0,
            keywords: vec!(),
            folders: Folders::new(),
            images: vec!(),
            libfiles: vec!(),
            dbconn: None
        }
    }

    pub fn open(&mut self) -> bool {
        let conn_attempt = Connection::open(&self.path);
        if let Ok(conn) = conn_attempt {
            self.dbconn = Some(conn);

            return true;
        }

        false
    }

    pub fn get_variable<T>(&self, name: &str) -> Option<T>
        where T: rusqlite::types::FromSql {

        if let Some(ref conn) = self.dbconn {
            if let Ok(mut stmt) = conn.prepare("SELECT value FROM Adobe_variablesTable WHERE name=?1") {
                let mut rows = stmt.query(&[&name]).unwrap();
                if let Some(Ok(row)) = rows.next() {
                    return Some(row.get(0));
                }
            }
        }
        None
    }

    pub fn load_version(&mut self) {
        if let Some(version) = self.get_variable::<String>("Adobe_DBVersion") {
            self.version = version;
            self.catalog_version = match self.version.as_str() {
                LR4_VERSION =>
                    CatalogVersion::Lr4,
                LR3_VERSION =>
                    CatalogVersion::Lr3,
                _ =>
                    CatalogVersion::Unknown
            };
        }

        if let Some(root_keyword_id) =
            self.get_variable::<f64>("AgLibraryKeyword_rootTagID") {
                self.root_keyword_id = root_keyword_id;
            }
    }

    pub fn load_objects<T: FromDb>(conn: &Connection) -> Vec<T> {
        let mut result: Vec<T> = vec!();
        let query = format!("SELECT {} FROM {}",
                            T::read_db_columns(),
                            T::read_db_tables());
        if let Ok(mut stmt) = conn.prepare(&query) {
            let mut rows = stmt.query(&[]).unwrap();
            while let Some(Ok(row)) = rows.next() {
                if let Some(object) = T::read_from(&row) {
                    result.push(object);
                }
            }
        }
        result
    }

    pub fn load_keywords(&mut self) -> &Vec<Keyword> {
        if self.keywords.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let mut result = Catalog::load_objects::<Keyword>(&conn);
                self.keywords.append(&mut result);
            }
        }
        return &self.keywords;
    }

    pub fn load_folders(&mut self) -> &Folders {
        if self.folders.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let folders = Catalog::load_objects::<RootFolder>(&conn);
                self.folders.append_root_folders(folders);
                let folders = Catalog::load_objects::<Folder>(&conn);
                self.folders.append_folders(folders);
            }
        }
        return &self.folders;
    }

    pub fn load_library_files(&mut self) -> &Vec<LibraryFile> {
        if self.libfiles.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let mut result = Catalog::load_objects::<LibraryFile>(&conn);
                self.libfiles.append(&mut result);
            }
        }
        return &self.libfiles;
    }

    pub fn load_images(&mut self) -> &Vec<Image> {
        if self.images.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let mut result = Catalog::load_objects::<Image>(&conn);
                self.images.append(&mut result);
            }
        }
        return &self.images;
    }
}
<commit_msg>Properly parse version<commit_after>
use rusqlite::Connection;
use rusqlite;

use folders::{Folders,Folder,RootFolder};
use fromdb::FromDb;
use images::Image;
use keyword::Keyword;
use libraryfile::LibraryFile;

const LR3_VERSION: i32 = 3;
const LR4_VERSION: i32 = 4;

/// Catalog version.
#[derive(Debug,PartialEq)]
pub enum CatalogVersion {
    Unknown,
    Lr3,
    Lr4
}

pub struct Catalog {
    /// catalog path
    path: String,
    pub version: String,
    pub catalog_version: CatalogVersion,
    pub root_keyword_id: f64,

    keywords: Vec<Keyword>,
    folders: Folders,
    images: Vec<Image>,
    libfiles: Vec<LibraryFile>,

    dbconn: Option<Connection>,
}

impl Catalog {

    pub fn new(path: &str) -> Catalog {
        Catalog {
            path: String::from(path),
            version: String::from(""),
            catalog_version: CatalogVersion::Unknown,
            root_keyword_id: 0.0,
            keywords: vec!(),
            folders: Folders::new(),
            images: vec!(),
            libfiles: vec!(),
            dbconn: None
        }
    }

    pub fn open(&mut self) -> bool {
        let conn_attempt = Connection::open(&self.path);
        if let Ok(conn) = conn_attempt {
            self.dbconn = Some(conn);

            return true;
        }

        false
    }

    pub fn get_variable<T>(&self, name: &str) -> Option<T>
        where T: rusqlite::types::FromSql {

        if let Some(ref conn) = self.dbconn {
            if let Ok(mut stmt) = conn.prepare("SELECT value FROM Adobe_variablesTable WHERE name=?1") {
                let mut rows = stmt.query(&[&name]).unwrap();
                if let Some(Ok(row)) = rows.next() {
                    return Some(row.get(0));
                }
            }
        }
        None
    }

    fn parse_version(mut v: String) -> i32 {
        v.truncate(2);
        if let Ok(version) = v.parse::<i32>() {
            version
        } else {
            0
        }
    }

    pub fn load_version(&mut self) {
        if let Some(version) = self.get_variable::<String>("Adobe_DBVersion") {
            self.version = version;
            let v = Catalog::parse_version(self.version.clone());
            self.catalog_version = match v {
                LR4_VERSION =>
                    CatalogVersion::Lr4,
                LR3_VERSION =>
                    CatalogVersion::Lr3,
                _ =>
                    CatalogVersion::Unknown
            };
        }

        if let Some(root_keyword_id) =
            self.get_variable::<f64>("AgLibraryKeyword_rootTagID") {
                self.root_keyword_id = root_keyword_id;
            }
    }

    pub fn load_objects<T: FromDb>(conn: &Connection) -> Vec<T> {
        let mut result: Vec<T> = vec!();
        let query = format!("SELECT {} FROM {}",
                            T::read_db_columns(),
                            T::read_db_tables());
        if let Ok(mut stmt) = conn.prepare(&query) {
            let mut rows = stmt.query(&[]).unwrap();
            while let Some(Ok(row)) = rows.next() {
                if let Some(object) = T::read_from(&row) {
                    result.push(object);
                }
            }
        }
        result
    }

    pub fn load_keywords(&mut self) -> &Vec<Keyword> {
        if self.keywords.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let mut result = Catalog::load_objects::<Keyword>(&conn);
                self.keywords.append(&mut result);
            }
        }
        return &self.keywords;
    }

    pub fn load_folders(&mut self) -> &Folders {
        if self.folders.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let folders = Catalog::load_objects::<RootFolder>(&conn);
                self.folders.append_root_folders(folders);
                let folders = Catalog::load_objects::<Folder>(&conn);
                self.folders.append_folders(folders);
            }
        }
        return &self.folders;
    }

    pub fn load_library_files(&mut self) -> &Vec<LibraryFile> {
        if self.libfiles.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let mut result = Catalog::load_objects::<LibraryFile>(&conn);
                self.libfiles.append(&mut result);
            }
        }
        return &self.libfiles;
    }

    pub fn load_images(&mut self) -> &Vec<Image> {
        if self.images.is_empty() {
            if let Some(ref conn) = self.dbconn {
                let mut result = Catalog::load_objects::<Image>(&conn);
                self.images.append(&mut result);
            }
        }
        return &self.images;
    }
}
<|endoftext|>


<commit_before>use configuration::Configuration;
use std::slice::SliceExt;
use std::cmp::{Ordering, min};
use score::Score;

#[derive(Debug)]
pub struct Search {
    pub config: Configuration,
    current: usize,
    pub query: String,
    pub selection: Option<String>,
    pub result: Vec<String>,
    done: bool,
}

impl Search {
    pub fn blank(config: Configuration) -> Search {
        let query = config.initial_search.clone();
        let previous_result = config.choices.clone();
        Search::new(config, query, previous_result, 0, false)
    }

    pub fn is_done(&self) -> bool {
        self.done
    }

    pub fn done(self) -> Search {
        Search::new(self.config, self.query, self.result, self.current, true)
    }

    fn new(config: Configuration, query: String, result: Vec<String>, index: usize, done: bool) -> Search {

        let selection = Search::select(&result, index);

        Search { config: config,
                 current: index,
                 query: query,
                 selection: selection,
                 result: result,
                 done: done}
    }

    fn new_for_index(self, index: usize) -> Search {
        Search::new(self.config, self.query, self.result, index, self.done)
    }

    fn new_for_query(self, new_query: String) -> Search {
        let new_result = Search::filter(new_query.as_slice(), &self.config.choices);

        Search::new(self.config, new_query, new_result, 0, self.done)
    }

    fn filter(query: &str, choices: &Vec<String>) -> Vec<String> {
        let mut filtered = choices.iter().filter_map( |choice| {
            let quality = Score::score(choice.as_slice(), query);
            if quality > 0.0 {
                Some((quality, choice.to_string()))
            } else {
                None
            }
        }).collect::<Vec<(f32, String)>>();

        filtered.sort_by( |&(quality_a, _), &(quality_b, _)| {
            quality_a.partial_cmp(&quality_b).unwrap_or(Ordering::Equal).reverse()
        });

        filtered.iter().map( |&(_, ref choice)| choice.to_string() ).collect::<Vec<String>>()
    }

    fn select(result: &Vec<String>, index: usize) -> Option<String> {
        if result.len() > 0 {
            Some(result[index].to_string())
        } else {
            None
        }
    }

    pub fn down(self) -> Search {
        let next_index = self.next_index();
        self.new_for_index(next_index)
    }

    pub fn up(self) -> Search {
        let next_index = self.prev_index();
        self.new_for_index(next_index)
    }

    pub fn append_to_search(self, input: &str) -> Search {
        let mut new_query = self.query.clone();
        new_query.push_str(input.as_slice());

        self.new_for_query(new_query)
    }

    pub fn backspace(self) -> Search {
        let mut new_query = self.query.clone();
        new_query.pop();

        self.new_for_query(new_query)
    }

    fn next_index(&self) -> usize {
        let next_index = self.current + 1;

        if next_index >= self.actual_limit() {
            0
        } else {
            next_index
        }
    }

    fn prev_index(&self) -> usize {
        if self.current == 0 {
            self.actual_limit() - 1
        } else {
            self.current - 1
        }
    }

    fn actual_limit(&self) -> usize {
        min(self.config.visible_limit, self.result.len())
    }
}

#[cfg(test)]
mod tests {
    use configuration::Configuration;
    use super::*;

    fn one_two_three() -> Vec<String> {
        vec!["one".to_string(),
             "two".to_string(),
             "three".to_string()]
    }

    #[test]
    fn it_selects_the_first_choice_by_default() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn it_selets_the_second_when_down_is_called() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_end_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_top_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.up().up().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_visible_limit() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, Some(2));
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").down().selection, Some("three".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results_twice() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").append_to_search("w").selection, Some("two".to_string()));
    }

    #[test]
    fn it_handles_not_matching_anything() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("x").selection, None);
    }

    #[test]
    fn up_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.up().selection, None);
    }

    #[test]
    fn down_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.down().selection, None);
    }

    #[test]
    fn backspaces_over_characters() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.query, "e");
        assert_eq!(search.backspace().query, "");
    }

    #[test]
    fn resets_the_index_when_removing_char_from_search() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.down().backspace().current, 0);
    }

    #[test]
    fn resets_the_index_when_adding_char_to_seach() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).down();

        assert_eq!(search.append_to_search("o").current, 0);
    }

    #[test]
    fn previous_results_appear_after_backspace() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("t");

        assert_eq!(search.backspace().result.len(), 3);
    }

    #[test]
    fn initial_search_is_not_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert!(!search.is_done());
    }

    #[test]
    fn done_search_is_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert!(search.is_done());
    }

    #[test]
    fn done_search_has_selection() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_bottom_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").down();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_top_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").up();

        assert_eq!(search.selection, Some("one".to_string()));
    }
}
<commit_msg>adds benchmark for filter<commit_after>use configuration::Configuration;
use std::slice::SliceExt;
use std::cmp::{Ordering, min};
use score::Score;

#[derive(Debug)]
pub struct Search {
    pub config: Configuration,
    current: usize,
    pub query: String,
    pub selection: Option<String>,
    pub result: Vec<String>,
    done: bool,
}

impl Search {
    pub fn blank(config: Configuration) -> Search {
        let query = config.initial_search.clone();
        let previous_result = config.choices.clone();
        Search::new(config, query, previous_result, 0, false)
    }

    pub fn is_done(&self) -> bool {
        self.done
    }

    pub fn done(self) -> Search {
        Search::new(self.config, self.query, self.result, self.current, true)
    }

    fn new(config: Configuration, query: String, result: Vec<String>, index: usize, done: bool) -> Search {

        let selection = Search::select(&result, index);

        Search { config: config,
                 current: index,
                 query: query,
                 selection: selection,
                 result: result,
                 done: done}
    }

    fn new_for_index(self, index: usize) -> Search {
        Search::new(self.config, self.query, self.result, index, self.done)
    }

    fn new_for_query(self, new_query: String) -> Search {
        let new_result = Search::filter(new_query.as_slice(), &self.config.choices);

        Search::new(self.config, new_query, new_result, 0, self.done)
    }

    pub fn filter(query: &str, choices: &Vec<String>) -> Vec<String> {
        let mut filtered = choices.iter().filter_map( |choice| {
            let quality = Score::score(choice.as_slice(), query);
            if quality > 0.0 {
                Some((quality, choice.to_string()))
            } else {
                None
            }
        }).collect::<Vec<(f32, String)>>();

        filtered.sort_by( |&(quality_a, _), &(quality_b, _)| {
            quality_a.partial_cmp(&quality_b).unwrap_or(Ordering::Equal).reverse()
        });

        filtered.iter().map( |&(_, ref choice)| choice.to_string() ).collect::<Vec<String>>()
    }

    fn select(result: &Vec<String>, index: usize) -> Option<String> {
        if result.len() > 0 {
            Some(result[index].to_string())
        } else {
            None
        }
    }

    pub fn down(self) -> Search {
        let next_index = self.next_index();
        self.new_for_index(next_index)
    }

    pub fn up(self) -> Search {
        let next_index = self.prev_index();
        self.new_for_index(next_index)
    }

    pub fn append_to_search(self, input: &str) -> Search {
        let mut new_query = self.query.clone();
        new_query.push_str(input.as_slice());

        self.new_for_query(new_query)
    }

    pub fn backspace(self) -> Search {
        let mut new_query = self.query.clone();
        new_query.pop();

        self.new_for_query(new_query)
    }

    fn next_index(&self) -> usize {
        let next_index = self.current + 1;

        if next_index >= self.actual_limit() {
            0
        } else {
            next_index
        }
    }

    fn prev_index(&self) -> usize {
        if self.current == 0 {
            self.actual_limit() - 1
        } else {
            self.current - 1
        }
    }

    fn actual_limit(&self) -> usize {
        min(self.config.visible_limit, self.result.len())
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use configuration::Configuration;
    use super::*;
    use self::test::Bencher;

    fn one_two_three() -> Vec<String> {
        vec!["one".to_string(),
             "two".to_string(),
             "three".to_string()]
    }

    #[test]
    fn it_selects_the_first_choice_by_default() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn it_selets_the_second_when_down_is_called() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_end_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_top_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.up().up().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_visible_limit() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, Some(2));
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").down().selection, Some("three".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results_twice() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").append_to_search("w").selection, Some("two".to_string()));
    }

    #[test]
    fn it_handles_not_matching_anything() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("x").selection, None);
    }

    #[test]
    fn up_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.up().selection, None);
    }

    #[test]
    fn down_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.down().selection, None);
    }

    #[test]
    fn backspaces_over_characters() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.query, "e");
        assert_eq!(search.backspace().query, "");
    }

    #[test]
    fn resets_the_index_when_removing_char_from_search() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.down().backspace().current, 0);
    }

    #[test]
    fn resets_the_index_when_adding_char_to_seach() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).down();

        assert_eq!(search.append_to_search("o").current, 0);
    }

    #[test]
    fn previous_results_appear_after_backspace() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("t");

        assert_eq!(search.backspace().result.len(), 3);
    }

    #[test]
    fn initial_search_is_not_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert!(!search.is_done());
    }

    #[test]
    fn done_search_is_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert!(search.is_done());
    }

    #[test]
    fn done_search_has_selection() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_bottom_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").down();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_top_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").up();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    fn input_times(n: usize) -> Vec<String> {
        let mut result: Vec<String> = Vec::new();
        for thing in one_two_three().iter().cycle().take(n) {
            result.push(thing.clone());
        }
        result
    }

    //254344 ns/iter (+/- 57744)
    #[bench]
    fn filter_speed(b: &mut Bencher) {
        let input = input_times(1000);
        let query = "t";

        b.iter(||{
            Search::filter(query, &input)
        });
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use fnv::FnvHasher;
use layer::{Layer, ScrollingState};
use std::collections::{HashMap, HashSet};
use std::hash::BuildHasherDefault;
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, PipelineId};
use webrender_traits::{ScrollEventPhase, ScrollLayerId, ScrollLayerInfo, ScrollLayerPixel};
use webrender_traits::{ScrollLayerRect, ScrollLayerState, ScrollLocation, ScrollToWorldTransform};
use webrender_traits::{ServoScrollRootId, WorldPoint, as_scroll_parent_rect};

pub type ScrollStates = HashMap<ScrollLayerId, ScrollingState, BuildHasherDefault<FnvHasher>>;

pub struct ScrollTree {
    pub layers: HashMap<ScrollLayerId, Layer, BuildHasherDefault<FnvHasher>>,
    pub pending_scroll_offsets: HashMap<(PipelineId, ServoScrollRootId), LayerPoint>,
    pub current_scroll_layer_id: Option<ScrollLayerId>,
    pub current_reference_frame_id: usize,

    /// The root reference frame, which is the true root of the ScrollTree. Initially
    /// this ID is not valid, which is indicated by ```layers``` being empty.
    pub root_reference_frame_id: ScrollLayerId,

    /// The root scroll layer, which is the first child of the root reference frame.
    /// Initially this ID is not valid, which is indicated by ```layers``` being empty.
    pub topmost_scroll_layer_id: ScrollLayerId,
}

impl ScrollTree {
    pub fn new() -> ScrollTree {
        let dummy_pipeline = PipelineId(0, 0);
        ScrollTree {
            layers: HashMap::with_hasher(Default::default()),
            pending_scroll_offsets: HashMap::new(),
            current_scroll_layer_id: None,
            root_reference_frame_id: ScrollLayerId::root_reference_frame(dummy_pipeline),
            topmost_scroll_layer_id: ScrollLayerId::root_scroll_layer(dummy_pipeline),
            current_reference_frame_id: 1,
        }
    }

    pub fn root_reference_frame_id(&self) -> ScrollLayerId {
        // TODO(mrobinson): We should eventually make this impossible to misuse.
        debug_assert!(!self.layers.is_empty());
        debug_assert!(self.layers.contains_key(&self.root_reference_frame_id));
        self.root_reference_frame_id
    }

    pub fn topmost_scroll_layer_id(&self) -> ScrollLayerId {
        // TODO(mrobinson): We should eventually make this impossible to misuse.
        debug_assert!(!self.layers.is_empty());
        debug_assert!(self.layers.contains_key(&self.topmost_scroll_layer_id));
        self.topmost_scroll_layer_id
    }

    pub fn establish_root(&mut self,
                          pipeline_id: PipelineId,
                          viewport_size: &LayerSize,
                          content_size: &LayerSize) {
        debug_assert!(self.layers.is_empty());

        let identity = LayerToScrollTransform::identity();
        let viewport = LayerRect::new(LayerPoint::zero(), *viewport_size);

        let root_reference_frame_id = ScrollLayerId::root_reference_frame(pipeline_id);
        self.root_reference_frame_id = root_reference_frame_id;
        let reference_frame = Layer::new(&viewport, viewport.size, &identity, pipeline_id);
        self.layers.insert(self.root_reference_frame_id, reference_frame);

        let scroll_layer = Layer::new(&viewport, *content_size, &identity, pipeline_id);
        let topmost_scroll_layer_id = ScrollLayerId::root_scroll_layer(pipeline_id);
        self.topmost_scroll_layer_id = topmost_scroll_layer_id;
        self.add_layer(scroll_layer, topmost_scroll_layer_id, root_reference_frame_id);
    }

    pub fn collect_layers_bouncing_back(&self)
                                        -> HashSet<ScrollLayerId, BuildHasherDefault<FnvHasher>> {
        let mut layers_bouncing_back = HashSet::with_hasher(Default::default());
        for (scroll_layer_id, layer) in self.layers.iter() {
            if layer.scrolling.bouncing_back {
                layers_bouncing_back.insert(*scroll_layer_id);
            }
        }
        layers_bouncing_back
    }

    fn find_scrolling_layer_at_point_in_layer(&self,
                                              cursor: &WorldPoint,
                                              scroll_layer_id: ScrollLayerId)
                                              -> Option<ScrollLayerId> {
        self.layers.get(&scroll_layer_id).and_then(|layer| {
            for child_layer_id in layer.children.iter().rev() {
            if let Some(layer_id) =
                self.find_scrolling_layer_at_point_in_layer(cursor, *child_layer_id) {
                    return Some(layer_id);
                }
            }

            if let ScrollLayerInfo::ReferenceFrame(_) = scroll_layer_id.info {
                return None;
            }

            if layer.ray_intersects_layer(cursor) {
                Some(scroll_layer_id)
            } else {
                None
            }
        })
    }

    pub fn find_scrolling_layer_at_point(&self, cursor: &WorldPoint) -> ScrollLayerId {
        self.find_scrolling_layer_at_point_in_layer(cursor, self.root_reference_frame_id())
            .unwrap_or(self.topmost_scroll_layer_id())
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let mut result = vec![];
        for (scroll_layer_id, scroll_layer) in self.layers.iter() {
            match scroll_layer_id.info {
                ScrollLayerInfo::Scrollable(_, servo_scroll_root_id) => {
                    result.push(ScrollLayerState {
                        pipeline_id: scroll_layer.pipeline_id,
                        scroll_root_id: servo_scroll_root_id,
                        scroll_offset: scroll_layer.scrolling.offset,
                    })
                }
                ScrollLayerInfo::ReferenceFrame(..) => {}
            }
        }
        result
    }

    pub fn drain(&mut self) -> ScrollStates {
        self.current_reference_frame_id = 1;

        let mut scroll_states = HashMap::with_hasher(Default::default());
        for (layer_id, old_layer) in &mut self.layers.drain() {
            scroll_states.insert(layer_id, old_layer.scrolling);
        }
        scroll_states
    }

    pub fn scroll_layers(&mut self,
                         origin: LayerPoint,
                         pipeline_id: PipelineId,
                         scroll_root_id: ServoScrollRootId)
                         -> bool {
        if self.layers.is_empty() {
            return false;
        }

        let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0));

        let mut scrolled_a_layer = false;
        let mut found_layer = false;
        for (layer_id, layer) in self.layers.iter_mut() {
            if layer_id.pipeline_id != pipeline_id {
                continue;
            }

            match layer_id.info {
                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
                ScrollLayerInfo::ReferenceFrame(..) => continue,
                ScrollLayerInfo::Scrollable(..) => {}
            }

            found_layer = true;
            scrolled_a_layer |= layer.set_scroll_origin(&origin);
        }

        if !found_layer {
            self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin);
        }

        scrolled_a_layer
    }

    pub fn scroll(&mut self,
                  scroll_location: ScrollLocation,
                  cursor: WorldPoint,
                  phase: ScrollEventPhase)
                  -> bool {
        if self.layers.is_empty() {
            return false;
        }

        let scroll_layer_id = match (
            phase,
            self.find_scrolling_layer_at_point(&cursor),
            self.current_scroll_layer_id) {
            (ScrollEventPhase::Start, scroll_layer_id, _) => {
                self.current_scroll_layer_id = Some(scroll_layer_id);
                scroll_layer_id
            },
            (_, scroll_layer_id, Some(cached_scroll_layer_id)) => {
                let scroll_layer_id = match self.layers.get(&cached_scroll_layer_id) {
                    Some(_) => cached_scroll_layer_id,
                    None => {
                        self.current_scroll_layer_id = Some(scroll_layer_id);
                        scroll_layer_id
                    },
                };
                scroll_layer_id
            },
            (_, _, None) => return false,
        };

        let topmost_scroll_layer_id = self.topmost_scroll_layer_id();
        let non_root_overscroll = if scroll_layer_id != topmost_scroll_layer_id {
            // true if the current layer is overscrolling,
            // and it is not the root scroll layer.
            let child_layer = self.layers.get(&scroll_layer_id).unwrap();
            let overscroll_amount = child_layer.overscroll_amount();
            overscroll_amount.width != 0.0 || overscroll_amount.height != 0.0
        } else {
            false
        };

        let switch_layer = match phase {
            ScrollEventPhase::Start => {
                // if this is a new gesture, we do not switch layer,
                // however we do save the state of non_root_overscroll,
                // for use in the subsequent Move phase.
                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
                current_layer.scrolling.should_handoff_scroll = non_root_overscroll;
                false
            },
            ScrollEventPhase::Move(_) => {
                // Switch layer if movement originated in a new gesture,
                // from a non root layer in overscroll.
                let current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
                current_layer.scrolling.should_handoff_scroll && non_root_overscroll
            },
            ScrollEventPhase::End => {
                // clean-up when gesture ends.
                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
                current_layer.scrolling.should_handoff_scroll = false;
                false
            },
        };

        let scroll_layer_info = if switch_layer {
            topmost_scroll_layer_id.info
        } else {
            scroll_layer_id.info
        };

        let scroll_root_id = match scroll_layer_info {
             ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
             _ => unreachable!("Tried to scroll a reference frame."),

        };

        let mut scrolled_a_layer = false;
        for (layer_id, layer) in self.layers.iter_mut() {
            if layer_id.pipeline_id != scroll_layer_id.pipeline_id {
                continue;
            }

            match layer_id.info {
                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
                ScrollLayerInfo::ReferenceFrame(..) => continue,
                _ => {}
            }

            let scrolled_this_layer = layer.scroll(scroll_location, phase);
            scrolled_a_layer = scrolled_a_layer || scrolled_this_layer;
        }
        scrolled_a_layer
    }

    pub fn update_all_layer_transforms(&mut self) {
        if self.layers.is_empty() {
            return;
        }

        let root_reference_frame_id = self.root_reference_frame_id();
        let root_viewport = self.layers[&root_reference_frame_id].local_viewport_rect;
        self.update_layer_transform(root_reference_frame_id,
                                    &ScrollToWorldTransform::identity(),
                                    &as_scroll_parent_rect(&root_viewport));
    }

    fn update_layer_transform(&mut self,
                              layer_id: ScrollLayerId,
                              parent_world_transform: &ScrollToWorldTransform,
                              parent_viewport_rect: &ScrollLayerRect) {
        // TODO(gw): This is an ugly borrow check workaround to clone these.
        //           Restructure this to avoid the clones!
        let (layer_transform_for_children, viewport_rect, layer_children) = {
            match self.layers.get_mut(&layer_id) {
                Some(layer) => {
                    layer.update_transform(parent_world_transform, parent_viewport_rect);

                    (layer.world_content_transform.with_source::<ScrollLayerPixel>(),
                     as_scroll_parent_rect(&layer.combined_local_viewport_rect),
                     layer.children.clone())
                }
                None => return,
            }
        };

        for child_layer_id in layer_children {
            self.update_layer_transform(child_layer_id,
                                        &layer_transform_for_children,
                                        &viewport_rect);
        }
    }

    pub fn tick_scrolling_bounce_animations(&mut self) {
        for (_, layer) in &mut self.layers {
            layer.tick_scrolling_bounce_animation()
        }
    }

    pub fn finalize_and_apply_pending_scroll_offsets(&mut self, old_states: ScrollStates) {
        // TODO(gw): These are all independent - can be run through thread pool if it shows up
        // in the profile!
        for (scroll_layer_id, layer) in &mut self.layers {
            let scrolling_state = match old_states.get(&scroll_layer_id) {
                Some(old_scrolling_state) => *old_scrolling_state,
                None => ScrollingState::new(),
            };

            layer.finalize(&scrolling_state);

            let scroll_root_id = match scroll_layer_id.info {
                ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
                _ => continue,
            };

            let pipeline_id = scroll_layer_id.pipeline_id;
            if let Some(pending_offset) =
                self.pending_scroll_offsets.get_mut(&(pipeline_id, scroll_root_id)) {
                layer.set_scroll_origin(pending_offset);
            }
        }

    }

    pub fn add_reference_frame(&mut self,
                               rect: LayerRect,
                               transform: LayerToScrollTransform,
                               pipeline_id: PipelineId,
                               parent_id: ScrollLayerId) -> ScrollLayerId {
        let reference_frame_id = ScrollLayerId {
            pipeline_id: pipeline_id,
            info: ScrollLayerInfo::ReferenceFrame(self.current_reference_frame_id),
        };
        self.current_reference_frame_id += 1;

        let layer = Layer::new(&rect, rect.size, &transform, pipeline_id);
        self.add_layer(layer, reference_frame_id, parent_id);
        reference_frame_id
    }

    pub fn add_layer(&mut self, layer: Layer, id: ScrollLayerId, parent_id: ScrollLayerId) {
        debug_assert!(!self.layers.contains_key(&id));
        self.layers.insert(id, layer);

        debug_assert!(parent_id != id);
        self.layers.get_mut(&parent_id).unwrap().add_child(id);
    }
}

<commit_msg>clearer variable names<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use fnv::FnvHasher;
use layer::{Layer, ScrollingState};
use std::collections::{HashMap, HashSet};
use std::hash::BuildHasherDefault;
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, PipelineId};
use webrender_traits::{ScrollEventPhase, ScrollLayerId, ScrollLayerInfo, ScrollLayerPixel};
use webrender_traits::{ScrollLayerRect, ScrollLayerState, ScrollLocation, ScrollToWorldTransform};
use webrender_traits::{ServoScrollRootId, WorldPoint, as_scroll_parent_rect};

pub type ScrollStates = HashMap<ScrollLayerId, ScrollingState, BuildHasherDefault<FnvHasher>>;

pub struct ScrollTree {
    pub layers: HashMap<ScrollLayerId, Layer, BuildHasherDefault<FnvHasher>>,
    pub pending_scroll_offsets: HashMap<(PipelineId, ServoScrollRootId), LayerPoint>,
    pub current_scroll_layer_id: Option<ScrollLayerId>,
    pub current_reference_frame_id: usize,

    /// The root reference frame, which is the true root of the ScrollTree. Initially
    /// this ID is not valid, which is indicated by ```layers``` being empty.
    pub root_reference_frame_id: ScrollLayerId,

    /// The root scroll layer, which is the first child of the root reference frame.
    /// Initially this ID is not valid, which is indicated by ```layers``` being empty.
    pub topmost_scroll_layer_id: ScrollLayerId,
}

impl ScrollTree {
    pub fn new() -> ScrollTree {
        let dummy_pipeline = PipelineId(0, 0);
        ScrollTree {
            layers: HashMap::with_hasher(Default::default()),
            pending_scroll_offsets: HashMap::new(),
            current_scroll_layer_id: None,
            root_reference_frame_id: ScrollLayerId::root_reference_frame(dummy_pipeline),
            topmost_scroll_layer_id: ScrollLayerId::root_scroll_layer(dummy_pipeline),
            current_reference_frame_id: 1,
        }
    }

    pub fn root_reference_frame_id(&self) -> ScrollLayerId {
        // TODO(mrobinson): We should eventually make this impossible to misuse.
        debug_assert!(!self.layers.is_empty());
        debug_assert!(self.layers.contains_key(&self.root_reference_frame_id));
        self.root_reference_frame_id
    }

    pub fn topmost_scroll_layer_id(&self) -> ScrollLayerId {
        // TODO(mrobinson): We should eventually make this impossible to misuse.
        debug_assert!(!self.layers.is_empty());
        debug_assert!(self.layers.contains_key(&self.topmost_scroll_layer_id));
        self.topmost_scroll_layer_id
    }

    pub fn establish_root(&mut self,
                          pipeline_id: PipelineId,
                          viewport_size: &LayerSize,
                          content_size: &LayerSize) {
        debug_assert!(self.layers.is_empty());

        let identity = LayerToScrollTransform::identity();
        let viewport = LayerRect::new(LayerPoint::zero(), *viewport_size);

        let root_reference_frame_id = ScrollLayerId::root_reference_frame(pipeline_id);
        self.root_reference_frame_id = root_reference_frame_id;
        let reference_frame = Layer::new(&viewport, viewport.size, &identity, pipeline_id);
        self.layers.insert(self.root_reference_frame_id, reference_frame);

        let scroll_layer = Layer::new(&viewport, *content_size, &identity, pipeline_id);
        let topmost_scroll_layer_id = ScrollLayerId::root_scroll_layer(pipeline_id);
        self.topmost_scroll_layer_id = topmost_scroll_layer_id;
        self.add_layer(scroll_layer, topmost_scroll_layer_id, root_reference_frame_id);
    }

    pub fn collect_layers_bouncing_back(&self)
                                        -> HashSet<ScrollLayerId, BuildHasherDefault<FnvHasher>> {
        let mut layers_bouncing_back = HashSet::with_hasher(Default::default());
        for (scroll_layer_id, layer) in self.layers.iter() {
            if layer.scrolling.bouncing_back {
                layers_bouncing_back.insert(*scroll_layer_id);
            }
        }
        layers_bouncing_back
    }

    fn find_scrolling_layer_at_point_in_layer(&self,
                                              cursor: &WorldPoint,
                                              scroll_layer_id: ScrollLayerId)
                                              -> Option<ScrollLayerId> {
        self.layers.get(&scroll_layer_id).and_then(|layer| {
            for child_layer_id in layer.children.iter().rev() {
            if let Some(layer_id) =
                self.find_scrolling_layer_at_point_in_layer(cursor, *child_layer_id) {
                    return Some(layer_id);
                }
            }

            if let ScrollLayerInfo::ReferenceFrame(_) = scroll_layer_id.info {
                return None;
            }

            if layer.ray_intersects_layer(cursor) {
                Some(scroll_layer_id)
            } else {
                None
            }
        })
    }

    pub fn find_scrolling_layer_at_point(&self, cursor: &WorldPoint) -> ScrollLayerId {
        self.find_scrolling_layer_at_point_in_layer(cursor, self.root_reference_frame_id())
            .unwrap_or(self.topmost_scroll_layer_id())
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let mut result = vec![];
        for (scroll_layer_id, scroll_layer) in self.layers.iter() {
            match scroll_layer_id.info {
                ScrollLayerInfo::Scrollable(_, servo_scroll_root_id) => {
                    result.push(ScrollLayerState {
                        pipeline_id: scroll_layer.pipeline_id,
                        scroll_root_id: servo_scroll_root_id,
                        scroll_offset: scroll_layer.scrolling.offset,
                    })
                }
                ScrollLayerInfo::ReferenceFrame(..) => {}
            }
        }
        result
    }

    pub fn drain(&mut self) -> ScrollStates {
        self.current_reference_frame_id = 1;

        let mut scroll_states = HashMap::with_hasher(Default::default());
        for (layer_id, old_layer) in &mut self.layers.drain() {
            scroll_states.insert(layer_id, old_layer.scrolling);
        }
        scroll_states
    }

    pub fn scroll_layers(&mut self,
                         origin: LayerPoint,
                         pipeline_id: PipelineId,
                         scroll_root_id: ServoScrollRootId)
                         -> bool {
        if self.layers.is_empty() {
            return false;
        }

        let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0));

        let mut scrolled_a_layer = false;
        let mut found_layer = false;
        for (layer_id, layer) in self.layers.iter_mut() {
            if layer_id.pipeline_id != pipeline_id {
                continue;
            }

            match layer_id.info {
                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
                ScrollLayerInfo::ReferenceFrame(..) => continue,
                ScrollLayerInfo::Scrollable(..) => {}
            }

            found_layer = true;
            scrolled_a_layer |= layer.set_scroll_origin(&origin);
        }

        if !found_layer {
            self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin);
        }

        scrolled_a_layer
    }

    pub fn scroll(&mut self,
                  scroll_location: ScrollLocation,
                  cursor: WorldPoint,
                  phase: ScrollEventPhase)
                  -> bool {
        if self.layers.is_empty() {
            return false;
        }

        let scroll_layer_id = match (
            phase,
            self.find_scrolling_layer_at_point(&cursor),
            self.current_scroll_layer_id) {
            (ScrollEventPhase::Start, scroll_layer_at_point_id, _) => {
                self.current_scroll_layer_id = Some(scroll_layer_at_point_id);
                scroll_layer_at_point_id
            },
            (_, scroll_layer_at_point_id, Some(cached_scroll_layer_id)) => {
                let scroll_layer_id = match self.layers.get(&cached_scroll_layer_id) {
                    Some(_) => cached_scroll_layer_id,
                    None => {
                        self.current_scroll_layer_id = Some(scroll_layer_at_point_id);
                        scroll_layer_at_point_id
                    },
                };
                scroll_layer_id
            },
            (_, _, None) => return false,
        };

        let topmost_scroll_layer_id = self.topmost_scroll_layer_id();
        let non_root_overscroll = if scroll_layer_id != topmost_scroll_layer_id {
            // true if the current layer is overscrolling,
            // and it is not the root scroll layer.
            let child_layer = self.layers.get(&scroll_layer_id).unwrap();
            let overscroll_amount = child_layer.overscroll_amount();
            overscroll_amount.width != 0.0 || overscroll_amount.height != 0.0
        } else {
            false
        };

        let switch_layer = match phase {
            ScrollEventPhase::Start => {
                // if this is a new gesture, we do not switch layer,
                // however we do save the state of non_root_overscroll,
                // for use in the subsequent Move phase.
                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
                current_layer.scrolling.should_handoff_scroll = non_root_overscroll;
                false
            },
            ScrollEventPhase::Move(_) => {
                // Switch layer if movement originated in a new gesture,
                // from a non root layer in overscroll.
                let current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
                current_layer.scrolling.should_handoff_scroll && non_root_overscroll
            },
            ScrollEventPhase::End => {
                // clean-up when gesture ends.
                let mut current_layer = self.layers.get_mut(&scroll_layer_id).unwrap();
                current_layer.scrolling.should_handoff_scroll = false;
                false
            },
        };

        let scroll_layer_info = if switch_layer {
            topmost_scroll_layer_id.info
        } else {
            scroll_layer_id.info
        };

        let scroll_root_id = match scroll_layer_info {
             ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
             _ => unreachable!("Tried to scroll a reference frame."),

        };

        let mut scrolled_a_layer = false;
        for (layer_id, layer) in self.layers.iter_mut() {
            if layer_id.pipeline_id != scroll_layer_id.pipeline_id {
                continue;
            }

            match layer_id.info {
                ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
                ScrollLayerInfo::ReferenceFrame(..) => continue,
                _ => {}
            }

            let scrolled_this_layer = layer.scroll(scroll_location, phase);
            scrolled_a_layer = scrolled_a_layer || scrolled_this_layer;
        }
        scrolled_a_layer
    }

    pub fn update_all_layer_transforms(&mut self) {
        if self.layers.is_empty() {
            return;
        }

        let root_reference_frame_id = self.root_reference_frame_id();
        let root_viewport = self.layers[&root_reference_frame_id].local_viewport_rect;
        self.update_layer_transform(root_reference_frame_id,
                                    &ScrollToWorldTransform::identity(),
                                    &as_scroll_parent_rect(&root_viewport));
    }

    fn update_layer_transform(&mut self,
                              layer_id: ScrollLayerId,
                              parent_world_transform: &ScrollToWorldTransform,
                              parent_viewport_rect: &ScrollLayerRect) {
        // TODO(gw): This is an ugly borrow check workaround to clone these.
        //           Restructure this to avoid the clones!
        let (layer_transform_for_children, viewport_rect, layer_children) = {
            match self.layers.get_mut(&layer_id) {
                Some(layer) => {
                    layer.update_transform(parent_world_transform, parent_viewport_rect);

                    (layer.world_content_transform.with_source::<ScrollLayerPixel>(),
                     as_scroll_parent_rect(&layer.combined_local_viewport_rect),
                     layer.children.clone())
                }
                None => return,
            }
        };

        for child_layer_id in layer_children {
            self.update_layer_transform(child_layer_id,
                                        &layer_transform_for_children,
                                        &viewport_rect);
        }
    }

    pub fn tick_scrolling_bounce_animations(&mut self) {
        for (_, layer) in &mut self.layers {
            layer.tick_scrolling_bounce_animation()
        }
    }

    pub fn finalize_and_apply_pending_scroll_offsets(&mut self, old_states: ScrollStates) {
        // TODO(gw): These are all independent - can be run through thread pool if it shows up
        // in the profile!
        for (scroll_layer_id, layer) in &mut self.layers {
            let scrolling_state = match old_states.get(&scroll_layer_id) {
                Some(old_scrolling_state) => *old_scrolling_state,
                None => ScrollingState::new(),
            };

            layer.finalize(&scrolling_state);

            let scroll_root_id = match scroll_layer_id.info {
                ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
                _ => continue,
            };

            let pipeline_id = scroll_layer_id.pipeline_id;
            if let Some(pending_offset) =
                self.pending_scroll_offsets.get_mut(&(pipeline_id, scroll_root_id)) {
                layer.set_scroll_origin(pending_offset);
            }
        }

    }

    pub fn add_reference_frame(&mut self,
                               rect: LayerRect,
                               transform: LayerToScrollTransform,
                               pipeline_id: PipelineId,
                               parent_id: ScrollLayerId) -> ScrollLayerId {
        let reference_frame_id = ScrollLayerId {
            pipeline_id: pipeline_id,
            info: ScrollLayerInfo::ReferenceFrame(self.current_reference_frame_id),
        };
        self.current_reference_frame_id += 1;

        let layer = Layer::new(&rect, rect.size, &transform, pipeline_id);
        self.add_layer(layer, reference_frame_id, parent_id);
        reference_frame_id
    }

    pub fn add_layer(&mut self, layer: Layer, id: ScrollLayerId, parent_id: ScrollLayerId) {
        debug_assert!(!self.layers.contains_key(&id));
        self.layers.insert(id, layer);

        debug_assert!(parent_id != id);
        self.layers.get_mut(&parent_id).unwrap().add_child(id);
    }
}

<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_escape];

macro_rules! rterrln (
    ($( $arg:expr),+) => ( {
        ::rt::util::dumb_println(fmt!( $($arg),+ ));
    } )
)

// Some basic logging
macro_rules! rtdebug_ (
    ($( $arg:expr),+) => ( {
        rterrln!( $($arg),+ )
    } )
)

// An alternate version with no output, for turning off logging. An
// earlier attempt that did not call the fmt! macro was insufficient,
// as a case of the "let bind each variable" approach eventually
// failed without an error message describing the invocation site.
macro_rules! rtdebug (
    ($( $arg:expr),+) => ( {
        let _x = fmt!( $($arg),+ );
    })
)

macro_rules! rtassert (
    ( $arg:expr ) => ( {
        if !$arg {
            rtabort!("assertion failed: %s", stringify!($arg));
        }
    } )
)

macro_rules! rtabort(
    ($( $msg:expr),+) => ( {
        ::rt::util::abort(fmt!($($msg),+));
    } )
)

<commit_msg>auto merge of #8419 : cmr/rust/fix-rtdebug, r=brson<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_escape];

macro_rules! rterrln (
    ($( $arg:expr),+) => ( {
        ::rt::util::dumb_println(fmt!( $($arg),+ ));
    } )
)

// Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build.
macro_rules! rtdebug (
    ($( $arg:expr),+) => ( {
        if cfg!(rtdebug) {
            rterrln!( $($arg),+ )
        }
    })
)

macro_rules! rtassert (
    ( $arg:expr ) => ( {
        if !$arg {
            rtabort!("assertion failed: %s", stringify!($arg));
        }
    } )
)

macro_rules! rtabort(
    ($( $msg:expr),+) => ( {
        ::rt::util::abort(fmt!($($msg),+));
    } )
)

<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Migrate documentation over from `std::vec` when it is removed.
#[doc(hidden)];

use cast::{forget, transmute};
use clone::Clone;
use cmp::{Eq, Ordering, TotalEq, TotalOrd};
use container::Container;
use iter::{DoubleEndedIterator, FromIterator, Iterator};
use libc::{free, c_void};
use mem::{size_of, move_val_init};
use num::CheckedMul;
use ops::Drop;
use option::{None, Option, Some};
use ptr::RawPtr;
use ptr;
use rt::global_heap::{malloc_raw, realloc_raw};
use raw::Slice;
use vec::{ImmutableVector, Items, MutItems, MutableVector, RevItems};

pub struct Vec<T> {
    priv len: uint,
    priv cap: uint,
    priv ptr: *mut T
}

impl<T> Vec<T> {
    #[inline]
    pub fn new() -> Vec<T> {
        Vec { len: 0, cap: 0, ptr: 0 as *mut T }
    }

    pub fn with_capacity(capacity: uint) -> Vec<T> {
        if capacity == 0 {
            Vec::new()
        } else {
            let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
            let ptr = unsafe { malloc_raw(size) };
            Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
        }
    }

    pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
        unsafe {
            let mut xs = Vec::with_capacity(length);
            while xs.len < length {
                move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len), op(xs.len));
                xs.len += 1;
            }
            xs
        }
    }
}

impl<T: Clone> Vec<T> {
    pub fn from_elem(length: uint, value: T) -> Vec<T> {
        unsafe {
            let mut xs = Vec::with_capacity(length);
            while xs.len < length {
                move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len), value.clone());
                xs.len += 1;
            }
            xs
        }
    }

    #[inline]
    pub fn push_all(&mut self, other: &[T]) {
        for element in other.iter() {
            self.push((*element).clone())
        }
    }
}

impl<T:Clone> Clone for Vec<T> {
    fn clone(&self) -> Vec<T> {
        let mut vector = Vec::with_capacity(self.len());
        for element in self.iter() {
            vector.push((*element).clone())
        }
        vector
    }
}

impl<T> FromIterator<T> for Vec<T> {
    fn from_iterator<I:Iterator<T>>(iterator: &mut I) -> Vec<T> {
        let (lower, _) = iterator.size_hint();
        let mut vector = Vec::with_capacity(lower);
        for element in *iterator {
            vector.push(element)
        }
        vector
    }
}

impl<T:Eq> Eq for Vec<T> {
    #[inline]
    fn eq(&self, other: &Vec<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T:TotalEq> TotalEq for Vec<T> {
    #[inline]
    fn equals(&self, other: &Vec<T>) -> bool {
        self.as_slice().equals(&other.as_slice())
    }
}

impl<T:TotalOrd> TotalOrd for Vec<T> {
    #[inline]
    fn cmp(&self, other: &Vec<T>) -> Ordering {
        self.as_slice().cmp(&other.as_slice())
    }
}

impl<T> Container for Vec<T> {
    #[inline]
    fn len(&self) -> uint {
        self.len
    }
}

impl<T> Vec<T> {
    #[inline]
    pub fn capacity(&self) -> uint {
        self.cap
    }

    pub fn reserve_exact(&mut self, capacity: uint) {
        if capacity >= self.len {
            let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
            self.cap = capacity;
            unsafe {
                self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T;
            }
        }
    }

    pub fn shrink_to_fit(&mut self) {
        if self.len == 0 {
            unsafe { free(self.ptr as *mut c_void) };
            self.cap = 0;
            self.ptr = 0 as *mut T;
        } else {
            unsafe {
                // Overflow check is unnecessary as the vector is already at least this large.
                self.ptr = realloc_raw(self.ptr as *mut u8, self.len * size_of::<T>()) as *mut T;
            }
            self.cap = self.len;
        }
    }

    #[inline]
    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            None
        } else {
            unsafe {
                self.len -= 1;
                Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
            }
        }
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        if self.len == self.cap {
            if self.cap == 0 { self.cap += 2 }
            let old_size = self.cap * size_of::<T>();
            self.cap = self.cap * 2;
            let size = old_size * 2;
            if old_size > size { fail!("capacity overflow") }
            unsafe {
                self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T;
            }
        }

        unsafe {
            let end = (self.ptr as *T).offset(self.len as int) as *mut T;
            move_val_init(&mut *end, value);
            self.len += 1;
        }
    }

    pub fn truncate(&mut self, len: uint) {
        unsafe {
            let mut i = len;
            // drop any extra elements
            while i < self.len {
                ptr::read(self.as_slice().unsafe_ref(i));
                i += 1;
            }
        }
        self.len = len;
    }

    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        let slice = Slice { data: self.ptr as *T, len: self.len };
        unsafe { transmute(slice) }
    }

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        let slice = Slice { data: self.ptr as *T, len: self.len };
        unsafe { transmute(slice) }
    }

    #[inline]
    pub fn move_iter(self) -> MoveItems<T> {
        unsafe {
            let iter = transmute(self.as_slice().iter());
            let ptr = self.ptr as *mut c_void;
            forget(self);
            MoveItems { allocation: ptr, iter: iter }
        }
    }

    #[inline]
    pub unsafe fn set_len(&mut self, len: uint) {
        self.len = len;
    }

    #[inline]
    pub fn get<'a>(&'a self, index: uint) -> &'a T {
        &self.as_slice()[index]
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
        &mut self.as_mut_slice()[index]
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> Items<'a,T> {
        self.as_slice().iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a,T> {
        self.as_mut_slice().mut_iter()
    }

    #[inline]
    pub fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
        self.as_mut_slice().sort_by(compare)
    }

    #[inline]
    pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] {
        self.as_slice().slice(start, end)
    }

    #[inline]
    pub fn tail<'a>(&'a self) -> &'a [T] {
        self.as_slice().tail()
    }

    #[inline]
    pub fn last<'a>(&'a self) -> Option<&'a T> {
        self.as_slice().last()
    }

    #[inline]
    pub fn mut_last<'a>(&'a mut self) -> Option<&'a mut T> {
        self.as_mut_slice().mut_last()
    }

    #[inline]
    pub fn swap_remove(&mut self, index: uint) -> Option<T> {
        let length = self.len();
        if index < length - 1 {
            self.as_mut_slice().swap(index, length - 1);
        } else if index >= length {
            return None
        }
        self.pop()
    }

    #[inline]
    pub fn unshift(&mut self, element: T) {
        self.insert(0, element)
    }

    pub fn insert(&mut self, index: uint, element: T) {
        let len = self.len();
        assert!(index <= len);
        // space for the new element
        self.reserve_exact(len + 1);

        unsafe { // infallible
            // The spot to put the new value
            {
                let slice = self.as_mut_slice();
                let p = slice.as_mut_ptr().offset(index as int);
                // Shift everything over to make space. (Duplicating the
                // `index`th element into two consecutive places.)
                ptr::copy_memory(p.offset(1), &*p, len - index);
                // Write it in, overwriting the first copy of the `index`th
                // element.
                move_val_init(&mut *p, element);
            }
            self.set_len(len + 1);
        }
    }

    #[inline]
    pub fn rev_iter<'a>(&'a self) -> RevItems<'a,T> {
        self.as_slice().rev_iter()
    }

    #[inline]
    pub fn map<U>(&self, f: |t: &T| -> U) -> Vec<U> {
        self.iter().map(f).collect()
    }

    pub fn push_all_move(&mut self, other: Vec<T>) {
        for element in other.move_iter() {
            self.push(element)
        }
    }

    pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] {
        self.as_slice().slice_from(start)
    }
}

#[inline]
pub fn append<T:Clone>(mut first: Vec<T>, second: &[T]) -> Vec<T> {
    first.push_all(second);
    first
}

#[unsafe_destructor]
impl<T> Drop for Vec<T> {
    fn drop(&mut self) {
        unsafe {
            for x in self.as_mut_slice().iter() {
                ptr::read(x);
            }
            free(self.ptr as *mut c_void)
        }
    }
}

pub struct MoveItems<T> {
    priv allocation: *mut c_void, // the block of memory allocated for the vector
    priv iter: Items<'static, T>
}

impl<T> Iterator<T> for MoveItems<T> {
    #[inline]
    fn next(&mut self) -> Option<T> {
        unsafe {
            self.iter.next().map(|x| ptr::read(x))
        }
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<T> DoubleEndedIterator<T> for MoveItems<T> {
    #[inline]
    fn next_back(&mut self) -> Option<T> {
        unsafe {
            self.iter.next_back().map(|x| ptr::read(x))
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for MoveItems<T> {
    fn drop(&mut self) {
        // destroy the remaining elements
        for _x in *self {}
        unsafe {
            free(self.allocation)
        }
    }
}
<commit_msg>std: Add Vec.reserve for rounding-up reservation.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Migrate documentation over from `std::vec` when it is removed.
#[doc(hidden)];

use cast::{forget, transmute};
use clone::Clone;
use cmp::{Eq, Ordering, TotalEq, TotalOrd};
use container::Container;
use iter::{DoubleEndedIterator, FromIterator, Iterator};
use libc::{free, c_void};
use mem::{size_of, move_val_init};
use num;
use num::CheckedMul;
use ops::Drop;
use option::{None, Option, Some};
use ptr::RawPtr;
use ptr;
use rt::global_heap::{malloc_raw, realloc_raw};
use raw::Slice;
use vec::{ImmutableVector, Items, MutItems, MutableVector, RevItems};

pub struct Vec<T> {
    priv len: uint,
    priv cap: uint,
    priv ptr: *mut T
}

impl<T> Vec<T> {
    #[inline]
    pub fn new() -> Vec<T> {
        Vec { len: 0, cap: 0, ptr: 0 as *mut T }
    }

    pub fn with_capacity(capacity: uint) -> Vec<T> {
        if capacity == 0 {
            Vec::new()
        } else {
            let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
            let ptr = unsafe { malloc_raw(size) };
            Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
        }
    }

    pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
        unsafe {
            let mut xs = Vec::with_capacity(length);
            while xs.len < length {
                move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len), op(xs.len));
                xs.len += 1;
            }
            xs
        }
    }
}

impl<T: Clone> Vec<T> {
    pub fn from_elem(length: uint, value: T) -> Vec<T> {
        unsafe {
            let mut xs = Vec::with_capacity(length);
            while xs.len < length {
                move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len), value.clone());
                xs.len += 1;
            }
            xs
        }
    }

    #[inline]
    pub fn push_all(&mut self, other: &[T]) {
        for element in other.iter() {
            self.push((*element).clone())
        }
    }
}

impl<T:Clone> Clone for Vec<T> {
    fn clone(&self) -> Vec<T> {
        let mut vector = Vec::with_capacity(self.len());
        for element in self.iter() {
            vector.push((*element).clone())
        }
        vector
    }
}

impl<T> FromIterator<T> for Vec<T> {
    fn from_iterator<I:Iterator<T>>(iterator: &mut I) -> Vec<T> {
        let (lower, _) = iterator.size_hint();
        let mut vector = Vec::with_capacity(lower);
        for element in *iterator {
            vector.push(element)
        }
        vector
    }
}

impl<T:Eq> Eq for Vec<T> {
    #[inline]
    fn eq(&self, other: &Vec<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T:TotalEq> TotalEq for Vec<T> {
    #[inline]
    fn equals(&self, other: &Vec<T>) -> bool {
        self.as_slice().equals(&other.as_slice())
    }
}

impl<T:TotalOrd> TotalOrd for Vec<T> {
    #[inline]
    fn cmp(&self, other: &Vec<T>) -> Ordering {
        self.as_slice().cmp(&other.as_slice())
    }
}

impl<T> Container for Vec<T> {
    #[inline]
    fn len(&self) -> uint {
        self.len
    }
}

impl<T> Vec<T> {
    #[inline]
    pub fn capacity(&self) -> uint {
        self.cap
    }

    pub fn reserve(&mut self, capacity: uint) {
        if capacity >= self.len {
            self.reserve_exact(num::next_power_of_two(capacity))
        }
    }

    pub fn reserve_exact(&mut self, capacity: uint) {
        if capacity >= self.len {
            let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
            self.cap = capacity;
            unsafe {
                self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T;
            }
        }
    }

    pub fn shrink_to_fit(&mut self) {
        if self.len == 0 {
            unsafe { free(self.ptr as *mut c_void) };
            self.cap = 0;
            self.ptr = 0 as *mut T;
        } else {
            unsafe {
                // Overflow check is unnecessary as the vector is already at least this large.
                self.ptr = realloc_raw(self.ptr as *mut u8, self.len * size_of::<T>()) as *mut T;
            }
            self.cap = self.len;
        }
    }

    #[inline]
    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            None
        } else {
            unsafe {
                self.len -= 1;
                Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
            }
        }
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        if self.len == self.cap {
            if self.cap == 0 { self.cap += 2 }
            let old_size = self.cap * size_of::<T>();
            self.cap = self.cap * 2;
            let size = old_size * 2;
            if old_size > size { fail!("capacity overflow") }
            unsafe {
                self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T;
            }
        }

        unsafe {
            let end = (self.ptr as *T).offset(self.len as int) as *mut T;
            move_val_init(&mut *end, value);
            self.len += 1;
        }
    }

    pub fn truncate(&mut self, len: uint) {
        unsafe {
            let mut i = len;
            // drop any extra elements
            while i < self.len {
                ptr::read(self.as_slice().unsafe_ref(i));
                i += 1;
            }
        }
        self.len = len;
    }

    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        let slice = Slice { data: self.ptr as *T, len: self.len };
        unsafe { transmute(slice) }
    }

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        let slice = Slice { data: self.ptr as *T, len: self.len };
        unsafe { transmute(slice) }
    }

    #[inline]
    pub fn move_iter(self) -> MoveItems<T> {
        unsafe {
            let iter = transmute(self.as_slice().iter());
            let ptr = self.ptr as *mut c_void;
            forget(self);
            MoveItems { allocation: ptr, iter: iter }
        }
    }

    #[inline]
    pub unsafe fn set_len(&mut self, len: uint) {
        self.len = len;
    }

    #[inline]
    pub fn get<'a>(&'a self, index: uint) -> &'a T {
        &self.as_slice()[index]
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
        &mut self.as_mut_slice()[index]
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> Items<'a,T> {
        self.as_slice().iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a,T> {
        self.as_mut_slice().mut_iter()
    }

    #[inline]
    pub fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
        self.as_mut_slice().sort_by(compare)
    }

    #[inline]
    pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] {
        self.as_slice().slice(start, end)
    }

    #[inline]
    pub fn tail<'a>(&'a self) -> &'a [T] {
        self.as_slice().tail()
    }

    #[inline]
    pub fn last<'a>(&'a self) -> Option<&'a T> {
        self.as_slice().last()
    }

    #[inline]
    pub fn mut_last<'a>(&'a mut self) -> Option<&'a mut T> {
        self.as_mut_slice().mut_last()
    }

    #[inline]
    pub fn swap_remove(&mut self, index: uint) -> Option<T> {
        let length = self.len();
        if index < length - 1 {
            self.as_mut_slice().swap(index, length - 1);
        } else if index >= length {
            return None
        }
        self.pop()
    }

    #[inline]
    pub fn unshift(&mut self, element: T) {
        self.insert(0, element)
    }

    pub fn insert(&mut self, index: uint, element: T) {
        let len = self.len();
        assert!(index <= len);
        // space for the new element
        self.reserve(len + 1);

        unsafe { // infallible
            // The spot to put the new value
            {
                let slice = self.as_mut_slice();
                let p = slice.as_mut_ptr().offset(index as int);
                // Shift everything over to make space. (Duplicating the
                // `index`th element into two consecutive places.)
                ptr::copy_memory(p.offset(1), &*p, len - index);
                // Write it in, overwriting the first copy of the `index`th
                // element.
                move_val_init(&mut *p, element);
            }
            self.set_len(len + 1);
        }
    }

    #[inline]
    pub fn rev_iter<'a>(&'a self) -> RevItems<'a,T> {
        self.as_slice().rev_iter()
    }

    #[inline]
    pub fn map<U>(&self, f: |t: &T| -> U) -> Vec<U> {
        self.iter().map(f).collect()
    }

    pub fn push_all_move(&mut self, other: Vec<T>) {
        for element in other.move_iter() {
            self.push(element)
        }
    }

    pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] {
        self.as_slice().slice_from(start)
    }
}

#[inline]
pub fn append<T:Clone>(mut first: Vec<T>, second: &[T]) -> Vec<T> {
    first.push_all(second);
    first
}

#[unsafe_destructor]
impl<T> Drop for Vec<T> {
    fn drop(&mut self) {
        unsafe {
            for x in self.as_mut_slice().iter() {
                ptr::read(x);
            }
            free(self.ptr as *mut c_void)
        }
    }
}

pub struct MoveItems<T> {
    priv allocation: *mut c_void, // the block of memory allocated for the vector
    priv iter: Items<'static, T>
}

impl<T> Iterator<T> for MoveItems<T> {
    #[inline]
    fn next(&mut self) -> Option<T> {
        unsafe {
            self.iter.next().map(|x| ptr::read(x))
        }
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<T> DoubleEndedIterator<T> for MoveItems<T> {
    #[inline]
    fn next_back(&mut self) -> Option<T> {
        unsafe {
            self.iter.next_back().map(|x| ptr::read(x))
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for MoveItems<T> {
    fn drop(&mut self) {
        // destroy the remaining elements
        for _x in *self {}
        unsafe {
            free(self.allocation)
        }
    }
}
<|endoftext|>


<commit_before>use finder::Checker;
#[cfg(unix)]
use libc;
#[cfg(unix)]
use std::ffi::CString;
use std::fs;
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
use std::path::Path;

pub struct ExecutableChecker;

impl ExecutableChecker {
    pub fn new() -> ExecutableChecker {
        ExecutableChecker
    }
}

impl Checker for ExecutableChecker {
    #[cfg(unix)]
    fn is_valid(&self, path: &Path) -> bool {
        CString::new(path.as_os_str().as_bytes())
            .and_then(|c| Ok(unsafe { libc::access(c.as_ptr(), libc::X_OK) == 0 }))
            .unwrap_or(false)
    }

    #[cfg(windows)]
    fn is_valid(&self, _path: &Path) -> bool {
        true
    }
}

pub struct ExistedChecker;

impl ExistedChecker {
    pub fn new() -> ExistedChecker {
        ExistedChecker
    }
}

impl Checker for ExistedChecker {
    #[cfg(target_os="windows")]
    fn is_valid(&self, path: &Path) -> bool {
        fs::symlink_metadata(path)
            .map(|metadata| metadata.is_file())
            .unwrap_or(false)
    }

    #[cfg(not(target_os="windows"))]
    fn is_valid(&self, path: &Path) -> bool {
        fs::metadata(path)
            .map(|metadata| metadata.is_file())
            .unwrap_or(false)
    }
}

pub struct CompositeChecker {
    checkers: Vec<Box<dyn Checker>>,
}

impl CompositeChecker {
    pub fn new() -> CompositeChecker {
        CompositeChecker {
            checkers: Vec::new(),
        }
    }

    pub fn add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker {
        self.checkers.push(checker);
        self
    }
}

impl Checker for CompositeChecker {
    fn is_valid(&self, path: &Path) -> bool {
        self.checkers.iter().all(|checker| checker.is_valid(path))
    }
}
<commit_msg>Update checker.rs<commit_after>use finder::Checker;
#[cfg(unix)]
use libc;
#[cfg(unix)]
use std::ffi::CString;
use std::fs;
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
use std::path::Path;

pub struct ExecutableChecker;

impl ExecutableChecker {
    pub fn new() -> ExecutableChecker {
        ExecutableChecker
    }
}

impl Checker for ExecutableChecker {
    #[cfg(unix)]
    fn is_valid(&self, path: &Path) -> bool {
        CString::new(path.as_os_str().as_bytes())
            .and_then(|c| Ok(unsafe { libc::access(c.as_ptr(), libc::X_OK) == 0 }))
            .unwrap_or(false)
    }

    #[cfg(windows)]
    fn is_valid(&self, _path: &Path) -> bool {
        true
    }
}

pub struct ExistedChecker;

impl ExistedChecker {
    pub fn new() -> ExistedChecker {
        ExistedChecker
    }
}

impl Checker for ExistedChecker {
    #[cfg(target_os="windows")]
    fn is_valid(&self, path: &Path) -> bool {
        fs::symlink_metadata(path)
            .map(|metadata| metadata.is_file())
            .unwrap_or(false)
    }

    #[cfg(not(target_os="windows"))]
    fn is_valid(&self, path: &Path) -> bool {
        fs::metadata(path)
            .map(|metadata| metadata.is_file())
            .unwrap_or(false)
    }
}

pub struct CompositeChecker {
    checkers: Vec<Box<dyn Checker>>,
}

impl CompositeChecker {
    pub fn new() -> CompositeChecker {
        CompositeChecker {
            checkers: Vec::new(),
        }
    }

    pub fn add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker {
        self.checkers.push(checker);
        self
    }
}

impl Checker for CompositeChecker {
    fn is_valid(&self, path: &Path) -> bool {
        self.checkers.iter().all(|checker| checker.is_valid(path))
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! poll {
    ($e:expr) => ({
        loop {
            match $e {
                ::futures::__rt::Ok(::futures::Async::Ready(e)) => {
                    break ::futures::__rt::Ok(e)
                }
                ::futures::__rt::Ok(::futures::Async::NotReady) => {}
                ::futures::__rt::Err(e) => {
                    break ::futures::__rt::Err(e)
                }
            }
            yield
        }
    })
}
<commit_msg>Fix API in new `futures-await`<commit_after>#[macro_export]
macro_rules! poll {
    ($e:expr) => ({
        loop {
            match $e {
                ::futures::__rt::Ok(::futures::Async::Ready(e)) => {
                    break ::futures::__rt::Ok(e)
                }
                ::futures::__rt::Ok(::futures::Async::NotReady) => {}
                ::futures::__rt::Err(e) => {
                    break ::futures::__rt::Err(e)
                }
            }
            yield ::futures::Async::NotReady;
        }
    })
}
<|endoftext|>


<commit_before>/// Given a `BTreeMap<String, Value>`, return a `Vec<_>` that
/// contains all the items wrapped inside the `Value`s.
///
/// Since `iron/params` returns `Result<Map, ParamsError>` (where
/// `Map` is defined as `BTreeMap<String, Value>`) and we're asked to
/// provide `VectorOfTerms<String>::build_terms()` a `Vec<String>`,
/// we need to assert that it `is_ok()` and eventually retrieving
/// its value using the convertion trait `FromValue`.
///
/// Either if the convertion result `is_none()` because of an error
/// or we originally got a `ParamsError`, an empty `Vec<String>` will
/// be returned.
///
/// Otherwise, the output will be a `Vec<String>` fill with all the
/// returned `String`s found inside the query string.
///
/// ```
/// # #[macro_use] extern crate honeysearch;
/// # extern crate params;
/// # use params::*;
///
/// # fn main() {
/// let mut params = Map::new();
/// params.assign("work_roles[]", Value::String("Fullstack".into())).unwrap();
/// params.assign("work_roles[]", Value::String("DevOps".into())).unwrap();
///
/// let work_roles: Vec<String> = vec_from_params!(params, "work_roles");
/// assert_eq!(work_roles, vec!["Fullstack", "DevOps"]);
/// # }
/// ```
///
/// ```
/// # #[macro_use] extern crate honeysearch;
/// # extern crate params;
/// # use params::*;
///
/// # fn main() {
/// let work_roles: Vec<String> = vec_from_params!(Map::new(), "work_roles");
/// assert_eq!(work_roles, Vec::<String>::new());
/// # }
/// ```
#[macro_export]
macro_rules! vec_from_params {
  ($params:expr, $param:expr) => {
    match $params.find(&[$param]) {
      Some(val) => Vec::from_value(val)
                       .unwrap_or(vec![]),
      None => vec![],
    }
  }
}

/// Like vec_from_params!, but all the elements are casted
/// to i32 (or discarded if the type conversion is impossibile).
#[macro_export]
macro_rules! i32_vec_from_params {
  ($params:expr, $param:expr) => {
    match $params.find(&[$param]) {
      Some(company_id) => i32::from_value(company_id)
                              .map(|id| vec![id])
                              .unwrap_or(vec![]),
      None => vec![]
    }
  }
}

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

  #[test]
  fn test_vec_from_params() {
    {
      let mut params = Map::new();
      params.assign("work_roles[]", Value::String("Fullstack".into())).unwrap();
      params.assign("work_roles[]", Value::String("DevOps".into())).unwrap();

      let work_roles: Vec<String> = vec_from_params!(params, "work_roles");
      assert_eq!(work_roles, vec!["Fullstack", "DevOps"]);
    }

    {
      let mut params = Map::new();
      params.assign("work_roles[]", Value::String("".into())).unwrap();

      let work_roles: Vec<String> = vec_from_params!(params, "work_roles");
      assert_eq!(work_roles, vec![""]); // TODO: `vec![]`?
    }

    {
      let work_roles: Vec<String> = vec_from_params!(Map::new(), "work_roles");
      assert_eq!(work_roles, Vec::<String>::new());
    }
  }

  #[test]
  fn test_i32_vec_from_params() {
    {
      let mut params = Map::new();
      params.assign("company_id", Value::String("4".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![4]);
    }

    {
      let mut params = Map::new();
      params.assign("company_id", Value::String("".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![]);
    }

    {
      let mut params = Map::new();
      params.assign("company_id", Value::String("madukapls".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![]);
    }

    {
      let mut params = Map::new();
      params.assign("company_id[]", Value::String("madukapls".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![]);
    }

    {
      let company_id: Vec<i32> = i32_vec_from_params!(Map::new(), "company_id");
      assert_eq!(company_id, vec![]);
    }
  }
}
<commit_msg>macros: remove unnecessary comma<commit_after>/// Given a `BTreeMap<String, Value>`, return a `Vec<_>` that
/// contains all the items wrapped inside the `Value`s.
///
/// Since `iron/params` returns `Result<Map, ParamsError>` (where
/// `Map` is defined as `BTreeMap<String, Value>`) and we're asked to
/// provide `VectorOfTerms<String>::build_terms()` a `Vec<String>`,
/// we need to assert that it `is_ok()` and eventually retrieving
/// its value using the convertion trait `FromValue`.
///
/// Either if the convertion result `is_none()` because of an error
/// or we originally got a `ParamsError`, an empty `Vec<String>` will
/// be returned.
///
/// Otherwise, the output will be a `Vec<String>` fill with all the
/// returned `String`s found inside the query string.
///
/// ```
/// # #[macro_use] extern crate honeysearch;
/// # extern crate params;
/// # use params::*;
///
/// # fn main() {
/// let mut params = Map::new();
/// params.assign("work_roles[]", Value::String("Fullstack".into())).unwrap();
/// params.assign("work_roles[]", Value::String("DevOps".into())).unwrap();
///
/// let work_roles: Vec<String> = vec_from_params!(params, "work_roles");
/// assert_eq!(work_roles, vec!["Fullstack", "DevOps"]);
/// # }
/// ```
///
/// ```
/// # #[macro_use] extern crate honeysearch;
/// # extern crate params;
/// # use params::*;
///
/// # fn main() {
/// let work_roles: Vec<String> = vec_from_params!(Map::new(), "work_roles");
/// assert_eq!(work_roles, Vec::<String>::new());
/// # }
/// ```
#[macro_export]
macro_rules! vec_from_params {
  ($params:expr, $param:expr) => {
    match $params.find(&[$param]) {
      Some(val) => Vec::from_value(val)
                       .unwrap_or(vec![]),
      None => vec![]
    }
  }
}

/// Like vec_from_params!, but all the elements are casted
/// to i32 (or discarded if the type conversion is impossibile).
#[macro_export]
macro_rules! i32_vec_from_params {
  ($params:expr, $param:expr) => {
    match $params.find(&[$param]) {
      Some(company_id) => i32::from_value(company_id)
                              .map(|id| vec![id])
                              .unwrap_or(vec![]),
      None => vec![]
    }
  }
}

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

  #[test]
  fn test_vec_from_params() {
    {
      let mut params = Map::new();
      params.assign("work_roles[]", Value::String("Fullstack".into())).unwrap();
      params.assign("work_roles[]", Value::String("DevOps".into())).unwrap();

      let work_roles: Vec<String> = vec_from_params!(params, "work_roles");
      assert_eq!(work_roles, vec!["Fullstack", "DevOps"]);
    }

    {
      let mut params = Map::new();
      params.assign("work_roles[]", Value::String("".into())).unwrap();

      let work_roles: Vec<String> = vec_from_params!(params, "work_roles");
      assert_eq!(work_roles, vec![""]); // TODO: `vec![]`?
    }

    {
      let work_roles: Vec<String> = vec_from_params!(Map::new(), "work_roles");
      assert_eq!(work_roles, Vec::<String>::new());
    }
  }

  #[test]
  fn test_i32_vec_from_params() {
    {
      let mut params = Map::new();
      params.assign("company_id", Value::String("4".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![4]);
    }

    {
      let mut params = Map::new();
      params.assign("company_id", Value::String("".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![]);
    }

    {
      let mut params = Map::new();
      params.assign("company_id", Value::String("madukapls".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![]);
    }

    {
      let mut params = Map::new();
      params.assign("company_id[]", Value::String("madukapls".into())).unwrap();

      let company_id: Vec<i32> = i32_vec_from_params!(params, "company_id");
      assert_eq!(company_id, vec![]);
    }

    {
      let company_id: Vec<i32> = i32_vec_from_params!(Map::new(), "company_id");
      assert_eq!(company_id, vec![]);
    }
  }
}
<|endoftext|>


<commit_before>//! Utility macros

/// Expands into a series of for loops with the given block of code which should
/// treat each type uniformly.
///
/// This is to avoid dynamic dispatch when chaining iterators over generic
/// collections when the types are known.
#[macro_export]
macro_rules! for_sequence {
  (
    $x:ident in $($collection:ident),* $do:block
  ) => {
    $(for $x in $collection $do)+
  }
}

/// Print the stringified expression followed by its debug formatting
#[macro_export]
macro_rules! show {
  ($e:expr) => {
    println!("{}: {:?}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its pretty debug formatting
#[macro_export]
macro_rules! pretty {
  ($e:expr) => {
    println!("{}: {:#?}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its display formatting
#[macro_export]
macro_rules! display {
  ($e:expr) => {
    println!("{}: {}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its bitstring formatting
#[macro_export]
macro_rules! bits {
  ($e:expr) => {
    println!("{}: {:b}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its hexadecimal formatting
#[macro_export]
macro_rules! hex {
  ($e:expr) => {
    println!("{}: {:x}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its pointer formatting
#[macro_export]
macro_rules! address {
  ($e:expr) => {
    println!("{}: {:p}", stringify!($e), $e);
  }
}
<commit_msg>change for_sequence! macro to take a pattern instead of identifier<commit_after>//! Utility macros

/// Expands into a series of for loops with the given block of code which should
/// treat each type uniformly.
///
/// This is to avoid dynamic dispatch when chaining iterators over generic
/// collections when the types are known.
#[macro_export]
macro_rules! for_sequence {
  (
    $pattern:pat in $($collection:ident),* $do:block
  ) => {
    $(for $pattern in $collection $do)+
  }
}

/// Print the stringified expression followed by its debug formatting
#[macro_export]
macro_rules! show {
  ($e:expr) => {
    println!("{}: {:?}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its pretty debug formatting
#[macro_export]
macro_rules! pretty {
  ($e:expr) => {
    println!("{}: {:#?}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its display formatting
#[macro_export]
macro_rules! display {
  ($e:expr) => {
    println!("{}: {}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its bitstring formatting
#[macro_export]
macro_rules! bits {
  ($e:expr) => {
    println!("{}: {:b}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its hexadecimal formatting
#[macro_export]
macro_rules! hex {
  ($e:expr) => {
    println!("{}: {:x}", stringify!($e), $e);
  }
}

/// Print the stringified expression followed by its pointer formatting
#[macro_export]
macro_rules! address {
  ($e:expr) => {
    println!("{}: {:p}", stringify!($e), $e);
  }
}
<|endoftext|>