<commit_before>use std::fmt::{Debug, Formatter};
use std::fmt::Result as FMTResult;
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;

use clap::ArgMatches;
use regex::Regex;

mod header;

use module::Module;
use runtime::Runtime;
use storage::file::File;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;
use module::helpers::cli::create_tag_filter;
use module::helpers::cli::create_hash_filter;
use module::helpers::cli::create_text_header_field_grep_filter;
use module::helpers::cli::create_content_grep_filter;
use module::helpers::cli::CliFileFilter;

pub struct Notes<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> Notes<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> Notes<'a> {
        Notes {
            rt: rt,
        }
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));
        let name   = matches.value_of("name")
                            .map(String::from)
                            .unwrap_or(String::from(""));
        let tags   = matches.value_of("tags")
                            .and_then(|s| Some(s.split(",").map(String::from).collect()))
                            .unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    name = '{:?}'", name);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(name, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt
            .store()
            .load(self, &parser, &fileid)
            .and_then(|file| {
                info!("Created file in memory: {}", fileid);
                Some(self.rt.store().persist(&parser, file))
            })
            .unwrap_or(false)
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        use ui::file::{FilePrinter, TablePrinter};
        use self::header::get_name_from_header;
        use self::header::get_tags_from_header;
        use std::process::exit;
        use module::helpers::cli::CliFileFilter;

        let parser  = Parser::new(JsonHeaderParser::new(None));

        let filter = {
            let hash_filter = create_hash_filter(matches, "id", true);
            let head_filter = create_text_header_field_grep_filter(matches, "match", "NAME", true);
            let text_filter = create_content_grep_filter(matches, "match", true);
            let tags_filter = create_tag_filter(matches, "tags", true);
            hash_filter.or(Box::new(head_filter)).and(Box::new(text_filter)).and(Box::new(tags_filter))
        };

        let printer = TablePrinter::new(self.rt.is_verbose(), self.rt.is_debugging());

        printer.print_files_custom(
            self.rt.store()
                    .load_for_module(self, &parser)
                    .into_iter()
                    .filter(|f| filter.filter_file(f)),
            &|file| {
                let fl      = file.deref().borrow();
                let hdr     = fl.header();
                let name    = get_name_from_header(hdr);
                let tags    = get_tags_from_header(hdr);

                debug!("Custom printer field: name = '{:?}'", name);
                debug!("Custom printer field: tags = '{:?}'", tags);

                vec![name, tags.join(", ")]
            }
        );
        true
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        let parser = Parser::new(JsonHeaderParser::new(None));

        let filter = {
            let hash_filter = create_hash_filter(matches, "id", false);
            let text_filter = create_text_header_field_grep_filter(matches, "match", "URL", false);
            let tags_filter = create_tag_filter(matches, "tags", false);
            hash_filter.or(Box::new(text_filter)).or(Box::new(tags_filter))
        };

        let result = self.rt
            .store()
            .load_for_module(self, &parser)
            .iter()
            .filter(|file| filter.filter_file(file))
            .map(|file| {
                debug!("File loaded, can remove now: {:?}", file);
                let f = file.deref().borrow();
                self.rt.store().remove(f.id().clone())
            })
            .fold((0, 0), |acc, succeeded| {
                let (worked, failed) = acc;
                if succeeded {
                    (worked + 1, failed)
                } else {
                    (worked, failed + 1)
                }
            });

        let (worked, failed) = result;

        info!("Removing succeeded for {} files", worked);
        info!("Removing failed for {} files", failed);

        return failed == 0;
    }

    fn command_add_tags(&self, matches: &ArgMatches) -> bool {
        use module::helpers::header::tags::data::alter_tags_in_files;
        use self::header::rebuild_header_with_tags;

        let parser = Parser::new(JsonHeaderParser::new(None));
        alter_tags_in_files(self, matches, &parser, |old_tags, cli_tags| {
            let mut new_tags = old_tags.clone();
            new_tags.append(&mut cli_tags.clone());
            new_tags
        }, rebuild_header_with_tags)
    }

    fn command_rm_tags(&self, matches: &ArgMatches) -> bool {
        use module::helpers::header::tags::data::alter_tags_in_files;
        use self::header::rebuild_header_with_tags;

        let parser = Parser::new(JsonHeaderParser::new(None));
        alter_tags_in_files(self, matches, &parser, |old_tags, cli_tags| {
            old_tags.clone()
                .into_iter()
                .filter(|tag| !cli_tags.contains(tag))
                .collect()
        }, rebuild_header_with_tags)
    }

    fn command_set_tags(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for Notes<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some("add_tags") => {
                self.command_add_tags(matches.subcommand_matches("add_tags").unwrap())
            },

            Some("rm_tags") => {
                self.command_rm_tags(matches.subcommand_matches("rm_tags").unwrap())
            },

            Some("set_tags") => {
                self.command_set_tags(matches.subcommand_matches("set_tags").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str{
        "notes"
    }

    fn runtime(&self) -> &Runtime {
        self.rt
    }

}

impl<'a> Debug for Notes<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> FMTResult {
        write!(fmt, "[Module][Notes]");
        Ok(())
    }

}
<commit_msg>Notes: Implement command_set_tags<commit_after>use std::fmt::{Debug, Formatter};
use std::fmt::Result as FMTResult;
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;

use clap::ArgMatches;
use regex::Regex;

mod header;

use module::Module;
use runtime::Runtime;
use storage::file::File;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;
use module::helpers::cli::create_tag_filter;
use module::helpers::cli::create_hash_filter;
use module::helpers::cli::create_text_header_field_grep_filter;
use module::helpers::cli::create_content_grep_filter;
use module::helpers::cli::CliFileFilter;

pub struct Notes<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> Notes<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> Notes<'a> {
        Notes {
            rt: rt,
        }
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));
        let name   = matches.value_of("name")
                            .map(String::from)
                            .unwrap_or(String::from(""));
        let tags   = matches.value_of("tags")
                            .and_then(|s| Some(s.split(",").map(String::from).collect()))
                            .unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    name = '{:?}'", name);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(name, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt
            .store()
            .load(self, &parser, &fileid)
            .and_then(|file| {
                info!("Created file in memory: {}", fileid);
                Some(self.rt.store().persist(&parser, file))
            })
            .unwrap_or(false)
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        use ui::file::{FilePrinter, TablePrinter};
        use self::header::get_name_from_header;
        use self::header::get_tags_from_header;
        use std::process::exit;
        use module::helpers::cli::CliFileFilter;

        let parser  = Parser::new(JsonHeaderParser::new(None));

        let filter = {
            let hash_filter = create_hash_filter(matches, "id", true);
            let head_filter = create_text_header_field_grep_filter(matches, "match", "NAME", true);
            let text_filter = create_content_grep_filter(matches, "match", true);
            let tags_filter = create_tag_filter(matches, "tags", true);
            hash_filter.or(Box::new(head_filter)).and(Box::new(text_filter)).and(Box::new(tags_filter))
        };

        let printer = TablePrinter::new(self.rt.is_verbose(), self.rt.is_debugging());

        printer.print_files_custom(
            self.rt.store()
                    .load_for_module(self, &parser)
                    .into_iter()
                    .filter(|f| filter.filter_file(f)),
            &|file| {
                let fl      = file.deref().borrow();
                let hdr     = fl.header();
                let name    = get_name_from_header(hdr);
                let tags    = get_tags_from_header(hdr);

                debug!("Custom printer field: name = '{:?}'", name);
                debug!("Custom printer field: tags = '{:?}'", tags);

                vec![name, tags.join(", ")]
            }
        );
        true
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        let parser = Parser::new(JsonHeaderParser::new(None));

        let filter = {
            let hash_filter = create_hash_filter(matches, "id", false);
            let text_filter = create_text_header_field_grep_filter(matches, "match", "URL", false);
            let tags_filter = create_tag_filter(matches, "tags", false);
            hash_filter.or(Box::new(text_filter)).or(Box::new(tags_filter))
        };

        let result = self.rt
            .store()
            .load_for_module(self, &parser)
            .iter()
            .filter(|file| filter.filter_file(file))
            .map(|file| {
                debug!("File loaded, can remove now: {:?}", file);
                let f = file.deref().borrow();
                self.rt.store().remove(f.id().clone())
            })
            .fold((0, 0), |acc, succeeded| {
                let (worked, failed) = acc;
                if succeeded {
                    (worked + 1, failed)
                } else {
                    (worked, failed + 1)
                }
            });

        let (worked, failed) = result;

        info!("Removing succeeded for {} files", worked);
        info!("Removing failed for {} files", failed);

        return failed == 0;
    }

    fn command_add_tags(&self, matches: &ArgMatches) -> bool {
        use module::helpers::header::tags::data::alter_tags_in_files;
        use self::header::rebuild_header_with_tags;

        let parser = Parser::new(JsonHeaderParser::new(None));
        alter_tags_in_files(self, matches, &parser, |old_tags, cli_tags| {
            let mut new_tags = old_tags.clone();
            new_tags.append(&mut cli_tags.clone());
            new_tags
        }, rebuild_header_with_tags)
    }

    fn command_rm_tags(&self, matches: &ArgMatches) -> bool {
        use module::helpers::header::tags::data::alter_tags_in_files;
        use self::header::rebuild_header_with_tags;

        let parser = Parser::new(JsonHeaderParser::new(None));
        alter_tags_in_files(self, matches, &parser, |old_tags, cli_tags| {
            old_tags.clone()
                .into_iter()
                .filter(|tag| !cli_tags.contains(tag))
                .collect()
        }, rebuild_header_with_tags)
    }

    fn command_set_tags(&self, matches: &ArgMatches) -> bool {
        use module::helpers::header::tags::data::alter_tags_in_files;
        use self::header::rebuild_header_with_tags;

        let parser = Parser::new(JsonHeaderParser::new(None));
        alter_tags_in_files(self, matches, &parser, |old_tags, cli_tags| {
            cli_tags.clone()
        }, rebuild_header_with_tags)
    }

}

impl<'a> Module<'a> for Notes<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some("add_tags") => {
                self.command_add_tags(matches.subcommand_matches("add_tags").unwrap())
            },

            Some("rm_tags") => {
                self.command_rm_tags(matches.subcommand_matches("rm_tags").unwrap())
            },

            Some("set_tags") => {
                self.command_set_tags(matches.subcommand_matches("set_tags").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str{
        "notes"
    }

    fn runtime(&self) -> &Runtime {
        self.rt
    }

}

impl<'a> Debug for Notes<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> FMTResult {
        write!(fmt, "[Module][Notes]");
        Ok(())
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::path::PathBuf;

use habitat_win_users::account::Account;

extern "C" {
    pub fn GetUserTokenStatus() -> u32;
}

fn get_sid_by_name(name: &str) -> Option<String> {
    match Account::from_name(name) {
        Some(acct) => {
            match acct.sid.to_string() {
                Ok(username) => Some(username),
                Err(_) => None,
            }
        }
        None => None,
    }
}

pub fn get_uid_by_name(owner: &str) -> Option<String> {
    get_sid_by_name(owner)
}

pub fn get_gid_by_name(group: &str) -> Option<String> {
    get_sid_by_name(group)
}

pub fn get_current_username() -> Option<String> {
    match env::var("USERNAME").ok() {
        Some(username) => Some(username.to_lowercase()),
        None => None,
    }
}

// this is a no-op on windows
pub fn get_current_groupname() -> Option<String> {
    Some(String::new())
}

pub fn get_effective_uid() -> u32 {
    unsafe { GetUserTokenStatus() }
}

pub fn get_home_for_user(username: &str) -> Option<PathBuf> {
    unimplemented!();
}

pub fn root_level_account() -> String {
    env::var("COMPUTERNAME").unwrap().to_uppercase() + "$"
}

#[cfg(test)]
mod tests {
    use std::env;

    use super::*;

    #[test]
    fn downcase_current_username() {
        env::set_var("USERNAME", "uSer");
        assert_eq!(get_current_username().unwrap(), "user")
    }

    #[test]
    fn return_none_when_no_user() {
        env::remove_var("USERNAME");
        assert_eq!(get_current_username(), None)
    }
}
<commit_msg>getting gid on windows should be a no-op<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::path::PathBuf;

use habitat_win_users::account::Account;

extern "C" {
    pub fn GetUserTokenStatus() -> u32;
}

fn get_sid_by_name(name: &str) -> Option<String> {
    match Account::from_name(name) {
        Some(acct) => {
            match acct.sid.to_string() {
                Ok(username) => Some(username),
                Err(_) => None,
            }
        }
        None => None,
    }
}

pub fn get_uid_by_name(owner: &str) -> Option<String> {
    get_sid_by_name(owner)
}

// this is a no-op on windows
pub fn get_gid_by_name(group: &str) -> Option<String> {
    Some(String::new())
}

pub fn get_current_username() -> Option<String> {
    match env::var("USERNAME").ok() {
        Some(username) => Some(username.to_lowercase()),
        None => None,
    }
}

// this is a no-op on windows
pub fn get_current_groupname() -> Option<String> {
    Some(String::new())
}

pub fn get_effective_uid() -> u32 {
    unsafe { GetUserTokenStatus() }
}

pub fn get_home_for_user(username: &str) -> Option<PathBuf> {
    unimplemented!();
}

pub fn root_level_account() -> String {
    env::var("COMPUTERNAME").unwrap().to_uppercase() + "$"
}

#[cfg(test)]
mod tests {
    use std::env;

    use super::*;

    #[test]
    fn downcase_current_username() {
        env::set_var("USERNAME", "uSer");
        assert_eq!(get_current_username().unwrap(), "user")
    }

    #[test]
    fn return_none_when_no_user() {
        env::remove_var("USERNAME");
        assert_eq!(get_current_username(), None)
    }
}
<|endoftext|>


<commit_before>use syntax_definition::*;
use scope::*;
use onig::{self, Region};
use std::usize;
use std::i32;

#[derive(Debug, Clone)]
pub struct ParseState {
    stack: Vec<StateLevel>,
    pub scope_stack: ScopeStack,
    first_line: bool,
}

#[derive(Debug, Clone)]
struct StateLevel {
    context: ContextPtr,
    prototype: Option<ContextPtr>,
    captures: Option<(Region, String)>,
}

#[derive(Debug)]
struct RegexMatch {
    regions: Region,
    context: ContextPtr,
    pat_index: usize,
}

impl ParseState {
    pub fn new(syntax: &SyntaxDefinition) -> ParseState {
        let start_state = StateLevel {
            context: syntax.contexts["main"].clone(),
            prototype: None,
            captures: None,
        };
        ParseState {
            stack: vec![start_state],
            scope_stack: ScopeStack::new(),
            first_line: true,
        }
    }

    pub fn parse_line(&mut self, line: &str) -> Vec<(usize, ScopeStackOp)> {
        assert!(self.stack.len() > 0,
                "Somehow main context was popped from the stack");
        let mut match_start = 0;
        let mut res = Vec::new();
        if self.first_line {
            let cur_level = &self.stack[self.stack.len() - 1];
            let context = cur_level.context.borrow();
            if !context.meta_content_scope.is_empty() {
                res.push((0, ScopeStackOp::Push(context.meta_content_scope[0])));
            }
            self.first_line = false;
        }

        // TODO push file syntax on first line
        // TODO set regex parameters correctly for start of file
        while self.parse_next_token(line, &mut match_start, &mut res) {
        }
        // apply operations to our scope to keep up
        // TODO do we even need to keep a scope stack in the parser state?
        for &(_, ref op) in res.iter() {
            self.scope_stack.apply(op);
        }
        return res;
    }

    fn parse_next_token(&mut self,
                        line: &str,
                        start: &mut usize,
                        ops: &mut Vec<(usize, ScopeStackOp)>)
                        -> bool {
        let cur_match = {
            let cur_level = &self.stack[self.stack.len() - 1];
            let mut min_start = usize::MAX;
            let mut cur_match: Option<RegexMatch> = None;
            let context_chain = self.stack
                .iter()
                .filter_map(|lvl| lvl.prototype.as_ref().map(|x| x.clone()))
                .chain(Some(cur_level.context.clone()).into_iter());
            // println!("{:#?}", cur_level);
            for ctx in context_chain {
                for (pat_context_ptr, pat_index) in context_iter(ctx) {
                    let pat_context = pat_context_ptr.borrow();
                    let match_pat = pat_context.match_at(pat_index);

                    // println!("{:?}", match_pat.regex_str);
                    let refs_regex = if cur_level.captures.is_some() && match_pat.regex.is_none() {
                        let &(ref region, ref s) = cur_level.captures.as_ref().unwrap();
                        Some(match_pat.compile_with_refs(region, s))
                    } else {
                        None
                    };
                    let regex = if let Some(ref rgx) = refs_regex {
                        rgx
                    } else {
                        match_pat.regex.as_ref().unwrap()
                    };
                    let mut regions = Region::new();
                    // TODO caching
                    let matched = regex.search_with_options(line,
                                                            *start,
                                                            line.len(),
                                                            onig::SEARCH_OPTION_NONE,
                                                            Some(&mut regions));
                    if let Some(match_start) = matched {
                        let match_end = regions.pos(0).unwrap().1;
                        // this is necessary to avoid infinite looping on dumb patterns
                        let does_something = match match_pat.operation {
                            MatchOperation::None => match_start != match_end,
                            _ => true,
                        };
                        if match_start < min_start && does_something {
                            min_start = match_start;
                            // TODO pass by immutable ref and re-use context and regions
                            cur_match = Some(RegexMatch {
                                regions: regions,
                                context: pat_context_ptr.clone(),
                                pat_index: pat_index,
                            });
                        }
                    }
                }
            }
            cur_match
        };

        if let Some(reg_match) = cur_match {
            let (_, match_end) = reg_match.regions.pos(0).unwrap();
            *start = match_end;
            let level_context = self.stack[self.stack.len() - 1].context.clone();
            self.exec_pattern(line, reg_match, level_context, ops);
            true
        } else {
            false
        }
    }

    fn exec_pattern(&mut self,
                    line: &str,
                    reg_match: RegexMatch,
                    level_context_ptr: ContextPtr,
                    ops: &mut Vec<(usize, ScopeStackOp)>) {
        let (match_start, match_end) = reg_match.regions.pos(0).unwrap();
        let context = reg_match.context.borrow();
        let pat = context.match_at(reg_match.pat_index);
        let level_context = level_context_ptr.borrow();
        // println!("running pattern {:?}", pat);

        self.push_meta_ops(true, match_start, &*level_context, &pat.operation, ops);
        for s in pat.scope.iter() {
            // println!("pushing {:?} at {}", s, match_start);
            ops.push((match_start, ScopeStackOp::Push(s.clone())));
        }
        if let Some(ref capture_map) = pat.captures {
            // captures could appear in an arbitrary order, have to produce ops in right order
            // ex: ((bob)|(hi))* could match hibob in wrong order, and outer has to push first
            // we don't have to handle a capture matching multiple times, Sublime doesn't
            let mut map: Vec<((usize, i32), ScopeStackOp)> = Vec::new();
            for (cap_index, scopes) in capture_map.iter() {
                if let Some((cap_start, cap_end)) = reg_match.regions.pos(*cap_index) {
                    for scope in scopes.iter() {
                        map.push(((cap_start, -((cap_end - cap_start) as i32)),
                                  ScopeStackOp::Push(scope.clone())));
                    }
                    map.push(((cap_end, i32::MIN), ScopeStackOp::Pop(scopes.len())));
                }
            }
            map.sort_by(|a, b| a.0.cmp(&b.0));
            for ((index, _), op) in map.into_iter() {
                ops.push((index, op));
            }
        }
        if !pat.scope.is_empty() {
            ops.push((match_end, ScopeStackOp::Pop(pat.scope.len())));
        }
        self.push_meta_ops(false, match_end, &*level_context, &pat.operation, ops);

        self.perform_op(line, &reg_match.regions, pat);
    }

    fn push_meta_ops(&self,
                     initial: bool,
                     index: usize,
                     cur_context: &Context,
                     match_op: &MatchOperation,
                     ops: &mut Vec<(usize, ScopeStackOp)>) {
        let involves_pop = match match_op {
            &MatchOperation::Pop => true,
            &MatchOperation::Set(_) => true,
            &MatchOperation::Push(_) => false,
            &MatchOperation::None => false,
        };
        // println!("metas ops for {:?}, is pop: {}, initial: {}",
        //          match_op,
        //          involves_pop,
        //          initial);
        // println!("{:?}", cur_context.meta_scope);
        if involves_pop {
            let v = if initial {
                &cur_context.meta_content_scope
            } else {
                &cur_context.meta_scope
            };
            if !v.is_empty() {
                ops.push((index, ScopeStackOp::Pop(v.len())));
            }
        }
        match match_op {
            &MatchOperation::Push(ref context_refs) |
            &MatchOperation::Set(ref context_refs) => {
                for r in context_refs {
                    let ctx_ptr = r.resolve();
                    let ctx = ctx_ptr.borrow();
                    let v = if initial {
                        &ctx.meta_scope
                    } else {
                        &ctx.meta_content_scope
                    };
                    for scope in v.iter() {
                        ops.push((index, ScopeStackOp::Push(scope.clone())));
                    }
                }
            }
            &MatchOperation::None |
            &MatchOperation::Pop => (),
        }
    }

    fn perform_op(&mut self, line: &str, regions: &Region, pat: &MatchPattern) {
        let ctx_refs = match pat.operation {
            MatchOperation::Push(ref ctx_refs) => ctx_refs,
            MatchOperation::Set(ref ctx_refs) => {
                self.stack.pop();
                ctx_refs
            }
            MatchOperation::Pop => {
                self.stack.pop();
                return;
            }
            MatchOperation::None => return,
        };
        for (i, r) in ctx_refs.iter().enumerate() {
            let proto = if i == 0 {
                pat.with_prototype.clone()
            } else {
                None
            };
            let ctx_ptr = r.resolve();
            let captures = {
                let ctx = ctx_ptr.borrow();
                if ctx.uses_backrefs {
                    // TODO maybe move the Region instead of cloning
                    Some((regions.clone(), line.to_owned()))
                } else {
                    None
                }
            };
            self.stack.push(StateLevel {
                context: ctx_ptr,
                prototype: proto,
                captures: captures,
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use package_set::PackageSet;
    use parser::*;
    use scope::*;
    use util::debug_print_ops;

    #[test]
    fn can_parse() {
        use scope::ScopeStackOp::{Push, Pop};
        let ps = PackageSet::load_from_folder("testdata/Packages").unwrap();
        let mut state = {
            let syntax = ps.find_syntax_by_name("Ruby on Rails").unwrap();
            ParseState::new(syntax)
        };
        let mut state2 = {
            let syntax = ps.find_syntax_by_name("HTML (Rails)").unwrap();
            ParseState::new(syntax)
        };

        let line = "module Bob::Wow::Troll::Five; 5; end";
        let ops = state.parse_line(line);
        debug_print_ops(line, &ops);

        let test_ops = vec![
            (0, Push(Scope::new("source.ruby.rails").unwrap())),
            (0, Push(Scope::new("meta.module.ruby").unwrap())),
            (0, Push(Scope::new("keyword.control.module.ruby").unwrap())),
            (6, Pop(1)),
            (7, Push(Scope::new("entity.name.type.module.ruby").unwrap())),
            (7, Push(Scope::new("entity.other.inherited-class.module.first.ruby").unwrap())),
            (10, Push(Scope::new("punctuation.separator.inheritance.ruby").unwrap())),
            (12, Pop(1)),
            (12, Pop(1)),
        ];
        assert_eq!(&ops[0..test_ops.len()], &test_ops[..]);

        let line2 = "def lol(wow = 5)";
        let ops2 = state.parse_line(line2);
        debug_print_ops(line2, &ops2);
        let test_ops2 =
            vec![(0, Push(Scope::new("meta.function.method.with-arguments.ruby").unwrap())),
                 (0, Push(Scope::new("keyword.control.def.ruby").unwrap())),
                 (3, Pop(1)),
                 (4, Push(Scope::new("entity.name.function.ruby").unwrap())),
                 (7, Pop(1)),
                 (7, Push(Scope::new("punctuation.definition.parameters.ruby").unwrap())),
                 (8, Pop(1)),
                 (8, Push(Scope::new("variable.parameter.function.ruby").unwrap())),
                 (12, Push(Scope::new("keyword.operator.assignment.ruby").unwrap())),
                 (13, Pop(1)),
                 (14, Push(Scope::new("constant.numeric.ruby").unwrap())),
                 (15, Pop(1)),
                 (15, Pop(1)),
                 (15, Push(Scope::new("punctuation.definition.parameters.ruby").unwrap())),
                 (16, Pop(1)),
                 (16, Pop(1))];
        assert_eq!(ops2, test_ops2);

        let line3 = "<script>var lol = '<% def wow(";
        let ops3 = state2.parse_line(line3);
        debug_print_ops(line3, &ops3);
        let mut test_stack = ScopeStack::new();
        test_stack.push(Scope::new("text.html.ruby").unwrap());
        test_stack.push(Scope::new("text.html.basic").unwrap());
        test_stack.push(Scope::new("source.js.embedded.html").unwrap());
        test_stack.push(Scope::new("string.quoted.single.js").unwrap());
        test_stack.push(Scope::new("source.ruby.rails.embedded.html").unwrap());
        test_stack.push(Scope::new("meta.function.method.with-arguments.ruby").unwrap());
        test_stack.push(Scope::new("variable.parameter.function.ruby").unwrap());
        println!("{:?}", state2.scope_stack);
        println!("{:?}", test_stack);
        assert_eq!(state2.scope_stack, test_stack);

        // for testing backrefs
        let line4 = "lol = <<-END wow END";
        let ops4 = state.parse_line(line4);
        debug_print_ops(line4, &ops4);
        let test_ops4 = vec![
            (4, Push(Scope::new("keyword.operator.assignment.ruby").unwrap())),
            (5, Pop(1)),
            (6, Push(Scope::new("string.unquoted.heredoc.ruby").unwrap())),
            (6, Push(Scope::new("punctuation.definition.string.begin.ruby").unwrap())),
            (12, Pop(1)),
            (16, Push(Scope::new("punctuation.definition.string.end.ruby").unwrap())),
            (20, Pop(1)),
            (20, Pop(1)),
        ];
        assert_eq!(ops4, test_ops4);

        // assert!(false);
    }
}
<commit_msg>Don't constantly allocate regions<commit_after>use syntax_definition::*;
use scope::*;
use onig::{self, Region};
use std::usize;
use std::i32;

#[derive(Debug, Clone)]
pub struct ParseState {
    stack: Vec<StateLevel>,
    pub scope_stack: ScopeStack,
    first_line: bool,
}

#[derive(Debug, Clone)]
struct StateLevel {
    context: ContextPtr,
    prototype: Option<ContextPtr>,
    captures: Option<(Region, String)>,
}

#[derive(Debug)]
struct RegexMatch {
    regions: Region,
    context: ContextPtr,
    pat_index: usize,
}

impl ParseState {
    pub fn new(syntax: &SyntaxDefinition) -> ParseState {
        let start_state = StateLevel {
            context: syntax.contexts["main"].clone(),
            prototype: None,
            captures: None,
        };
        ParseState {
            stack: vec![start_state],
            scope_stack: ScopeStack::new(),
            first_line: true,
        }
    }

    pub fn parse_line(&mut self, line: &str) -> Vec<(usize, ScopeStackOp)> {
        assert!(self.stack.len() > 0,
                "Somehow main context was popped from the stack");
        let mut match_start = 0;
        let mut res = Vec::new();
        if self.first_line {
            let cur_level = &self.stack[self.stack.len() - 1];
            let context = cur_level.context.borrow();
            if !context.meta_content_scope.is_empty() {
                res.push((0, ScopeStackOp::Push(context.meta_content_scope[0])));
            }
            self.first_line = false;
        }

        // TODO push file syntax on first line
        // TODO set regex parameters correctly for start of file
        let mut regions = Region::with_capacity(8);
        while self.parse_next_token(line, &mut match_start, &mut regions, &mut res) {
        }
        // apply operations to our scope to keep up
        // TODO do we even need to keep a scope stack in the parser state?
        for &(_, ref op) in res.iter() {
            self.scope_stack.apply(op);
        }
        return res;
    }

    fn parse_next_token(&mut self,
                        line: &str,
                        start: &mut usize,
                        regions: &mut Region,
                        ops: &mut Vec<(usize, ScopeStackOp)>)
                        -> bool {
        let cur_match = {
            let cur_level = &self.stack[self.stack.len() - 1];
            let mut min_start = usize::MAX;
            let mut cur_match: Option<RegexMatch> = None;
            let context_chain = self.stack
                .iter()
                .filter_map(|lvl| lvl.prototype.as_ref().map(|x| x.clone()))
                .chain(Some(cur_level.context.clone()).into_iter());
            // println!("{:#?}", cur_level);
            for ctx in context_chain {
                for (pat_context_ptr, pat_index) in context_iter(ctx) {
                    let pat_context = pat_context_ptr.borrow();
                    let match_pat = pat_context.match_at(pat_index);

                    // println!("{:?}", match_pat.regex_str);
                    let refs_regex = if cur_level.captures.is_some() && match_pat.regex.is_none() {
                        let &(ref region, ref s) = cur_level.captures.as_ref().unwrap();
                        Some(match_pat.compile_with_refs(region, s))
                    } else {
                        None
                    };
                    let regex = if let Some(ref rgx) = refs_regex {
                        rgx
                    } else {
                        match_pat.regex.as_ref().unwrap()
                    };
                    // TODO caching
                    let matched = regex.search_with_options(line,
                                                            *start,
                                                            line.len(),
                                                            onig::SEARCH_OPTION_NONE,
                                                            Some(regions));
                    if let Some(match_start) = matched {
                        let match_end = regions.pos(0).unwrap().1;
                        // this is necessary to avoid infinite looping on dumb patterns
                        let does_something = match match_pat.operation {
                            MatchOperation::None => match_start != match_end,
                            _ => true,
                        };
                        if match_start < min_start && does_something {
                            min_start = match_start;
                            // TODO pass by immutable ref and re-use context and regions
                            cur_match = Some(RegexMatch {
                                regions: regions.clone(),
                                context: pat_context_ptr.clone(),
                                pat_index: pat_index,
                            });
                        }
                    }
                }
            }
            cur_match
        };

        if let Some(reg_match) = cur_match {
            let (_, match_end) = reg_match.regions.pos(0).unwrap();
            *start = match_end;
            let level_context = self.stack[self.stack.len() - 1].context.clone();
            self.exec_pattern(line, reg_match, level_context, ops);
            true
        } else {
            false
        }
    }

    fn exec_pattern(&mut self,
                    line: &str,
                    reg_match: RegexMatch,
                    level_context_ptr: ContextPtr,
                    ops: &mut Vec<(usize, ScopeStackOp)>) {
        let (match_start, match_end) = reg_match.regions.pos(0).unwrap();
        let context = reg_match.context.borrow();
        let pat = context.match_at(reg_match.pat_index);
        let level_context = level_context_ptr.borrow();
        // println!("running pattern {:?}", pat);

        self.push_meta_ops(true, match_start, &*level_context, &pat.operation, ops);
        for s in pat.scope.iter() {
            // println!("pushing {:?} at {}", s, match_start);
            ops.push((match_start, ScopeStackOp::Push(s.clone())));
        }
        if let Some(ref capture_map) = pat.captures {
            // captures could appear in an arbitrary order, have to produce ops in right order
            // ex: ((bob)|(hi))* could match hibob in wrong order, and outer has to push first
            // we don't have to handle a capture matching multiple times, Sublime doesn't
            let mut map: Vec<((usize, i32), ScopeStackOp)> = Vec::new();
            for (cap_index, scopes) in capture_map.iter() {
                if let Some((cap_start, cap_end)) = reg_match.regions.pos(*cap_index) {
                    for scope in scopes.iter() {
                        map.push(((cap_start, -((cap_end - cap_start) as i32)),
                                  ScopeStackOp::Push(scope.clone())));
                    }
                    map.push(((cap_end, i32::MIN), ScopeStackOp::Pop(scopes.len())));
                }
            }
            map.sort_by(|a, b| a.0.cmp(&b.0));
            for ((index, _), op) in map.into_iter() {
                ops.push((index, op));
            }
        }
        if !pat.scope.is_empty() {
            ops.push((match_end, ScopeStackOp::Pop(pat.scope.len())));
        }
        self.push_meta_ops(false, match_end, &*level_context, &pat.operation, ops);

        self.perform_op(line, &reg_match.regions, pat);
    }

    fn push_meta_ops(&self,
                     initial: bool,
                     index: usize,
                     cur_context: &Context,
                     match_op: &MatchOperation,
                     ops: &mut Vec<(usize, ScopeStackOp)>) {
        let involves_pop = match match_op {
            &MatchOperation::Pop => true,
            &MatchOperation::Set(_) => true,
            &MatchOperation::Push(_) => false,
            &MatchOperation::None => false,
        };
        // println!("metas ops for {:?}, is pop: {}, initial: {}",
        //          match_op,
        //          involves_pop,
        //          initial);
        // println!("{:?}", cur_context.meta_scope);
        if involves_pop {
            let v = if initial {
                &cur_context.meta_content_scope
            } else {
                &cur_context.meta_scope
            };
            if !v.is_empty() {
                ops.push((index, ScopeStackOp::Pop(v.len())));
            }
        }
        match match_op {
            &MatchOperation::Push(ref context_refs) |
            &MatchOperation::Set(ref context_refs) => {
                for r in context_refs {
                    let ctx_ptr = r.resolve();
                    let ctx = ctx_ptr.borrow();
                    let v = if initial {
                        &ctx.meta_scope
                    } else {
                        &ctx.meta_content_scope
                    };
                    for scope in v.iter() {
                        ops.push((index, ScopeStackOp::Push(scope.clone())));
                    }
                }
            }
            &MatchOperation::None |
            &MatchOperation::Pop => (),
        }
    }

    fn perform_op(&mut self, line: &str, regions: &Region, pat: &MatchPattern) {
        let ctx_refs = match pat.operation {
            MatchOperation::Push(ref ctx_refs) => ctx_refs,
            MatchOperation::Set(ref ctx_refs) => {
                self.stack.pop();
                ctx_refs
            }
            MatchOperation::Pop => {
                self.stack.pop();
                return;
            }
            MatchOperation::None => return,
        };
        for (i, r) in ctx_refs.iter().enumerate() {
            let proto = if i == 0 {
                pat.with_prototype.clone()
            } else {
                None
            };
            let ctx_ptr = r.resolve();
            let captures = {
                let ctx = ctx_ptr.borrow();
                if ctx.uses_backrefs {
                    // TODO maybe move the Region instead of cloning
                    Some((regions.clone(), line.to_owned()))
                } else {
                    None
                }
            };
            self.stack.push(StateLevel {
                context: ctx_ptr,
                prototype: proto,
                captures: captures,
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use package_set::PackageSet;
    use parser::*;
    use scope::*;
    use util::debug_print_ops;

    #[test]
    fn can_parse() {
        use scope::ScopeStackOp::{Push, Pop};
        let ps = PackageSet::load_from_folder("testdata/Packages").unwrap();
        let mut state = {
            let syntax = ps.find_syntax_by_name("Ruby on Rails").unwrap();
            ParseState::new(syntax)
        };
        let mut state2 = {
            let syntax = ps.find_syntax_by_name("HTML (Rails)").unwrap();
            ParseState::new(syntax)
        };

        let line = "module Bob::Wow::Troll::Five; 5; end";
        let ops = state.parse_line(line);
        debug_print_ops(line, &ops);

        let test_ops = vec![
            (0, Push(Scope::new("source.ruby.rails").unwrap())),
            (0, Push(Scope::new("meta.module.ruby").unwrap())),
            (0, Push(Scope::new("keyword.control.module.ruby").unwrap())),
            (6, Pop(1)),
            (7, Push(Scope::new("entity.name.type.module.ruby").unwrap())),
            (7, Push(Scope::new("entity.other.inherited-class.module.first.ruby").unwrap())),
            (10, Push(Scope::new("punctuation.separator.inheritance.ruby").unwrap())),
            (12, Pop(1)),
            (12, Pop(1)),
        ];
        assert_eq!(&ops[0..test_ops.len()], &test_ops[..]);

        let line2 = "def lol(wow = 5)";
        let ops2 = state.parse_line(line2);
        debug_print_ops(line2, &ops2);
        let test_ops2 =
            vec![(0, Push(Scope::new("meta.function.method.with-arguments.ruby").unwrap())),
                 (0, Push(Scope::new("keyword.control.def.ruby").unwrap())),
                 (3, Pop(1)),
                 (4, Push(Scope::new("entity.name.function.ruby").unwrap())),
                 (7, Pop(1)),
                 (7, Push(Scope::new("punctuation.definition.parameters.ruby").unwrap())),
                 (8, Pop(1)),
                 (8, Push(Scope::new("variable.parameter.function.ruby").unwrap())),
                 (12, Push(Scope::new("keyword.operator.assignment.ruby").unwrap())),
                 (13, Pop(1)),
                 (14, Push(Scope::new("constant.numeric.ruby").unwrap())),
                 (15, Pop(1)),
                 (15, Pop(1)),
                 (15, Push(Scope::new("punctuation.definition.parameters.ruby").unwrap())),
                 (16, Pop(1)),
                 (16, Pop(1))];
        assert_eq!(ops2, test_ops2);

        let line3 = "<script>var lol = '<% def wow(";
        let ops3 = state2.parse_line(line3);
        debug_print_ops(line3, &ops3);
        let mut test_stack = ScopeStack::new();
        test_stack.push(Scope::new("text.html.ruby").unwrap());
        test_stack.push(Scope::new("text.html.basic").unwrap());
        test_stack.push(Scope::new("source.js.embedded.html").unwrap());
        test_stack.push(Scope::new("string.quoted.single.js").unwrap());
        test_stack.push(Scope::new("source.ruby.rails.embedded.html").unwrap());
        test_stack.push(Scope::new("meta.function.method.with-arguments.ruby").unwrap());
        test_stack.push(Scope::new("variable.parameter.function.ruby").unwrap());
        println!("{:?}", state2.scope_stack);
        println!("{:?}", test_stack);
        assert_eq!(state2.scope_stack, test_stack);

        // for testing backrefs
        let line4 = "lol = <<-END wow END";
        let ops4 = state.parse_line(line4);
        debug_print_ops(line4, &ops4);
        let test_ops4 = vec![
            (4, Push(Scope::new("keyword.operator.assignment.ruby").unwrap())),
            (5, Pop(1)),
            (6, Push(Scope::new("string.unquoted.heredoc.ruby").unwrap())),
            (6, Push(Scope::new("punctuation.definition.string.begin.ruby").unwrap())),
            (12, Pop(1)),
            (16, Push(Scope::new("punctuation.definition.string.end.ruby").unwrap())),
            (20, Pop(1)),
            (20, Pop(1)),
        ];
        assert_eq!(ops4, test_ops4);

        // assert!(false);
    }
}
<|endoftext|>


<commit_before>use std::str;

const COMMENT_START: char = '#';
const STRING_BOUNDARY: char = '"';
const ASSIGNMENT_OPERATOR: char = '=';

#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
    Comment(String),
    Assignment(Option<String>, Expression),
}

#[derive(Debug, PartialEq, Clone)]
pub enum Expression {
    Text(String),
}

named!(pub parse< Vec<Statement> >, fold_many0!(statement, Vec::new(), |mut acc: Vec<_>, item| {
    acc.push(item);
    acc
}));

named!(statement<Statement>, ws!(alt!(
    comment => {|content: &str| Statement::Comment(content.to_owned())} |
    assignment => {|(name, expr): (Option<&str>, Expression)| Statement::Assignment(name.map(|s| s.to_owned()), expr)}
)));

named!(comment<&str>,
    do_parse!(
        char!(COMMENT_START) >>
        content: take_until_and_consume!("\n") >>
        (str::from_utf8(content).unwrap())
    )
);

named!(assignment<(Option<&str>, Expression)>,
    do_parse!(
        name: assignment_name >>
        char!(ASSIGNMENT_OPERATOR) >>
        expr: expression >>
        char!('\n') >>
        (name, expr)
    )
);

named!(assignment_name< Option<&str> >,
    map!(
        opt!(assignment_name_impl),
        |n: Option<&'a [u8]>| n.and_then(|s| str::from_utf8(s).ok())
    )
);

// Without this separation, type inference fails
named!(assignment_name_impl<&[u8]>,
    take_while1_s!(is_valid_assignment_name_char)
);

named!(expression<Expression>,
    alt!(
        expr_text => {|text: &str| Expression::Text(text.to_owned())}
    )
);

named!(expr_text<&str>,
    map!(
        delimited!(
            char!(STRING_BOUNDARY),
            take_while!(is_string_boundary),
            char!(STRING_BOUNDARY)
        ),
        |s: &'a [u8]| str::from_utf8(s).unwrap()
    )
);

fn is_valid_assignment_name_char(c: u8) -> bool {
    let ch = c as char;
    ch.is_alphanumeric() || ch == '_'
}

fn is_string_boundary(c: u8) -> bool {
    c as char == STRING_BOUNDARY
}
<commit_msg>Fixed bug that was preventing parser from working<commit_after>use std::str;

const COMMENT_START: char = '#';
const STRING_BOUNDARY: char = '"';
const ASSIGNMENT_OPERATOR: char = '=';

#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
    Comment(String),
    Assignment(Option<String>, Expression),
}

#[derive(Debug, PartialEq, Clone)]
pub enum Expression {
    Text(String),
}

named!(pub parse< Vec<Statement> >, fold_many0!(statement, Vec::new(), |mut acc: Vec<_>, item| {
    acc.push(item);
    acc
}));

named!(statement<Statement>, ws!(alt!(
    comment => {|content: &str| Statement::Comment(content.to_owned())} |
    assignment => {|(name, expr): (Option<&str>, Expression)| Statement::Assignment(name.map(|s| s.to_owned()), expr)}
)));

named!(comment<&str>,
    do_parse!(
        char!(COMMENT_START) >>
        content: take_until_and_consume!("\n") >>
        (str::from_utf8(content).unwrap())
    )
);

named!(assignment<(Option<&str>, Expression)>,
    do_parse!(
        name: assignment_name >>
        char!(ASSIGNMENT_OPERATOR) >>
        expr: expression >>
        char!('\n') >>
        (name, expr)
    )
);

named!(assignment_name< Option<&str> >,
    map!(
        opt!(assignment_name_impl),
        |n: Option<&'a [u8]>| n.and_then(|s| str::from_utf8(s).ok())
    )
);

// Without this separation, type inference fails
named!(assignment_name_impl<&[u8]>,
    take_while1_s!(is_valid_assignment_name_char)
);

named!(expression<Expression>,
    alt!(
        expr_text => {|text: &str| Expression::Text(text.to_owned())}
    )
);

named!(expr_text<&str>,
    map_res!(
        delimited!(
            char!(STRING_BOUNDARY),
            take_till!(is_string_boundary),
            char!(STRING_BOUNDARY)
        ),
        |s: &'a [u8]| str::from_utf8(s)
    )
);

fn is_valid_assignment_name_char(c: u8) -> bool {
    let ch = c as char;
    ch.is_alphanumeric() || ch == '_'
}

fn is_string_boundary(c: u8) -> bool {
    c as char == STRING_BOUNDARY
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use std::str::Chars;
use std::iter::FromIterator;
use std::marker::PhantomData;

use combine::{Parser, ParseResult, Stream, parser};
use combine::char::{CrLf, Tab, tab, char, crlf};
use combine::combinator::{Many, FnParser, NoneOf, Skip, Or, Token, or, many, none_of};

pub type Name = String;
pub type SelectionSet = Vec<Selection>;

#[derive(Debug,PartialEq)]
pub struct Document {
    definitions: Vec<Definition>,
}

#[derive(Debug,PartialEq)]
pub enum Definition {
    OperationDefinition(Operation),
    SelectionSetDefinition(SelectionSet),
    FragmentDefinition(Fragment),
}

#[derive(Debug,PartialEq)]
pub struct Operation {
    op_type: OperationType,
    name: Option<Name>,
    variable_definitions: Vec<VariableDefinition>,
    directives: Vec<Directive>,
}

impl Operation {
    fn new(op_type: OperationType,
           name: Option<Name>,
           variable_definitions: Vec<VariableDefinition>,
           directives: Vec<Directive>)
           -> Operation {
        Operation {
            op_type: op_type,
            name: name,
            variable_definitions: variable_definitions,
            directives: directives,
        }
    }
}

#[derive(Debug,PartialEq)]
pub enum OperationType {
    Query,
    Mutation,
}

#[derive(Debug,PartialEq)]
pub struct VariableDefinition {
    variable: Variable,
    var_type: Type,
    default_value: Option<Value>,
}

type Variable = String;

#[derive(Debug,PartialEq)]
pub enum Type {
    NamedType(Name),
    ListType(Box<Type>),
    NonNullType(Box<Type>),
}

#[derive(Debug,PartialEq)]
pub enum Value {
    Var(Variable),
    IntValue(i32),
    FloatValue(f32),
    StringValue(String),
    BooleanValue(bool),
    NullValue,
    EnumValue(String),
    ListValue(Vec<Value>),
    ObjectValue(HashMap<String, Value>),
}

#[derive(Debug,PartialEq)]
pub struct Directive {
    name: Name,
    arguments: Vec<Argument>,
}

#[derive(Debug,PartialEq)]
pub struct Argument {
    name: Name,
    value: Value,
}

#[derive(Debug,PartialEq)]
pub enum Selection {
    FieldSelection(Field),
    FragmentSpread(Name, Vec<Directive>),
    InlineFragment(Option<Type>, Vec<Directive>, SelectionSet),
}

#[derive(Debug,PartialEq)]
pub struct Field {
    alias: Option<Name>,
    name: Name,
    arguments: Vec<Argument>,
    directives: Vec<Directive>,
    selection_set: SelectionSet,
}

impl Field {
    fn new(alias: Option<Name>,
           name: Name,
           arguments: Vec<Argument>,
           directives: Vec<Directive>,
           selection_set: SelectionSet)
           -> Field {
        Field {
            alias: alias,
            name: name,
            arguments: arguments,
            directives: directives,
            selection_set: selection_set,
        }
    }
}

#[derive(Debug,PartialEq)]
pub struct Fragment {
    name: Name,
    type_condition: Type,
    directives: Vec<Directive>,
    selection_set: SelectionSet,
}

// ok wtf is going on here
type WhiteSpace<I> = Or<Token<I>, Tab<I>>;
pub fn white_space<I: Stream<Item = char>>() -> WhiteSpace<I> {
    char(' ').or(tab())
}

// https://doc.rust-lang.org/error-index.html#E0207
// struct LineTerminator<T> {
//   phantom: PhantomData<T>,
// }

// impl<T> LineTerminator<T> {
//   fn new() -> Self {
//     LineTerminator {
//       phantom: PhantomData
//     }
//   }
// }

macro_rules! make_parser_struct {
  ($name: ident) => {
    pub struct $name<T> {
      phantom: PhantomData<T>,
    }

    impl<T> $name<T> {
      fn new() -> Self {
        $name {
          phantom: PhantomData
        }
      }
    }
  }
}

macro_rules! make_parser {

    // base case
    () => {};

    ($name:ident ($input_var:ident : $input_item_type:ty) -> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {

      pub struct $name<T> {
        phantom: PhantomData<T>,
      }

      impl<T> $name<T> {
          pub fn new() -> Self {
              $name {
                phantom: PhantomData
              }
          }
      }

      impl<I> Parser for $name<I> where I: Stream<Item=$input_item_type> {
        type Input = I;
        type Output = $output_type;

        fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
          $($tmpl)*
        }
      }

      make_parser!($($rest)*);
    };

    ($name:ident ($input_var:ident : $input_item_type:ty , $($field:ident : &$typ:ty),*)
      -> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {

        pub struct $name<'a, T> {
          phantom: PhantomData<T>,
          $( $field: &'a $typ),*
        }

        impl<'a, T> $name<'a, T> {
          pub fn new($($field: &'a $typ),*) -> Self {
            $name {
              phantom: PhantomData,
              $( $field: $field),*
            }
          }
        }

        impl<'a, I> Parser for $name<'a, I> where I: Stream<Item=$input_item_type> {
          type Input = I;
          type Output = $output_type;

          fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
            let &mut $name { phantom, $($field),* } = self;

            $($tmpl)*
          }
        }

        make_parser!($($rest)*);
    };

}

// make_parser_struct!(LineTerminator);

// impl<I> Parser for LineTerminator<I> where I: Stream<Item=char> {
//   type Input = I;
//   type Output = char;

//   fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
//     crlf()
//       .or(char('\r'))
//       .or(char('\n'))
//       .parse_stream(input)
//   }
// }

// make_parser_struct!(Comment);

// impl<I> Parser for Comment<I> where I: Stream<Item=char> {
//   type Input = I;
//   type Output = char;

//   fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
//     char('#')
//       .skip(LineTerminator::new())
//       .parse_stream(input)
//   }
// }

make_parser!(
  LineTerminator(input: char) -> char {
    crlf()
      .or(char('\r'))
      .or(char('\n'))
      .parse_stream(input)
  }
);

make_parser!(
  Comment(input: char) -> char {
    char('#')
      .skip(LineTerminator::new())
      .parse_stream(input)
  }
);

// TODO: combine definitions
// make_parser!(
//   LineTerminator(input: char) -> char {
//     crlf()
//       .or(char('\r'))
//       .or(char('\n'))
//       .parse_stream(input)
//   }

//   Comment(input: char) -> char {
//     char('#')
//       .skip(LineTerminator::new())
//       .parse_stream(input)
//   }
// );

// ok wtf is going on here
// type LineTerminator<I> = Or<Or<CrLf<I>, Token<I>>, Token<I>>;
// pub fn line_terminator<I: Stream<Item = char>>() -> impl Parser<Input=I> {
//     crlf().or(char('\r')).or(char('\n'))
// }

// fn foo<I: Stream<Item = char>>(input: I) -> ParseResult<I::Item, I> {
//   crlf().or(char('\r')).or(char('\n')).parse_stream(input)
// }

// ok wtf is going on here
// type Comment<I> = Skip<Token<I>, LineTerminator<I>>;
// pub fn comment<I: Stream<Item = char>>() -> impl Parser<Input=I>
// {

//   // let lol = line_terminator();

//     char('#')
//         // .skip(many(none_of("".chars())))
//         .skip(LineTerminator::new())
//         // .skip()
// }

// pub fn comma<I: U8Input>(i: I) -> SimpleResult<I,u8>
// {
//   token(i, b',')
// }

// pub fn operation_definition<I: U8Input>(i: I) -> SimpleResult<I,Definition>
// {
//   parse!{i;
//     let op_type = operation_type();
//     white_space() <|> line_terminator();
//     let name = option(|i| name(i).map(Some), None);

//     ret {
//       let op = Operation::new(op_type, name, Vec::new(), Vec::new());
//       Definition::OperationDefinition(op)
//     }
//   }
// }

// pub fn operation_type<I: U8Input>(i: I) -> SimpleResult<I,OperationType>
// {
//   let op_type = |i,b,r| string(i,b).map(|_| r);
//   parse!{i;
//       op_type(b"query", OperationType::Query) <|>
//       op_type(b"mutation", OperationType::Mutation)
//   }
// }

// pub fn name<I: U8Input>(i: I) -> SimpleResult<I,Name>
// {
//   parse!{i;
//     let start = satisfy(|c| is_alpha(c) || c == b'_');
//     let rest = take_while(|c| is_alphanumeric(c) || c == b'_');

//     ret {
//       let mut start = String::from_utf8(vec![start]).unwrap();
//       let rest = String::from_utf8(rest.to_vec()).unwrap();
//       start.push_str(&rest);
//       start
//     }
//   }
// }

// pub fn alias<I: U8Input>(i: I) -> SimpleResult<I, Option<Name>>
// {
//   let parser = |i: I| {
//       parse!{i;
//         let name = name();

//         either(white_space, line_terminator);
//         token(b':');

//         ret Some(name)
//       }
//   };

//   option(i, parser, None)
// }

#[cfg(test)]
mod tests {
    use super::*;
    use combine::{Parser};

    #[test]
    fn test_parse_comment() {
      assert_eq!(Comment::new().parse("#\r\n").map(|x| x.0), Ok('#'));
    }

    #[test]
    fn test_operation_type() {}

    #[test]
    fn test_alias() {}
}
<commit_msg>is_clr<commit_after>use std::collections::HashMap;

use std::str::Chars;
use std::iter::FromIterator;
use std::marker::PhantomData;

use combine::{Parser, ParseResult, Stream, parser};
use combine::char::{CrLf, Tab, tab, char, crlf};
use combine::combinator::{Many, FnParser, NoneOf, Skip, Or, Token, or, many, none_of};

pub type Name = String;
pub type SelectionSet = Vec<Selection>;

#[derive(Debug,PartialEq)]
pub struct Document {
    definitions: Vec<Definition>,
}

#[derive(Debug,PartialEq)]
pub enum Definition {
    OperationDefinition(Operation),
    SelectionSetDefinition(SelectionSet),
    FragmentDefinition(Fragment),
}

#[derive(Debug,PartialEq)]
pub struct Operation {
    op_type: OperationType,
    name: Option<Name>,
    variable_definitions: Vec<VariableDefinition>,
    directives: Vec<Directive>,
}

impl Operation {
    fn new(op_type: OperationType,
           name: Option<Name>,
           variable_definitions: Vec<VariableDefinition>,
           directives: Vec<Directive>)
           -> Operation {
        Operation {
            op_type: op_type,
            name: name,
            variable_definitions: variable_definitions,
            directives: directives,
        }
    }
}

#[derive(Debug,PartialEq)]
pub enum OperationType {
    Query,
    Mutation,
}

#[derive(Debug,PartialEq)]
pub struct VariableDefinition {
    variable: Variable,
    var_type: Type,
    default_value: Option<Value>,
}

type Variable = String;

#[derive(Debug,PartialEq)]
pub enum Type {
    NamedType(Name),
    ListType(Box<Type>),
    NonNullType(Box<Type>),
}

#[derive(Debug,PartialEq)]
pub enum Value {
    Var(Variable),
    IntValue(i32),
    FloatValue(f32),
    StringValue(String),
    BooleanValue(bool),
    NullValue,
    EnumValue(String),
    ListValue(Vec<Value>),
    ObjectValue(HashMap<String, Value>),
}

#[derive(Debug,PartialEq)]
pub struct Directive {
    name: Name,
    arguments: Vec<Argument>,
}

#[derive(Debug,PartialEq)]
pub struct Argument {
    name: Name,
    value: Value,
}

#[derive(Debug,PartialEq)]
pub enum Selection {
    FieldSelection(Field),
    FragmentSpread(Name, Vec<Directive>),
    InlineFragment(Option<Type>, Vec<Directive>, SelectionSet),
}

#[derive(Debug,PartialEq)]
pub struct Field {
    alias: Option<Name>,
    name: Name,
    arguments: Vec<Argument>,
    directives: Vec<Directive>,
    selection_set: SelectionSet,
}

impl Field {
    fn new(alias: Option<Name>,
           name: Name,
           arguments: Vec<Argument>,
           directives: Vec<Directive>,
           selection_set: SelectionSet)
           -> Field {
        Field {
            alias: alias,
            name: name,
            arguments: arguments,
            directives: directives,
            selection_set: selection_set,
        }
    }
}

#[derive(Debug,PartialEq)]
pub struct Fragment {
    name: Name,
    type_condition: Type,
    directives: Vec<Directive>,
    selection_set: SelectionSet,
}

// ok wtf is going on here
type WhiteSpace<I> = Or<Token<I>, Tab<I>>;
pub fn white_space<I: Stream<Item = char>>() -> WhiteSpace<I> {
    char(' ').or(tab())
}

// https://doc.rust-lang.org/error-index.html#E0207
// struct LineTerminator<T> {
//   phantom: PhantomData<T>,
// }

// impl<T> LineTerminator<T> {
//   fn new() -> Self {
//     LineTerminator {
//       phantom: PhantomData
//     }
//   }
// }

macro_rules! make_parser_struct {
  ($name: ident) => {
    pub struct $name<T> {
      phantom: PhantomData<T>,
    }

    impl<T> $name<T> {
      fn new() -> Self {
        $name {
          phantom: PhantomData
        }
      }
    }
  }
}

macro_rules! make_parser {

    // base case
    () => {};

    ($name:ident ($input_var:ident : $input_item_type:ty) -> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {

      pub struct $name<T> {
        phantom: PhantomData<T>,
      }

      impl<T> $name<T> {
          pub fn new() -> Self {
              $name {
                phantom: PhantomData
              }
          }
      }

      impl<I> Parser for $name<I> where I: Stream<Item=$input_item_type> {
        type Input = I;
        type Output = $output_type;

        fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
          $($tmpl)*
        }
      }

      make_parser!($($rest)*);
    };

    ($name:ident ($input_var:ident : $input_item_type:ty , $($field:ident : &$typ:ty),*)
      -> $output_type:ty { $($tmpl:tt)* } $($rest:tt)*) => {

        pub struct $name<'a, T> {
          phantom: PhantomData<T>,
          $( $field: &'a $typ),*
        }

        impl<'a, T> $name<'a, T> {
          pub fn new($($field: &'a $typ),*) -> Self {
            $name {
              phantom: PhantomData,
              $( $field: $field),*
            }
          }
        }

        impl<'a, I> Parser for $name<'a, I> where I: Stream<Item=$input_item_type> {
          type Input = I;
          type Output = $output_type;

          fn parse_stream(&mut self, $input_var: I) -> ParseResult<Self::Output, Self::Input> {
            let &mut $name { phantom, $($field),* } = self;

            $($tmpl)*
          }
        }

        make_parser!($($rest)*);
    };

}

// make_parser_struct!(LineTerminator);

// impl<I> Parser for LineTerminator<I> where I: Stream<Item=char> {
//   type Input = I;
//   type Output = char;

//   fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
//     crlf()
//       .or(char('\r'))
//       .or(char('\n'))
//       .parse_stream(input)
//   }
// }

// make_parser_struct!(Comment);

// impl<I> Parser for Comment<I> where I: Stream<Item=char> {
//   type Input = I;
//   type Output = char;

//   fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> {
//     char('#')
//       .skip(LineTerminator::new())
//       .parse_stream(input)
//   }
// }

make_parser!(
  LineTerminator(input: char, is_clr: &bool) -> char {

    if !is_clr {
      return crlf()
        .or(char('\r'))
        .parse_stream(input);
    }

    crlf()
      .or(char('\r'))
      .or(char('\n'))
      .parse_stream(input)
  }
);

make_parser!(
  Comment(input: char) -> char {
    char('#')
      .skip(LineTerminator::new(&true))
      .parse_stream(input)
  }
);

// TODO: combine definitions
// make_parser!(
//   LineTerminator(input: char) -> char {
//     crlf()
//       .or(char('\r'))
//       .or(char('\n'))
//       .parse_stream(input)
//   }

//   Comment(input: char) -> char {
//     char('#')
//       .skip(LineTerminator::new())
//       .parse_stream(input)
//   }
// );

// ok wtf is going on here
// type LineTerminator<I> = Or<Or<CrLf<I>, Token<I>>, Token<I>>;
// pub fn line_terminator<I: Stream<Item = char>>() -> impl Parser<Input=I> {
//     crlf().or(char('\r')).or(char('\n'))
// }

// fn foo<I: Stream<Item = char>>(input: I) -> ParseResult<I::Item, I> {
//   crlf().or(char('\r')).or(char('\n')).parse_stream(input)
// }

// ok wtf is going on here
// type Comment<I> = Skip<Token<I>, LineTerminator<I>>;
// pub fn comment<I: Stream<Item = char>>() -> impl Parser<Input=I>
// {

//   // let lol = line_terminator();

//     char('#')
//         // .skip(many(none_of("".chars())))
//         .skip(LineTerminator::new())
//         // .skip()
// }

// pub fn comma<I: U8Input>(i: I) -> SimpleResult<I,u8>
// {
//   token(i, b',')
// }

// pub fn operation_definition<I: U8Input>(i: I) -> SimpleResult<I,Definition>
// {
//   parse!{i;
//     let op_type = operation_type();
//     white_space() <|> line_terminator();
//     let name = option(|i| name(i).map(Some), None);

//     ret {
//       let op = Operation::new(op_type, name, Vec::new(), Vec::new());
//       Definition::OperationDefinition(op)
//     }
//   }
// }

// pub fn operation_type<I: U8Input>(i: I) -> SimpleResult<I,OperationType>
// {
//   let op_type = |i,b,r| string(i,b).map(|_| r);
//   parse!{i;
//       op_type(b"query", OperationType::Query) <|>
//       op_type(b"mutation", OperationType::Mutation)
//   }
// }

// pub fn name<I: U8Input>(i: I) -> SimpleResult<I,Name>
// {
//   parse!{i;
//     let start = satisfy(|c| is_alpha(c) || c == b'_');
//     let rest = take_while(|c| is_alphanumeric(c) || c == b'_');

//     ret {
//       let mut start = String::from_utf8(vec![start]).unwrap();
//       let rest = String::from_utf8(rest.to_vec()).unwrap();
//       start.push_str(&rest);
//       start
//     }
//   }
// }

// pub fn alias<I: U8Input>(i: I) -> SimpleResult<I, Option<Name>>
// {
//   let parser = |i: I| {
//       parse!{i;
//         let name = name();

//         either(white_space, line_terminator);
//         token(b':');

//         ret Some(name)
//       }
//   };

//   option(i, parser, None)
// }

#[cfg(test)]
mod tests {
    use super::*;
    use combine::{Parser};

    #[test]
    fn test_parse_comment() {
      assert_eq!(Comment::new().parse("#\r\n").map(|x| x.0), Ok('#'));
    }

    #[test]
    fn test_operation_type() {}

    #[test]
    fn test_alias() {}
}
<|endoftext|>


<commit_before>use std::env;
use ansi_term::Colour::{Cyan, Blue, Red};
use ansi_term::ANSIStrings;
use git2;
use git2::{Repository, StatusOptions};
use regex::Regex;
use clap::{ArgMatches, App, SubCommand};

fn first_char(s: &str) -> String {
  let chars: Vec<char> = s.chars().collect();
  match chars.len() {
    0 => String::from(""),
    _ => chars[0].to_string(),
  }
}

fn fmt_current_path(cwd: &str) -> String {
  let friendly_path = if let Some(path) = env::home_dir() {
    Regex::new(path.to_str().unwrap()).unwrap().replace(cwd, "~").to_string()
  } else {
    String::from("")
  };

  let mut friendly_path_split: Vec<&str> = friendly_path.split('/').collect();
  let current_dir = friendly_path_split.pop().unwrap().to_string();
  let mut short_path: Vec<String> = friendly_path_split.iter().map(|s| first_char(s)).collect();
  short_path.push(current_dir);
  short_path.join("/")
}

fn repo_status(r: &Repository) -> String {
  let mut opts = StatusOptions::new();
  opts.include_untracked(true);
  let head = r.head().unwrap();
  let shorthand = Cyan.paint(head.shorthand().unwrap().to_string());
  let statuses = r.statuses(Some(&mut opts)).unwrap();

  let mut is_dirty = false;

  for entry in statuses.iter().filter(
    |e| e.status() != git2::STATUS_CURRENT,
  ) {
    is_dirty = match entry.status() {
      s if s.contains(git2::STATUS_INDEX_NEW) => true,
      s if s.contains(git2::STATUS_INDEX_MODIFIED) => true,
      s if s.contains(git2::STATUS_INDEX_DELETED) => true,
      s if s.contains(git2::STATUS_INDEX_RENAMED) => true,
      s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => true,
      s if s.contains(git2::STATUS_WT_NEW) => true,
      s if s.contains(git2::STATUS_WT_MODIFIED) => true,
      s if s.contains(git2::STATUS_WT_DELETED) => true,
      s if s.contains(git2::STATUS_WT_RENAMED) => true,
      s if s.contains(git2::STATUS_WT_TYPECHANGE) => true,
      _ => false,
    };

    if is_dirty { break }
  }
  let mut out = vec![shorthand];
  if is_dirty == true {
    out.push(Red.bold().paint("*"));
  }

  ANSIStrings(&out).to_string()
}

pub fn display(_sub: &ArgMatches) {
  let my_path = env::current_dir().unwrap();
  let display_path = Blue.paint(fmt_current_path(my_path.to_str().unwrap()));

  let branch = match Repository::open(my_path) {
    Ok(repo) => repo_status(&repo),
    Err(_e) => String::from(""),
  };
  let display_branch = Cyan.paint(branch);

  println!("");
  println!("{} {}", display_path, display_branch);
}

pub fn cli_arguments<'a>() -> App<'a, 'a> {
  SubCommand::with_name("precmd")
}
<commit_msg>Remove redundant true equality comparison<commit_after>use std::env;
use ansi_term::Colour::{Cyan, Blue, Red};
use ansi_term::ANSIStrings;
use git2;
use git2::{Repository, StatusOptions};
use regex::Regex;
use clap::{ArgMatches, App, SubCommand};

fn first_char(s: &str) -> String {
  let chars: Vec<char> = s.chars().collect();
  match chars.len() {
    0 => String::from(""),
    _ => chars[0].to_string(),
  }
}

fn fmt_current_path(cwd: &str) -> String {
  let friendly_path = if let Some(path) = env::home_dir() {
    Regex::new(path.to_str().unwrap()).unwrap().replace(cwd, "~").to_string()
  } else {
    String::from("")
  };

  let mut friendly_path_split: Vec<&str> = friendly_path.split('/').collect();
  let current_dir = friendly_path_split.pop().unwrap().to_string();
  let mut short_path: Vec<String> = friendly_path_split.iter().map(|s| first_char(s)).collect();
  short_path.push(current_dir);
  short_path.join("/")
}

fn repo_status(r: &Repository) -> String {
  let mut opts = StatusOptions::new();
  opts.include_untracked(true);
  let head = r.head().unwrap();
  let shorthand = Cyan.paint(head.shorthand().unwrap().to_string());
  let statuses = r.statuses(Some(&mut opts)).unwrap();

  let mut is_dirty = false;

  for entry in statuses.iter().filter(
    |e| e.status() != git2::STATUS_CURRENT,
  ) {
    is_dirty = match entry.status() {
      s if s.contains(git2::STATUS_INDEX_NEW) => true,
      s if s.contains(git2::STATUS_INDEX_MODIFIED) => true,
      s if s.contains(git2::STATUS_INDEX_DELETED) => true,
      s if s.contains(git2::STATUS_INDEX_RENAMED) => true,
      s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => true,
      s if s.contains(git2::STATUS_WT_NEW) => true,
      s if s.contains(git2::STATUS_WT_MODIFIED) => true,
      s if s.contains(git2::STATUS_WT_DELETED) => true,
      s if s.contains(git2::STATUS_WT_RENAMED) => true,
      s if s.contains(git2::STATUS_WT_TYPECHANGE) => true,
      _ => false,
    };

    if is_dirty { break }
  }
  let mut out = vec![shorthand];
  if is_dirty {
    out.push(Red.bold().paint("*"));
  }

  ANSIStrings(&out).to_string()
}

pub fn display(_sub: &ArgMatches) {
  let my_path = env::current_dir().unwrap();
  let display_path = Blue.paint(fmt_current_path(my_path.to_str().unwrap()));

  let branch = match Repository::open(my_path) {
    Ok(repo) => repo_status(&repo),
    Err(_e) => String::from(""),
  };
  let display_branch = Cyan.paint(branch);

  println!("");
  println!("{} {}", display_path, display_branch);
}

pub fn cli_arguments<'a>() -> App<'a, 'a> {
  SubCommand::with_name("precmd")
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

extern crate serde_json;

use std::fs::File;
use std::io::{Write, BufWriter};

type CvName = String;

pub type MiscExtRange = String;

pub type GeneUniquename = String;
pub type GeneName = String;
pub type TypeName = String;
pub type GeneProduct = String;

pub type TermName = String;
pub type TermId = String;
pub type TermDef = String;

pub type Evidence = String;

pub type TypeFeatureAnnotationMap =
    HashMap<TypeName, Vec<FeatureAnnotation>>;
pub type TypeReferenceAnnotationMap =
    HashMap<TypeName, Vec<ReferenceAnnotation>>;
pub type TypeInteractionAnnotationMap =
    HashMap<TypeName, Vec<InteractionAnnotation>>;

pub type UniquenameGeneMap =
    HashMap<GeneUniquename, GeneDetails>;

pub type TranscriptUniquename = String;

pub type UniquenameTranscriptMap =
    HashMap<TranscriptUniquename, TranscriptDetails>;

pub type GenotypeUniquename = String;

pub type UniquenameGenotypeMap =
    HashMap<GenotypeUniquename, GenotypeDetails>;

pub type AlleleUniquename = String;

pub type UniquenameAlleleShortMap =
    HashMap<AlleleUniquename, AlleleShort>;

pub type IdGeneMap = HashMap<GeneUniquename, GeneDetails>;
pub type IdGeneShortMap = HashMap<GeneUniquename, GeneShort>;
pub type IdTermDetailsMap = HashMap<TermId, Rc<TermDetails>>;
pub type IdReferenceMap = HashMap<TermId, ReferenceDetails>;

include!(concat!(env!("OUT_DIR"), "/data_serde.rs"));

impl WebData {
    fn get_genes(&self) -> &IdGeneMap {
        &self.genes
    }
    fn get_terms(&self) -> &IdTermDetailsMap {
        &self.terms
    }

    fn write_reference_details(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.references).unwrap();
        let file_name = String::new() + &output_dir + "/references.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (reference_uniquename, reference_details) in &self.references {
            let s = serde_json::to_string(&reference_details).unwrap();
            let file_name = String::new() + &output_dir + "/reference/" + &reference_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_details(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.genes).unwrap();
        let file_name = String::new() + &output_dir + "/genes.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (gene_uniquename, gene_details) in &self.genes {
            let s = serde_json::to_string(&gene_details).unwrap();
            let file_name = String::new() + &output_dir + "/gene/" + &gene_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_summary(&self, output_dir: &str, organism_genus_species: &str) {
        let gene_summaries =
            self.gene_summaries.values()
            .filter(|gene_short| {
                let gene_uniquename = &gene_short.uniquename;
                let gene_details = self.get_genes().get(gene_uniquename).unwrap();
                let feature_org_genus_species = String::new() +
                    &gene_details.organism.genus + "_" + &gene_details.organism.species;
                feature_org_genus_species == organism_genus_species
            })
            .map(|gene_short| gene_short.clone())
            .collect::<Vec<GeneShort>>();
        let s = serde_json::to_string(&gene_summaries).unwrap();
        let file_name = String::new() + &output_dir + "/gene_summaries.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    fn write_terms(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.terms).unwrap();
        let file_name = String::new() + &output_dir + "/terms.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");

        for (termid, term_details) in &self.terms {
            let s = serde_json::to_string(&term_details).unwrap();
            let file_name = String::new() + &output_dir + "/term/" + &termid + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_metadata(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.metadata).unwrap();
        let file_name = String::new() + &output_dir + "/metadata.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    pub fn write(&self, output_dir: &str, organism_genus_species: &str) {
        self.write_reference_details(output_dir);
        self.write_gene_details(output_dir);
        self.write_gene_summary(output_dir, organism_genus_species);
        self.write_terms(output_dir);
        self.write_metadata(output_dir);

        println!("wrote {} genes", self.get_genes().len());
        println!("wrote {} terms", self.get_terms().len());
    }
}
<commit_msg>Don't write genes/terms/refs.json files for now<commit_after>use std::collections::HashMap;

extern crate serde_json;

use std::fs::File;
use std::io::{Write, BufWriter};

type CvName = String;

pub type MiscExtRange = String;

pub type GeneUniquename = String;
pub type GeneName = String;
pub type TypeName = String;
pub type GeneProduct = String;

pub type TermName = String;
pub type TermId = String;
pub type TermDef = String;

pub type Evidence = String;

pub type TypeFeatureAnnotationMap =
    HashMap<TypeName, Vec<FeatureAnnotation>>;
pub type TypeReferenceAnnotationMap =
    HashMap<TypeName, Vec<ReferenceAnnotation>>;
pub type TypeInteractionAnnotationMap =
    HashMap<TypeName, Vec<InteractionAnnotation>>;

pub type UniquenameGeneMap =
    HashMap<GeneUniquename, GeneDetails>;

pub type TranscriptUniquename = String;

pub type UniquenameTranscriptMap =
    HashMap<TranscriptUniquename, TranscriptDetails>;

pub type GenotypeUniquename = String;

pub type UniquenameGenotypeMap =
    HashMap<GenotypeUniquename, GenotypeDetails>;

pub type AlleleUniquename = String;

pub type UniquenameAlleleShortMap =
    HashMap<AlleleUniquename, AlleleShort>;

pub type IdGeneMap = HashMap<GeneUniquename, GeneDetails>;
pub type IdGeneShortMap = HashMap<GeneUniquename, GeneShort>;
pub type IdTermDetailsMap = HashMap<TermId, Rc<TermDetails>>;
pub type IdReferenceMap = HashMap<TermId, ReferenceDetails>;

include!(concat!(env!("OUT_DIR"), "/data_serde.rs"));

impl WebData {
    fn get_genes(&self) -> &IdGeneMap {
        &self.genes
    }
    fn get_terms(&self) -> &IdTermDetailsMap {
        &self.terms
    }

    fn write_reference_details(&self, output_dir: &str) {
        for (reference_uniquename, reference_details) in &self.references {
            let s = serde_json::to_string(&reference_details).unwrap();
            let file_name = String::new() + &output_dir + "/reference/" + &reference_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_details(&self, output_dir: &str) {
        for (gene_uniquename, gene_details) in &self.genes {
            let s = serde_json::to_string(&gene_details).unwrap();
            let file_name = String::new() + &output_dir + "/gene/" + &gene_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_gene_summary(&self, output_dir: &str, organism_genus_species: &str) {
        let gene_summaries =
            self.gene_summaries.values()
            .filter(|gene_short| {
                let gene_uniquename = &gene_short.uniquename;
                let gene_details = self.get_genes().get(gene_uniquename).unwrap();
                let feature_org_genus_species = String::new() +
                    &gene_details.organism.genus + "_" + &gene_details.organism.species;
                feature_org_genus_species == organism_genus_species
            })
            .map(|gene_short| gene_short.clone())
            .collect::<Vec<GeneShort>>();
        let s = serde_json::to_string(&gene_summaries).unwrap();
        let file_name = String::new() + &output_dir + "/gene_summaries.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    fn write_terms(&self, output_dir: &str) {
        for (termid, term_details) in &self.terms {
            let s = serde_json::to_string(&term_details).unwrap();
            let file_name = String::new() + &output_dir + "/term/" + &termid + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write!");
        }
    }

    fn write_metadata(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.metadata).unwrap();
        let file_name = String::new() + &output_dir + "/metadata.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    pub fn write(&self, output_dir: &str, organism_genus_species: &str) {
        self.write_reference_details(output_dir);
        self.write_gene_details(output_dir);
        self.write_gene_summary(output_dir, organism_genus_species);
        self.write_terms(output_dir);
        self.write_metadata(output_dir);

        println!("wrote {} genes", self.get_genes().len());
        println!("wrote {} terms", self.get_terms().len());
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate protobuf;
extern crate serde_protobuf;
extern crate serde_value;

use std::fs;
use std::io::Read;
use self::serde::de::Deserialize;
use self::serde_protobuf::descriptor::Descriptors;
use self::serde_protobuf::de::Deserializer;
use self::serde_value::Value;

pub fn process_single(read: &mut Read) {
    let mut buffer = Vec::new();
    read.read(&mut buffer).unwrap();

    let mut byte_is = protobuf::CodedInputStream::from_bytes(&buffer);

    let mut file = fs::File::open("testdata/address.fdset").unwrap();

    let proto = protobuf::parse_from_reader(&mut file).unwrap();

    let descriptors = Descriptors::from_proto(&proto);
    let mut deserializer = Deserializer::for_named_message(&descriptors, "pq-rs", byte_is).unwrap();
    let value = Value::deserialize(&mut deserializer).unwrap();
    println!("{:?}", value);
}

pub fn process_stream(read: &mut Read) {
    let mut stream = protobuf::stream::CodedInputStream::new(read);

    loop {
        match stream.eof() {
            Err(e) => panic!(e),
            Ok(true) => break,
            Ok(false) => break,
            //todo: actually do deserialization here
        }
    }
}
<commit_msg>Compiles now<commit_after>extern crate serde;
extern crate protobuf;
extern crate serde_protobuf;
extern crate serde_value;

use std::fs;
use std::io::Read;
use self::serde::de::Deserialize;
use self::serde_protobuf::descriptor::Descriptors;
use self::serde_protobuf::de::Deserializer;
use self::serde_value::Value;
use self::protobuf::{CodedInputStream, parse_from_reader};

pub fn process_single(read: &mut Read) {
    let mut file = fs::File::open("testdata/address.fdset").unwrap();
    let proto = parse_from_reader(&mut file).unwrap();
    let descriptors = Descriptors::from_proto(&proto);

    let mut buffer = Vec::new();
    read.read(&mut buffer).unwrap();
    let mut byte_is = CodedInputStream::from_bytes(&buffer);

    let mut deserializer = Deserializer::for_named_message(&descriptors, ".google.protobuf.FileDescriptorSet", byte_is).unwrap();
    let value = Value::deserialize(&mut deserializer).unwrap();
    println!("{:?}", value);
}

pub fn process_stream(read: &mut Read) {
    let mut stream = protobuf::stream::CodedInputStream::new(read);

    loop {
        match stream.eof() {
            Err(e) => panic!(e),
            Ok(true) => break,
            Ok(false) => break,
            //todo: actually do deserialization here
        }
    }
}
<|endoftext|>


<commit_before>//! Endpoints for typing notifications.
<commit_msg>Add typing endpoint.<commit_after>//! Endpoints for typing notifications.

/// PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}
///
/// [Matrix spec link](http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid)
pub mod set_typing {
    use ruma_identifiers::{UserId, RoomId};

    /// Details about this API endpoint.
    pub struct Endpoint;

    /// This API endpoint's path parameters.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct PathParams {
        pub room_id: RoomId,
        pub user_id: UserId
    }

    /// This API endpoint's body parameters.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct BodyParams {
        pub typing: bool,
        pub timeout: Option<u64>
    }

    impl ::Endpoint for Endpoint {
        type BodyParams = BodyParams;
        type PathParams = PathParams;
        type QueryParams = ();
        type Response = ();

        fn method() -> ::Method {
            ::Method::Put
        }

        fn request_path(params: Self::PathParams) -> String {
            format!(
                "/_matrix/client/r0/rooms/{}/typing/{}",
                params.room_id,
                params.user_id
            )
        }

        fn router_path() -> String {
            "/_matrix/client/r0/rooms/:room_id/invite/:user_id".to_string()
        }
    }
}
<|endoftext|>