<commit_before>use ide_db::{
    assists::{AssistId, AssistKind},
    base_db::FileId,
    defs::Definition,
    search::FileReference,
    syntax_helpers::node_ext::full_path_of_name_ref,
};
use syntax::{
    ast::{self, NameLike, NameRef},
    AstNode, SyntaxKind, TextRange,
};

use crate::{AssistContext, Assists};

// Assist: unnecessary_async
//
// Removes the `async` mark from functions which have no `.await` in their body.
// Looks for calls to the functions and removes the `.await` on the call site.
//
// ```
// pub async f$0n foo() {}
// pub async fn bar() { foo().await }
// ```
// ->
// ```
// pub fn foo() {}
// pub async fn bar() { foo() }
// ```
pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let function: ast::Fn = ctx.find_node_at_offset()?;

    // Do nothing if the cursor is not on the prototype. This is so that the check does not pollute
    // when the user asks us for assists when in the middle of the function body.
    // We consider the prototype to be anything that is before the body of the function.
    let cursor_position = ctx.offset();
    if cursor_position >= function.body()?.syntax().text_range().start() {
        return None;
    }
    // Do nothing if the function isn't async.
    if let None = function.async_token() {
        return None;
    }
    // Do nothing if the function has an `await` expression in its body.
    if function.body()?.syntax().descendants().find_map(ast::AwaitExpr::cast).is_some() {
        return None;
    }

    // Remove the `async` keyword plus whitespace after it, if any.
    let async_range = {
        let async_token = function.async_token()?;
        let next_token = async_token.next_token()?;
        if matches!(next_token.kind(), SyntaxKind::WHITESPACE) {
            TextRange::new(async_token.text_range().start(), next_token.text_range().end())
        } else {
            async_token.text_range()
        }
    };

    // Otherwise, we may remove the `async` keyword.
    acc.add(
        AssistId("unnecessary_async", AssistKind::QuickFix),
        "Remove unnecessary async",
        async_range,
        |edit| {
            // Remove async on the function definition.
            edit.replace(async_range, "");

            // Remove all `.await`s from calls to the function we remove `async` from.
            if let Some(fn_def) = ctx.sema.to_def(&function) {
                for await_expr in find_all_references(ctx, &Definition::Function(fn_def))
                    // Keep only references that correspond NameRefs.
                    .filter_map(|(_, reference)| match reference.name {
                        NameLike::NameRef(nameref) => Some(nameref),
                        _ => None,
                    })
                    // Keep only references that correspond to await expressions
                    .filter_map(|nameref| find_await_expression(ctx, &nameref))
                {
                    if let Some(await_token) = &await_expr.await_token() {
                        edit.replace(await_token.text_range(), "");
                    }
                    if let Some(dot_token) = &await_expr.dot_token() {
                        edit.replace(dot_token.text_range(), "");
                    }
                }
            }
        },
    )
}

fn find_all_references(
    ctx: &AssistContext<'_>,
    def: &Definition,
) -> impl Iterator<Item = (FileId, FileReference)> {
    def.usages(&ctx.sema).all().into_iter().flat_map(|(file_id, references)| {
        references.into_iter().map(move |reference| (file_id, reference))
    })
}

/// Finds the await expression for the given `NameRef`.
/// If no await expression is found, returns None.
fn find_await_expression(ctx: &AssistContext<'_>, nameref: &NameRef) -> Option<ast::AwaitExpr> {
    // From the nameref, walk up the tree to the await expression.
    let await_expr = if let Some(path) = full_path_of_name_ref(&nameref) {
        // Function calls.
        path.syntax()
            .parent()
            .and_then(ast::PathExpr::cast)?
            .syntax()
            .parent()
            .and_then(ast::CallExpr::cast)?
            .syntax()
            .parent()
            .and_then(ast::AwaitExpr::cast)
    } else {
        // Method calls.
        nameref
            .syntax()
            .parent()
            .and_then(ast::MethodCallExpr::cast)?
            .syntax()
            .parent()
            .and_then(ast::AwaitExpr::cast)
    };

    ctx.sema.original_ast_node(await_expr?)
}

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

    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn applies_on_empty_function() {
        check_assist(unnecessary_async, "pub async f$0n f() {}", "pub fn f() {}")
    }

    #[test]
    fn applies_and_removes_whitespace() {
        check_assist(unnecessary_async, "pub async       f$0n f() {}", "pub fn f() {}")
    }

    #[test]
    fn does_not_apply_on_non_async_function() {
        check_assist_not_applicable(unnecessary_async, "pub f$0n f() {}")
    }

    #[test]
    fn applies_on_function_with_a_non_await_expr() {
        check_assist(unnecessary_async, "pub async f$0n f() { f2() }", "pub fn f() { f2() }")
    }

    #[test]
    fn does_not_apply_on_function_with_an_await_expr() {
        check_assist_not_applicable(unnecessary_async, "pub async f$0n f() { f2().await }")
    }

    #[test]
    fn applies_and_removes_await_on_reference() {
        check_assist(
            unnecessary_async,
            r#"
pub async fn f4() { }
pub async f$0n f2() { }
pub async fn f() { f2().await }
pub async fn f3() { f2().await }"#,
            r#"
pub async fn f4() { }
pub fn f2() { }
pub async fn f() { f2() }
pub async fn f3() { f2() }"#,
        )
    }

    #[test]
    fn applies_and_removes_await_from_within_module() {
        check_assist(
            unnecessary_async,
            r#"
pub async fn f4() { }
mod a { pub async f$0n f2() { } }
pub async fn f() { a::f2().await }
pub async fn f3() { a::f2().await }"#,
            r#"
pub async fn f4() { }
mod a { pub fn f2() { } }
pub async fn f() { a::f2() }
pub async fn f3() { a::f2() }"#,
        )
    }

    #[test]
    fn applies_and_removes_await_on_inner_await() {
        check_assist(
            unnecessary_async,
            // Ensure that it is the first await on the 3rd line that is removed
            r#"
pub async fn f() { f2().await }
pub async f$0n f2() -> i32 { 1 }
pub async fn f3() { f4(f2().await).await }
pub async fn f4(i: i32) { }"#,
            r#"
pub async fn f() { f2() }
pub fn f2() -> i32 { 1 }
pub async fn f3() { f4(f2()).await }
pub async fn f4(i: i32) { }"#,
        )
    }

    #[test]
    fn applies_and_removes_await_on_outer_await() {
        check_assist(
            unnecessary_async,
            // Ensure that it is the second await on the 3rd line that is removed
            r#"
pub async fn f() { f2().await }
pub async f$0n f2(i: i32) { }
pub async fn f3() { f2(f4().await).await }
pub async fn f4() -> i32 { 1 }"#,
            r#"
pub async fn f() { f2() }
pub fn f2(i: i32) { }
pub async fn f3() { f2(f4().await) }
pub async fn f4() -> i32 { 1 }"#,
        )
    }

    #[test]
    fn applies_on_method_call() {
        check_assist(
            unnecessary_async,
            r#"
pub struct S { }
impl S { pub async f$0n f2(&self) { } }
pub async fn f(s: &S) { s.f2().await }"#,
            r#"
pub struct S { }
impl S { pub fn f2(&self) { } }
pub async fn f(s: &S) { s.f2() }"#,
        )
    }

    #[test]
    fn does_not_apply_on_function_with_a_nested_await_expr() {
        check_assist_not_applicable(
            unnecessary_async,
            "async f$0n f() { if true { loop { f2().await } } }",
        )
    }

    #[test]
    fn does_not_apply_when_not_on_prototype() {
        check_assist_not_applicable(unnecessary_async, "pub async fn f() { $0f2() }")
    }
}
<commit_msg>Auto merge of #13508 - koka831:fix/13492, r=jonas-schievink<commit_after>use ide_db::{
    assists::{AssistId, AssistKind},
    base_db::FileId,
    defs::Definition,
    search::FileReference,
    syntax_helpers::node_ext::full_path_of_name_ref,
};
use syntax::{
    ast::{self, NameLike, NameRef},
    AstNode, SyntaxKind, TextRange,
};

use crate::{AssistContext, Assists};

// Assist: unnecessary_async
//
// Removes the `async` mark from functions which have no `.await` in their body.
// Looks for calls to the functions and removes the `.await` on the call site.
//
// ```
// pub async f$0n foo() {}
// pub async fn bar() { foo().await }
// ```
// ->
// ```
// pub fn foo() {}
// pub async fn bar() { foo() }
// ```
pub(crate) fn unnecessary_async(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let function: ast::Fn = ctx.find_node_at_offset()?;

    // Do nothing if the cursor is not on the prototype. This is so that the check does not pollute
    // when the user asks us for assists when in the middle of the function body.
    // We consider the prototype to be anything that is before the body of the function.
    let cursor_position = ctx.offset();
    if cursor_position >= function.body()?.syntax().text_range().start() {
        return None;
    }
    // Do nothing if the function isn't async.
    if let None = function.async_token() {
        return None;
    }
    // Do nothing if the function has an `await` expression in its body.
    if function.body()?.syntax().descendants().find_map(ast::AwaitExpr::cast).is_some() {
        return None;
    }
    // Do nothing if the method is a member of trait.
    if let Some(impl_) = function.syntax().ancestors().nth(2).and_then(ast::Impl::cast) {
        if let Some(_) = impl_.trait_() {
            return None;
        }
    }

    // Remove the `async` keyword plus whitespace after it, if any.
    let async_range = {
        let async_token = function.async_token()?;
        let next_token = async_token.next_token()?;
        if matches!(next_token.kind(), SyntaxKind::WHITESPACE) {
            TextRange::new(async_token.text_range().start(), next_token.text_range().end())
        } else {
            async_token.text_range()
        }
    };

    // Otherwise, we may remove the `async` keyword.
    acc.add(
        AssistId("unnecessary_async", AssistKind::QuickFix),
        "Remove unnecessary async",
        async_range,
        |edit| {
            // Remove async on the function definition.
            edit.replace(async_range, "");

            // Remove all `.await`s from calls to the function we remove `async` from.
            if let Some(fn_def) = ctx.sema.to_def(&function) {
                for await_expr in find_all_references(ctx, &Definition::Function(fn_def))
                    // Keep only references that correspond NameRefs.
                    .filter_map(|(_, reference)| match reference.name {
                        NameLike::NameRef(nameref) => Some(nameref),
                        _ => None,
                    })
                    // Keep only references that correspond to await expressions
                    .filter_map(|nameref| find_await_expression(ctx, &nameref))
                {
                    if let Some(await_token) = &await_expr.await_token() {
                        edit.replace(await_token.text_range(), "");
                    }
                    if let Some(dot_token) = &await_expr.dot_token() {
                        edit.replace(dot_token.text_range(), "");
                    }
                }
            }
        },
    )
}

fn find_all_references(
    ctx: &AssistContext<'_>,
    def: &Definition,
) -> impl Iterator<Item = (FileId, FileReference)> {
    def.usages(&ctx.sema).all().into_iter().flat_map(|(file_id, references)| {
        references.into_iter().map(move |reference| (file_id, reference))
    })
}

/// Finds the await expression for the given `NameRef`.
/// If no await expression is found, returns None.
fn find_await_expression(ctx: &AssistContext<'_>, nameref: &NameRef) -> Option<ast::AwaitExpr> {
    // From the nameref, walk up the tree to the await expression.
    let await_expr = if let Some(path) = full_path_of_name_ref(&nameref) {
        // Function calls.
        path.syntax()
            .parent()
            .and_then(ast::PathExpr::cast)?
            .syntax()
            .parent()
            .and_then(ast::CallExpr::cast)?
            .syntax()
            .parent()
            .and_then(ast::AwaitExpr::cast)
    } else {
        // Method calls.
        nameref
            .syntax()
            .parent()
            .and_then(ast::MethodCallExpr::cast)?
            .syntax()
            .parent()
            .and_then(ast::AwaitExpr::cast)
    };

    ctx.sema.original_ast_node(await_expr?)
}

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

    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn applies_on_empty_function() {
        check_assist(unnecessary_async, "pub async f$0n f() {}", "pub fn f() {}")
    }

    #[test]
    fn applies_and_removes_whitespace() {
        check_assist(unnecessary_async, "pub async       f$0n f() {}", "pub fn f() {}")
    }

    #[test]
    fn does_not_apply_on_non_async_function() {
        check_assist_not_applicable(unnecessary_async, "pub f$0n f() {}")
    }

    #[test]
    fn applies_on_function_with_a_non_await_expr() {
        check_assist(unnecessary_async, "pub async f$0n f() { f2() }", "pub fn f() { f2() }")
    }

    #[test]
    fn does_not_apply_on_function_with_an_await_expr() {
        check_assist_not_applicable(unnecessary_async, "pub async f$0n f() { f2().await }")
    }

    #[test]
    fn applies_and_removes_await_on_reference() {
        check_assist(
            unnecessary_async,
            r#"
pub async fn f4() { }
pub async f$0n f2() { }
pub async fn f() { f2().await }
pub async fn f3() { f2().await }"#,
            r#"
pub async fn f4() { }
pub fn f2() { }
pub async fn f() { f2() }
pub async fn f3() { f2() }"#,
        )
    }

    #[test]
    fn applies_and_removes_await_from_within_module() {
        check_assist(
            unnecessary_async,
            r#"
pub async fn f4() { }
mod a { pub async f$0n f2() { } }
pub async fn f() { a::f2().await }
pub async fn f3() { a::f2().await }"#,
            r#"
pub async fn f4() { }
mod a { pub fn f2() { } }
pub async fn f() { a::f2() }
pub async fn f3() { a::f2() }"#,
        )
    }

    #[test]
    fn applies_and_removes_await_on_inner_await() {
        check_assist(
            unnecessary_async,
            // Ensure that it is the first await on the 3rd line that is removed
            r#"
pub async fn f() { f2().await }
pub async f$0n f2() -> i32 { 1 }
pub async fn f3() { f4(f2().await).await }
pub async fn f4(i: i32) { }"#,
            r#"
pub async fn f() { f2() }
pub fn f2() -> i32 { 1 }
pub async fn f3() { f4(f2()).await }
pub async fn f4(i: i32) { }"#,
        )
    }

    #[test]
    fn applies_and_removes_await_on_outer_await() {
        check_assist(
            unnecessary_async,
            // Ensure that it is the second await on the 3rd line that is removed
            r#"
pub async fn f() { f2().await }
pub async f$0n f2(i: i32) { }
pub async fn f3() { f2(f4().await).await }
pub async fn f4() -> i32 { 1 }"#,
            r#"
pub async fn f() { f2() }
pub fn f2(i: i32) { }
pub async fn f3() { f2(f4().await) }
pub async fn f4() -> i32 { 1 }"#,
        )
    }

    #[test]
    fn applies_on_method_call() {
        check_assist(
            unnecessary_async,
            r#"
pub struct S { }
impl S { pub async f$0n f2(&self) { } }
pub async fn f(s: &S) { s.f2().await }"#,
            r#"
pub struct S { }
impl S { pub fn f2(&self) { } }
pub async fn f(s: &S) { s.f2() }"#,
        )
    }

    #[test]
    fn does_not_apply_on_function_with_a_nested_await_expr() {
        check_assist_not_applicable(
            unnecessary_async,
            "async f$0n f() { if true { loop { f2().await } } }",
        )
    }

    #[test]
    fn does_not_apply_when_not_on_prototype() {
        check_assist_not_applicable(unnecessary_async, "pub async fn f() { $0f2() }")
    }

    #[test]
    fn does_not_apply_on_async_trait_method() {
        check_assist_not_applicable(
            unnecessary_async,
            r#"
trait Trait {
    async fn foo();
}
impl Trait for () {
    $0async fn foo() {}
}"#,
        );
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

pub use clap::App;

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

use configuration::Configuration;
use logger::ImagLogger;

use libimagstore::store::Store;

pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Configuration,
    cli_matches: ArgMatches<'a, '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, 'a, 'a, 'a, 'a>) -> Runtime<'a> {
        let matches = cli_spec.get_matches();
        let rtp : PathBuf = matches.value_of("runtimepath").unwrap_or("~/.imag/").into();
        let storepath = matches.value_of("storepath")
                                .map(PathBuf::from)
                                .unwrap_or({
                                    let mut spath = rtp.clone();
                                    spath.push("/store");
                                    spath
                                });
        Runtime {
            cli_matches: matches,
            configuration: Configuration::new(&rtp).unwrap_or(Configuration::default()),
            rtp: rtp,
            store: Store::new(storepath),
        }
    }

    /**
     * appname should be "imag-foo"
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a, 'a, 'a, '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")
                .short("c")
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("runtimepath")
                .short("r")
                .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))
    }

    pub fn init_logger(&self) {
        let lvl = if self.is_debugging() {
            LogLevelFilter::Debug
        } else if self.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();
    }

    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    pub fn store(&self) -> &Store {
        &self.store
    }

}

<commit_msg>Add documentation to Runtime type<commit_after>use std::path::PathBuf;

pub use clap::App;

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

use configuration::Configuration;
use logger::ImagLogger;

use libimagstore::store::Store;

pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Configuration,
    cli_matches: ArgMatches<'a, '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, 'a, 'a, 'a, 'a>) -> Runtime<'a> {
        let matches = cli_spec.get_matches();
        let rtp : PathBuf = matches.value_of("runtimepath").unwrap_or("~/.imag/").into();
        let storepath = matches.value_of("storepath")
                                .map(PathBuf::from)
                                .unwrap_or({
                                    let mut spath = rtp.clone();
                                    spath.push("/store");
                                    spath
                                });
        Runtime {
            cli_matches: matches,
            configuration: Configuration::new(&rtp).unwrap_or(Configuration::default()),
            rtp: rtp,
            store: Store::new(storepath),
        }
    }

    /**
     * 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, 'a, 'a, '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")
                .short("c")
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("runtimepath")
                .short("r")
                .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))
    }

    /**
     * Initialize the internal logger
     */
    pub fn init_logger(&self) {
        let lvl = if self.is_debugging() {
            LogLevelFilter::Debug
        } else if self.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 store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

}

<|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;

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 libimagstorestdhook::debug::DebugHook;
        use libimagutil::trace::trace_error;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();
        let is_debugging = matches.is_present("debugging");

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map(PathBuf::from)
            .unwrap_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.");
                    })
            });
        let storepath = matches.value_of("storepath")
                                .map(PathBuf::from)
                                .unwrap_or({
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                });

        let cfg = Configuration::new(&rtp);
        let cfg = if cfg.is_err() {
            let e = cfg.err().unwrap();
            if e.kind() != ConfigErrorKind::NoConfigFileFound {
                let cause : Option<Box<Error>> = Some(Box::new(e));
                return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause));
            } else {
                trace_error(&e);
                None
            }
        } else {
            Some(cfg.unwrap())
        };

        let store_config = {
            match &cfg {
                &Some(ref c) => c.store_config().map(|c| c.clone()),
                &None => None,
            }
        };

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

        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)) {
                        trace_error(&e);
                        warn!("Registering debug hook with store failed");
                    }
                }
            }

            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().map(|s| s.clone()),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

<commit_msg>Spit out the traceback for hook registration errors only in debug mode<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;

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 libimagutil::trace::trace_error;
        use libimagutil::trace::trace_error_dbg;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();
        let is_debugging = matches.is_present("debugging");

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map(PathBuf::from)
            .unwrap_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.");
                    })
            });
        let storepath = matches.value_of("storepath")
                                .map(PathBuf::from)
                                .unwrap_or({
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                });

        let cfg = Configuration::new(&rtp);
        let cfg = if cfg.is_err() {
            let e = cfg.err().unwrap();
            if e.kind() != ConfigErrorKind::NoConfigFileFound {
                let cause : Option<Box<Error>> = Some(Box::new(e));
                return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause));
            } else {
                trace_error(&e);
                None
            }
        } else {
            Some(cfg.unwrap())
        };

        let store_config = {
            match &cfg {
                &Some(ref c) => c.store_config().map(|c| c.clone()),
                &None => None,
            }
        };

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

        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().map(|s| s.clone()),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

<|endoftext|>


<commit_before>//! # The Rust core allocation and collections library
//!
//! This library provides smart pointers and collections for managing
//! heap-allocated values.
//!
//! This library, like libcore, normally doesn’t need to be used directly
//! since its contents are re-exported in the [`std` crate](../std/index.html).
//! Crates that use the `#![no_std]` attribute however will typically
//! not depend on `std`, so they’d use this crate instead.
//!
//! ## Boxed values
//!
//! The [`Box`] type is a smart pointer type. There can only be one owner of a
//! [`Box`], and the owner can decide to mutate the contents, which live on the
//! heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended
//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and
//! only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using [`Box`]) is too
//! constraining for an application, and is often paired with the [`Cell`] or
//! [`RefCell`] types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It
//! provides all the same functionality of [`Rc`], except it requires that the
//! contained type `T` is shareable. Additionally, [`Arc<T>`][`Arc`] is itself
//! sendable while [`Rc<T>`][`Rc`] is not.
//!
//! This type allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
//!
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
//!
//! [`Arc`]: sync
//! [`Box`]: boxed
//! [`Cell`]: core::cell
//! [`Rc`]: rc
//! [`RefCell`]: core::cell

// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(
    html_playground_url = "https://play.rust-lang.org/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
    test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(
    not(bootstrap),
    doc(cfg_hide(
        not(test),
        not(any(test, bootstrap)),
        any(not(feature = "miri-test-libstd"), test, doctest),
        no_global_oom_handling,
        not(no_global_oom_handling),
        target_has_atomic = "ptr"
    ))
)]
#![no_std]
#![needs_allocator]
//
// Lints:
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(deprecated_in_future)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
//
// Library features:
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_windows)]
#![feature(async_stream)]
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
#![feature(const_cow_is_borrowed)]
#![feature(core_intrinsics)]
#![feature(dispatch_from_dyn)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_zip)]
#![feature(layout_for_ptr)]
#![feature(maybe_uninit_extra)]
#![feature(maybe_uninit_slice)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(option_result_unwrap_unchecked)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(receiver_trait)]
#![feature(set_ptr_value)]
#![feature(slice_group_by)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_range)]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
#![feature(try_trait_v2)]
#![feature(unicode_internals)]
#![feature(unsize)]
//
// Language features:
#![feature(allocator_internals)]
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
#![feature(destructuring_assignment)]
#![feature(dropck_eyepatch)]
#![feature(exclusive_range_pattern)]
#![feature(fundamental)]
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(lang_items)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(staged_api)]
#![cfg_attr(test, feature(test))]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
//
// Rustdoc features:
#![feature(doc_cfg)]
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]`
// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad
// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs
// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing.
#![feature(intra_doc_pointers)]

// Allow testing this library
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;

// Module with internal macros used by other modules (needs to be included before other modules).
#[macro_use]
mod macros;

// Heaps provided for low-level allocation strategies

pub mod alloc;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::Box;
}
pub mod borrow;
pub mod collections;
pub mod fmt;
pub mod raw_vec;
pub mod rc;
pub mod slice;
pub mod str;
pub mod string;
#[cfg(target_has_atomic = "ptr")]
pub mod sync;
#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))]
pub mod task;
#[cfg(test)]
mod tests;
pub mod vec;

#[doc(hidden)]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
pub mod __export {
    pub use core::format_args;
}
<commit_msg>Reenable feature(nll) in alloc.<commit_after>//! # The Rust core allocation and collections library
//!
//! This library provides smart pointers and collections for managing
//! heap-allocated values.
//!
//! This library, like libcore, normally doesn’t need to be used directly
//! since its contents are re-exported in the [`std` crate](../std/index.html).
//! Crates that use the `#![no_std]` attribute however will typically
//! not depend on `std`, so they’d use this crate instead.
//!
//! ## Boxed values
//!
//! The [`Box`] type is a smart pointer type. There can only be one owner of a
//! [`Box`], and the owner can decide to mutate the contents, which live on the
//! heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended
//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and
//! only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using [`Box`]) is too
//! constraining for an application, and is often paired with the [`Cell`] or
//! [`RefCell`] types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It
//! provides all the same functionality of [`Rc`], except it requires that the
//! contained type `T` is shareable. Additionally, [`Arc<T>`][`Arc`] is itself
//! sendable while [`Rc<T>`][`Rc`] is not.
//!
//! This type allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
//!
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
//!
//! [`Arc`]: sync
//! [`Box`]: boxed
//! [`Cell`]: core::cell
//! [`Rc`]: rc
//! [`RefCell`]: core::cell

// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(
    html_playground_url = "https://play.rust-lang.org/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
    test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(
    not(bootstrap),
    doc(cfg_hide(
        not(test),
        not(any(test, bootstrap)),
        any(not(feature = "miri-test-libstd"), test, doctest),
        no_global_oom_handling,
        not(no_global_oom_handling),
        target_has_atomic = "ptr"
    ))
)]
#![no_std]
#![needs_allocator]
//
// Lints:
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(deprecated_in_future)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
//
// Library features:
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_windows)]
#![feature(async_stream)]
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
#![feature(const_cow_is_borrowed)]
#![feature(core_intrinsics)]
#![feature(dispatch_from_dyn)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_zip)]
#![feature(layout_for_ptr)]
#![feature(maybe_uninit_extra)]
#![feature(maybe_uninit_slice)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(option_result_unwrap_unchecked)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(receiver_trait)]
#![feature(set_ptr_value)]
#![feature(slice_group_by)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_range)]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
#![feature(try_trait_v2)]
#![feature(unicode_internals)]
#![feature(unsize)]
//
// Language features:
#![feature(allocator_internals)]
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
#![feature(destructuring_assignment)]
#![feature(dropck_eyepatch)]
#![feature(exclusive_range_pattern)]
#![feature(fundamental)]
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(lang_items)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nll)] // Not necessary, but here to test the `nll` feature.
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(staged_api)]
#![cfg_attr(test, feature(test))]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
//
// Rustdoc features:
#![feature(doc_cfg)]
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]`
// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad
// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs
// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing.
#![feature(intra_doc_pointers)]

// Allow testing this library
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;

// Module with internal macros used by other modules (needs to be included before other modules).
#[macro_use]
mod macros;

// Heaps provided for low-level allocation strategies

pub mod alloc;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::Box;
}
pub mod borrow;
pub mod collections;
pub mod fmt;
pub mod raw_vec;
pub mod rc;
pub mod slice;
pub mod str;
pub mod string;
#[cfg(target_has_atomic = "ptr")]
pub mod sync;
#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))]
pub mod task;
#[cfg(test)]
mod tests;
pub mod vec;

#[doc(hidden)]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
pub mod __export {
    pub use core::format_args;
}
<|endoftext|>


<commit_before>//! Varint decode utilities.

use crate::error::WireError;
use crate::varint::MAX_VARINT_ENCODED_LEN;

/// Decode a varint, and return decoded value and decoded byte count.
#[inline]
fn decode_varint64_full(rem: &[u8]) -> crate::Result<Option<(u64, usize)>> {
    let mut r: u64 = 0;
    for (i, &b) in rem.iter().enumerate() {
        if i == MAX_VARINT_ENCODED_LEN {
            return Err(WireError::IncorrectVarint.into());
        }

        if i == 9 && (b & 0x7f) > 1 {
            return Err(WireError::IncorrectVarint.into());
        }
        r = r | (((b & 0x7f) as u64) << (i as u64 * 7));
        if b < 0x80 {
            return Ok(Some((r, i + 1)));
        }
    }
    Ok(None)
}

/// Try decode a varint. Return `None` if the buffer does not contain complete varint.
#[inline]
pub(crate) fn decode_varint64(buf: &[u8]) -> crate::Result<Option<(u64, usize)>> {
    if buf.len() >= 1 && buf[0] < 0x80 {
        // The the most common case.
        let ret = buf[0] as u64;
        let consume = 1;
        Ok(Some((ret, consume)))
    } else if buf.len() >= 2 && buf[1] < 0x80 {
        // Handle the case of two bytes too.
        let ret = (buf[0] & 0x7f) as u64 | (buf[1] as u64) << 7;
        let consume = 2;
        Ok(Some((ret, consume)))
    } else {
        // Read from array when buf at at least 10 bytes,
        // max len for varint.
        decode_varint64_full(buf)
    }
}

/// Try decode a varint. Return `None` if the buffer does not contain complete varint.
#[inline]
pub(crate) fn decode_varint32(buf: &[u8]) -> crate::Result<Option<(u32, usize)>> {
    // TODO: optimize
    match decode_varint64(buf)? {
        Some((v, consumed)) => {
            if v > u32::MAX as u64 {
                return Err(WireError::U32Overflow(v).into());
            }
            Ok(Some((v as u32, consumed)))
        }
        None => Ok(None),
    }
}
<commit_msg>Tests for varint decoding<commit_after>//! Varint decode utilities.

use crate::error::WireError;
use crate::varint::MAX_VARINT_ENCODED_LEN;

/// Decode a varint, and return decoded value and decoded byte count.
#[inline]
fn decode_varint64_full(rem: &[u8]) -> crate::Result<Option<(u64, usize)>> {
    let mut r: u64 = 0;
    for (i, &b) in rem.iter().enumerate() {
        if i == MAX_VARINT_ENCODED_LEN {
            return Err(WireError::IncorrectVarint.into());
        }

        if i == 9 && (b & 0x7f) > 1 {
            return Err(WireError::IncorrectVarint.into());
        }
        r = r | (((b & 0x7f) as u64) << (i as u64 * 7));
        if b < 0x80 {
            return Ok(Some((r, i + 1)));
        }
    }
    Ok(None)
}

/// Try decode a varint. Return `None` if the buffer does not contain complete varint.
#[inline]
pub(crate) fn decode_varint64(buf: &[u8]) -> crate::Result<Option<(u64, usize)>> {
    if buf.len() >= 1 && buf[0] < 0x80 {
        // The the most common case.
        let ret = buf[0] as u64;
        let consume = 1;
        Ok(Some((ret, consume)))
    } else if buf.len() >= 2 && buf[1] < 0x80 {
        // Handle the case of two bytes too.
        let ret = (buf[0] & 0x7f) as u64 | (buf[1] as u64) << 7;
        let consume = 2;
        Ok(Some((ret, consume)))
    } else {
        // Read from array when buf at at least 10 bytes,
        // max len for varint.
        decode_varint64_full(buf)
    }
}

/// Try decode a varint. Return `None` if the buffer does not contain complete varint.
#[inline]
pub(crate) fn decode_varint32(buf: &[u8]) -> crate::Result<Option<(u32, usize)>> {
    // TODO: optimize
    match decode_varint64(buf)? {
        Some((v, consumed)) => {
            if v > u32::MAX as u64 {
                return Err(WireError::U32Overflow(v).into());
            }
            Ok(Some((v as u32, consumed)))
        }
        None => Ok(None),
    }
}

#[cfg(test)]
mod tests {
    use crate::hex::decode_hex;
    use crate::varint::decode::decode_varint32;
    use crate::varint::decode::decode_varint64;

    #[test]
    fn test_decode_varint64() {
        assert_eq!((0, 1), decode_varint64(&decode_hex("00")).unwrap().unwrap());
        assert_eq!(
            (u64::MAX, 10),
            decode_varint64(&decode_hex("ff ff ff ff ff ff ff ff ff 01"))
                .unwrap()
                .unwrap()
        );
        assert!(decode_varint64(&decode_hex("ff ff ff ff ff ff ff ff ff 02")).is_err());
    }

    #[test]
    fn test_decode_varint32() {
        assert_eq!((0, 1), decode_varint32(&decode_hex("00")).unwrap().unwrap());
        assert_eq!(
            (u32::MAX, 5),
            decode_varint32(&decode_hex("ff ff ff ff 0f"))
                .unwrap()
                .unwrap()
        );
        assert!(decode_varint32(&decode_hex("ff ff ff ff 10")).is_err());
    }
}
<|endoftext|>


<commit_before>use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::ops::Deref;

use crate::backend::allocator::{Allocator, Buffer, Format};

pub const SLOT_CAP: usize = 3;

pub struct Swapchain<A: Allocator<B>, B: Buffer> {
    allocator: A,

    width: u32,
    height: u32,
    format: Format,

    slots: [Slot<B>; SLOT_CAP],
}

pub struct Slot<B: Buffer> {
    buffer: Arc<Option<B>>,
    acquired: Arc<AtomicBool>,
}

impl<B: Buffer> Default for Slot<B> {
    fn default() -> Self {
        Slot {
            buffer: Arc::new(None),
            acquired: Arc::new(AtomicBool::new(false)),
        }
    }
}

impl<B: Buffer> Clone for Slot<B> {
    fn clone(&self) -> Self {
        Slot {
            buffer: self.buffer.clone(),
            acquired: self.acquired.clone(),
        }
    }
}

impl<B: Buffer> Deref for Slot<B> {
    type Target = B;
    fn deref(&self) -> &B {
        Option::as_ref(&*self.buffer).unwrap()
    }
}

impl<B: Buffer> Drop for Slot<B> {
    fn drop(&mut self) {
        self.acquired.store(false, Ordering::AcqRel);
    }
}

impl<A: Allocator<B>, B: Buffer> Swapchain<A, B> {
    pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain<A, B> {
        Swapchain {
            allocator,
            width,
            height,
            format,
            slots: Default::default(),
        }
    }

    pub fn acquire(&mut self) -> Result<Option<Slot<B>>, A::Error> {
        if let Some(free_slot) = self.slots.iter_mut().filter(|s| !s.acquired.load(Ordering::SeqCst)).next() {
            if free_slot.buffer.is_none() {
                free_slot.buffer = Arc::new(Some(self.allocator.create_buffer(self.width, self.height, self.format)?));
            }
            assert!(!free_slot.buffer.is_some());

            if !free_slot.acquired.swap(true, Ordering::AcqRel) {
                return Ok(Some(free_slot.clone()));
            }

        }

        // no free slots
        Ok(None)
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        if self.width == width && self.height == height {
            return;
        }

        self.width = width;
        self.height = height;

        for mut slot in &mut self.slots {
            let _ = std::mem::replace(&mut slot, &mut Slot::default());
        }
    }
}<commit_msg>swapchain: fix borked resize logic<commit_after>use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::ops::Deref;

use crate::backend::allocator::{Allocator, Buffer, Format};

pub const SLOT_CAP: usize = 3;

pub struct Swapchain<A: Allocator<B>, B: Buffer> {
    allocator: A,

    width: u32,
    height: u32,
    format: Format,

    slots: [Slot<B>; SLOT_CAP],
}

pub struct Slot<B: Buffer> {
    buffer: Arc<Option<B>>,
    acquired: Arc<AtomicBool>,
}

impl<B: Buffer> Default for Slot<B> {
    fn default() -> Self {
        Slot {
            buffer: Arc::new(None),
            acquired: Arc::new(AtomicBool::new(false)),
        }
    }
}

impl<B: Buffer> Clone for Slot<B> {
    fn clone(&self) -> Self {
        Slot {
            buffer: self.buffer.clone(),
            acquired: self.acquired.clone(),
        }
    }
}

impl<B: Buffer> Deref for Slot<B> {
    type Target = B;
    fn deref(&self) -> &B {
        Option::as_ref(&*self.buffer).unwrap()
    }
}

impl<B: Buffer> Drop for Slot<B> {
    fn drop(&mut self) {
        self.acquired.store(false, Ordering::AcqRel);
    }
}

impl<A: Allocator<B>, B: Buffer> Swapchain<A, B> {
    pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain<A, B> {
        Swapchain {
            allocator,
            width,
            height,
            format,
            slots: Default::default(),
        }
    }

    pub fn acquire(&mut self) -> Result<Option<Slot<B>>, A::Error> {
        if let Some(free_slot) = self.slots.iter_mut().filter(|s| !s.acquired.load(Ordering::SeqCst)).next() {
            if free_slot.buffer.is_none() {
                free_slot.buffer = Arc::new(Some(self.allocator.create_buffer(self.width, self.height, self.format)?));
            }
            assert!(!free_slot.buffer.is_some());

            if !free_slot.acquired.swap(true, Ordering::AcqRel) {
                return Ok(Some(free_slot.clone()));
            }

        }

        // no free slots
        Ok(None)
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        if self.width == width && self.height == height {
            return;
        }

        self.width = width;
        self.height = height;
        self.slots = Default::default();
    }
}<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2015 van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;

use claxon::{Block, FlacReader};
use hound::{WavSpec, WavWriter};
use std::env;
use std::path;

fn main() {
    let arg = env::args().nth(1).expect("no file given");
    let fname = path::Path::new(&arg);
    let mut reader = FlacReader::open(fname).expect("failed to open FLAC stream");

    let spec = WavSpec {
        // TODO: u8 for channels, is that weird? Would u32 be better?
        channels: reader.streaminfo().channels as u16,
        sample_rate: reader.streaminfo().sample_rate,
        // TODO: again, would u32 be better, even if the range is smaller?
        bits_per_sample: reader.streaminfo().bits_per_sample as u16,
        sample_format: hound::SampleFormat::Int,
    };
    let fname_wav = fname.with_extension("wav");
    let mut wav_writer = WavWriter::create(fname_wav, spec).expect("failed to create wav file");
    {
        // TODO: Write fallback for other sample widths and channel numbers.
        assert!(reader.streaminfo().bits_per_sample == 16);
        assert!(reader.streaminfo().channels == 2);

        let mut frame_reader = reader.blocks();
        let mut block = Block::empty();
        loop {
            // Read a single frame. Recycle the buffer from the previous frame to
            // avoid allocations as much as possible.
            match frame_reader.read_next_or_eof(block.into_buffer()) {
                Ok(Some(next_block)) => block = next_block,
                Ok(None) => break, // EOF.
                Err(error) => panic!("{}", error),
            }

            let mut sample_writer = wav_writer.get_i16_writer(block.duration() * 2);

            // Write the samples in the block to the wav file, channels interleaved.
            for (left, right) in block.stereo_samples() {
                // The `stereo_samples()` iterator does not yield more samples
                // than the duration of the block, so we never write more
                // samples to the writer than requested, hence using the
                // unchecked functions is safe here.
                unsafe {
                    sample_writer.write_sample_unchecked(left);
                    sample_writer.write_sample_unchecked(right);
                }
            }

            sample_writer.flush().expect("failed to write samples to wav file");
        }
    }

    wav_writer.finalize().expect("failed to finalize wav file");
}
<commit_msg>Make decode example deal with multiple files<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2015 van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;

use claxon::{Block, FlacReader};
use hound::{WavSpec, WavWriter};
use std::env;
use std::path::Path;

fn decode_file(fname: &Path) {
    let mut reader = FlacReader::open(fname).expect("failed to open FLAC stream");

    // TODO: Write fallback for other sample widths and channel numbers.
    assert!(reader.streaminfo().bits_per_sample == 16);
    assert!(reader.streaminfo().channels == 2);

    let spec = WavSpec {
        // TODO: u8 for channels, is that weird? Would u32 be better?
        channels: reader.streaminfo().channels as u16,
        sample_rate: reader.streaminfo().sample_rate,
        // TODO: again, would u32 be better, even if the range is smaller?
        bits_per_sample: reader.streaminfo().bits_per_sample as u16,
        sample_format: hound::SampleFormat::Int,
    };

    let fname_wav = fname.with_extension("wav");
    let mut wav_writer = WavWriter::create(fname_wav, spec).expect("failed to create wav file");

    let mut frame_reader = reader.blocks();
    let mut block = Block::empty();
    loop {
        // Read a single frame. Recycle the buffer from the previous frame to
        // avoid allocations as much as possible.
        match frame_reader.read_next_or_eof(block.into_buffer()) {
            Ok(Some(next_block)) => block = next_block,
            Ok(None) => break, // EOF.
            Err(error) => panic!("{}", error),
        }

        let mut sample_writer = wav_writer.get_i16_writer(block.duration() * 2);

        // Write the samples in the block to the wav file, channels interleaved.
        for (left, right) in block.stereo_samples() {
            // The `stereo_samples()` iterator does not yield more samples
            // than the duration of the block, so we never write more
            // samples to the writer than requested, hence using the
            // unchecked functions is safe here.
            unsafe {
                sample_writer.write_sample_unchecked(left);
                sample_writer.write_sample_unchecked(right);
            }
        }

        sample_writer.flush().expect("failed to write samples to wav file");
    }

    wav_writer.finalize().expect("failed to finalize wav file");
}

fn main() {
    let mut no_args = true;

    for fname in env::args().skip(1) {
        no_args = false;

        print!("{}", fname);
        decode_file(&Path::new(&fname));
        println!(": done");
    }

    if no_args {
        println!("no files to decode");
    }
}
<|endoftext|>


<commit_before>extern crate maxminddb;

use std::net::IpAddr;
use std::str::FromStr;

use maxminddb::geoip2;

fn main() {
    let reader = maxminddb::Reader::open_readfile("/usr/local/share/GeoIP/GeoIP2-City.mmdb").unwrap();
    let ip: IpAddr = FromStr::from_str("128.101.101.101").unwrap();
    let city: geoip2::City = reader.lookup(ip).unwrap();
    println!("{:?}", city);
}
<commit_msg>Add DensityIncome, Domain and ASN records, update country<commit_after>extern crate maxminddb;

use std::net::IpAddr;
use std::str::FromStr;

use maxminddb::geoip2;

fn main() {
    let reader =
        maxminddb::Reader::open_readfile("/usr/local/share/GeoIP/GeoIP2-City.mmdb").unwrap();
    let ip: IpAddr = FromStr::from_str("128.101.101.101").unwrap();
    let city: geoip2::City = reader.lookup(ip).unwrap();
    println!("{:?}", city);
}
<|endoftext|>


<commit_before>#[link(name = "wgfem",
  vers = "0.8",
  url = "https://github.com/scharris/WGFEM-Rust")];

#[license = "MIT"];
#[crate_type = "exe"];
#[feature(globs)];
#[feature(macro_rules)];
#[feature(link_args)];

extern mod extra;

pub mod common;
pub mod monomial;
pub mod polynomial;
pub mod vector_monomial;
mod quadrature;
#[path="linear_algebra.rs"]
mod la;
pub mod dense_matrix;
pub mod sparse_matrix;
pub mod storage_by_ints;
pub mod mesh;
pub mod rectangle_mesh;
pub mod weak_gradient;
pub mod wg_basis;
pub mod projection;
pub mod variational_bilinear_form;
pub mod vbf_laplace;
pub mod wg_solution;
pub mod wg_solver;
pub mod wg_error_estimates;
pub mod main;

#[cfg(test)]
mod tests {
  // no tests for common
  mod test_monomial;
  mod test_polynomial;
  mod test_vector_monomial;
  mod test_dense_matrix;
  mod test_sparse_matrix;
  mod test_storage_by_ints;
  mod test_la;
  // no tests for quadrature
  // no tests for abstract mesh
  mod test_rectangle_mesh;
  mod test_weak_gradient;
  mod test_wg_basis;
  mod test_projection;
  mod test_variational_bilinear_form;
  mod test_vbf_laplace;
}

<commit_msg>Replace link attribute with new create_id attribute.<commit_after>#[crate_id = "wgfem#0.8.1"];

#[license = "MIT"];
#[crate_type = "exe"];
#[feature(globs)];
#[feature(macro_rules)];
#[feature(link_args)];

extern mod extra;

pub mod common;
pub mod monomial;
pub mod polynomial;
pub mod vector_monomial;
mod quadrature;
#[path="linear_algebra.rs"]
mod la;
pub mod dense_matrix;
pub mod sparse_matrix;
pub mod storage_by_ints;
pub mod mesh;
pub mod rectangle_mesh;
pub mod weak_gradient;
pub mod wg_basis;
pub mod projection;
pub mod variational_bilinear_form;
pub mod vbf_laplace;
pub mod wg_solution;
pub mod wg_solver;
pub mod wg_error_estimates;
pub mod main;

#[cfg(test)]
mod tests {
  // no tests for common
  mod test_monomial;
  mod test_polynomial;
  mod test_vector_monomial;
  mod test_dense_matrix;
  mod test_sparse_matrix;
  mod test_storage_by_ints;
  mod test_la;
  // no tests for quadrature
  // no tests for abstract mesh
  mod test_rectangle_mesh;
  mod test_weak_gradient;
  mod test_wg_basis;
  mod test_projection;
  mod test_variational_bilinear_form;
  mod test_vbf_laplace;
}

<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Averages/Mean_angle

use std::num::Float;

fn mean_angle(angles: &[f64]) -> f64 {
    let mean_cos = angles.iter().map(|&x| (x * Float::pi() / 180.).cos())
                                .fold(0., |a, b| a + b) / (angles.len() as f64);
    let mean_sin = angles.iter().map(|&x| (x * Float::pi() / 180.).sin())
                                .fold(0., |a, b| a + b) / (angles.len() as f64);

    mean_sin.atan2(mean_cos) * 180. / Float::pi()
}

fn main() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    println!("Mean angle of first set is {} degrees", mean_angle(set1));
    println!("Mean angle of second set is {} degrees", mean_angle(set2));
    println!("Mean angle of third set is {} degrees", mean_angle(set3));
}
<commit_msg>Added tests for mean angle<commit_after>// Implements http://rosettacode.org/wiki/Averages/Mean_angle

use std::num::Float;

fn mean_angle(angles: &[f64]) -> f64 {
    let mean_cos = angles.iter().map(|&x| (x * Float::pi() / 180.).cos())
                                .fold(0., |a, b| a + b) / (angles.len() as f64);
    let mean_sin = angles.iter().map(|&x| (x * Float::pi() / 180.).sin())
                                .fold(0., |a, b| a + b) / (angles.len() as f64);

    mean_sin.atan2(mean_cos) * 180. / Float::pi()
}

#[cfg(not(test))]
fn main() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    println!("Mean angle of first set is {} degrees", mean_angle(set1));
    println!("Mean angle of second set is {} degrees", mean_angle(set2));
    println!("Mean angle of third set is {} degrees", mean_angle(set3));
}

#[test]
fn basic_tests() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    // We need to round the numbers
    assert!(mean_angle(set1).round() == 0.);
    assert!(mean_angle(set2).round() == -90.);
    assert!(mean_angle(set3).round() == 20.);
}<|endoftext|>


<commit_before>//! Utility methods and constructors for Lua objects

use std::fmt::Display;
use std::convert::From;
use rlua::{self, Lua, Table, UserData, AnyUserData, Value,
           FromLua, ToLua, Function};
use super::signal;
use super::class::Class;
use super::property::Property;

/// All Lua objects can be cast to this.
#[derive(Clone, Debug)]
pub struct Object<'lua> {
    table: Table<'lua>
}

impl <'lua> From<Table<'lua>> for Object<'lua> {
    fn from(table: Table<'lua>) -> Self {
        Object { table }
    }
}

/// Construct a new object, used when using the default Objectable::new.
pub struct ObjectBuilder<'lua>{
    lua: &'lua Lua,
    object: Object<'lua>
}

impl <'lua> ObjectBuilder<'lua> {
    pub fn add_to_meta(self, new_meta: Table<'lua>) -> rlua::Result<Self> {
        let meta = self.object.table.get_metatable()
            .expect("Object had no meta table");
        for entry in new_meta.pairs::<rlua::Value, rlua::Value>() {
            let (key, value) = entry?;
            meta.set(key, value)?;
        }
        self.object.table.set_metatable(Some(meta));
        Ok(self)
    }

    #[allow(dead_code)]
    pub fn add_to_signals(self, name: String, func: rlua::Function)
                          -> rlua::Result<Self> {
        signal::connect_signal(self.lua, self.object.clone(), name, &[func])?;
        Ok(self)
    }

    pub fn build(self) -> Object<'lua> {
        self.object
    }
}

/// Trait implemented by all objects that represent OO lua objects.
///
/// This trait allows casting an object gotten back from the Lua runtime
/// into a concrete object so that Rust can do things with it.
///
/// You can't do anything to the object until it has been converted into a
/// canonical form using this trait.
pub trait Objectable<'lua, T, S: UserData + Default + Display + Clone> {
    fn cast(obj: Object<'lua>) -> rlua::Result<T> {
        let data = obj.table.get::<_, AnyUserData>("userdata")?;
        if data.is::<S>() {
            Ok(Self::_wrap(obj.table))
        } else {
            use rlua::Error::RuntimeError;
            Err(RuntimeError("Could not cast object to concrete type".into()))
        }
    }

    /// Given the internal object table, constructs a concrete object out
    /// of it.
    ///
    /// This is only used internally, which is why it's prefixed with a "_"
    /// Please do not use it outside of object.rs.
    fn _wrap(table: Table<'lua>) -> T;

    fn state(&self) -> rlua::Result<S> {
        self.get_table().get::<_, S>("userdata")
    }

    fn set_state(&self, data: S) -> rlua::Result<()> {
        self.get_table().set("userdata", data)
    }

    /// Gets the internal table for the concrete object.
    /// Used internally by cast, though there's nothing wrong with it being
    /// used outside of internal object use.
    fn get_table(&self) -> Table<'lua>;

    fn allocate(lua: &'lua Lua, class: Class) -> rlua::Result<ObjectBuilder<'lua>>
    {
        // This is the format of the lua objects in Way Cooler:
        /*
        -- This is the weird wrapper table, binding the user data and the object table together
        {
            -- Actual user data object, e.g the Rust object
            userdata = <user_data_here>,
            -- This is the object data table, e.g the thing that in Awesome
            -- is linked to the user data with lua_setuservalue
            data = {},
            -- That metatable that is allocated in the new macro for objects.
            -- It can access both the userdata and the lua data fields
            __metatable = {}
        }
        */
        let object = S::default();
        // TODO Increment the instance count
        let wrapper_table = lua.create_table();
        wrapper_table.set("userdata", object)?;
        let data_table = lua.create_table();
        wrapper_table.set("data", data_table)?;
        let meta = lua.create_table();
        meta.set("__class", class)?;
        meta.set("properties", Vec::<Property>::new().to_lua(lua)?)?;
        meta.set("signals", lua.create_table())?;
        meta.set("connect_signal",
                 lua.create_function(connect_signal))?;
        meta.set("disconnect_signal",
                 lua.create_function(disconnect_signal))?;
        meta.set("emit_signal", lua.create_function(emit_signal))?;
        meta.set("__index", lua.create_function(default_index))?;
        meta.set("__newindex", lua.create_function(default_newindex))?;
        meta.set("__tostring", lua.create_function(|_, wrapper_table: Table| {
            Ok(format!("{}", wrapper_table.get::<_, S>("userdata")?))
        }))?;
        wrapper_table.set_metatable(Some(meta));
        // TODO Emit new signal event
        let object = Object { table: wrapper_table };
        Ok(ObjectBuilder { object, lua })
    }
}

impl <'lua> ToLua<'lua> for Object<'lua> {
    fn to_lua(self, _: &'lua Lua) -> rlua::Result<Value<'lua>> {
        Ok(Value::Table(self.table))
    }
}

impl <'lua> Object<'lua> {
    /// Coerces a concrete object into a generic object.
    ///
    /// This requires a check to ensure data integrity, and it's often useless.
    /// Please don't use this method unless you need to.
    #[allow(dead_code)]
    #[deprecated]
    pub fn to_object<T, S, O>(obj: O) -> Self
        where S: Default + Display + Clone + UserData,
              O: Objectable<'lua, T, S>
    {
        let table = obj.get_table();
        assert!(table.contains_key("userdata")
                .expect("Could not get userdata field of object wrapper table"),
                "Table did not have special \"userdata\" field");
        assert!(table.contains_key("data")
                .expect("Could not get data field of object wrapper table"),
                "Table did not have special \"data\" field"
        );
        Object { table }
    }

    pub fn signals(&self) -> rlua::Result<rlua::Table<'lua>> {
        self.table.get::<_, Table>("signals")
    }

    pub fn table(self) -> rlua::Table<'lua> {
        self.table
    }
}

/// Default indexing of an Awesome object.
///
/// Automatically looks up contents in meta table, so instead of overriding this
/// it's easier to just add the required data in the meta table.
pub fn default_index<'lua>(lua: &'lua Lua,
                           (obj_table, index): (Table<'lua>, Value<'lua>))
                           -> rlua::Result<Value<'lua>> {
    // Look up in metatable first
    let meta = obj_table.get_metatable()
        .expect("Object had no metatable");
    if meta.get::<_, Table>("__class").is_ok() {
        if let Ok(val) = meta.raw_get::<_, Value>(index.clone()) {
            match val {
                Value::Nil => {},
                val => return Ok(val)
            }
        }
    }
    let index = String::from_lua(index, lua)?;
    match index.as_str() {
        "valid" => {
            Ok(Value::Boolean(
                if let Ok(class) = meta.get::<_, Table>("__class") {
                    let class: Class = class.into();
                    class.checker()?
                        .map(|checker| checker(obj_table.into()))
                        .unwrap_or(true)
                } else {
                    false
                }))
        },
        "data" => {
            obj_table.to_lua(lua)
        },
        index => {
            // Try see if there is a property of the class with the name
            if let Ok(class) = meta.get::<_, Table>("__class") {
                let props = class.get::<_, Vec<Property>>("properties")?;
                for prop in props {
                    if prop.name.as_str() == index {
                        // Property exists and has an index callback
                        if let Some(index) = prop.cb_index {
                            return index.call(obj_table)
                        }
                    }
                }
                match class.get::<_, Function>("__index_miss_handler") {
                    Ok(function) => {
                        return function.bind(obj_table)?.call(index)
                    },
                    Err(_) => {}
                }
            }
            // TODO property miss handler if index doesn't exst
            Ok(rlua::Value::Nil)
        }
    }
}

/// Default new indexing (assignment) of an Awesome object.
///
/// Automatically looks up contents in meta table, so instead of overriding this
/// it's easier to just add the required data in the meta table.
pub fn default_newindex<'lua>(_: &'lua Lua,
                              (obj_table, index, val):
                              (Table<'lua>, String, Value<'lua>))
                              -> rlua::Result<Value<'lua>> {
    // Look up in metatable first
    if let Some(meta) = obj_table.get_metatable() {
        if let Ok(val) = meta.raw_get::<_, Value>(index.clone()) {
            match val {
                Value::Nil => {},
                val => return Ok(val)
            }
        }
        let class = meta.get::<_, Table>("__class")?;
        let props = class.get::<_, Vec<Property>>("properties")?;
        for prop in props {
            if prop.name.as_str() == index {
                // Property exists and has a newindex callback
                if let Some(newindex) = prop.cb_newindex {
                    return newindex.bind(obj_table)?.call(val)
                }
            }
        }
        match class.get::<_, Function>("__newindex_miss_handler") {
            Ok(function) => {
                return function.bind(obj_table)?.call(index)
            },
            Err(_) => {}
        }
        // TODO property miss handler if index doesn't exst
    }
    Ok(Value::Nil)
}

fn connect_signal(lua: &Lua, (obj_table, signal, func): (Table, String, Function))
                  -> rlua::Result<()> {
    signal::connect_signal(lua, obj_table.into(), signal, &[func])
}

fn disconnect_signal(lua: &Lua, (obj_table, signal): (Table, String))
                     -> rlua::Result<()> {
    signal::disconnect_signal(lua, obj_table.into(), signal)
}

fn emit_signal(lua: &Lua, (obj_table, signal, args): (Table, String, Value))
               -> rlua::Result<()> {
    signal::emit_signal(lua, obj_table.into(), signal, args)
}
<commit_msg>Fix default_newindex to pass all needed arguments<commit_after>//! Utility methods and constructors for Lua objects

use std::fmt::Display;
use std::convert::From;
use rlua::{self, Lua, Table, UserData, AnyUserData, Value,
           FromLua, ToLua, Function};
use super::signal;
use super::class::Class;
use super::property::Property;

/// All Lua objects can be cast to this.
#[derive(Clone, Debug)]
pub struct Object<'lua> {
    table: Table<'lua>
}

impl <'lua> From<Table<'lua>> for Object<'lua> {
    fn from(table: Table<'lua>) -> Self {
        Object { table }
    }
}

/// Construct a new object, used when using the default Objectable::new.
pub struct ObjectBuilder<'lua>{
    lua: &'lua Lua,
    object: Object<'lua>
}

impl <'lua> ObjectBuilder<'lua> {
    pub fn add_to_meta(self, new_meta: Table<'lua>) -> rlua::Result<Self> {
        let meta = self.object.table.get_metatable()
            .expect("Object had no meta table");
        for entry in new_meta.pairs::<rlua::Value, rlua::Value>() {
            let (key, value) = entry?;
            meta.set(key, value)?;
        }
        self.object.table.set_metatable(Some(meta));
        Ok(self)
    }

    #[allow(dead_code)]
    pub fn add_to_signals(self, name: String, func: rlua::Function)
                          -> rlua::Result<Self> {
        signal::connect_signal(self.lua, self.object.clone(), name, &[func])?;
        Ok(self)
    }

    pub fn build(self) -> Object<'lua> {
        self.object
    }
}

/// Trait implemented by all objects that represent OO lua objects.
///
/// This trait allows casting an object gotten back from the Lua runtime
/// into a concrete object so that Rust can do things with it.
///
/// You can't do anything to the object until it has been converted into a
/// canonical form using this trait.
pub trait Objectable<'lua, T, S: UserData + Default + Display + Clone> {
    fn cast(obj: Object<'lua>) -> rlua::Result<T> {
        let data = obj.table.get::<_, AnyUserData>("userdata")?;
        if data.is::<S>() {
            Ok(Self::_wrap(obj.table))
        } else {
            use rlua::Error::RuntimeError;
            Err(RuntimeError("Could not cast object to concrete type".into()))
        }
    }

    /// Given the internal object table, constructs a concrete object out
    /// of it.
    ///
    /// This is only used internally, which is why it's prefixed with a "_"
    /// Please do not use it outside of object.rs.
    fn _wrap(table: Table<'lua>) -> T;

    fn state(&self) -> rlua::Result<S> {
        self.get_table().get::<_, S>("userdata")
    }

    fn set_state(&self, data: S) -> rlua::Result<()> {
        self.get_table().set("userdata", data)
    }

    /// Gets the internal table for the concrete object.
    /// Used internally by cast, though there's nothing wrong with it being
    /// used outside of internal object use.
    fn get_table(&self) -> Table<'lua>;

    fn allocate(lua: &'lua Lua, class: Class) -> rlua::Result<ObjectBuilder<'lua>>
    {
        // This is the format of the lua objects in Way Cooler:
        /*
        -- This is the weird wrapper table, binding the user data and the object table together
        {
            -- Actual user data object, e.g the Rust object
            userdata = <user_data_here>,
            -- This is the object data table, e.g the thing that in Awesome
            -- is linked to the user data with lua_setuservalue
            data = {},
            -- That metatable that is allocated in the new macro for objects.
            -- It can access both the userdata and the lua data fields
            __metatable = {}
        }
        */
        let object = S::default();
        // TODO Increment the instance count
        let wrapper_table = lua.create_table();
        wrapper_table.set("userdata", object)?;
        let data_table = lua.create_table();
        wrapper_table.set("data", data_table)?;
        let meta = lua.create_table();
        meta.set("__class", class)?;
        meta.set("properties", Vec::<Property>::new().to_lua(lua)?)?;
        meta.set("signals", lua.create_table())?;
        meta.set("connect_signal",
                 lua.create_function(connect_signal))?;
        meta.set("disconnect_signal",
                 lua.create_function(disconnect_signal))?;
        meta.set("emit_signal", lua.create_function(emit_signal))?;
        meta.set("__index", lua.create_function(default_index))?;
        meta.set("__newindex", lua.create_function(default_newindex))?;
        meta.set("__tostring", lua.create_function(|_, wrapper_table: Table| {
            Ok(format!("{}", wrapper_table.get::<_, S>("userdata")?))
        }))?;
        wrapper_table.set_metatable(Some(meta));
        // TODO Emit new signal event
        let object = Object { table: wrapper_table };
        Ok(ObjectBuilder { object, lua })
    }
}

impl <'lua> ToLua<'lua> for Object<'lua> {
    fn to_lua(self, _: &'lua Lua) -> rlua::Result<Value<'lua>> {
        Ok(Value::Table(self.table))
    }
}

impl <'lua> Object<'lua> {
    /// Coerces a concrete object into a generic object.
    ///
    /// This requires a check to ensure data integrity, and it's often useless.
    /// Please don't use this method unless you need to.
    #[allow(dead_code)]
    #[deprecated]
    pub fn to_object<T, S, O>(obj: O) -> Self
        where S: Default + Display + Clone + UserData,
              O: Objectable<'lua, T, S>
    {
        let table = obj.get_table();
        assert!(table.contains_key("userdata")
                .expect("Could not get userdata field of object wrapper table"),
                "Table did not have special \"userdata\" field");
        assert!(table.contains_key("data")
                .expect("Could not get data field of object wrapper table"),
                "Table did not have special \"data\" field"
        );
        Object { table }
    }

    pub fn signals(&self) -> rlua::Result<rlua::Table<'lua>> {
        self.table.get::<_, Table>("signals")
    }

    pub fn table(self) -> rlua::Table<'lua> {
        self.table
    }
}

/// Default indexing of an Awesome object.
///
/// Automatically looks up contents in meta table, so instead of overriding this
/// it's easier to just add the required data in the meta table.
pub fn default_index<'lua>(lua: &'lua Lua,
                           (obj_table, index): (Table<'lua>, Value<'lua>))
                           -> rlua::Result<Value<'lua>> {
    // Look up in metatable first
    let meta = obj_table.get_metatable()
        .expect("Object had no metatable");
    if meta.get::<_, Table>("__class").is_ok() {
        if let Ok(val) = meta.raw_get::<_, Value>(index.clone()) {
            match val {
                Value::Nil => {},
                val => return Ok(val)
            }
        }
    }
    let index = String::from_lua(index, lua)?;
    match index.as_str() {
        "valid" => {
            Ok(Value::Boolean(
                if let Ok(class) = meta.get::<_, Table>("__class") {
                    let class: Class = class.into();
                    class.checker()?
                        .map(|checker| checker(obj_table.into()))
                        .unwrap_or(true)
                } else {
                    false
                }))
        },
        "data" => {
            obj_table.to_lua(lua)
        },
        index => {
            // Try see if there is a property of the class with the name
            if let Ok(class) = meta.get::<_, Table>("__class") {
                let props = class.get::<_, Vec<Property>>("properties")?;
                for prop in props {
                    if prop.name.as_str() == index {
                        // Property exists and has an index callback
                        if let Some(index) = prop.cb_index {
                            return index.call(obj_table)
                        }
                    }
                }
                match class.get::<_, Function>("__index_miss_handler") {
                    Ok(function) => {
                        return function.bind(obj_table)?.call(index)
                    },
                    Err(_) => {}
                }
            }
            // TODO property miss handler if index doesn't exst
            Ok(rlua::Value::Nil)
        }
    }
}

/// Default new indexing (assignment) of an Awesome object.
///
/// Automatically looks up contents in meta table, so instead of overriding this
/// it's easier to just add the required data in the meta table.
pub fn default_newindex<'lua>(_: &'lua Lua,
                              (obj_table, index, val):
                              (Table<'lua>, String, Value<'lua>))
                              -> rlua::Result<Value<'lua>> {
    // Look up in metatable first
    if let Some(meta) = obj_table.get_metatable() {
        if let Ok(val) = meta.raw_get::<_, Value>(index.clone()) {
            match val {
                Value::Nil => {},
                val => return Ok(val)
            }
        }
        let class = meta.get::<_, Table>("__class")?;
        let props = class.get::<_, Vec<Property>>("properties")?;
        for prop in props {
            if prop.name.as_str() == index {
                // Property exists and has a newindex callback
                if let Some(newindex) = prop.cb_newindex {
                    return newindex.bind(obj_table)?.call(val)
                }
            }
        }
        match class.get::<_, Function>("__newindex_miss_handler") {
            Ok(function) => {
                return function.bind(obj_table)?.call((index, val))
            },
            Err(_) => {}
        }
        // TODO property miss handler if index doesn't exst
    }
    Ok(Value::Nil)
}

fn connect_signal(lua: &Lua, (obj_table, signal, func): (Table, String, Function))
                  -> rlua::Result<()> {
    signal::connect_signal(lua, obj_table.into(), signal, &[func])
}

fn disconnect_signal(lua: &Lua, (obj_table, signal): (Table, String))
                     -> rlua::Result<()> {
    signal::disconnect_signal(lua, obj_table.into(), signal)
}

fn emit_signal(lua: &Lua, (obj_table, signal, args): (Table, String, Value))
               -> rlua::Result<()> {
    signal::emit_signal(lua, obj_table.into(), signal, args)
}
<|endoftext|>