<commit_before>/// This macro provides a more user-friendly wrapper around the `Select` struct.
///
/// It is similar in syntax to a `match` expression: It takes a list of cases,
/// each of the form `operation(arguments) => expression`. Note that
/// `expression` may be a block as well. The individual cases may optionally be
/// separated by commas. As with `match`, the whole macro invocation is treated
/// as an expression, so values can be returned from the individual cases.
///
/// A simple example to illustrate:
///
/// ```
/// select_loop! {
///     send(tx0, value) => println!("Sent value to tx0!"),
///     send(tx1, value) => { println!("Sent value to tx1!") }
/// }
/// ```
///
/// Please keep in mind the standard rules of the `Select`:
///
/// 1. No two cases may use the same end of the same channel. In the example
///    above this means that even if `tx0` and `tx1` are different `Sender`
///    instances, they must not belong to the same channel.
///
/// The following operations are supported by the macro:
///
/// * **`send($tx:expr, $variable:ident) => ...`:** Attempt to `send` the value of
///   `$variable` with `$tx`. If sending fails, the value of `$variable` is
///   automatically recovered. For convenience, `$variable` is automatically
///   made mutable by the macro.
/// * **`send($tx:expr, mut $field:expr) => ...`:** Attempt to `send` the value of
///   `$variable` with `$tx`. If sending fails, the value of `$variable` is
///   automatically recovered. Different from the previous version, this version
///   assumes that `$field` is mutable. And while the macro accepts any
///   expression for `$field`, it only really makes sense to specify plain
///   variables or direct field references (e.g. `some_struct.some_field`).
/// * **`send($tx:expr, eval $expr:expr) => ...`:** Attempt to `send` the result of
///   evaluating `$expr` with `$tx`. *Warning:* $expr is evaluated once in every
///   loop iteration. In some iterations, its result may simply be discarded
///   with no actual attempt at sending it.
/// * **`recv($rx:expr, $variable:ident) => ...`:** Attempt to receive a value from
///   `$rx`. If successful, the received value will be available in `$variable`
///    for the expression of this case.
/// * **`disconnected() => ...`:** This case is triggered when all channels in the
///   loop have disconnected.
/// * **`would_block() => ...`:** This case is triggered when all channels in the
///   loop would block.
/// * **`timed_out($duration:expr) => ...`:** Enables a timeout for the select loop.
///   If the timeout is reached without any of the other cases triggering, this
///   case is triggered. If there are multiple `timed_out` cases, only the
///   duration from the last case is registered.
///
#[macro_export]
macro_rules! select_loop {
    // The main entrypoint
    {$($method:ident($($args:tt)*) => $body:expr$(,)*)*} => {
        #[allow(unused_mut, unused_variables)]
        {
            let mut state = $crate::Select::new();

            // Build the prelude.
            //
            // This currently performs two tasks:
            //
            // 1) Make all variables used in send(_, $ident) mutable (the
            //    variable will move into the loop anyway, so we can move it
            //    here as well).
            // 2) If a timeout was specified, overwrite the above state with one
            //    which has the timeout set.
            $(select_loop!(@prelude(state) $method($($args)*));)*

            // The actual select loop which a user would write manually
            #[allow(unreachable_code)]
            'select: loop {
                // This double-loop construct is used to guard against the user
                // using unlabeled breaks / continues in their code.
                //
                // It works by abusing rustc's control flow analysis:
                //
                // 1) The _guard variable is declared
                // 2) The generated code will assign a value to _guard [A0]
                //    immediately after an operation was successful (before
                //    running any user code)
                // 3) There is another assignment to _guard [A1] directly after
                //    the inner loop.
                // 4) If the user has an unlabeled break in their code, rustc
                //    will complain because both [A0] and [A1] assign to guard.
                //    If the user has an unlabeled continue in their code, rustc
                //    will complain because [A0] may assign to guard twice.
                // 5) Directly after executing the user code, we break the
                //    outer loop, so we don't trigger the error ourselves.
                // 6) To avoid an infinite loop, we manually continue to the
                //    outer loop at the very end of the inner loop.
                let _dont_use_an_unlabeled_continue_or_break_in_select_loop;
                loop {
                    $(
                        // Build the actual method invocations.
                        select_loop! {
                            @impl(
                                'select,
                                state,
                                _dont_use_an_unlabeled_continue_or_break_in_select_loop
                            )
                            $method($($args)*) => $body
                        }
                    )*
                    continue 'select;
                }
                _dont_use_an_unlabeled_continue_or_break_in_select_loop = ();
            }
        }
    };

    //The individual method invocations
    {@impl($select:tt, $state:ident, $guard:ident) send($tx:expr, $val:ident) => $body:expr} => {
        match $state.send(&*&$tx, $val) {
            Ok(()) => {
                $guard = ();
                break $select $body;
            }
            Err($crate::SelectSendError(val)) => {
                $val = val;
            }
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) send($tx:expr, mut $val:expr) => $body:expr} => {
        match $state.send(&*&$tx, $val) {
            Ok(()) => {
                $guard = ();
                break $select $body;
            }
            Err($crate::SelectSendError(val)) => {
                $val = val;
            }
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) send($tx:expr, eval $val:expr) => $body:expr} => {
        if let Ok(()) = $state.send(&*&$tx, $val) {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) recv($rx:expr, $val:ident) => $body:expr} => {
        if let Ok($val) = $state.recv(&*&$rx) {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) disconnected() => $body:expr} => {
        if $state.disconnected() {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) would_block() => $body:expr} => {
        if $state.would_block() {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) timed_out($_timeout:expr) => $body:expr} => {
        if $state.timed_out() {
            $guard = ();
            break $select $body;
        }
    };

    // The prelude helpers
    {@prelude($state:ident) send($tx:expr, $val:ident)} => {
        let mut $val = $val;
    };
    {@prelude($state:ident) timed_out($timeout:expr)} => {
        let mut $state = $crate::Select::with_timeout($timeout);
    };
    {@prelude($state:ident) $($tail:tt)*} => {};
}

#[cfg(test)]
mod tests {
    use ::{Receiver, Sender};
    use std::time::Duration;

    struct _Foo(String);

    fn _it_compiles(
        mut struct_val: _Foo,
        immutable_var: String,
        eval_var: String,
        rx0: Receiver<String>,
        rx1: &Receiver<u32>,
        tx0: &mut Sender<String>,
        tx1: Sender<String>,
        tx2: Sender<String>,
        tx3: Sender<String>,
        tx4: Sender<String>,
        tx5: Sender<u32>,
    ) -> Option<String> {
        select_loop! {
            recv(rx0, val) => Some(val),
            recv(rx1, val) => Some(val.to_string()),
            send(tx0, mut struct_val.0) => Some(immutable_var),
            send(tx1, immutable_var) => Some(struct_val.0),
            send(tx2, eval struct_val.0.clone()) => Some(struct_val.0),
            send(tx3, immutable_var) => Some(eval_var),
            send(tx4, eval eval_var.clone()) => Some(eval_var),
            send(tx5, eval 42) => None,
            disconnected() => Some("disconnected".into()),
            would_block() => Some("would_block".into()),
            timed_out(Duration::from_secs(1)) => Some("timed_out".into()),
            //The previous timeout duration is overwritten
            timed_out(Duration::from_secs(2)) => Some("timet_out".into()),
        }
    }
}
<commit_msg>ignore doc-code, recv(mut, _)<commit_after>/// This macro provides a more user-friendly wrapper around the `Select` struct.
///
/// It is similar in syntax to a `match` expression: It takes a list of cases,
/// each of the form `operation(arguments) => expression`. Note that
/// `expression` may be a block as well. The individual cases may optionally be
/// separated by commas. As with `match`, the whole macro invocation is treated
/// as an expression, so values can be returned from the individual cases.
///
/// A simple example to illustrate:
///
/// ```ignore
/// select_loop! {
///     send(tx0, value) => println!("Sent value to tx0!"),
///     send(tx1, value) => { println!("Sent value to tx1!") }
/// }
/// ```
///
/// Please keep in mind the standard rules of the `Select`:
///
/// 1. No two cases may use the same end of the same channel. In the example
///    above this means that even if `tx0` and `tx1` are different `Sender`
///    instances, they must not belong to the same channel.
///
/// The following operations are supported by the macro:
///
/// * **`send($tx:expr, $variable:ident) => ...`:** Attempt to `send` the value of
///   `$variable` with `$tx`. If sending fails, the value of `$variable` is
///   automatically recovered. For convenience, `$variable` is automatically
///   made mutable by the macro.
/// * **`send($tx:expr, mut $field:expr) => ...`:** Attempt to `send` the value of
///   `$variable` with `$tx`. If sending fails, the value of `$variable` is
///   automatically recovered. Different from the previous version, this version
///   assumes that `$field` is mutable. And while the macro accepts any
///   expression for `$field`, it only really makes sense to specify plain
///   variables or direct field references (e.g. `some_struct.some_field`).
/// * **`send($tx:expr, eval $expr:expr) => ...`:** Attempt to `send` the result of
///   evaluating `$expr` with `$tx`. *Warning:* $expr is evaluated once in every
///   loop iteration. In some iterations, its result may simply be discarded
///   with no actual attempt at sending it.
/// * **`recv($rx:expr, $variable:ident) => ...`:** Attempt to receive a value from
///   `$rx`. If successful, the received value will be available in `$variable`
///    for the expression of this case.
/// * **`recv($rx:expr, mut $variable:ident) => ...`:** Attempt to receive a value
///   from `$rx`. If successful, the received value will be available in the
///   mutable `$variable` for the expression of this case.
/// * **`recv($rx:expr, _) => ...`:** Attempt to receive a value
///   from `$rx`. If successful, the received value is discarded.
/// * **`disconnected() => ...`:** This case is triggered when all channels in the
///   loop have disconnected.
/// * **`would_block() => ...`:** This case is triggered when all channels in the
///   loop would block.
/// * **`timed_out($duration:expr) => ...`:** Enables a timeout for the select loop.
///   If the timeout is reached without any of the other cases triggering, this
///   case is triggered. If there are multiple `timed_out` cases, only the
///   duration from the last case is registered.
///
#[macro_export]
macro_rules! select_loop {
    // The main entrypoint
    {$($method:ident($($args:tt)*) => $body:expr$(,)*)*} => {
        #[allow(unused_mut, unused_variables)]
        {
            let mut state = $crate::Select::new();

            // Build the prelude.
            //
            // This currently performs two tasks:
            //
            // 1) Make all variables used in send(_, $ident) mutable (the
            //    variable will move into the loop anyway, so we can move it
            //    here as well).
            // 2) If a timeout was specified, overwrite the above state with one
            //    which has the timeout set.
            $(select_loop!(@prelude(state) $method($($args)*));)*

            // The actual select loop which a user would write manually
            #[allow(unreachable_code)]
            'select: loop {
                // This double-loop construct is used to guard against the user
                // using unlabeled breaks / continues in their code.
                //
                // It works by abusing rustc's control flow analysis:
                //
                // 1) The _guard variable is declared
                // 2) The generated code will assign a value to _guard [A0]
                //    immediately after an operation was successful (before
                //    running any user code)
                // 3) There is another assignment to _guard [A1] directly after
                //    the inner loop.
                // 4) If the user has an unlabeled break in their code, rustc
                //    will complain because both [A0] and [A1] assign to guard.
                //    If the user has an unlabeled continue in their code, rustc
                //    will complain because [A0] may assign to guard twice.
                // 5) Directly after executing the user code, we break the
                //    outer loop, so we don't trigger the error ourselves.
                // 6) To avoid an infinite loop, we manually continue to the
                //    outer loop at the very end of the inner loop.
                let _dont_use_an_unlabeled_continue_or_break_in_select_loop;
                loop {
                    $(
                        // Build the actual method invocations.
                        select_loop! {
                            @impl(
                                'select,
                                state,
                                _dont_use_an_unlabeled_continue_or_break_in_select_loop
                            )
                            $method($($args)*) => $body
                        }
                    )*
                    continue 'select;
                }
                _dont_use_an_unlabeled_continue_or_break_in_select_loop = ();
            }
        }
    };

    //The individual method invocations
    {@impl($select:tt, $state:ident, $guard:ident) send($tx:expr, $val:ident) => $body:expr} => {
        match $state.send(&*&$tx, $val) {
            Ok(()) => {
                $guard = ();
                break $select $body;
            }
            Err($crate::SelectSendError(val)) => {
                $val = val;
            }
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) send($tx:expr, mut $val:expr) => $body:expr} => {
        match $state.send(&*&$tx, $val) {
            Ok(()) => {
                $guard = ();
                break $select $body;
            }
            Err($crate::SelectSendError(val)) => {
                $val = val;
            }
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) send($tx:expr, eval $val:expr) => $body:expr} => {
        if let Ok(()) = $state.send(&*&$tx, $val) {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) recv($rx:expr, _) => $body:expr} => {
        if let Ok(_) = $state.recv(&*&$rx) {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) recv($rx:expr, $val:ident) => $body:expr} => {
        if let Ok($val) = $state.recv(&*&$rx) {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) recv($rx:expr, mut $val:ident) => $body:expr} => {
        if let Ok(mut $val) = $state.recv(&*&$rx) {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) disconnected() => $body:expr} => {
        if $state.disconnected() {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) would_block() => $body:expr} => {
        if $state.would_block() {
            $guard = ();
            break $select $body;
        }
    };
    {@impl($select:tt, $state:ident, $guard:ident) timed_out($_timeout:expr) => $body:expr} => {
        if $state.timed_out() {
            $guard = ();
            break $select $body;
        }
    };

    // The prelude helpers
    {@prelude($state:ident) send($tx:expr, $val:ident)} => {
        let mut $val = $val;
    };
    {@prelude($state:ident) timed_out($timeout:expr)} => {
        let mut $state = $crate::Select::with_timeout($timeout);
    };
    {@prelude($state:ident) $($tail:tt)*} => {};
}

#[cfg(test)]
mod tests {
    use ::{Receiver, Sender};
    use std::time::Duration;

    struct _Foo(String);

    fn _it_compiles(
        mut struct_val: _Foo,
        immutable_var: String,
        eval_var: String,
        rx0: Receiver<String>,
        rx1: &Receiver<u32>,
        rx2: Receiver<String>,
        rx3: Receiver<String>,
        tx0: &mut Sender<String>,
        tx1: Sender<String>,
        tx2: Sender<String>,
        tx3: Sender<String>,
        tx4: Sender<String>,
        tx5: Sender<u32>,
    ) -> Option<String> {
        select_loop! {
            recv(rx0, val) => Some(val),
            recv(rx1, val) => Some(val.to_string()),
            recv(rx2, mut val) => Some(val.as_mut_str().to_owned()),
            recv(rx3, _) => None,
            send(tx0, mut struct_val.0) => Some(immutable_var),
            send(tx1, immutable_var) => Some(struct_val.0),
            send(tx2, eval struct_val.0.clone()) => Some(struct_val.0),
            send(tx3, immutable_var) => Some(eval_var),
            send(tx4, eval eval_var.clone()) => Some(eval_var),
            send(tx5, eval 42) => None,
            disconnected() => Some("disconnected".into()),
            would_block() => Some("would_block".into()),
            timed_out(Duration::from_secs(1)) => Some("timed_out".into()),
            //The previous timeout duration is overwritten
            timed_out(Duration::from_secs(2)) => Some("timet_out".into()),
        }
    }
}
<|endoftext|>


<commit_before>// Deny warnings, except in `dev` mode

// To update this list
// 1. Run `rustc -W help`
// 2. Grab all `default=warn` warnings
// 3. Paste them here, deleting `warnings`, and any with `deprecated` in the name
#![deny(const_err,
        dead_code,
        illegal_floating_point_literal_pattern,
        improper_ctypes,
        non_camel_case_types,
        non_shorthand_field_patterns,
        non_snake_case,
        non_upper_case_globals,
        no_mangle_generic_items,
        overflowing_literals,
        path_statements,
        patterns_in_fns_without_body,
        plugin_as_library,
        private_in_public,
        private_no_mangle_fns,
        private_no_mangle_statics,
        renamed_and_removed_lints,
        stable_features,
        unconditional_recursion,
        unions_with_drop_fields,
        unknown_lints,
        unreachable_code,
        unreachable_patterns,
        unused_allocation,
        unused_assignments,
        unused_attributes,
        unused_comparisons,
        unused_features,
        unused_imports,
        unused_macros,
        unused_must_use,
        unused_mut,
        unused_parens,
        unused_unsafe,
        unused_variables,
        while_true)]
// This list is select `allow` warnings
#![deny(trivial_casts,
       trivial_numeric_casts,
       unused_extern_crates,
       unused_import_braces)]
#![cfg_attr(feature="cargo-clippy", allow(
        cyclomatic_complexity,
        needless_pass_by_value))]
#![cfg_attr(feature="dev", warn(warnings))]

extern crate cobalt;
extern crate env_logger;
extern crate notify;
extern crate ghp;

extern crate hyper;

#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

mod build;
mod error;
mod serve;
mod new;

use std::env;

use clap::{Arg, App, SubCommand, AppSettings};
use cobalt::{Config, Dump, jekyll};
use cobalt::{list_syntaxes, list_syntax_themes};
use env_logger::LogBuilder;
use log::{LogRecord, LogLevelFilter};

use error::*;

quick_main!(run);

fn run() -> Result<()> {
    let app_cli = App::new("Cobalt")
        .version(crate_version!())
        .author("Benny Klotz <r3qnbenni@gmail.com>, Johann Hofmann")
        .about("A static site generator written in Rust.")
        .setting(AppSettings::SubcommandRequired)
        .setting(AppSettings::GlobalVersion)
        .arg(Arg::with_name("config")
                 .short("c")
                 .long("config")
                 .value_name("FILE")
                 .help("Config file to use [default: .cobalt.yml]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("source")
                 .short("s")
                 .long("source")
                 .value_name("DIR")
                 .help("Source folder [default: ./]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("destination")
                 .short("d")
                 .long("destination")
                 .value_name("DIR")
                 .help("Destination folder [default: ./]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("layouts")
                 .short("l")
                 .long("layouts")
                 .value_name("DIR")
                 .help("Layout templates folder [default: ./_layouts]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("posts")
                 .short("p")
                 .long("posts")
                 .value_name("DIR")
                 .help("Posts folder [default: ./posts]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("drafts")
                 .long("drafts")
                 .help("Include drafts.")
                 .global(true)
                 .takes_value(false))
        .arg(Arg::with_name("log-level")
                 .short("L")
                 .long("log-level")
                 .possible_values(&["error", "warn", "info", "debug", "trace", "off"])
                 .help("Log level [default: info]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("trace")
                 .long("trace")
                 .help("Log ultra-verbose (trace level) information")
                 .global(true)
                 .takes_value(false))
        .arg(Arg::with_name("silent")
                 .long("silent")
                 .help("Suppress all output")
                 .global(true)
                 .takes_value(false))
        .arg(Arg::with_name("dump")
                 .long("dump")
                 .possible_values(&Dump::variants())
                 .help("Dump the specified internal state")
                 .global(true)
                 .multiple(true)
                 .takes_value(true))
        .subcommand(SubCommand::with_name("init")
                        .about("create a new cobalt project")
                        .arg(Arg::with_name("DIRECTORY")
                                 .help("Suppress all output")
                                 .default_value("./")
                                 .index(1)))
        .subcommand(SubCommand::with_name("new")
                        .about("Create a new post or page")
                        .arg(Arg::with_name("FILETYPE")
                                 .help("Type of file to create eg post or page")
                                 .default_value("post")
                                 .takes_value(true))
                        .arg(Arg::with_name("FILENAME")
                                 .help("File to create")
                                 .default_value_if("FILETYPE", Some("page"), "new_page.md")
                                 .default_value("new_post.md")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("build")
                        .about("build the cobalt project at the source dir")
                        .arg(Arg::with_name("import")
                                 .short("i")
                                 .long("import")
                                 .help("Import after build to gh-pages branch")
                                 .takes_value(false))
                        .arg(Arg::with_name("branch")
                                 .short("b")
                                 .long("branch")
                                 .value_name("BRANCH")
                                 .help("Branch that will be used to import the site to")
                                 .default_value("gh-pages")
                                 .takes_value(true))
                        .arg(Arg::with_name("message")
                                 .short("m")
                                 .long("message")
                                 .value_name("COMMIT-MESSAGE")
                                 .help("Commit message that will be used on import")
                                 .default_value("cobalt site import")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("clean").about("cleans directory set as destination"))
        .subcommand(SubCommand::with_name("serve")
                        .about("build and serve the cobalt project at the source dir")
                        .arg(Arg::with_name("port")
                                 .short("P")
                                 .long("port")
                                 .value_name("INT")
                                 .help("Port to serve from")
                                 .default_value("3000")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("watch")
                        .about("build, serve, and watch the project at the source dir")
                        .arg(Arg::with_name("port")
                                 .short("P")
                                 .long("port")
                                 .value_name("INT")
                                 .help("Port to serve from")
                                 .default_value("3000")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("import")
                        .about("moves the contents of the dest folder to the gh-pages branch")
                        .arg(Arg::with_name("branch")
                                 .short("b")
                                 .long("branch")
                                 .value_name("BRANCH")
                                 .help("Branch that will be used to import the site to")
                                 .default_value("gh-pages")
                                 .takes_value(true))
                        .arg(Arg::with_name("message")
                                 .short("m")
                                 .long("message")
                                 .value_name("COMMIT-MESSAGE")
                                 .help("Commit message that will be used on import")
                                 .default_value("cobalt site import")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("list-syntax-themes").about("list available themes"))
        .subcommand(SubCommand::with_name("list-syntaxes").about("list supported syntaxes"))
        .subcommand(SubCommand::with_name("convert-jekyll")
                        .about("convert jekyll website to cobalt")
                        .arg(Arg::with_name("jksrc")
                                 .long("jksrc")
                                 .value_name("JEKYLL-FILE-OR-DIR")
                                 .help("Jekyll posts' directory")
                                 .required(true)
                                 .takes_value(true))
                        .arg(Arg::with_name("jkdst")
                                 .long("jkdst")
                                 .value_name("DIR")
                                 .help("Output dir of converted posts")
                                 .takes_value(true)
                                 .default_value("./posts")));

    let global_matches = app_cli.get_matches();

    let (command, matches) = match global_matches.subcommand() {
        (command, Some(matches)) => (command, matches),
        (_, None) => unreachable!(),
    };

    let format = |record: &LogRecord| {
        let level = format!("[{}]", record.level()).to_lowercase();
        format!("{:8} {}", level, record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    match matches
              .value_of("log-level")
              .or_else(|| global_matches.value_of("log-level")) {
        Some("error") => builder.filter(None, LogLevelFilter::Error),
        Some("warn") => builder.filter(None, LogLevelFilter::Warn),
        Some("debug") => builder.filter(None, LogLevelFilter::Debug),
        Some("trace") => builder.filter(None, LogLevelFilter::Trace),
        Some("off") => builder.filter(None, LogLevelFilter::Off),
        Some("info") | _ => builder.filter(None, LogLevelFilter::Info),
    };

    if matches.is_present("trace") {
        builder.filter(None, LogLevelFilter::Trace);
    }

    if matches.is_present("silent") {
        builder.filter(None, LogLevelFilter::Off);
    }

    builder.init().unwrap();

    let config_path = matches
        .value_of("config")
        .or_else(|| global_matches.value_of("config"));

    // Fetch config information if available
    let mut config: Config = if let Some(config_path) = config_path {
        Config::from_file(config_path)
            .chain_err(|| format!("Error reading config file {:?}", config_path))?
    } else {
        let cwd = env::current_dir().expect("How does this fail?");
        Config::from_cwd(cwd)?
    };

    config.source = matches
        .value_of("source")
        .or_else(|| global_matches.value_of("source"))
        .map(str::to_string)
        .unwrap_or(config.source);

    config.dest = matches
        .value_of("destination")
        .or_else(|| global_matches.value_of("destination"))
        .map(str::to_string)
        .unwrap_or(config.dest);

    config.layouts = matches
        .value_of("layouts")
        .or_else(|| global_matches.value_of("layouts"))
        .map(str::to_string)
        .unwrap_or(config.layouts);

    config.posts = matches
        .value_of("posts")
        .or_else(|| global_matches.value_of("posts"))
        .map(str::to_string)
        .unwrap_or(config.posts);

    config.include_drafts = matches.is_present("drafts");

    if global_matches.is_present("dump") {
        let mut dump = values_t!(global_matches, "dump", Dump)?;
        config.dump.append(&mut dump);
        info!("Setting: {:?}", config.dump);
    }
    if matches.is_present("dump") {
        let mut dump = values_t!(matches, "dump", Dump)?;
        config.dump.append(&mut dump);
        info!("Setting: {:?}", config.dump);
    }

    match command {
        "init" => new::init_command(config, matches),
        "new" => new::new_command(config, matches),
        "build" => build::build_command(config, matches),
        "clean" => build::clean_command(config, matches),
        "serve" => serve::serve_command(config, matches),
        "watch" => serve::watch_command(config, matches),
        "import" => build::import_command(config, matches),
        "list-syntax-themes" => {
            for name in list_syntax_themes() {
                println!("{}", name);
            }
            Ok(())
        }
        "list-syntaxes" => {
            for name in list_syntaxes() {
                println!("{}", name);
            }
            Ok(())
        }
        "convert-jekyll" => {
            let source = matches.value_of("jksrc").unwrap().to_string();
            let dest = matches.value_of("jkdst").unwrap().to_string();
            jekyll::jk_document::convert_from_jk(std::path::Path::new(&source),
                                                 std::path::Path::new(&dest))
                .chain_err(|| "Jekyll conversion failed.")
        }
        _ => {
            bail!(global_matches.usage());
        }
    }.chain_err(|| format!("{} command failed", command))?;

    Ok(())
}
<commit_msg>feat: Remove source/posts/layouts flags<commit_after>// Deny warnings, except in `dev` mode

// To update this list
// 1. Run `rustc -W help`
// 2. Grab all `default=warn` warnings
// 3. Paste them here, deleting `warnings`, and any with `deprecated` in the name
#![deny(const_err,
        dead_code,
        illegal_floating_point_literal_pattern,
        improper_ctypes,
        non_camel_case_types,
        non_shorthand_field_patterns,
        non_snake_case,
        non_upper_case_globals,
        no_mangle_generic_items,
        overflowing_literals,
        path_statements,
        patterns_in_fns_without_body,
        plugin_as_library,
        private_in_public,
        private_no_mangle_fns,
        private_no_mangle_statics,
        renamed_and_removed_lints,
        stable_features,
        unconditional_recursion,
        unions_with_drop_fields,
        unknown_lints,
        unreachable_code,
        unreachable_patterns,
        unused_allocation,
        unused_assignments,
        unused_attributes,
        unused_comparisons,
        unused_features,
        unused_imports,
        unused_macros,
        unused_must_use,
        unused_mut,
        unused_parens,
        unused_unsafe,
        unused_variables,
        while_true)]
// This list is select `allow` warnings
#![deny(trivial_casts,
       trivial_numeric_casts,
       unused_extern_crates,
       unused_import_braces)]
#![cfg_attr(feature="cargo-clippy", allow(
        cyclomatic_complexity,
        needless_pass_by_value))]
#![cfg_attr(feature="dev", warn(warnings))]

extern crate cobalt;
extern crate env_logger;
extern crate notify;
extern crate ghp;

extern crate hyper;

#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

mod build;
mod error;
mod serve;
mod new;

use std::env;

use clap::{Arg, App, SubCommand, AppSettings};
use cobalt::{Config, Dump, jekyll};
use cobalt::{list_syntaxes, list_syntax_themes};
use env_logger::LogBuilder;
use log::{LogRecord, LogLevelFilter};

use error::*;

quick_main!(run);

fn run() -> Result<()> {
    let app_cli = App::new("Cobalt")
        .version(crate_version!())
        .author("Benny Klotz <r3qnbenni@gmail.com>, Johann Hofmann")
        .about("A static site generator written in Rust.")
        .setting(AppSettings::SubcommandRequired)
        .setting(AppSettings::GlobalVersion)
        .arg(Arg::with_name("config")
                 .short("c")
                 .long("config")
                 .value_name("FILE")
                 .help("Config file to use [default: .cobalt.yml]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("destination")
                 .short("d")
                 .long("destination")
                 .value_name("DIR")
                 .help("Destination folder [default: ./]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("drafts")
                 .long("drafts")
                 .help("Include drafts.")
                 .global(true)
                 .takes_value(false))
        .arg(Arg::with_name("log-level")
                 .short("L")
                 .long("log-level")
                 .possible_values(&["error", "warn", "info", "debug", "trace", "off"])
                 .help("Log level [default: info]")
                 .global(true)
                 .takes_value(true))
        .arg(Arg::with_name("trace")
                 .long("trace")
                 .help("Log ultra-verbose (trace level) information")
                 .global(true)
                 .takes_value(false))
        .arg(Arg::with_name("silent")
                 .long("silent")
                 .help("Suppress all output")
                 .global(true)
                 .takes_value(false))
        .arg(Arg::with_name("dump")
                 .long("dump")
                 .possible_values(&Dump::variants())
                 .help("Dump the specified internal state")
                 .global(true)
                 .multiple(true)
                 .takes_value(true))
        .subcommand(SubCommand::with_name("init")
                        .about("create a new cobalt project")
                        .arg(Arg::with_name("DIRECTORY")
                                 .help("Suppress all output")
                                 .default_value("./")
                                 .index(1)))
        .subcommand(SubCommand::with_name("new")
                        .about("Create a new post or page")
                        .arg(Arg::with_name("FILETYPE")
                                 .help("Type of file to create eg post or page")
                                 .default_value("post")
                                 .takes_value(true))
                        .arg(Arg::with_name("FILENAME")
                                 .help("File to create")
                                 .default_value_if("FILETYPE", Some("page"), "new_page.md")
                                 .default_value("new_post.md")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("build")
                        .about("build the cobalt project at the source dir")
                        .arg(Arg::with_name("import")
                                 .short("i")
                                 .long("import")
                                 .help("Import after build to gh-pages branch")
                                 .takes_value(false))
                        .arg(Arg::with_name("branch")
                                 .short("b")
                                 .long("branch")
                                 .value_name("BRANCH")
                                 .help("Branch that will be used to import the site to")
                                 .default_value("gh-pages")
                                 .takes_value(true))
                        .arg(Arg::with_name("message")
                                 .short("m")
                                 .long("message")
                                 .value_name("COMMIT-MESSAGE")
                                 .help("Commit message that will be used on import")
                                 .default_value("cobalt site import")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("clean").about("cleans directory set as destination"))
        .subcommand(SubCommand::with_name("serve")
                        .about("build and serve the cobalt project at the source dir")
                        .arg(Arg::with_name("port")
                                 .short("P")
                                 .long("port")
                                 .value_name("INT")
                                 .help("Port to serve from")
                                 .default_value("3000")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("watch")
                        .about("build, serve, and watch the project at the source dir")
                        .arg(Arg::with_name("port")
                                 .short("P")
                                 .long("port")
                                 .value_name("INT")
                                 .help("Port to serve from")
                                 .default_value("3000")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("import")
                        .about("moves the contents of the dest folder to the gh-pages branch")
                        .arg(Arg::with_name("branch")
                                 .short("b")
                                 .long("branch")
                                 .value_name("BRANCH")
                                 .help("Branch that will be used to import the site to")
                                 .default_value("gh-pages")
                                 .takes_value(true))
                        .arg(Arg::with_name("message")
                                 .short("m")
                                 .long("message")
                                 .value_name("COMMIT-MESSAGE")
                                 .help("Commit message that will be used on import")
                                 .default_value("cobalt site import")
                                 .takes_value(true)))
        .subcommand(SubCommand::with_name("list-syntax-themes").about("list available themes"))
        .subcommand(SubCommand::with_name("list-syntaxes").about("list supported syntaxes"))
        .subcommand(SubCommand::with_name("convert-jekyll")
                        .about("convert jekyll website to cobalt")
                        .arg(Arg::with_name("jksrc")
                                 .long("jksrc")
                                 .value_name("JEKYLL-FILE-OR-DIR")
                                 .help("Jekyll posts' directory")
                                 .required(true)
                                 .takes_value(true))
                        .arg(Arg::with_name("jkdst")
                                 .long("jkdst")
                                 .value_name("DIR")
                                 .help("Output dir of converted posts")
                                 .takes_value(true)
                                 .default_value("./posts")));

    let global_matches = app_cli.get_matches();

    let (command, matches) = match global_matches.subcommand() {
        (command, Some(matches)) => (command, matches),
        (_, None) => unreachable!(),
    };

    let format = |record: &LogRecord| {
        let level = format!("[{}]", record.level()).to_lowercase();
        format!("{:8} {}", level, record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    match matches
              .value_of("log-level")
              .or_else(|| global_matches.value_of("log-level")) {
        Some("error") => builder.filter(None, LogLevelFilter::Error),
        Some("warn") => builder.filter(None, LogLevelFilter::Warn),
        Some("debug") => builder.filter(None, LogLevelFilter::Debug),
        Some("trace") => builder.filter(None, LogLevelFilter::Trace),
        Some("off") => builder.filter(None, LogLevelFilter::Off),
        Some("info") | _ => builder.filter(None, LogLevelFilter::Info),
    };

    if matches.is_present("trace") {
        builder.filter(None, LogLevelFilter::Trace);
    }

    if matches.is_present("silent") {
        builder.filter(None, LogLevelFilter::Off);
    }

    builder.init().unwrap();

    let config_path = matches
        .value_of("config")
        .or_else(|| global_matches.value_of("config"));

    // Fetch config information if available
    let mut config: Config = if let Some(config_path) = config_path {
        Config::from_file(config_path)
            .chain_err(|| format!("Error reading config file {:?}", config_path))?
    } else {
        let cwd = env::current_dir().expect("How does this fail?");
        Config::from_cwd(cwd)?
    };

    config.dest = matches
        .value_of("destination")
        .or_else(|| global_matches.value_of("destination"))
        .map(str::to_string)
        .unwrap_or(config.dest);

    config.include_drafts = matches.is_present("drafts");

    if global_matches.is_present("dump") {
        let mut dump = values_t!(global_matches, "dump", Dump)?;
        config.dump.append(&mut dump);
        info!("Setting: {:?}", config.dump);
    }
    if matches.is_present("dump") {
        let mut dump = values_t!(matches, "dump", Dump)?;
        config.dump.append(&mut dump);
        info!("Setting: {:?}", config.dump);
    }

    match command {
        "init" => new::init_command(config, matches),
        "new" => new::new_command(config, matches),
        "build" => build::build_command(config, matches),
        "clean" => build::clean_command(config, matches),
        "serve" => serve::serve_command(config, matches),
        "watch" => serve::watch_command(config, matches),
        "import" => build::import_command(config, matches),
        "list-syntax-themes" => {
            for name in list_syntax_themes() {
                println!("{}", name);
            }
            Ok(())
        }
        "list-syntaxes" => {
            for name in list_syntaxes() {
                println!("{}", name);
            }
            Ok(())
        }
        "convert-jekyll" => {
            let source = matches.value_of("jksrc").unwrap().to_string();
            let dest = matches.value_of("jkdst").unwrap().to_string();
            jekyll::jk_document::convert_from_jk(std::path::Path::new(&source),
                                                 std::path::Path::new(&dest))
                .chain_err(|| "Jekyll conversion failed.")
        }
        _ => {
            bail!(global_matches.usage());
        }
    }.chain_err(|| format!("{} command failed", command))?;

    Ok(())
}
<|endoftext|>


<commit_before>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[crate_id="bloomfilter#0.1"];
#[crate_type = "rlib"];
#[warn(non_camel_case_types, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern crate collections;
extern crate rand;

use std::cmp;
use std::hash::Hash;
use std::num;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use collections::bitv;

#[cfg(test)]
use rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv sips: [SipHasher, ..2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let sip = self.sips[k_i];
            let hash = sip.hash(item);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::task_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<commit_msg>Use the new inner attribute syntax<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![desc = "A fast Bloom filter implementation."]
#![license = "BSD"]
#![crate_id="bloomfilter#0.1"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)]

extern crate collections;
extern crate rand;

use std::cmp;
use std::hash::Hash;
use std::num;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use collections::bitv;

#[cfg(test)]
use rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv sips: [SipHasher, ..2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let sip = self.sips[k_i];
            let hash = sip.hash(item);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::task_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<|endoftext|>


<commit_before>//! Allows a future or stream to execute for a maximum amount of time.
//!
//! See [`Timeout`] documentation for more details.
//!
//! [`Timeout`]: struct.Timeout.html

use crate::clock::now;
use crate::Delay;
#[cfg(feature = "async-traits")]
use futures_core::ready;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};
use std::time::{Duration, Instant};

/// Allows a `Future` or `Stream` to execute for a limited amount of time.
///
/// If the future or stream completes before the timeout has expired, then
/// `Timeout` returns the completed value. Otherwise, `Timeout` returns an
/// [`Error`].
///
/// # Futures and Streams
///
/// The exact behavor depends on if the inner value is a `Future` or a `Stream`.
/// In the case of a `Future`, `Timeout` will require the future to complete by
/// a fixed deadline. In the case of a `Stream`, `Timeout` will allow each item
/// to take the entire timeout before returning an error.
///
/// In order to set an upper bound on the processing of the *entire* stream,
/// then a timeout should be set on the future that processes the stream. For
/// example:
///
/// ```rust
/// // import the `timeout` function, usually this is done
/// // with `use tokio::prelude::*`
/// use tokio::prelude::FutureExt;
/// use futures::Stream;
/// use futures::sync::mpsc;
/// use std::time::Duration;
///
/// let (tx, rx) = mpsc::unbounded();
/// # tx.unbounded_send(()).unwrap();
/// # drop(tx);
///
/// let process = rx.for_each(|item| {
///     // do something with `item`
/// # drop(item);
/// # Ok(())
/// });
///
/// # tokio::runtime::current_thread::block_on_all(
/// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
/// process.timeout(Duration::from_millis(10))
/// # ).unwrap();
/// ```
///
/// # Cancelation
///
/// Cancelling a `Timeout` is done by dropping the value. No additional cleanup
/// or other work is required.
///
/// The original future or stream may be obtained by calling [`Timeout::into_inner`]. This
/// consumes the `Timeout`.
///
/// [`Error`]: struct.Error.html
/// [`Timeout::into_inner`]: struct.Timeout.html#method.into_iter
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Timeout<T> {
    value: T,
    delay: Delay,
}

/// Error returned by `Timeout`.
#[derive(Debug)]
pub struct Elapsed(());

impl<T> Timeout<T> {
    /// Create a new `Timeout` that allows `value` to execute for a duration of
    /// at most `timeout`.
    ///
    /// The exact behavior depends on if `value` is a `Future` or a `Stream`.
    ///
    /// See [type] level documentation for more details.
    ///
    /// [type]: #
    ///
    /// # Examples
    ///
    /// Create a new `Timeout` set to expire in 10 milliseconds.
    ///
    /// ```rust
    /// use tokio::timer::Timeout;
    /// use futures::Future;
    /// use futures::sync::oneshot;
    /// use std::time::Duration;
    ///
    /// let (tx, rx) = oneshot::channel();
    /// # tx.send(()).unwrap();
    ///
    /// # tokio::runtime::current_thread::block_on_all(
    /// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
    /// Timeout::new(rx, Duration::from_millis(10))
    /// # ).unwrap();
    /// ```
    pub fn new(value: T, timeout: Duration) -> Timeout<T> {
        let delay = Delay::new_timeout(now() + timeout, timeout);
        Timeout::new_with_delay(value, delay)
    }

    pub(crate) fn new_with_delay(value: T, delay: Delay) -> Timeout<T> {
        Timeout { value, delay }
    }

    /// Gets a reference to the underlying value in this timeout.
    pub fn get_ref(&self) -> &T {
        &self.value
    }

    /// Gets a mutable reference to the underlying value in this timeout.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.value
    }

    /// Consumes this timeout, returning the underlying value.
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T: Future> Timeout<T> {
    /// Create a new `Timeout` that completes when `future` completes or when
    /// `deadline` is reached.
    ///
    /// This function differs from `new` in that:
    ///
    /// * It only accepts `Future` arguments.
    /// * It sets an explicit `Instant` at which the timeout expires.
    pub fn new_at(future: T, deadline: Instant) -> Timeout<T> {
        let delay = Delay::new(deadline);

        Timeout {
            value: future,
            delay,
        }
    }
}

impl<T> Future for Timeout<T>
where
    T: Future,
{
    type Output = Result<T::Output, Elapsed>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // First, try polling the future

        // Safety: we never move `self.value`
        unsafe {
            let p = self.as_mut().map_unchecked_mut(|me| &mut me.value);
            if let Poll::Ready(v) = p.poll(cx) {
                return Poll::Ready(Ok(v));
            }
        }

        // Now check the timer
        // Safety: X_X!
        unsafe {
            match self.map_unchecked_mut(|me| &mut me.delay).poll(cx) {
                Poll::Ready(()) => Poll::Ready(Err(Elapsed(()))),
                Poll::Pending => Poll::Pending,
            }
        }
    }
}

#[cfg(feature = "async-traits")]
impl<T> futures_core::Stream for Timeout<T>
where
    T: futures_core::Stream,
{
    type Item = Result<T::Item, Elapsed>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
        // Safety: T might be !Unpin, but we never move neither `value`
        // nor `delay`.
        //
        // ... X_X
        unsafe {
            // First, try polling the future
            let v = self
                .as_mut()
                .map_unchecked_mut(|me| &mut me.value)
                .poll_next(cx);

            if let Poll::Ready(v) = v {
                if v.is_some() {
                    self.as_mut().get_unchecked_mut().delay.reset_timeout();
                }
                return Poll::Ready(v.map(Ok));
            }

            // Now check the timer
            ready!(self.as_mut().map_unchecked_mut(|me| &mut me.delay).poll(cx));

            // if delay was ready, timeout elapsed!
            self.as_mut().get_unchecked_mut().delay.reset_timeout();
            Poll::Ready(Some(Err(Elapsed(()))))
        }
    }
}

// ===== impl Elapsed =====

impl fmt::Display for Elapsed {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        "deadline has elapsed".fmt(fmt)
    }
}

impl std::error::Error for Elapsed {}
<commit_msg>timer: impl Into<std::io::Error> for Elpased (#1321)<commit_after>//! Allows a future or stream to execute for a maximum amount of time.
//!
//! See [`Timeout`] documentation for more details.
//!
//! [`Timeout`]: struct.Timeout.html

use crate::clock::now;
use crate::Delay;
#[cfg(feature = "async-traits")]
use futures_core::ready;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};
use std::time::{Duration, Instant};

/// Allows a `Future` or `Stream` to execute for a limited amount of time.
///
/// If the future or stream completes before the timeout has expired, then
/// `Timeout` returns the completed value. Otherwise, `Timeout` returns an
/// [`Error`].
///
/// # Futures and Streams
///
/// The exact behavor depends on if the inner value is a `Future` or a `Stream`.
/// In the case of a `Future`, `Timeout` will require the future to complete by
/// a fixed deadline. In the case of a `Stream`, `Timeout` will allow each item
/// to take the entire timeout before returning an error.
///
/// In order to set an upper bound on the processing of the *entire* stream,
/// then a timeout should be set on the future that processes the stream. For
/// example:
///
/// ```rust
/// // import the `timeout` function, usually this is done
/// // with `use tokio::prelude::*`
/// use tokio::prelude::FutureExt;
/// use futures::Stream;
/// use futures::sync::mpsc;
/// use std::time::Duration;
///
/// let (tx, rx) = mpsc::unbounded();
/// # tx.unbounded_send(()).unwrap();
/// # drop(tx);
///
/// let process = rx.for_each(|item| {
///     // do something with `item`
/// # drop(item);
/// # Ok(())
/// });
///
/// # tokio::runtime::current_thread::block_on_all(
/// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
/// process.timeout(Duration::from_millis(10))
/// # ).unwrap();
/// ```
///
/// # Cancelation
///
/// Cancelling a `Timeout` is done by dropping the value. No additional cleanup
/// or other work is required.
///
/// The original future or stream may be obtained by calling [`Timeout::into_inner`]. This
/// consumes the `Timeout`.
///
/// [`Error`]: struct.Error.html
/// [`Timeout::into_inner`]: struct.Timeout.html#method.into_iter
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Timeout<T> {
    value: T,
    delay: Delay,
}

/// Error returned by `Timeout`.
#[derive(Debug)]
pub struct Elapsed(());

impl<T> Timeout<T> {
    /// Create a new `Timeout` that allows `value` to execute for a duration of
    /// at most `timeout`.
    ///
    /// The exact behavior depends on if `value` is a `Future` or a `Stream`.
    ///
    /// See [type] level documentation for more details.
    ///
    /// [type]: #
    ///
    /// # Examples
    ///
    /// Create a new `Timeout` set to expire in 10 milliseconds.
    ///
    /// ```rust
    /// use tokio::timer::Timeout;
    /// use futures::Future;
    /// use futures::sync::oneshot;
    /// use std::time::Duration;
    ///
    /// let (tx, rx) = oneshot::channel();
    /// # tx.send(()).unwrap();
    ///
    /// # tokio::runtime::current_thread::block_on_all(
    /// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
    /// Timeout::new(rx, Duration::from_millis(10))
    /// # ).unwrap();
    /// ```
    pub fn new(value: T, timeout: Duration) -> Timeout<T> {
        let delay = Delay::new_timeout(now() + timeout, timeout);
        Timeout::new_with_delay(value, delay)
    }

    pub(crate) fn new_with_delay(value: T, delay: Delay) -> Timeout<T> {
        Timeout { value, delay }
    }

    /// Gets a reference to the underlying value in this timeout.
    pub fn get_ref(&self) -> &T {
        &self.value
    }

    /// Gets a mutable reference to the underlying value in this timeout.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.value
    }

    /// Consumes this timeout, returning the underlying value.
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T: Future> Timeout<T> {
    /// Create a new `Timeout` that completes when `future` completes or when
    /// `deadline` is reached.
    ///
    /// This function differs from `new` in that:
    ///
    /// * It only accepts `Future` arguments.
    /// * It sets an explicit `Instant` at which the timeout expires.
    pub fn new_at(future: T, deadline: Instant) -> Timeout<T> {
        let delay = Delay::new(deadline);

        Timeout {
            value: future,
            delay,
        }
    }
}

impl<T> Future for Timeout<T>
where
    T: Future,
{
    type Output = Result<T::Output, Elapsed>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // First, try polling the future

        // Safety: we never move `self.value`
        unsafe {
            let p = self.as_mut().map_unchecked_mut(|me| &mut me.value);
            if let Poll::Ready(v) = p.poll(cx) {
                return Poll::Ready(Ok(v));
            }
        }

        // Now check the timer
        // Safety: X_X!
        unsafe {
            match self.map_unchecked_mut(|me| &mut me.delay).poll(cx) {
                Poll::Ready(()) => Poll::Ready(Err(Elapsed(()))),
                Poll::Pending => Poll::Pending,
            }
        }
    }
}

#[cfg(feature = "async-traits")]
impl<T> futures_core::Stream for Timeout<T>
where
    T: futures_core::Stream,
{
    type Item = Result<T::Item, Elapsed>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
        // Safety: T might be !Unpin, but we never move neither `value`
        // nor `delay`.
        //
        // ... X_X
        unsafe {
            // First, try polling the future
            let v = self
                .as_mut()
                .map_unchecked_mut(|me| &mut me.value)
                .poll_next(cx);

            if let Poll::Ready(v) = v {
                if v.is_some() {
                    self.as_mut().get_unchecked_mut().delay.reset_timeout();
                }
                return Poll::Ready(v.map(Ok));
            }

            // Now check the timer
            ready!(self.as_mut().map_unchecked_mut(|me| &mut me.delay).poll(cx));

            // if delay was ready, timeout elapsed!
            self.as_mut().get_unchecked_mut().delay.reset_timeout();
            Poll::Ready(Some(Err(Elapsed(()))))
        }
    }
}

// ===== impl Elapsed =====

impl fmt::Display for Elapsed {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        "deadline has elapsed".fmt(fmt)
    }
}

impl std::error::Error for Elapsed {}

impl Into<std::io::Error> for Elapsed {
    fn into(self) -> std::io::Error {
        std::io::ErrorKind::TimedOut.into()
    }
}
<|endoftext|>


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

// https://leetcode.com/problems/number-of-people-aware-of-a-secret/
pub fn people_aware_of_secret(n: i32, delay: i32, forget: i32) -> i32 {
    let mut answer: i64 = if 1 + forget > n { 1 } else { 0 };
    let mut list: LinkedList<i32> = LinkedList::new();
    list.push_back(1);
    loop {
        let front = list.pop_front();
        match front {
            Some(day) => {
                if day > n {
                    break;
                }
                let secret_day = day + delay;
                for d in secret_day..(secret_day + (forget - delay)) {
                    if d > n {
                        break;
                    }
                    list.push_back(d);
                    if d + forget > n {
                        answer += 1;
                    }
                }
            }
            None => break,
        }
    }
    (answer % 1_000_000_007) as i32
}

fn main() {
    println!("{}", people_aware_of_secret(6, 2, 4)); // 5
    println!("{}", people_aware_of_secret(4, 1, 3)); // 6
    println!("{}", people_aware_of_secret(10, 3, 5)); // 5
    println!("{}", people_aware_of_secret(1000, 500, 600)); // 100
    println!("{}", people_aware_of_secret(100, 20, 30)); // 6775
    println!("{}", people_aware_of_secret(1000, 2, 1000)); // 517691607
}
<commit_msg>Solve problem 2327<commit_after>// https://leetcode.com/problems/number-of-people-aware-of-a-secret/
pub fn people_aware_of_secret(n: i32, delay: i32, forget: i32) -> i32 {
    fn f(n: i32, delay: i32, forget: i32, day: i32, memo: &mut Vec<Vec<i64>>) -> i64 {
        if day > n {
            return 0;
        }
        let secret_day = day + delay;
        if memo[n as usize][secret_day as usize] != -1 {
            return memo[n as usize][secret_day as usize];
        }
        let mut sum: i64 = if day + forget <= n { 0 } else { 1 };
        for d in secret_day..(secret_day + (forget - delay)) {
            sum += f(n, delay, forget, d, memo) % 1_000_000_007;
        }
        memo[n as usize][secret_day as usize] = sum;
        sum
    }

    let mut memo = vec![vec![-1i64; (n + delay + 1) as usize]; (n + delay + 1) as usize];
    (f(n, delay, forget, 1, &mut memo) % 1_000_000_007) as i32
}

fn main() {
    println!("{}", people_aware_of_secret(6, 2, 4)); // 5
    println!("{}", people_aware_of_secret(4, 1, 3)); // 6
    println!("{}", people_aware_of_secret(10, 3, 5)); // 5
    println!("{}", people_aware_of_secret(10, 2, 4)); // 14
    println!("{}", people_aware_of_secret(1000, 500, 600)); // 100
    println!("{}", people_aware_of_secret(100, 20, 30)); // 6775
    println!("{}", people_aware_of_secret(1000, 2, 1000)); // 517691607
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/number-of-distinct-averages/
pub fn distinct_averages(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", distinct_averages(vec![4, 1, 4, 0, 3, 5])); // 2
    println!("{}", distinct_averages(vec![1, 100])); // 1
}
<commit_msg>Solve problem 2465<commit_after>use std::collections::HashSet;

// https://leetcode.com/problems/number-of-distinct-averages/
pub fn distinct_averages(mut nums: Vec<i32>) -> i32 {
    nums.sort();
    let mut set: HashSet<String> = HashSet::new();
    let mut i = 0;
    let mut j = nums.len() - 1;
    while i < j {
        let average = (nums[i] + nums[j]) as f32 / 2 as f32;
        set.insert(format!("{}", average));
        i += 1;
        j -= 1;
    }
    set.len() as i32
}

fn main() {
    println!("{}", distinct_averages(vec![4, 1, 4, 0, 3, 5])); // 2
    println!("{}", distinct_averages(vec![1, 100])); // 1
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
    #[inline]
    pub fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

pub fn minimum_operations(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
    todo!()
}

fn main() {}
<commit_msg>Update problem 2471<commit_after>// https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
    #[inline]
    pub fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

pub fn minimum_operations(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
    todo!()
}

fn main() {
    fn create_node(value: i32) -> Option<Rc<RefCell<TreeNode>>> {
        Some(Rc::new(RefCell::new(TreeNode::new(value))))
    }

    fn add_left(
        parent: &Option<Rc<RefCell<TreeNode>>>,
        value: i32,
    ) -> Option<Rc<RefCell<TreeNode>>> {
        parent.as_ref().unwrap().as_ref().borrow_mut().left = create_node(value);
        parent.as_ref().unwrap().as_ref().borrow().left.clone()
    }

    fn add_right(
        parent: &Option<Rc<RefCell<TreeNode>>>,
        value: i32,
    ) -> Option<Rc<RefCell<TreeNode>>> {
        parent.as_ref().unwrap().as_ref().borrow_mut().right = create_node(value);
        parent.as_ref().unwrap().as_ref().borrow().right.clone()
    }

    fn to_tree(nodes: Vec<Option<i32>>) -> Option<Rc<RefCell<TreeNode>>> {
        let mut deque: VecDeque<Option<Rc<RefCell<TreeNode>>>> = VecDeque::new();
        let root = create_node(nodes[0].unwrap());
        deque.push_back(root.clone());
        let mut i = 1;
        while i < nodes.len() {
            let parent = deque.pop_front().unwrap();
            let mut has_left = false;
            if let Some(left) = nodes[i] {
                deque.push_back(add_left(&parent, left));
                has_left = true;
            }
            let mut has_right = false;
            if i + 1 < nodes.len() {
                if let Some(right) = nodes[i + 1] {
                    deque.push_back(add_right(&parent, right));
                    has_right = true;
                }
            }
            if !has_left && !has_right {
                deque.push_back(parent);
            }
            i += 2;
        }
        root
    }

    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(4),
            Some(3),
            Some(7),
            Some(6),
            Some(8),
            Some(5),
            None,
            None,
            None,
            None,
            Some(9),
            None,
            Some(10)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(3),
            Some(2),
            Some(7),
            Some(6),
            Some(5),
            Some(4)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(4),
            Some(5),
            Some(6)
        ]))
    ); // 0
}
<|endoftext|>


<commit_before>use std::fmt::Display;
use std::io::{Result, Write};

use analysis::general::StatusedTypeId;
use analysis::imports::Imports;
use config::Config;
use git::repo_hash;
use gir_version::VERSION;
use version::Version;
use writer::primitives::tabs;

pub fn start_comments(w: &mut Write, conf: &Config) -> Result<()>{
    try!(writeln!(w, "// This file was generated by gir ({}) from gir-files ({})",
            VERSION, repo_hash(&conf.girs_dir).unwrap_or_else(|_| "???".into())));
    try!(writeln!(w, "// DO NOT EDIT"));

    Ok(())
}

pub fn uses(w: &mut Write, imports: &Imports, min_cfg_version: Version)
        -> Result<()>{
    try!(writeln!(w, ""));
    for (name, version) in imports.iter() {
        try!(version_condition(w, min_cfg_version, version.clone(), false, 0));
        try!(writeln!(w, "use {};", name));
    }

    Ok(())
}

pub fn define_object_type(w: &mut Write, type_name: &str, glib_name: &str,
        glib_func_name: &str, parents: &[&StatusedTypeId]) -> Result<()> {
    //TODO: don't generate for parents without traits
    let parents: Vec<&str> = parents.iter()
        .filter(|p| !p.status.ignored())
        .map(|p| &p.name[..])
        .collect();

    try!(writeln!(w, ""));
    try!(writeln!(w, "glib_wrapper! {{"));
    if parents.is_empty() {
        try!(writeln!(w, "\tpub struct {}(Object<ffi::{}>);", type_name, glib_name));
    }
    else {
        try!(writeln!(w, "\tpub struct {}(Object<ffi::{}>): {};", type_name, glib_name,
            parents.join(", ")));
    }
    try!(writeln!(w, ""));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tget_type => || ffi::{}(),", glib_func_name));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_boxed_type(w: &mut Write, type_name: &str, glib_name: &str,
                                copy_fn: &str, free_fn: &str) -> Result<()>{
    try!(writeln!(w, ""));
    try!(writeln!(w, "glib_wrapper! {{"));
    try!(writeln!(w, "\tpub struct {}(Boxed<ffi::{}>);", type_name, glib_name));
    try!(writeln!(w, ""));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tcopy => |ptr| ffi::{}(mut_override(ptr)),", copy_fn));
    try!(writeln!(w, "\t\tfree => |ptr| ffi::{}(ptr),", free_fn));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn version_condition(w: &mut Write, min_cfg_version: Version,
        version: Option<Version>, commented: bool, indent: usize) -> Result<()> {
    let s = version_condition_string(min_cfg_version, version, commented, indent);
    if let Some(s) = s {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn version_condition_string(min_cfg_version: Version,
        version: Option<Version>, commented: bool, indent: usize) -> Option<String> {
    match version {
        Some(v) if v >= min_cfg_version => {
            let comment = if commented { "//" } else { "" };
            Some(format!("{}{}#[cfg({})]", tabs(indent), comment, v.to_cfg()))
        }
        _ => None
    }
}

pub fn cfg_condition(w: &mut Write, cfg_condition: &Option<String>, commented: bool, indent: usize)
                     -> Result<()> {
    let s = cfg_condition_string(cfg_condition, commented, indent);
    if let Some(s) = s {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_condition_string(cfg_condition: &Option<String>, commented: bool, indent: usize)
                            -> Option<String> {
    match cfg_condition.as_ref() {
        Some(v) => {
            let comment = if commented { "//" } else { "" };
            Some(format!("{}{}#[cfg({})]", tabs(indent), comment, v))
        }
        None => None,
    }
}

pub fn write_vec<T: Display>(w: &mut Write, v: &[T]) -> Result<()> {
    for s in v {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}
<commit_msg>Don't emit version cfgs for the minimal supported version<commit_after>use std::fmt::Display;
use std::io::{Result, Write};

use analysis::general::StatusedTypeId;
use analysis::imports::Imports;
use config::Config;
use git::repo_hash;
use gir_version::VERSION;
use version::Version;
use writer::primitives::tabs;

pub fn start_comments(w: &mut Write, conf: &Config) -> Result<()>{
    try!(writeln!(w, "// This file was generated by gir ({}) from gir-files ({})",
            VERSION, repo_hash(&conf.girs_dir).unwrap_or_else(|_| "???".into())));
    try!(writeln!(w, "// DO NOT EDIT"));

    Ok(())
}

pub fn uses(w: &mut Write, imports: &Imports, min_cfg_version: Version)
        -> Result<()>{
    try!(writeln!(w, ""));
    for (name, version) in imports.iter() {
        try!(version_condition(w, min_cfg_version, version.clone(), false, 0));
        try!(writeln!(w, "use {};", name));
    }

    Ok(())
}

pub fn define_object_type(w: &mut Write, type_name: &str, glib_name: &str,
        glib_func_name: &str, parents: &[&StatusedTypeId]) -> Result<()> {
    //TODO: don't generate for parents without traits
    let parents: Vec<&str> = parents.iter()
        .filter(|p| !p.status.ignored())
        .map(|p| &p.name[..])
        .collect();

    try!(writeln!(w, ""));
    try!(writeln!(w, "glib_wrapper! {{"));
    if parents.is_empty() {
        try!(writeln!(w, "\tpub struct {}(Object<ffi::{}>);", type_name, glib_name));
    }
    else {
        try!(writeln!(w, "\tpub struct {}(Object<ffi::{}>): {};", type_name, glib_name,
            parents.join(", ")));
    }
    try!(writeln!(w, ""));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tget_type => || ffi::{}(),", glib_func_name));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_boxed_type(w: &mut Write, type_name: &str, glib_name: &str,
                                copy_fn: &str, free_fn: &str) -> Result<()>{
    try!(writeln!(w, ""));
    try!(writeln!(w, "glib_wrapper! {{"));
    try!(writeln!(w, "\tpub struct {}(Boxed<ffi::{}>);", type_name, glib_name));
    try!(writeln!(w, ""));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tcopy => |ptr| ffi::{}(mut_override(ptr)),", copy_fn));
    try!(writeln!(w, "\t\tfree => |ptr| ffi::{}(ptr),", free_fn));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn version_condition(w: &mut Write, min_cfg_version: Version,
        version: Option<Version>, commented: bool, indent: usize) -> Result<()> {
    let s = version_condition_string(min_cfg_version, version, commented, indent);
    if let Some(s) = s {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn version_condition_string(min_cfg_version: Version,
        version: Option<Version>, commented: bool, indent: usize) -> Option<String> {
    match version {
        Some(v) if v > min_cfg_version => {
            let comment = if commented { "//" } else { "" };
            Some(format!("{}{}#[cfg({})]", tabs(indent), comment, v.to_cfg()))
        }
        _ => None
    }
}

pub fn cfg_condition(w: &mut Write, cfg_condition: &Option<String>, commented: bool, indent: usize)
                     -> Result<()> {
    let s = cfg_condition_string(cfg_condition, commented, indent);
    if let Some(s) = s {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_condition_string(cfg_condition: &Option<String>, commented: bool, indent: usize)
                            -> Option<String> {
    match cfg_condition.as_ref() {
        Some(v) => {
            let comment = if commented { "//" } else { "" };
            Some(format!("{}{}#[cfg({})]", tabs(indent), comment, v))
        }
        None => None,
    }
}

pub fn write_vec<T: Display>(w: &mut Write, v: &[T]) -> Result<()> {
    for s in v {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}
<|endoftext|>