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

use core::libc::{c_char, c_int, c_void, size_t};

// errors.h

pub type Error = c_int;
pub static OK: c_int = 0;
pub static REPROCESS: c_int = 1;
pub static ENCODINGCHANGE: c_int = 2;
pub static PAUSED: c_int = 3;
pub static NOMEM: c_int = 5;
pub static BADPARM: c_int = 6;
pub static INVALID: c_int = 7;
pub static FILENOTFOUND: c_int = 8;
pub static NEEDDATA: c_int = 9;
pub static BADENCODING: c_int = 10;
pub static UNKNOWN: c_int = 11;

#[cfg(target_os = "macos")]
#[nolink]
#[link_args="-L../libhubbub -lhubbub -L../libparserutils -lparserutils -liconv"]
pub extern mod linking { }

#[cfg(target_os = "linux")]
#[nolink]
#[link_args="-L../libhubbub -lhubbub -L../libparserutils -lparserutils"]
pub extern mod linking { }

#[nolink]
pub extern mod error {
    pub fn hubbub_error_to_string(error: Error) -> *u8;
}

// parser.h

pub type Parser = c_void;

pub type ParserOptType = c_int;
pub static PARSER_TOKEN_HANDLER: c_int = 0;
pub static PARSER_ERROR_HANDLER: c_int = 1;
pub static PARSER_CONTENT_MODEL: c_int = 2;
pub static PARSER_TREE_HANDLER: c_int = 3;
pub static PARSER_DOCUMENT_NODE: c_int = 4;
pub static PARSER_ENABLE_SCRIPTING: c_int = 5;
pub static PARSER_PAUSE: c_int = 6;

pub struct ParserOptParamsTokenHandler {
    handler: *u8,
    pw: *c_void
}

pub struct ParserOptParamsErrorHandler {
    handler: *u8,
    pw: *c_void
}

pub struct ParserOptParamsContentModel {
    content_model: ContentModel
}

#[nolink]
pub extern mod parser {
    pub fn hubbub_parser_create(enc: *u8,
                                fix_enc: bool,
                                alloc: *u8,
                                pw: *c_void,
                                parser: **Parser)
                             -> Error;
    pub fn hubbub_parser_destroy(parser: *Parser) -> Error;
    pub fn hubbub_parser_setopt(parser: *Parser, opt_type: ParserOptType, params: *c_void)
                             -> Error;
    pub fn hubbub_parser_parse_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
    pub fn hubbub_parser_insert_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
    pub fn hubbub_parser_completed(parser: *Parser) -> Error;
    pub fn hubbub_parser_read_charset(parser: *Parser, source: *CharsetSource) -> *c_char;
}

// tree.h

pub struct TreeHandler {
    create_comment: *u8,
    create_doctype: *u8,
    create_element: *u8,
    create_text: *u8,
    ref_node: *u8,
    unref_node: *u8,
    append_child: *u8,
    insert_before: *u8,
    remove_child: *u8,
    clone_node: *u8,
    reparent_children: *u8,
    get_parent: *u8,
    has_children: *u8,
    form_associate: *u8,
    add_attributes: *u8,
    set_quirks_mode: *u8,
    encoding_change: *u8,
    complete_script: *u8,
    ctx: *c_void
}

// types.h

// Source of charset information, in order of importance.
// A client-dictated charset will override all others.
// A document-specified charset will override autodetection or the default.
pub type CharsetSource = c_int;
pub static CHARSET_UNKNOWN: c_int = 0;
pub static CHARSET_TENTATIVE: c_int = 1;
pub static CHARSET_CONFIDENT: c_int = 2;

// Content model flag
pub type ContentModel = c_int;
pub static CONTENT_MODEL_PCDATA: c_int = 0;
pub static CONTENT_MODEL_RCDATA: c_int = 1;
pub static CONTENT_MODEL_CDATA: c_int = 2;
pub static CONTENT_MODEL_PLAINTEXT: c_int = 3;

// Quirks mode flag
pub type QuirksMode = c_int;
pub static QUIRKS_MODE_NONE: c_int = 0;
pub static QUIRKS_MODE_LIMITED: c_int = 1;
pub static QUIRKS_MODE_FULL: c_int = 2;

pub type TokenType = c_int;
pub static TOKEN_DOCTYPE: c_int = 0;
pub static TOKEN_START_TAG: c_int = 1;
pub static TOKEN_END_TAG: c_int = 2;
pub static TOKEN_COMMENT: c_int = 3;
pub static TOKEN_CHARACTER: c_int = 4;
pub static TOKEN_EOF: c_int = 5;

pub type NS = c_int;
pub static NS_NULL: c_int = 0;
pub static NS_HTML: c_int = 1;
pub static NS_MATHML: c_int = 2;
pub static NS_SVG: c_int = 3;
pub static NS_XLINK: c_int = 4;
pub static NS_XML: c_int = 5;
pub static NS_XMLNS: c_int = 6;

pub struct String {
    ptr: *u8,
    len: size_t
}

pub struct Attribute {
    ns: NS,
    name: String,
    value: String,
}

pub struct Doctype {
    name: String,
    public_missing: bool,
    public_id: String,
    system_missing: bool,
    system_id: String,
    force_quirks: bool,
}

pub struct Tag {
    ns: NS,
    name: String,
    n_attributes: u32,
    attributes: *Attribute,
    self_closing: bool,
}

// Token data
pub struct Token {
    token_type: TokenType,
    data: u8,   // union: one of Doctype, Tag, Comment (string), or Character (string)
}

<commit_msg>Update for language changes<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::libc::{c_char, c_int, c_void, size_t};

// errors.h

pub type Error = c_int;
pub static OK: c_int = 0;
pub static REPROCESS: c_int = 1;
pub static ENCODINGCHANGE: c_int = 2;
pub static PAUSED: c_int = 3;
pub static NOMEM: c_int = 5;
pub static BADPARM: c_int = 6;
pub static INVALID: c_int = 7;
pub static FILENOTFOUND: c_int = 8;
pub static NEEDDATA: c_int = 9;
pub static BADENCODING: c_int = 10;
pub static UNKNOWN: c_int = 11;

#[cfg(target_os = "macos")]
#[nolink]
#[link_args="-L../../hubbub/libhubbub -lhubbub -L../../libparserutils/libparserutils -lparserutils -liconv"]
pub extern mod linking { }

#[cfg(target_os = "linux")]
#[nolink]
#[link_args="-L../../hubbub/libhubbub -lhubbub -L../../libparserutils/libparserutils -lparserutils"]
pub extern mod linking { }

#[nolink]
pub extern mod error {
    pub fn hubbub_error_to_string(error: Error) -> *u8;
}

// parser.h

pub type Parser = c_void;

pub type ParserOptType = c_int;
pub static PARSER_TOKEN_HANDLER: c_int = 0;
pub static PARSER_ERROR_HANDLER: c_int = 1;
pub static PARSER_CONTENT_MODEL: c_int = 2;
pub static PARSER_TREE_HANDLER: c_int = 3;
pub static PARSER_DOCUMENT_NODE: c_int = 4;
pub static PARSER_ENABLE_SCRIPTING: c_int = 5;
pub static PARSER_PAUSE: c_int = 6;

pub struct ParserOptParamsTokenHandler {
    handler: *u8,
    pw: *c_void
}

pub struct ParserOptParamsErrorHandler {
    handler: *u8,
    pw: *c_void
}

pub struct ParserOptParamsContentModel {
    content_model: ContentModel
}

#[nolink]
pub extern mod parser {
    pub fn hubbub_parser_create(enc: *u8,
                                fix_enc: bool,
                                alloc: *u8,
                                pw: *c_void,
                                parser: **Parser)
                             -> Error;
    pub fn hubbub_parser_destroy(parser: *Parser) -> Error;
    pub fn hubbub_parser_setopt(parser: *Parser, opt_type: ParserOptType, params: *c_void)
                             -> Error;
    pub fn hubbub_parser_parse_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
    pub fn hubbub_parser_insert_chunk(parser: *Parser, data: *u8, len: size_t) -> Error;
    pub fn hubbub_parser_completed(parser: *Parser) -> Error;
    pub fn hubbub_parser_read_charset(parser: *Parser, source: *CharsetSource) -> *c_char;
}

// tree.h

pub struct TreeHandler {
    create_comment: *u8,
    create_doctype: *u8,
    create_element: *u8,
    create_text: *u8,
    ref_node: *u8,
    unref_node: *u8,
    append_child: *u8,
    insert_before: *u8,
    remove_child: *u8,
    clone_node: *u8,
    reparent_children: *u8,
    get_parent: *u8,
    has_children: *u8,
    form_associate: *u8,
    add_attributes: *u8,
    set_quirks_mode: *u8,
    encoding_change: *u8,
    complete_script: *u8,
    ctx: *c_void
}

// types.h

// Source of charset information, in order of importance.
// A client-dictated charset will override all others.
// A document-specified charset will override autodetection or the default.
pub type CharsetSource = c_int;
pub static CHARSET_UNKNOWN: c_int = 0;
pub static CHARSET_TENTATIVE: c_int = 1;
pub static CHARSET_CONFIDENT: c_int = 2;

// Content model flag
pub type ContentModel = c_int;
pub static CONTENT_MODEL_PCDATA: c_int = 0;
pub static CONTENT_MODEL_RCDATA: c_int = 1;
pub static CONTENT_MODEL_CDATA: c_int = 2;
pub static CONTENT_MODEL_PLAINTEXT: c_int = 3;

// Quirks mode flag
pub type QuirksMode = c_int;
pub static QUIRKS_MODE_NONE: c_int = 0;
pub static QUIRKS_MODE_LIMITED: c_int = 1;
pub static QUIRKS_MODE_FULL: c_int = 2;

pub type TokenType = c_int;
pub static TOKEN_DOCTYPE: c_int = 0;
pub static TOKEN_START_TAG: c_int = 1;
pub static TOKEN_END_TAG: c_int = 2;
pub static TOKEN_COMMENT: c_int = 3;
pub static TOKEN_CHARACTER: c_int = 4;
pub static TOKEN_EOF: c_int = 5;

pub type NS = c_int;
pub static NS_NULL: c_int = 0;
pub static NS_HTML: c_int = 1;
pub static NS_MATHML: c_int = 2;
pub static NS_SVG: c_int = 3;
pub static NS_XLINK: c_int = 4;
pub static NS_XML: c_int = 5;
pub static NS_XMLNS: c_int = 6;

pub struct String {
    ptr: *u8,
    len: size_t
}

pub struct Attribute {
    ns: NS,
    name: String,
    value: String,
}

pub struct Doctype {
    name: String,
    public_missing: bool,
    public_id: String,
    system_missing: bool,
    system_id: String,
    force_quirks: bool,
}

pub struct Tag {
    ns: NS,
    name: String,
    n_attributes: u32,
    attributes: *Attribute,
    self_closing: bool,
}

// Token data
pub struct Token {
    token_type: TokenType,
    data: u8,   // union: one of Doctype, Tag, Comment (string), or Character (string)
}

<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::process::Command;
use std::env;
use std::io::stderr;
use std::io::Write;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use logger::ImagLogger;

use libimagstore::store::Store;

#[derive(Debug)]
pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;
        use std::error::Error;

        use libimagstore::hook::position::HookPosition;
        use libimagstore::error::StoreErrorKind;
        use libimagstorestdhook::debug::DebugHook;
        use libimagerror::trace::trace_error;
        use libimagerror::trace::trace_error_dbg;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");

        Runtime::init_logger(is_debugging, is_verbose);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            }, PathBuf::from);
        let storepath = matches.value_of("storepath")
                                .map_or_else(|| {
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                }, PathBuf::from);

        let cfg = match Configuration::new(&rtp) {
            Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound {
                let cause : Option<Box<Error>> = Some(Box::new(e));
                return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause));
            } else {
                warn!("No config file found.");
                warn!("Continuing without configuration file");
                None
            },

            Ok(cfg) => Some(cfg),
        };

        let store_config = match cfg {
            Some(ref c) => c.store_config().cloned(),
            None        => None,
        };

        if is_debugging {
            write!(stderr(), "Config: {:?}\n", cfg).ok();
            write!(stderr(), "Store-config: {:?}\n", store_config).ok();
        }

        Store::new(storepath, store_config).map(|mut store| {
            // If we are debugging, generate hooks for all positions
            if is_debugging {
                let hooks = vec![
                    (DebugHook::new(HookPosition::PreCreate), HookPosition::PreCreate),
                    (DebugHook::new(HookPosition::PostCreate), HookPosition::PostCreate),
                    (DebugHook::new(HookPosition::PreRetrieve), HookPosition::PreRetrieve),
                    (DebugHook::new(HookPosition::PostRetrieve), HookPosition::PostRetrieve),
                    (DebugHook::new(HookPosition::PreUpdate), HookPosition::PreUpdate),
                    (DebugHook::new(HookPosition::PostUpdate), HookPosition::PostUpdate),
                    (DebugHook::new(HookPosition::PreDelete), HookPosition::PreDelete),
                    (DebugHook::new(HookPosition::PostDelete), HookPosition::PostDelete),
                ];

                // Put all debug hooks into the aspect "debug".
                // If it fails, trace the error and warn, but continue.
                for (hook, position) in hooks {
                    if let Err(e) = store.register_hook(position, &String::from("debug"), Box::new(hook)) {
                        if e.err_type() == StoreErrorKind::HookRegisterError {
                            trace_error_dbg(&e);
                            warn!("Registering debug hook with store failed");
                        } else {
                            trace_error(&e);
                        };
                    }
                }
            }

            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err(|e| {
            RuntimeError::new(RuntimeErrorKind::Instantiate, Some(Box::new(e)))
        })
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name("verbosity")
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("debugging")
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("config")
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("runtimepath")
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("storepath")
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("editor")
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool) {
        let lvl = if is_debugging {
            LogLevelFilter::Debug
        } else if is_verbose {
            LogLevelFilter::Info
        } else {
            LogLevelFilter::Error
        };

        log::set_logger(|max_log_lvl| {
            max_log_lvl.set(lvl);
            debug!("Init logger with {}", lvl);
            Box::new(ImagLogger::new(lvl.to_log_level().unwrap()))
        })
        .map_err(|_| {
            panic!("Could not setup logger");
        })
        .ok();
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match self.configuration {
                    Some(ref c) => c.editor().cloned(),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

<commit_msg>Add env_logger as fallback if IMAG_LOG_ENV is present<commit_after>use std::path::PathBuf;
use std::process::Command;
use std::env;
use std::io::stderr;
use std::io::Write;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use logger::ImagLogger;

use libimagstore::store::Store;

#[derive(Debug)]
pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;
        use std::error::Error;

        use libimagstore::hook::position::HookPosition;
        use libimagstore::error::StoreErrorKind;
        use libimagstorestdhook::debug::DebugHook;
        use libimagerror::trace::trace_error;
        use libimagerror::trace::trace_error_dbg;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");

        Runtime::init_logger(is_debugging, is_verbose);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            }, PathBuf::from);
        let storepath = matches.value_of("storepath")
                                .map_or_else(|| {
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                }, PathBuf::from);

        let cfg = match Configuration::new(&rtp) {
            Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound {
                let cause : Option<Box<Error>> = Some(Box::new(e));
                return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause));
            } else {
                warn!("No config file found.");
                warn!("Continuing without configuration file");
                None
            },

            Ok(cfg) => Some(cfg),
        };

        let store_config = match cfg {
            Some(ref c) => c.store_config().cloned(),
            None        => None,
        };

        if is_debugging {
            write!(stderr(), "Config: {:?}\n", cfg).ok();
            write!(stderr(), "Store-config: {:?}\n", store_config).ok();
        }

        Store::new(storepath, store_config).map(|mut store| {
            // If we are debugging, generate hooks for all positions
            if is_debugging {
                let hooks = vec![
                    (DebugHook::new(HookPosition::PreCreate), HookPosition::PreCreate),
                    (DebugHook::new(HookPosition::PostCreate), HookPosition::PostCreate),
                    (DebugHook::new(HookPosition::PreRetrieve), HookPosition::PreRetrieve),
                    (DebugHook::new(HookPosition::PostRetrieve), HookPosition::PostRetrieve),
                    (DebugHook::new(HookPosition::PreUpdate), HookPosition::PreUpdate),
                    (DebugHook::new(HookPosition::PostUpdate), HookPosition::PostUpdate),
                    (DebugHook::new(HookPosition::PreDelete), HookPosition::PreDelete),
                    (DebugHook::new(HookPosition::PostDelete), HookPosition::PostDelete),
                ];

                // Put all debug hooks into the aspect "debug".
                // If it fails, trace the error and warn, but continue.
                for (hook, position) in hooks {
                    if let Err(e) = store.register_hook(position, &String::from("debug"), Box::new(hook)) {
                        if e.err_type() == StoreErrorKind::HookRegisterError {
                            trace_error_dbg(&e);
                            warn!("Registering debug hook with store failed");
                        } else {
                            trace_error(&e);
                        };
                    }
                }
            }

            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err(|e| {
            RuntimeError::new(RuntimeErrorKind::Instantiate, Some(Box::new(e)))
        })
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name("verbosity")
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("debugging")
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("config")
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("runtimepath")
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("storepath")
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("editor")
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool) {
        use std::env::var as env_var;
        use env_logger;

        if env_var("IMAG_LOG_ENV").is_ok() {
            env_logger::init().unwrap();
        } else {
            let lvl = if is_debugging {
                LogLevelFilter::Debug
            } else if is_verbose {
                LogLevelFilter::Info
            } else {
                LogLevelFilter::Error
            };

            log::set_logger(|max_log_lvl| {
                max_log_lvl.set(lvl);
                debug!("Init logger with {}", lvl);
                Box::new(ImagLogger::new(lvl.to_log_level().unwrap()))
            })
            .map_err(|_| {
                panic!("Could not setup logger");
            })
            .ok();
        }
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match self.configuration {
                    Some(ref c) => c.editor().cloned(),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

<|endoftext|>


<commit_before>//
//
//
use core::iter::range;
use core::iter::{FromIterator,Iterator};
use core::slice::{SliceExt,AsSlice};
use core::option::Option::{self,Some,None};
use core::ptr::PtrExt;
use core::num::Int;
use core::ops::{Drop,Index,IndexMut,Deref,DerefMut,Fn};
use core::marker::Send;
use lib::clone::Clone;
use lib::collections::{MutableSeq};

/// Growable array of items
pub struct Vec<T>
{
	data: *mut T,
	size: usize,
	capacity: usize,
}
// Sendable if the innards are sendable
unsafe impl<T: Send> Send for Vec<T> {}

/// Owning iterator
pub struct MoveItems<T>
{
	data: *mut T,
	count: usize,
	ofs: usize,
}

impl<T> Vec<T>
{
	/// Create a new, empty vector
	pub fn new() -> Vec<T>
	{
		Vec::with_capacity(0)
	}
	/// Create a vector with an initialised capacity
	pub fn with_capacity(size: usize) -> Vec<T>
	{
		Vec {
			data: unsafe { ::memory::heap::alloc_array::<T>( size ) },
			size: 0,
			capacity: size,
		}
	}
	/// Populate vector using a provided callback
	pub fn from_fn<Fcn>(length: usize, op: Fcn) -> Vec<T>
	where
		Fcn: Fn(usize) -> T
	{
		let mut ret = Vec::with_capacity(length);
		for i in range(0, length) {
			ret.push( op(i) );
		}
		ret
	}

	/// Obtain a mutable pointer to an item within the vector
	fn get_mut_ptr(&mut self, index: usize) -> *mut T
	{
		if index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { self.data.offset(index as isize) }
	}

	/// Move contents into an iterator (consuming self)
	pub fn into_iter(self) -> MoveItems<T>
	{
		let dataptr = self.data;
		let count = self.size;
		unsafe { ::core::mem::forget(self) };
		MoveItems {
			data: dataptr,
			ofs: 0,
			count: count,
		}
	}

	fn reserve(&mut self, size: usize)
	{
		let newcap = ::lib::num::round_up(size, 1 << (64-size.leading_zeros()));
		if newcap > self.capacity
		{
			unsafe {
				let newptr = ::memory::heap::alloc_array::<T>( newcap );
				for i in range(0, self.size) {
					let val = self.move_ent(i as usize);
					::core::ptr::write(newptr.offset(i as isize), val);
				}
				if self.capacity > 0 {
					::memory::heap::dealloc_array( self.data, self.capacity );
				}
				self.data = newptr;
				self.capacity = newcap;
			}
		}
	}

	pub fn slice_mut<'a>(&'a mut self) -> &'a mut [T]
	{
		unsafe { ::core::mem::transmute( ::core::raw::Slice { data: self.data as *const T, len: self.size } ) }
	}

	/// Move out of a slot in the vector, leaving unitialise memory in its place
	unsafe fn move_ent(&mut self, pos: usize) -> T
	{
		::core::ptr::read(self.data.offset(pos as isize) as *const _)
	}
}

impl<T> Deref for Vec<T>
{
	type Target = [T];
	fn deref(&self) -> &[T] {
		self.as_slice()
	}
}
impl<T> DerefMut for Vec<T>
{
	fn deref_mut(&mut self) -> &mut [T] {
		self.slice_mut()
	}
}

impl<T:Clone> Vec<T>
{
	pub fn from_elem(size: usize, elem: T) -> Vec<T>
	{
		Vec::from_fn( size, |_| elem.clone() )
	}

	pub fn push_all(&mut self, other: &[T])
	{
		let newlen = self.size + other.len();
		self.reserve(newlen);
		for v in other.iter() {
			self.push(v.clone());
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for Vec<T>
{
	fn drop(&mut self)
	{
		log_debug!("Vec::drop() - Dropping vector at {:p} w/ {} ents", self.data, self.size);
		unsafe {
			for i in range(0, self.size) {
				::core::mem::drop( ::core::ptr::read(self.get_mut_ptr(i) as *const T) );
			}
			::memory::heap::dealloc_array( self.data, self.capacity );
		}
	}
}

impl<T> Index<usize> for Vec<T>
{
	type Output = T;
	fn index<'a>(&'a self, index: &usize) -> &'a T
	{
		if *index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &*self.data.offset(*index as isize) }
	}
}
impl<T> IndexMut<usize> for Vec<T>
{
	type Output = T;
	fn index_mut<'a>(&'a mut self, index: &usize) -> &'a mut T
	{
		if *index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &mut *self.data.offset(*index as isize) }
	}
}

impl<T> ::core::slice::AsSlice<T> for Vec<T>
{
	fn as_slice<'a>(&'a self) -> &'a [T]
	{
		let rawslice = ::core::raw::Slice { data: self.data as *const T, len: self.size };
		unsafe { ::core::mem::transmute( rawslice ) }
	}
}

//impl<T: ::core::fmt::Show> ::core::fmt::Show for Vec<T>
//{
//	fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::result::Result<(),::core::fmt::Error>
//	{
//		write!(f, "{}", self.as_slice())
//	}
//}

impl<T> MutableSeq<T> for Vec<T>
{
	fn push(&mut self, t: T)
	{
		let pos = self.size;
		self.reserve(pos + 1);
		self.size += 1;
		let ptr = self.get_mut_ptr(pos);
		//log_debug!("Vec.push {}", HexDump(&t));
		unsafe { ::core::ptr::write(ptr, t); }
	}
	fn pop(&mut self) -> Option<T>
	{
		if self.size == 0
		{
			None
		}
		else
		{
			self.size -= 1;
			let pos = self.size;
			Some( unsafe { self.move_ent(pos) } )
		}
	}
}

impl<T> FromIterator<T> for Vec<T>
{
	fn from_iter<IT: Iterator<Item=T>>(iterator: IT) -> Vec<T>
	{
		let mut ret = Vec::new();
		for val in iterator
		{
			ret.push(val);
		}
		ret
	}
}

impl<T> MoveItems<T>
{
	/// Pop an item from the iterator
	fn pop_item(&mut self) -> T
	{
		//log_debug!("MoveItems.pop_item() ofs={}, count={}, data={}", self.ofs, self.count, self.data);
		assert!(self.ofs < self.count);
		let v: T = unsafe {
			let ptr = self.data.offset(self.ofs as isize);
			::core::ptr::read(ptr as *const _)
			};
		//log_debug!("MoveItems.pop_item() v = {}", HexDump(&v));
		self.ofs += 1;
		v
	}
}

impl<T> Iterator for MoveItems<T>
{
	type Item = T;
	fn next(&mut self) -> Option<T>
	{
		if self.ofs == self.count
		{
			None
		}
		else
		{
			Some( self.pop_item() )
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for MoveItems<T>
{
	fn drop(&mut self)
	{
		for _ in range(self.ofs, self.count) {
			self.pop_item();
		}
		unsafe {
			::memory::heap::dealloc_array( self.data, self.count );
		}
	}
}

// vim: ft=rust
<commit_msg>Add type hint to vector<commit_after>//
//
//
use core::iter::range;
use core::iter::{FromIterator,Iterator};
use core::slice::{SliceExt,AsSlice};
use core::option::Option::{self,Some,None};
use core::ptr::PtrExt;
use core::num::Int;
use core::ops::{Drop,Index,IndexMut,Deref,DerefMut,Fn};
use core::marker::Send;
use lib::clone::Clone;
use lib::collections::{MutableSeq};

/// Growable array of items
pub struct Vec<T>
{
	data: *mut T,
	size: usize,
	capacity: usize,
}
// Sendable if the innards are sendable
unsafe impl<T: Send> Send for Vec<T> {}

/// Owning iterator
pub struct MoveItems<T>
{
	data: *mut T,
	count: usize,
	ofs: usize,
}

impl<T> Vec<T>
{
	/// Create a new, empty vector
	pub fn new() -> Vec<T>
	{
		Vec::with_capacity(0)
	}
	/// Create a vector with an initialised capacity
	pub fn with_capacity(size: usize) -> Vec<T>
	{
		Vec {
			data: unsafe { ::memory::heap::alloc_array::<T>( size ) },
			size: 0,
			capacity: size,
		}
	}
	/// Populate vector using a provided callback
	pub fn from_fn<Fcn>(length: usize, op: Fcn) -> Vec<T>
	where
		Fcn: Fn(usize) -> T
	{
		let mut ret = Vec::with_capacity(length);
		for i in range(0, length) {
			ret.push( op(i) );
		}
		ret
	}

	/// Obtain a mutable pointer to an item within the vector
	fn get_mut_ptr(&mut self, index: usize) -> *mut T
	{
		if index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { self.data.offset(index as isize) }
	}

	/// Move contents into an iterator (consuming self)
	pub fn into_iter(self) -> MoveItems<T>
	{
		let dataptr = self.data;
		let count = self.size;
		unsafe { ::core::mem::forget(self) };
		MoveItems {
			data: dataptr,
			ofs: 0,
			count: count,
		}
	}

	fn reserve(&mut self, size: usize)
	{
		let newcap = ::lib::num::round_up(size, 1 << (64-size.leading_zeros()));
		if newcap > self.capacity
		{
			unsafe {
				let newptr = ::memory::heap::alloc_array::<T>( newcap );
				for i in range(0, self.size) {
					let val = self.move_ent(i as usize);
					::core::ptr::write(newptr.offset(i as isize), val);
				}
				if self.capacity > 0 {
					::memory::heap::dealloc_array( self.data, self.capacity );
				}
				self.data = newptr;
				self.capacity = newcap;
			}
		}
	}

	pub fn slice_mut<'a>(&'a mut self) -> &'a mut [T]
	{
		unsafe { ::core::mem::transmute( ::core::raw::Slice { data: self.data as *const T, len: self.size } ) }
	}

	/// Move out of a slot in the vector, leaving unitialise memory in its place
	unsafe fn move_ent(&mut self, pos: usize) -> T
	{
		::core::ptr::read(self.data.offset(pos as isize) as *const _)
	}
}

impl<T> Deref for Vec<T>
{
	type Target = [T];
	fn deref(&self) -> &[T] {
		self.as_slice()
	}
}
impl<T> DerefMut for Vec<T>
{
	fn deref_mut(&mut self) -> &mut [T] {
		self.slice_mut()
	}
}

impl<T:Clone> Vec<T>
{
	pub fn from_elem(size: usize, elem: T) -> Vec<T>
	{
		Vec::from_fn( size, |_| elem.clone() )
	}

	pub fn push_all(&mut self, other: &[T])
	{
		let newlen = self.size + other.len();
		self.reserve(newlen);
		for v in other.iter() {
			self.push(v.clone());
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for Vec<T>
{
	fn drop(&mut self)
	{
		log_debug!("Vec::drop() - Dropping vector at {:p} w/ {} ents", self.data, self.size);
		unsafe {
			for i in range(0, self.size) {
				::core::mem::drop( ::core::ptr::read(self.get_mut_ptr(i) as *const T) );
			}
			::memory::heap::dealloc_array( self.data, self.capacity );
		}
	}
}

impl<T> Index<usize> for Vec<T>
{
	type Output = T;
	fn index<'a>(&'a self, index: &usize) -> &'a T
	{
		if *index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &*self.data.offset(*index as isize) }
	}
}
impl<T> IndexMut<usize> for Vec<T>
{
	type Output = T;
	fn index_mut<'a>(&'a mut self, index: &usize) -> &'a mut T
	{
		if *index >= self.size {
			panic!("Index out of range, {} >= {}", index, self.size);
		}
		unsafe { &mut *self.data.offset(*index as isize) }
	}
}

impl<T> ::core::slice::AsSlice<T> for Vec<T>
{
	fn as_slice<'a>(&'a self) -> &'a [T]
	{
		let rawslice = ::core::raw::Slice { data: self.data as *const T, len: self.size };
		unsafe { ::core::mem::transmute( rawslice ) }
	}
}

//impl<T: ::core::fmt::Show> ::core::fmt::Show for Vec<T>
//{
//	fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::result::Result<(),::core::fmt::Error>
//	{
//		write!(f, "{}", self.as_slice())
//	}
//}

impl<T> MutableSeq<T> for Vec<T>
{
	fn push(&mut self, t: T)
	{
		let pos = self.size;
		self.reserve(pos + 1);
		self.size += 1;
		let ptr = self.get_mut_ptr(pos);
		//log_debug!("Vec.push {}", HexDump(&t));
		unsafe { ::core::ptr::write(ptr, t); }
	}
	fn pop(&mut self) -> Option<T>
	{
		if self.size == 0
		{
			None
		}
		else
		{
			self.size -= 1;
			let pos = self.size;
			Some( unsafe { self.move_ent(pos) } )
		}
	}
}

impl<T> FromIterator<T> for Vec<T>
{
	fn from_iter<IT: Iterator<Item=T>>(iterator: IT) -> Vec<T>
	{
		let mut ret = Vec::new();
		if let (_, Some(size)) = iterator.size_hint()
		{
			ret.reserve(size);
		}
		for val in iterator
		{
			ret.push(val);
		}
		ret
	}
}

impl<T> MoveItems<T>
{
	/// Pop an item from the iterator
	fn pop_item(&mut self) -> T
	{
		//log_debug!("MoveItems.pop_item() ofs={}, count={}, data={}", self.ofs, self.count, self.data);
		assert!(self.ofs < self.count);
		let v: T = unsafe {
			let ptr = self.data.offset(self.ofs as isize);
			::core::ptr::read(ptr as *const _)
			};
		//log_debug!("MoveItems.pop_item() v = {}", HexDump(&v));
		self.ofs += 1;
		v
	}
}

impl<T> Iterator for MoveItems<T>
{
	type Item = T;
	fn next(&mut self) -> Option<T>
	{
		if self.ofs == self.count
		{
			None
		}
		else
		{
			Some( self.pop_item() )
		}
	}
}

#[unsafe_destructor]
impl<T> Drop for MoveItems<T>
{
	fn drop(&mut self)
	{
		for _ in range(self.ofs, self.count) {
			self.pop_item();
		}
		unsafe {
			::memory::heap::dealloc_array( self.data, self.count );
		}
	}
}

// vim: ft=rust
<|endoftext|>


<commit_before>// Copyright 2021 Vector 35 Inc.
//
// 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 binaryninjacore_sys::{
    BNBeginUndoActions,
    BNCloseFile,
    BNCloseProject,
    BNCommitUndoActions,
    BNCreateDatabase,
    BNCreateFileMetadata,
    BNFileMetadata,
    BNFreeFileMetadata,
    BNGetCurrentOffset,
    BNGetCurrentView,
    BNGetFileViewOfType,
    BNGetFilename,
    BNIsAnalysisChanged,
    BNIsBackedByDatabase,
    //BNSetFileMetadataNavigationHandler,
    BNIsFileModified,
    BNIsProjectOpen,
    BNMarkFileModified,
    BNMarkFileSaved,
    BNNavigate,
    BNNewFileReference,
    BNOpenDatabaseForConfiguration,
    BNOpenExistingDatabase,
    BNOpenProject,
    BNRedo,
    BNSaveAutoSnapshot,
    BNSetFilename,
    BNUndo,
};

use crate::binaryview::BinaryView;

use crate::rc::*;
use crate::string::*;

use std::ptr;

#[derive(PartialEq, Eq, Hash)]
pub struct FileMetadata {
    pub(crate) handle: *mut BNFileMetadata,
}

unsafe impl Send for FileMetadata {}
unsafe impl Sync for FileMetadata {}

impl FileMetadata {
    pub(crate) fn from_raw(handle: *mut BNFileMetadata) -> Self {
        Self { handle }
    }

    pub fn new() -> Ref<Self> {
        unsafe {
            Ref::new(Self {
                handle: BNCreateFileMetadata(),
            })
        }
    }

    pub fn with_filename<S: BnStrCompatible>(name: S) -> Ref<Self> {
        let ret = FileMetadata::new();
        ret.set_filename(name);
        ret
    }

    pub fn close(&self) {
        unsafe {
            BNCloseFile(self.handle);
        }
    }

    pub fn filename(&self) -> BnString {
        unsafe {
            let raw = BNGetFilename(self.handle);
            BnString::from_raw(raw)
        }
    }

    pub fn set_filename<S: BnStrCompatible>(&self, name: S) {
        let name = name.as_bytes_with_nul();

        unsafe {
            BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _);
        }
    }

    pub fn modified(&self) -> bool {
        unsafe { BNIsFileModified(self.handle) }
    }

    pub fn mark_modified(&self) {
        unsafe {
            BNMarkFileModified(self.handle);
        }
    }

    pub fn mark_saved(&self) {
        unsafe {
            BNMarkFileSaved(self.handle);
        }
    }

    pub fn is_analysis_changed(&self) -> bool {
        unsafe { BNIsAnalysisChanged(self.handle) }
    }

    pub fn is_database_backed<S: BnStrCompatible>(&self, view_type: S) -> bool {
        let view_type = view_type.as_bytes_with_nul();

        unsafe { BNIsBackedByDatabase(self.handle, view_type.as_ref().as_ptr() as *const _) }
    }

    pub fn begin_undo_actions(&self) {
        unsafe {
            BNBeginUndoActions(self.handle);
        }
    }

    pub fn commit_undo_actions(&self) {
        unsafe {
            BNCommitUndoActions(self.handle);
        }
    }

    pub fn undo(&self) {
        unsafe {
            BNUndo(self.handle);
        }
    }

    pub fn redo(&self) {
        unsafe {
            BNRedo(self.handle);
        }
    }

    pub fn current_view(&self) -> BnString {
        unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) }
    }

    pub fn current_offset(&self) -> u64 {
        unsafe { BNGetCurrentOffset(self.handle) }
    }

    pub fn navigate_to<S: BnStrCompatible>(&self, view: S, offset: u64) -> Result<(), ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    pub fn get_view_of_type<S: BnStrCompatible>(&self, view: S) -> Result<Ref<BinaryView>, ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            let res = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _);

            if res.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(res))
            }
        }
    }

    pub fn create_database<S: BnStrCompatible>(&self, filename: S) -> bool {
        let filename = filename.as_bytes_with_nul();
        let raw = "Raw";

        unsafe {
            BNCreateDatabase(
                BNGetFileViewOfType(self.handle, raw.as_ptr() as *mut _),
                filename.as_ref().as_ptr() as *mut _,
                ptr::null_mut() as *mut _,
            )
        }
    }

    pub fn save_auto_snapshot(&self) -> bool {
        let raw = "Raw";
        unsafe {
            BNSaveAutoSnapshot(
                BNGetFileViewOfType(self.handle, raw.as_ptr() as *mut _),
                ptr::null_mut() as *mut _,
            )
        }
    }

    pub fn open_database_for_configuration<S: BnStrCompatible>(
        &self,
        filename: S,
    ) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        unsafe {
            let bv =
                BNOpenDatabaseForConfiguration(self.handle, filename.as_ref().as_ptr() as *const _);

            if bv.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(bv))
            }
        }
    }

    pub fn open_database<S: BnStrCompatible>(&self, filename: S) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        let filename_ptr = filename.as_ref().as_ptr() as *mut _;

        let view = unsafe { BNOpenExistingDatabase(self.handle, filename_ptr) };

        // TODO : add optional progress function
        // let view = match progress_func {
        //     None => BNOpenExistingDatabase(self.handle, filename_ptr),
        //     _ => BNOpenExistingDatabaseWithProgress(self.handle, str(filename), None, ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, cur, total: progress_func(cur, total)))
        // };

        if view.is_null() {
            Err(())
        } else {
            Ok(unsafe { BinaryView::from_raw(view) })
        }
    }

    pub fn open_project(&self) -> bool {
        unsafe { BNOpenProject(self.handle) }
    }

    pub fn close_project(&self) {
        unsafe {
            BNCloseProject(self.handle);
        }
    }

    pub fn is_project_open(&self) -> bool {
        unsafe { BNIsProjectOpen(self.handle) }
    }
}

impl ToOwned for FileMetadata {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for FileMetadata {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewFileReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreeFileMetadata(handle.handle);
    }
}

/*
BNCreateDatabase,
BNCreateDatabaseWithProgress,
*/
<commit_msg>Rust API : fix save apis<commit_after>// Copyright 2021 Vector 35 Inc.
//
// 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 binaryninjacore_sys::{
    BNBeginUndoActions,
    BNCloseFile,
    BNCloseProject,
    BNCommitUndoActions,
    BNCreateDatabase,
    BNCreateFileMetadata,
    BNFileMetadata,
    BNFreeFileMetadata,
    BNGetCurrentOffset,
    BNGetCurrentView,
    BNGetFileViewOfType,
    BNGetFilename,
    BNIsAnalysisChanged,
    BNIsBackedByDatabase,
    //BNSetFileMetadataNavigationHandler,
    BNIsFileModified,
    BNIsProjectOpen,
    BNMarkFileModified,
    BNMarkFileSaved,
    BNNavigate,
    BNNewFileReference,
    BNOpenDatabaseForConfiguration,
    BNOpenExistingDatabase,
    BNOpenProject,
    BNRedo,
    BNSaveAutoSnapshot,
    BNSetFilename,
    BNUndo,
};

use crate::binaryview::BinaryView;

use crate::rc::*;
use crate::string::*;

use std::ptr;

#[derive(PartialEq, Eq, Hash)]
pub struct FileMetadata {
    pub(crate) handle: *mut BNFileMetadata,
}

unsafe impl Send for FileMetadata {}
unsafe impl Sync for FileMetadata {}

impl FileMetadata {
    pub(crate) fn from_raw(handle: *mut BNFileMetadata) -> Self {
        Self { handle }
    }

    pub fn new() -> Ref<Self> {
        unsafe {
            Ref::new(Self {
                handle: BNCreateFileMetadata(),
            })
        }
    }

    pub fn with_filename<S: BnStrCompatible>(name: S) -> Ref<Self> {
        let ret = FileMetadata::new();
        ret.set_filename(name);
        ret
    }

    pub fn close(&self) {
        unsafe {
            BNCloseFile(self.handle);
        }
    }

    pub fn filename(&self) -> BnString {
        unsafe {
            let raw = BNGetFilename(self.handle);
            BnString::from_raw(raw)
        }
    }

    pub fn set_filename<S: BnStrCompatible>(&self, name: S) {
        let name = name.as_bytes_with_nul();

        unsafe {
            BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _);
        }
    }

    pub fn modified(&self) -> bool {
        unsafe { BNIsFileModified(self.handle) }
    }

    pub fn mark_modified(&self) {
        unsafe {
            BNMarkFileModified(self.handle);
        }
    }

    pub fn mark_saved(&self) {
        unsafe {
            BNMarkFileSaved(self.handle);
        }
    }

    pub fn is_analysis_changed(&self) -> bool {
        unsafe { BNIsAnalysisChanged(self.handle) }
    }

    pub fn is_database_backed<S: BnStrCompatible>(&self, view_type: S) -> bool {
        let view_type = view_type.as_bytes_with_nul();

        unsafe { BNIsBackedByDatabase(self.handle, view_type.as_ref().as_ptr() as *const _) }
    }

    pub fn begin_undo_actions(&self) {
        unsafe {
            BNBeginUndoActions(self.handle);
        }
    }

    pub fn commit_undo_actions(&self) {
        unsafe {
            BNCommitUndoActions(self.handle);
        }
    }

    pub fn undo(&self) {
        unsafe {
            BNUndo(self.handle);
        }
    }

    pub fn redo(&self) {
        unsafe {
            BNRedo(self.handle);
        }
    }

    pub fn current_view(&self) -> BnString {
        unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) }
    }

    pub fn current_offset(&self) -> u64 {
        unsafe { BNGetCurrentOffset(self.handle) }
    }

    pub fn navigate_to<S: BnStrCompatible>(&self, view: S, offset: u64) -> Result<(), ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    pub fn get_view_of_type<S: BnStrCompatible>(&self, view: S) -> Result<Ref<BinaryView>, ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            let res = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _);

            if res.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(res))
            }
        }
    }

    pub fn create_database<S: BnStrCompatible>(&self, filename: S) -> bool {
        let filename = filename.as_bytes_with_nul();
        let raw = "Raw".as_bytes_with_nul();

        unsafe {
            BNCreateDatabase(
                BNGetFileViewOfType(self.handle, raw.as_ptr() as *mut _),
                filename.as_ref().as_ptr() as *mut _,
                ptr::null_mut() as *mut _,
            )
        }
    }

    pub fn save_auto_snapshot(&self) -> bool {
        let raw = "Raw".as_bytes_with_nul();
        unsafe {
            BNSaveAutoSnapshot(
                BNGetFileViewOfType(self.handle, raw.as_ptr() as *mut _),
                ptr::null_mut() as *mut _,
            )
        }
    }

    pub fn open_database_for_configuration<S: BnStrCompatible>(
        &self,
        filename: S,
    ) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        unsafe {
            let bv =
                BNOpenDatabaseForConfiguration(self.handle, filename.as_ref().as_ptr() as *const _);

            if bv.is_null() {
                Err(())
            } else {
                Ok(BinaryView::from_raw(bv))
            }
        }
    }

    pub fn open_database<S: BnStrCompatible>(&self, filename: S) -> Result<Ref<BinaryView>, ()> {
        let filename = filename.as_bytes_with_nul();
        let filename_ptr = filename.as_ref().as_ptr() as *mut _;

        let view = unsafe { BNOpenExistingDatabase(self.handle, filename_ptr) };

        // TODO : add optional progress function
        // let view = match progress_func {
        //     None => BNOpenExistingDatabase(self.handle, filename_ptr),
        //     _ => BNOpenExistingDatabaseWithProgress(self.handle, str(filename), None, ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, cur, total: progress_func(cur, total)))
        // };

        if view.is_null() {
            Err(())
        } else {
            Ok(unsafe { BinaryView::from_raw(view) })
        }
    }

    pub fn open_project(&self) -> bool {
        unsafe { BNOpenProject(self.handle) }
    }

    pub fn close_project(&self) {
        unsafe {
            BNCloseProject(self.handle);
        }
    }

    pub fn is_project_open(&self) -> bool {
        unsafe { BNIsProjectOpen(self.handle) }
    }
}

impl ToOwned for FileMetadata {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for FileMetadata {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewFileReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreeFileMetadata(handle.handle);
    }
}

/*
BNCreateDatabase,
BNCreateDatabaseWithProgress,
*/
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;

extern crate bytes;
extern crate tokio;
extern crate tokio_codec;
extern crate tokio_io;

extern crate serde;
extern crate serde_json;

use bytes::BytesMut;
use std::io;
use tokio::codec::{Encoder,Decoder};
use tokio::prelude::*;
use tokio::net::TcpListener;
use std::collections::HashMap;
use std::sync::{Mutex, Arc};

#[derive(Clone,Copy)]
pub struct ExampleJSONParser;
impl ExampleJSONParser {
    fn new() -> ExampleJSONParser {
        ExampleJSONParser{}
    }
}

impl ExampleJSONParser {
    fn parse(&self, info: &Vec<u8>)  -> Message {
        let vec_to_parse = info.clone();
        let message = String::from_utf8(vec_to_parse).unwrap();
        println!("Json parser for: {:?}", message);
        let msg: Message = match serde_json::from_str(&message)  {
            Err(..) =>   {println!("It was not parsed correctly"); Message::new_empty() },
            Ok(msg) => msg,
        };
        return msg
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Message {
    operation: String,
}

impl Message {
    fn new(operation: String) -> Message {
        Message {operation: operation}
    }
    fn new_empty() -> Message  {
        Message {operation: "".to_string()}
    }

}
pub trait Operation {
    fn run(self);
}

impl Operation for Message {
    fn run (self) {
        println!("hello!");
    }
}

pub struct MyBytesCodec {
    json_parser: ExampleJSONParser,
    //operations: HashMap<String, Arc<Mutex<dyn Operation + Send + 'static>>>,
    operations: HashMap<String, Box<dyn Operation + Send>>,
}

impl MyBytesCodec {
    fn new() -> MyBytesCodec {
        MyBytesCodec{json_parser: ExampleJSONParser::new(), operations: HashMap::new()}
    }
}

impl Decoder for MyBytesCodec {
    type Item = Message;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
        if buf.len() == 0 {
            return Ok(None);
        }
        let data = buf.clone().to_vec();
        let cloned_data = data.clone();
        let parsed = self.json_parser.parse(&cloned_data);
        buf.clear();
        Ok(Some(parsed))
    }
}

impl Encoder for MyBytesCodec {
    type Item = Message;
    type Error = io::Error;

    fn encode(&mut self, data: Message, buf: &mut BytesMut) -> io::Result<()> {
        buf.extend(serde_json::to_string(&data)?.into_bytes());
        Ok(())
    }
}

fn main() {
    let addr = "127.0.0.1:12345".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");
    let server = listener.incoming()
            .map_err(|e| eprintln!("accept failed = {:?}", e))
            .for_each(move |socket| {
                let framed = MyBytesCodec::new().framed(socket);
                let (_writer, reader) = framed.split();

                /* function to handle connection  */
                let handle_conn = reader.for_each(|message| {
                    println!("my parsed message!!: {:?}", serde_json::to_string(&message));
                    Ok(())
                })
                .and_then(|()| {
                    println!("Socket received FIN packet and closed connection");
                    Ok(())
                })
                .or_else(|err| {
                    println!("Socked closed with error: {:?}", err);
                    Err(err)

                })
                .then(|result| {
                    println!("Socket closed with result: {:?}", result);
                    Ok(())
                });

            tokio::spawn(handle_conn)
    });
    tokio::run(server);
}

<commit_msg>Fixed operator to use function inside hash<commit_after>#[macro_use]
extern crate serde_derive;

extern crate bytes;
extern crate tokio;
extern crate tokio_codec;
extern crate tokio_io;

extern crate serde;
extern crate serde_json;

use bytes::BytesMut;
use std::io;
use tokio::codec::{Encoder,Decoder};
use tokio::prelude::*;
use tokio::net::TcpListener;
use std::collections::HashMap;
use std::sync::{Mutex, Arc};
use std::rc::Rc;

#[derive(Clone,Copy)]
pub struct ExampleJSONParser;
impl ExampleJSONParser {
    fn new() -> ExampleJSONParser {
        ExampleJSONParser{}
    }
}

impl ExampleJSONParser {
    fn parse(&self, info: &Vec<u8>)  -> Message {
        let vec_to_parse = info.clone();
        let message = String::from_utf8(vec_to_parse).unwrap();
        println!("Json parser for: {:?}", message);
        let msg: Message = match serde_json::from_str(&message)  {
            Err(..) =>   {println!("It was not parsed correctly"); Message::new_empty() },
            Ok(msg) => msg,
        };
        return msg
    }
}

#[derive(Clone)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Message {
    operation: String,
}

impl Message{
    fn new(operation: String) -> Message {
        Message {operation: operation}
    }
    fn new_empty() -> Message  {
        Message {operation: "".to_string()}
    }

}

pub trait Operation {
    fn run(self);
}

impl Operation for Message {
    fn run (self) {
        println!("hello!");
    }
}

pub struct MyBytesCodec {
    json_parser: ExampleJSONParser,
}

impl MyBytesCodec {
    fn new() -> MyBytesCodec {
        MyBytesCodec{json_parser: ExampleJSONParser::new()}
    }
}

impl Decoder for MyBytesCodec {
    type Item = Message;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
        if buf.len() == 0 {
            return Ok(None);
        }
        let data = buf.clone().to_vec();
        let cloned_data = data.clone();
        let parsed = self.json_parser.parse(&cloned_data);
        buf.clear();
        Ok(Some(parsed))
    }
}

impl Encoder for MyBytesCodec {
    type Item = Message;
    type Error = io::Error;

    fn encode(&mut self, data: Message, buf: &mut BytesMut) -> io::Result<()> {
        buf.extend(serde_json::to_string(&data)?.into_bytes());
        Ok(())
    }
}

fn main() {
    let operations: HashMap<String, Message> = HashMap::new();
    let shared_oper = Arc::new(Mutex::new(operations));

    let addr = "127.0.0.1:12345".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");
    let server = listener.incoming()
            .map_err(|e| eprintln!("accept failed = {:?}", e))
            .for_each(move |socket| {
                let framed = MyBytesCodec::new().framed(socket);
                let (_writer, reader) = framed.split();
                let operations = shared_oper.clone();
                /* function to handle connection  */
                let handle_conn = reader.for_each(move |message| {
                    println!("my parsed message!!: {:?}", serde_json::to_string(&message));

                    if (operations.lock().unwrap().contains_key(&message.operation)) {
                        let extracted_operations = operations.lock().unwrap();
                        extracted_operations.get(&message.operation).unwrap().clone().run();
                    }

                    Ok(())
                })
                .and_then(|()| {
                    println!("Socket received FIN packet and closed connection");
                    Ok(())
                })
                .or_else(|err| {
                    println!("Socked closed with error: {:?}", err);
                    Err(err)

                })
                .then(|result| {
                    println!("Socket closed with result: {:?}", result);
                    Ok(())
                });

            tokio::spawn(handle_conn)
    });
    tokio::run(server);
}

<|endoftext|>


<commit_before>//! Tests for reverse-string
//!
//! Generated by [script][script] using [canonical data][canonical-data]
//!
//! [script]: https://github.com/exercism/rust/blob/b829ce2/bin/init_exercise.py
//! [canonical-data]: https://raw.githubusercontent.com/exercism/problem-specifications/main/exercises/reverse-string/canonical_data.json

use reverse_string::*;

/// Process a single test case for the property `reverse`
fn process_reverse_case(input: &str, expected: &str) {
    assert_eq!(&reverse(input), expected)
}

#[test]
/// empty string
fn test_an_empty_string() {
    process_reverse_case("", "");
}

#[test]
#[ignore]
/// a word
fn test_a_word() {
    process_reverse_case("robot", "tobor");
}

#[test]
#[ignore]
/// a capitalized word
fn test_a_capitalized_word() {
    process_reverse_case("Ramen", "nemaR");
}

#[test]
#[ignore]
/// a sentence with punctuation
fn test_a_sentence_with_punctuation() {
    process_reverse_case("I'm hungry!", "!yrgnuh m'I");
}

#[test]
#[ignore]
/// a palindrome
fn test_a_palindrome() {
    process_reverse_case("racecar", "racecar");
}

#[test]
#[ignore]
/// an even-sized word
fn test_an_even_sized_word() {
    process_reverse_case("drawer", "reward");
}

#[test]
#[ignore]
/// wide characters
fn test_wide_characters() {
    process_reverse_case("子猫", "猫子");
}

#[test]
#[ignore]
#[cfg(feature = "grapheme")]
/// grapheme clusters
fn test_grapheme_clusters() {
    process_reverse_case("uüu", "uüu");
}
<commit_msg>Pass all standard tests<commit_after>//! Tests for reverse-string
//!
//! Generated by [script][script] using [canonical data][canonical-data]
//!
//! [script]: https://github.com/exercism/rust/blob/b829ce2/bin/init_exercise.py
//! [canonical-data]: https://raw.githubusercontent.com/exercism/problem-specifications/main/exercises/reverse-string/canonical_data.json

use reverse_string::*;

/// Process a single test case for the property `reverse`
fn process_reverse_case(input: &str, expected: &str) {
    assert_eq!(&reverse(input), expected)
}

#[test]
/// empty string
fn test_an_empty_string() {
    process_reverse_case("", "");
}

#[test]
/// a word
fn test_a_word() {
    process_reverse_case("robot", "tobor");
}

#[test]
/// a capitalized word
fn test_a_capitalized_word() {
    process_reverse_case("Ramen", "nemaR");
}

#[test]
/// a sentence with punctuation
fn test_a_sentence_with_punctuation() {
    process_reverse_case("I'm hungry!", "!yrgnuh m'I");
}

#[test]
/// a palindrome
fn test_a_palindrome() {
    process_reverse_case("racecar", "racecar");
}

#[test]
/// an even-sized word
fn test_an_even_sized_word() {
    process_reverse_case("drawer", "reward");
}

#[test]
/// wide characters
fn test_wide_characters() {
    process_reverse_case("子猫", "猫子");
}

#[test]
#[ignore]
#[cfg(feature = "grapheme")]
/// grapheme clusters
fn test_grapheme_clusters() {
    process_reverse_case("uüu", "uüu");
}
<|endoftext|>


<commit_before>extern crate syn;
use syn::*;

#[test]
fn test_unit() {
    let raw = "struct Unit;";

    let expected = MacroInput {
        ident: "Unit".into(),
        vis: Visibility::Inherited,
        attrs: Vec::new(),
        generics: Generics::default(),
        body: Body::Struct(VariantData::Unit),
    };

    assert_eq!(expected, parse_macro_input(raw).unwrap());
}

#[test]
fn test_struct() {
    let raw = "
        #[derive(Debug, Clone)]
        pub struct Item {
            pub ident: Ident,
            pub attrs: Vec<Attribute>,
        }
    ";

    let expected = MacroInput {
        ident: "Item".into(),
        vis: Visibility::Public,
        attrs: vec![Attribute {
            style: AttrStyle::Outer,
            path: "derive".into(),
            tts: vec![
                TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
                    TokenTree::Token(Token::Ident(Ident::from("Debug"))),
                    TokenTree::Token(Token::Comma),
                    TokenTree::Token(Token::Ident(Ident::from("Clone"))),
                ]})
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(VariantData::Struct(vec![Field {
                                                        ident: Some("ident".into()),
                                                        vis: Visibility::Public,
                                                        attrs: Vec::new(),
                                                        ty: Ty::Path(None, "Ident".into()),
                                                    },
                                                    Field {
                                                        ident: Some("attrs".into()),
                                                        vis: Visibility::Public,
                                                        attrs: Vec::new(),
                                                        ty: Ty::Path(None,
                                                                     Path {
                                                                         global: false,
                                                                         segments: vec![
                        PathSegment {
                            ident: "Vec".into(),
                            parameters: PathParameters::AngleBracketed(
                                AngleBracketedParameterData {
                                    lifetimes: Vec::new(),
                                    types: vec![Ty::Path(None, "Attribute".into())],
                                    bindings: Vec::new(),
                                },
                            ),
                        }
                    ],
                                                                     }),
                                                    }])),
    };

    let actual = parse_macro_input(raw).unwrap();

    assert_eq!(expected, actual);

    let expected_meta_item = MetaItem::List(vec![
        NestedMetaItem::MetaItem(Ident::from("Debug"), MetaItem::Word),
        NestedMetaItem::MetaItem(Ident::from("Clone"), MetaItem::Word),
    ]);

    assert_eq!(expected_meta_item, actual.attrs[0].meta_item().unwrap());
}

#[test]
#[cfg(feature = "full")]
fn test_enum() {
    let raw = r#"
        /// See the std::result module documentation for details.
        #[must_use]
        pub enum Result<T, E> {
            Ok(T),
            Err(E),
            Surprise = 0isize,

            // Smuggling data into a proc_macro_derive,
            // in the style of https://github.com/dtolnay/proc-macro-hack
            ProcMacroHack = (0, "data").0,
        }
    "#;

    let expected = MacroInput {
        ident: "Result".into(),
        vis: Visibility::Public,
        attrs: vec![
            Attribute {
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(
                        "/// See the std::result module documentation for details.".into(),
                        StrStyle::Cooked,
                    ))),
                ],
                is_sugared_doc: true,
            },
            Attribute {
                style: AttrStyle::Outer,
                path: "must_use".into(),
                tts: vec![],
                is_sugared_doc: false,
            },
        ],
        generics: Generics {
            lifetimes: Vec::new(),
            ty_params: vec![TyParam {
                                attrs: Vec::new(),
                                ident: "T".into(),
                                bounds: Vec::new(),
                                default: None,
                            },
                            TyParam {
                                attrs: Vec::new(),
                                ident: "E".into(),
                                bounds: Vec::new(),
                                default: None,
                            }],
            where_clause: WhereClause { predicates: Vec::new() },
        },
        body: Body::Enum(vec![
            Variant {
                ident: "Ok".into(),
                attrs: Vec::new(),
                data: VariantData::Tuple(vec![
                    Field {
                        ident: None,
                        vis: Visibility::Inherited,
                        attrs: Vec::new(),
                        ty: Ty::Path(None, "T".into()),
                    },
                ]),
                discriminant: None,
            },
            Variant {
                ident: "Err".into(),
                attrs: Vec::new(),
                data: VariantData::Tuple(vec![
                    Field {
                        ident: None,
                        vis: Visibility::Inherited,
                        attrs: Vec::new(),
                        ty: Ty::Path(None, "E".into()),
                    },
                ]),
                discriminant: None,
            },
            Variant {
                ident: "Surprise".into(),
                attrs: Vec::new(),
                data: VariantData::Unit,
                discriminant: Some(ConstExpr::Lit(Lit::Int(0, IntTy::Isize))),
            },
            Variant {
                ident: "ProcMacroHack".into(),
                attrs: Vec::new(),
                data: VariantData::Unit,
                discriminant: Some(ConstExpr::Other(Expr {
                    node: ExprKind::TupField(
                        Box::new(Expr {
                            node: ExprKind::Tup(vec![
                                Expr {
                                    node: ExprKind::Lit(Lit::Int(0, IntTy::Unsuffixed)),
                                    attrs: Vec::new(),
                                },
                                Expr {
                                    node: ExprKind::Lit(Lit::Str("data".into(), StrStyle::Cooked)),
                                    attrs: Vec::new(),
                                },
                            ]),
                            attrs: Vec::new(),
                        }),
                        0
                    ),
                    attrs: Vec::new(),
                })),
            },
        ]),
    };

    let actual = parse_macro_input(raw).unwrap();

    assert_eq!(expected, actual);

    let expected_meta_items = vec![
        MetaItem::NameValue(Lit::Str(
            "/// See the std::result module documentation for details.".into(),
            StrStyle::Cooked,
        )),
        MetaItem::Word,
    ];

    let actual_meta_items: Vec<_> = actual.attrs.into_iter().map(|attr| attr.meta_item().unwrap()).collect();

    assert_eq!(expected_meta_items, actual_meta_items);
}
<commit_msg>fixup! Test for attributes with paths.<commit_after>extern crate syn;
use syn::*;

#[test]
fn test_unit() {
    let raw = "struct Unit;";

    let expected = MacroInput {
        ident: "Unit".into(),
        vis: Visibility::Inherited,
        attrs: Vec::new(),
        generics: Generics::default(),
        body: Body::Struct(VariantData::Unit),
    };

    assert_eq!(expected, parse_macro_input(raw).unwrap());
}

#[test]
fn test_struct() {
    let raw = "
        #[derive(Debug, Clone)]
        pub struct Item {
            pub ident: Ident,
            pub attrs: Vec<Attribute>,
        }
    ";

    let expected = MacroInput {
        ident: "Item".into(),
        vis: Visibility::Public,
        attrs: vec![Attribute {
            style: AttrStyle::Outer,
            path: "derive".into(),
            tts: vec![
                TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
                    TokenTree::Token(Token::Ident(Ident::from("Debug"))),
                    TokenTree::Token(Token::Comma),
                    TokenTree::Token(Token::Ident(Ident::from("Clone"))),
                ]})
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(VariantData::Struct(vec![Field {
                                                        ident: Some("ident".into()),
                                                        vis: Visibility::Public,
                                                        attrs: Vec::new(),
                                                        ty: Ty::Path(None, "Ident".into()),
                                                    },
                                                    Field {
                                                        ident: Some("attrs".into()),
                                                        vis: Visibility::Public,
                                                        attrs: Vec::new(),
                                                        ty: Ty::Path(None,
                                                                     Path {
                                                                         global: false,
                                                                         segments: vec![
                        PathSegment {
                            ident: "Vec".into(),
                            parameters: PathParameters::AngleBracketed(
                                AngleBracketedParameterData {
                                    lifetimes: Vec::new(),
                                    types: vec![Ty::Path(None, "Attribute".into())],
                                    bindings: Vec::new(),
                                },
                            ),
                        }
                    ],
                                                                     }),
                                                    }])),
    };

    let actual = parse_macro_input(raw).unwrap();

    assert_eq!(expected, actual);

    let expected_meta_item = MetaItem::List(vec![
        NestedMetaItem::MetaItem(Ident::from("Debug"), MetaItem::Word),
        NestedMetaItem::MetaItem(Ident::from("Clone"), MetaItem::Word),
    ]);

    assert_eq!(expected_meta_item, actual.attrs[0].meta_item().unwrap());
}

#[test]
#[cfg(feature = "full")]
fn test_enum() {
    let raw = r#"
        /// See the std::result module documentation for details.
        #[must_use]
        pub enum Result<T, E> {
            Ok(T),
            Err(E),
            Surprise = 0isize,

            // Smuggling data into a proc_macro_derive,
            // in the style of https://github.com/dtolnay/proc-macro-hack
            ProcMacroHack = (0, "data").0,
        }
    "#;

    let expected = MacroInput {
        ident: "Result".into(),
        vis: Visibility::Public,
        attrs: vec![
            Attribute {
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(
                        "/// See the std::result module documentation for details.".into(),
                        StrStyle::Cooked,
                    ))),
                ],
                is_sugared_doc: true,
            },
            Attribute {
                style: AttrStyle::Outer,
                path: "must_use".into(),
                tts: vec![],
                is_sugared_doc: false,
            },
        ],
        generics: Generics {
            lifetimes: Vec::new(),
            ty_params: vec![TyParam {
                                attrs: Vec::new(),
                                ident: "T".into(),
                                bounds: Vec::new(),
                                default: None,
                            },
                            TyParam {
                                attrs: Vec::new(),
                                ident: "E".into(),
                                bounds: Vec::new(),
                                default: None,
                            }],
            where_clause: WhereClause { predicates: Vec::new() },
        },
        body: Body::Enum(vec![
            Variant {
                ident: "Ok".into(),
                attrs: Vec::new(),
                data: VariantData::Tuple(vec![
                    Field {
                        ident: None,
                        vis: Visibility::Inherited,
                        attrs: Vec::new(),
                        ty: Ty::Path(None, "T".into()),
                    },
                ]),
                discriminant: None,
            },
            Variant {
                ident: "Err".into(),
                attrs: Vec::new(),
                data: VariantData::Tuple(vec![
                    Field {
                        ident: None,
                        vis: Visibility::Inherited,
                        attrs: Vec::new(),
                        ty: Ty::Path(None, "E".into()),
                    },
                ]),
                discriminant: None,
            },
            Variant {
                ident: "Surprise".into(),
                attrs: Vec::new(),
                data: VariantData::Unit,
                discriminant: Some(ConstExpr::Lit(Lit::Int(0, IntTy::Isize))),
            },
            Variant {
                ident: "ProcMacroHack".into(),
                attrs: Vec::new(),
                data: VariantData::Unit,
                discriminant: Some(ConstExpr::Other(Expr {
                    node: ExprKind::TupField(
                        Box::new(Expr {
                            node: ExprKind::Tup(vec![
                                Expr {
                                    node: ExprKind::Lit(Lit::Int(0, IntTy::Unsuffixed)),
                                    attrs: Vec::new(),
                                },
                                Expr {
                                    node: ExprKind::Lit(Lit::Str("data".into(), StrStyle::Cooked)),
                                    attrs: Vec::new(),
                                },
                            ]),
                            attrs: Vec::new(),
                        }),
                        0
                    ),
                    attrs: Vec::new(),
                })),
            },
        ]),
    };

    let actual = parse_macro_input(raw).unwrap();

    assert_eq!(expected, actual);

    let expected_meta_items = vec![
        MetaItem::NameValue(Lit::Str(
            "/// See the std::result module documentation for details.".into(),
            StrStyle::Cooked,
        )),
        MetaItem::Word,
    ];

    let actual_meta_items: Vec<_> = actual.attrs.into_iter().map(|attr| attr.meta_item().unwrap()).collect();

    assert_eq!(expected_meta_items, actual_meta_items);
}

#[test]
fn test_attr_with_path() {
    let raw =r#"
        #[::attr_args::identity
            fn main() { assert_eq!(foo(), "Hello, world!"); }]
        struct Dummy;
    "#;

    let expected = MacroInput {
        ident: "Dummy".into(),
        vis: Visibility::Inherited,
        attrs: vec![Attribute {
            style: AttrStyle::Outer,
            path: Path { global: true, segments: vec!["attr_args".into(), "identity".into()] },
            tts: vec![
                TokenTree::Token(Token::Ident(Ident::from("fn"))),
                TokenTree::Token(Token::Ident(Ident::from("main"))),
                TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![] }),
                TokenTree::Delimited(Delimited { delim: DelimToken::Brace, tts: vec![
                    TokenTree::Token(Token::Ident(Ident::from("assert_eq"))),
                    TokenTree::Token(Token::Not),
                    TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
                        TokenTree::Token(Token::Ident(Ident::from("foo"))),
                        TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![] }),
                        TokenTree::Token(Token::Comma),
                        TokenTree::Token(Token::Literal(Lit::Str("Hello, world!".into(), StrStyle::Cooked))),
                    ]}),
                    TokenTree::Token(Token::Semi),
                ]})
            ],
            is_sugared_doc: false,
        }],
        generics: Generics::default(),
        body: Body::Struct(VariantData::Unit),
    };

    let actual = parse_macro_input(raw).unwrap();

    assert_eq!(expected, actual);

    assert!(actual.attrs[0].meta_item().is_none());
}
<|endoftext|>


<commit_before>// This module implements simple request and response objects.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use http;
use http::server::request::RequestUri::AbsolutePath;
use http::headers::request::HeaderCollection;
use url::Url;
use url::form_urlencoded::parse as form_urlencoded_parse;

use datastructures::{Headers, MultiDict};
use httputils::{get_name_by_http_code, get_content_type};

/// Request type.
pub struct Request {
    pub request: http::server::Request,
    form: Option<MultiDict>,
}

impl Request {
    /// Create a `Request`.
    pub fn new(request: http::server::Request) -> Request {
        Request {
            request: request,
            form: None,
        }
    }

    /// The parsed URL parameters.
    pub fn args(&self) -> MultiDict {
        let mut args = MultiDict::new();
        match self.request.request_uri {
            AbsolutePath(ref url) => {
                let url = Url::parse(url.as_slice()).unwrap();
                match url.query_pairs() {
                    Some(pairs) => {
                        for &(ref k, ref v) in pairs.iter() {
                            args.add(k.as_slice(), v.as_slice());
                        }
                    },
                    None => (),
                }
            },
            _ => (),
        }
        return args;
    }

    /// This method is used internally to retrieve submitted data.
    fn load_form_data(&mut self) {
        if self.form.is_some() {
            return
        }
        let form = match self.request.headers.content_type {
            Some(ref content_type) => {
                if content_type.type_ == String::from_str("application") &&
                    (content_type.subtype == String::from_str("x-www-form-urlencoded") ||
                     content_type.subtype == String::from_str("x-url-encoded")) {
                    let mut form = MultiDict::new();
                    for &(ref k, ref v) in form_urlencoded_parse(self.request.body.as_slice()).iter() {
                        form.add(k.as_slice(), v.as_slice());
                    }
                    form
                } else {
                    MultiDict::new()
                }
            },
            None => {
                MultiDict::new()
            }
        };
        self.form = Some(form);
    }

    /// The form parameters.
    pub fn form(&mut self) -> &MultiDict {
        self.load_form_data();
        self.form.as_ref().unwrap()
    }

    /// The headers.
    pub fn headers(&self) -> &HeaderCollection {
        &self.request.headers
    }
}

/// Response type.  It is just one container with a couple of parameters
/// (headers, body, status code etc).
#[deriving(Clone)]
pub struct Response {
    pub status_code: int,
    pub headers: Headers,
    pub body: String,
}

impl Response {
    /// Create a `Response`.
    pub fn new(body: String) -> Response {
        let mut response = Response {
            status_code: 200,
            headers: Headers::new(None),
            body: body,
        };
        let content_length = response.body.len().to_string();
        response.headers.set("Content-Type", "text/html; charset=utf-8");
        response.headers.set("Content-Length", content_length.as_slice());
        return response;
    }

    /// Get status name.
    pub fn status_name(&self) -> &str {
        match get_name_by_http_code(self.status_code) {
            Some(name) => name,
            None => "UNKNOWN",
        }
    }

    /// Sets a new string as response body.  The content length is set
    /// automatically.
    pub fn set_data(&mut self, value: String) {
        self.body = value;
        let content_length = self.body.len().to_string();
        self.headers.set("Content-Length", content_length.as_slice());
    }

    /// Returns the response content type if available.
    pub fn content_type(&self) -> Option<String> {
        let rv = self.headers.get("Content-Type");
        rv.map(|content_type| content_type.clone())
    }

    /// Set response content type.
    pub fn set_content_type(&mut self, value: &str) {
        self.headers.set("Content-Type", get_content_type(value, "utf-8").as_slice());
    }

    /// Returns the response content length if available.
    pub fn content_length(&self) -> Option<uint> {
        let rv = self.headers.get("Content-Length");
        match rv {
            Some(content_length) => from_str(content_length.as_slice()),
            None => None,
        }
    }

    /// Set content length.
    pub fn set_content_length(&mut self, value: uint) {
        self.headers.set("Content-Length", value.to_string().as_slice());
    }
}
<commit_msg>Added args cache<commit_after>// This module implements simple request and response objects.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use http;
use http::server::request::RequestUri::AbsolutePath;
use http::headers::request::HeaderCollection;
use url;
use url::form_urlencoded::parse as form_urlencoded_parse;

use datastructures::{Headers, MultiDict};
use httputils::{get_name_by_http_code, get_content_type};

/// Request type.
pub struct Request {
    pub request: http::server::Request,
    url: Option<url::Url>,
    args: Option<MultiDict>,
    form: Option<MultiDict>,
}

impl Request {
    /// Create a `Request`.
    pub fn new(request: http::server::Request) -> Request {
        let url = match request.request_uri {
            AbsolutePath(ref url) => {
                match url::Url::parse(url.as_slice()) {
                    Ok(url) => Some(url),
                    Err(_) => None,
                }
            },
            _ => None,
        };
        Request {
            request: request,
            url: url,
            args: None,
            form: None,
        }
    }

    /// The parsed URL parameters.
    pub fn args(&mut self) -> &MultiDict {
        if self.args.is_none() {
            let mut args = MultiDict::new();
            if self.url.is_some() {
                match self.url.as_ref().unwrap().query_pairs() {
                    Some(pairs) => {
                        for &(ref k, ref v) in pairs.iter() {
                            args.add(k.as_slice(), v.as_slice());
                        }
                    },
                    None => (),
                }
            }
            self.args = Some(args);
        }
        return self.args.as_ref().unwrap();
    }

    /// This method is used internally to retrieve submitted data.
    fn load_form_data(&mut self) {
        if self.form.is_some() {
            return
        }
        let form = match self.request.headers.content_type {
            Some(ref content_type) => {
                if content_type.type_ == String::from_str("application") &&
                    (content_type.subtype == String::from_str("x-www-form-urlencoded") ||
                     content_type.subtype == String::from_str("x-url-encoded")) {
                    let mut form = MultiDict::new();
                    for &(ref k, ref v) in form_urlencoded_parse(self.request.body.as_slice()).iter() {
                        form.add(k.as_slice(), v.as_slice());
                    }
                    form
                } else {
                    MultiDict::new()
                }
            },
            None => {
                MultiDict::new()
            }
        };
        self.form = Some(form);
    }

    /// The form parameters.
    pub fn form(&mut self) -> &MultiDict {
        self.load_form_data();
        self.form.as_ref().unwrap()
    }

    /// The headers.
    pub fn headers(&self) -> &HeaderCollection {
        &self.request.headers
    }
}

/// Response type.  It is just one container with a couple of parameters
/// (headers, body, status code etc).
#[deriving(Clone)]
pub struct Response {
    pub status_code: int,
    pub headers: Headers,
    pub body: String,
}

impl Response {
    /// Create a `Response`.
    pub fn new(body: String) -> Response {
        let mut response = Response {
            status_code: 200,
            headers: Headers::new(None),
            body: body,
        };
        let content_length = response.body.len().to_string();
        response.headers.set("Content-Type", "text/html; charset=utf-8");
        response.headers.set("Content-Length", content_length.as_slice());
        return response;
    }

    /// Get status name.
    pub fn status_name(&self) -> &str {
        match get_name_by_http_code(self.status_code) {
            Some(name) => name,
            None => "UNKNOWN",
        }
    }

    /// Sets a new string as response body.  The content length is set
    /// automatically.
    pub fn set_data(&mut self, value: String) {
        self.body = value;
        let content_length = self.body.len().to_string();
        self.headers.set("Content-Length", content_length.as_slice());
    }

    /// Returns the response content type if available.
    pub fn content_type(&self) -> Option<String> {
        let rv = self.headers.get("Content-Type");
        rv.map(|content_type| content_type.clone())
    }

    /// Set response content type.
    pub fn set_content_type(&mut self, value: &str) {
        self.headers.set("Content-Type", get_content_type(value, "utf-8").as_slice());
    }

    /// Returns the response content length if available.
    pub fn content_length(&self) -> Option<uint> {
        let rv = self.headers.get("Content-Length");
        match rv {
            Some(content_length) => from_str(content_length.as_slice()),
            None => None,
        }
    }

    /// Set content length.
    pub fn set_content_length(&mut self, value: uint) {
        self.headers.set("Content-Length", value.to_string().as_slice());
    }
}
<|endoftext|>


<commit_before>//! Search for projects by name
//!
//! https://docs.gitlab.com/ce/api/projects.html#search-for-projects-by-name
//!
//! # Search for projects by name
//!
//! Search for projects by name which are accessible to the authenticated user.
//!
//! ```text
//! GET /projects/search/QUERY
//! ```
//!
//! Parameters:
//!
//! | Attribute | Type | Required | Description |
//! | --------- | ---- | -------- | ----------- |
//! | `query` | string | yes | A string contained in the project name |
//! | `order_by` | string | no | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields |
//! | `sort` | string | no | Return requests sorted in `asc` or `desc` order |
<commit_msg>Add projects search<commit_after>//! Search for projects by name
//!
//! https://docs.gitlab.com/ce/api/projects.html#search-for-projects-by-name
//!
//! # Search for projects by name
//!
//! Search for projects by name which are accessible to the authenticated user.
//!
//! ```text
//! GET /projects/search/QUERY
//! ```
//!
//! Parameters:
//!
//! | Attribute | Type | Required | Description |
//! | --------- | ---- | -------- | ----------- |
//! | `query` | string | yes | A string contained in the project name |
//! | `order_by` | string | no | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields |
//! | `sort` | string | no | Return requests sorted in `asc` or `desc` order |

use BuildQuery;

#[derive(Debug, Copy, Clone)]
pub enum ListingOrderBy {
    Id,
    Name,
    // Path,
    CreatedAt,
    // UpdatedAt,
    LastActivityAt,
}

#[derive(Debug, Copy, Clone)]
pub enum ListingSort {
    Asc,
    Desc,
}

#[derive(Default, Debug, Clone)]
pub struct Listing {
    /// A string contained in the project name.
    query:  String,
    /// Return requests ordered by. Default is `ListingOrderBy::CreatedAt`.
    order_by:  Option<ListingOrderBy>,
    /// Return requests sorted. Default is `ListingSort::Desc`.
    sort: Option<ListingSort>,
}

impl Listing {
    pub fn new(query: String) -> Listing {
        Listing {
            query: query,
            ..Default::default()
        }
    }
    pub fn order_by(&mut self, order_by: ListingOrderBy) -> &mut Listing {
        self.order_by = Some(order_by);
        self
    }
    fn sort(&mut self, sort: ListingSort) -> &mut Listing {
        self.sort = Some(sort);
        self
    }
}

impl BuildQuery for Listing {
    fn build_query(&self) -> String {

        let mut query = format!("projects/search/{}", self.query);

        let amp_char = "&";
        let none_char = "";
        let mut split_char = &none_char;

        // Append a "?" only if at least one of the `Option` is `Some(_)` or if
        // strings contain something.
        query.push_str(match (&self.order_by,
                              &self.sort) {
            (&None, &None) => "",
            _ => "?",
        });

        self.order_by.map(|order_by| {
            query.push_str(split_char);
            split_char = &amp_char;

            query.push_str("order_by=");
            query.push_str(match order_by {
                ListingOrderBy::Id => "id",
                ListingOrderBy::Name => "name",
                // ListingOrderBy::Path => "path",
                ListingOrderBy::CreatedAt => "created_at",
                // ListingOrderBy::UpdatedAt => "updated_at",
                ListingOrderBy::LastActivityAt => "last_activity_at",
            });
        });

        self.sort.map(|sort| {
            query.push_str(split_char);
            split_char = &amp_char;

            query.push_str("sort=");
            query.push_str(match sort {
                ListingSort::Asc => "asc",
                ListingSort::Desc => "desc",
            });
        });

        query
    }
}

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

    const TEST_SEARCH_QUERY: &'static str = "SearchPattern";

    #[test]
    fn build_query_default() {
        let expected_string = format!("projects/search/{}", TEST_SEARCH_QUERY);
        let listing = Listing::new(TEST_SEARCH_QUERY.to_string());
        let query = listing.build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_order_by() {
        let expected_string = format!("projects/search/{}?order_by=id", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::Id).build_query();
        assert_eq!(query, expected_string);

        let expected_string = format!("projects/search/{}?order_by=name", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::Name).build_query();
        assert_eq!(query, expected_string);

        // let expected_string = format!("projects/search/{}?order_by=path", TEST_SEARCH_QUERY);
        // let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::Path).build_query();
        // assert_eq!(query, expected_string);

        let expected_string = format!("projects/search/{}?order_by=created_at", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::CreatedAt).build_query();
        assert_eq!(query, expected_string);

        // let expected_string = format!("projects/search/{}?order_by=updated_at", TEST_SEARCH_QUERY);
        // let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::UpdatedAt).build_query();
        // assert_eq!(query, expected_string);

        let expected_string = format!("projects/search/{}?order_by=last_activity_at", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::LastActivityAt).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn build_query_sort() {
        let expected_string = format!("projects/search/{}?sort=asc", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).sort(ListingSort::Asc).build_query();
        assert_eq!(query, expected_string);

        let expected_string = format!("projects/search/{}?sort=desc", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).sort(ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
    }

    #[test]
    fn groups_build_query_multiple() {
        let expected_string = format!("projects/search/{}?order_by=created_at&sort=desc", TEST_SEARCH_QUERY);
        let query = Listing::new(TEST_SEARCH_QUERY.to_string()).order_by(ListingOrderBy::CreatedAt).sort(ListingSort::Desc).build_query();
        assert_eq!(query, expected_string);
    }
}
<|endoftext|>