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

use ::chrono::prelude::*;
use ::chrono::Duration;
use ::chrono_english::*;
use ::structopt::clap::Shell;
use ::structopt::StructOpt;

#[derive(StructOpt, Debug)]
pub enum SubCommand {
    /// Enqueue a task for execution.
    Add {
        /// The command that should be added.
        command: Vec<String>,

        /// Start the task immediately.
        #[structopt(name = "immediate", short, long, conflicts_with = "stash")]
        start_immediately: bool,

        /// Create the task in stashed state.
        /// Useful to avoid immediate execution if the queue is empty.
        #[structopt(name = "stashed", short, long, conflicts_with = "immediate")]
        stashed: bool,

        /// Delays enqueueing the task until <delay> elapses. See enqueue for accepted formats.
        #[structopt(name = "delay", short, long, conflicts_with = "immediate", parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,

        /// Assign the task to a group. Groups kind of act as separate queues.
        /// I.e. all groups run in parallel and you can specify the amount of parallel tasks for each group.
        /// If no group is specified, the default group will be used.
        #[structopt(name = "group", short, long)]
        group: Option<String>,

        /// Start the task once all specified tasks have successfully finished.
        /// As soon as one of the dependencies fails, this task will fail as well.
        #[structopt(name = "after", short, long)]
        dependencies: Vec<usize>,
    },
    /// Remove tasks from the list.
    /// Running or paused tasks need to be killed first.
    Remove {
        /// The task ids to be removed.
        #[structopt(required = true)]
        task_ids: Vec<usize>,
    },
    /// Switches the queue position of two commands. Only works on queued and stashed commands.
    Switch {
        /// The first task id.
        task_id_1: usize,
        /// The second task id.
        task_id_2: usize,
    },
    /// Stashed tasks won't be automatically started.
    /// Either `enqueue` them, to be normally handled or explicitly `start` them.
    Stash {
        /// The id(s) of the tasks you want to stash.
        #[structopt(required = true)]
        task_ids: Vec<usize>,
    },
    /// Enqueue stashed tasks. They'll be handled normally afterwards.
    #[structopt(after_help = "DELAY FORMAT:

    The --delay argument must be either a number of seconds or a \"date expression\" similar to GNU \
    `date -d` with some extensions. It does not attempt to parse all natural language, but is \
    incredibly flexible. Here are some supported examples.

    2020-04-01T18:30:00   // RFC 3339 timestamp
    2020-4-1 18:2:30      // Optional leading zeros
    2020-4-1 5:30pm       // Informal am/pm time
    2020-4-1 5pm          // Optional minutes and seconds
    April 1 2020 18:30:00 // English months
    1 Apr 8:30pm          // Implies current year
    4/1                   // American form date
    wednesday 10:30pm     // The closest wednesday in the future at 22:30
    wednesday             // The closest wednesday in the future
    4 months              // 4 months from today at 00:00:00
    1 week                // 1 week at the current time
    1days                 // 1 day from today at the current time
    1d 03:00              // The closest 3:00 after 1 day (24 hours)
    3h                    // 3 hours from now
    3600s                 // 3600 seconds from now
")]
    Enqueue {
        /// The id(s) of the tasks you want to enqueue.
        task_ids: Vec<usize>,

        /// Delay enqueuing the tasks until <delay> elapses. See DELAY FORMAT below.
        #[structopt(name = "delay", short, long, parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,
    },

    /// Resume operation of specific tasks or groups of tasks.
    /// By default, this resumes the default queue and all it's tasks.
    /// Can also be used force specific tasks to start.
    #[structopt(verbatim_doc_comment)]
    Start {
        /// Enforce starting these tasks. Paused tasks will be started again.
        /// This doesn't affect anything other than these tasks.
        task_ids: Vec<usize>,

        /// Start a specific group and all paused tasks in it.
        #[structopt(short, long, group("start"))]
        group: Option<String>,

        /// Start a everything (Default queue and all groups)!
        /// All groups will be set to `running` and all paused tasks will be resumed.
        #[structopt(short, long, group("start"))]
        all: bool,

        /// Also resume direct child processes of your paused tasks.
        /// By default only the main process will get a SIGSTART.
        #[structopt(short, long, group("start"))]
        children: bool,
    },

    /// Restart task(s).
    /// Identical tasks will be created and by defualt enqueued.
    Restart {
        /// The tasks you want to restart.
        #[structopt(required = true)]
        task_ids: Vec<usize>,

        /// Immediately start the task(s).
        #[structopt(name = "immediate", short, long)]
        start_immediately: bool,

        /// Create the task in stashed state.
        /// Useful to avoid immediate execution.
        #[structopt(short, long, conflicts_with = "immediate")]
        stashed: bool,

        /// Edit the command of the task before restarting
        #[structopt(short, long)]
        edit: bool,

        /// Edit the path of the task before restarting
        #[structopt(short, long)]
        path: bool,
    },

    /// Pause either running tasks or specific groups of tasks.
    /// By default, pauses the default queue and all it's tasks.
    /// A paused queue (group) won't start any new tasks.
    /// Everything can be resumed with `start`.
    #[structopt(verbatim_doc_comment)]
    Pause {
        /// Pause these specific tasks.
        /// Doesn't affect the default queue, groups or any other tasks.
        task_ids: Vec<usize>,

        /// Pause a specific group.
        #[structopt(short, long, group("pause"))]
        group: Option<String>,

        /// Pause everything (Default queue and all groups)!
        #[structopt(short, long, group("pause"))]
        all: bool,

        /// Don't pause already running tasks and let them finish by themselves,
        ///  when pausing with `default`, `all` or `group`.
        #[structopt(short, long, group("pause"))]
        wait: bool,

        /// Also pause direct child processes of a task's main process.
        /// By default only the main process will get a SIGSTOP.
        /// This is useful when calling bash scripts, which start other processes themselves.
        /// This operation is not recursive!
        #[structopt(short, long, group("pause"))]
        children: bool,
    },

    /// Kill specific running tasks or various groups of tasks.
    Kill {
        /// The tasks that should be killed.
        task_ids: Vec<usize>,

        /// Kill all running tasks in the default queue. Pause the default queue.
        #[structopt(short, long, group("kill"))]
        default: bool,

        /// Kill all running in a group. Pauses the group.
        #[structopt(short, long, group("kill"))]
        group: Option<String>,

        /// Kill ALL running tasks. This also pauses everything
        #[structopt(short, long, group("kill"))]
        all: bool,

        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[structopt(short, long, group("kill"))]
        children: bool,
    },

    /// Send something to a task. Useful for sending confirmations such as 'y\n'.
    Send {
        /// The id of the task.
        task_id: usize,

        /// The input that should be sent to the process.
        input: String,
    },

    /// Edit the command or path of a stashed or queued task.
    /// This edits the command of the task by default.
    #[structopt(verbatim_doc_comment)]
    Edit {
        /// The id of the task.
        task_id: usize,

        /// Edit the path of the task.
        #[structopt(short, long)]
        path: bool,
    },

    /// Manage groups.
    /// By default, this will simply display all known groups.
    Group {
        /// Add a group
        #[structopt(short, long)]
        add: Option<String>,

        /// Remove a group.
        /// This will move all tasks in this group to the default group!
        #[structopt(short, long)]
        remove: Option<String>,
    },

    /// Display the current status of all tasks.
    Status {
        /// Print the current state as json to stdout.
        /// This doesn't include stdout/stderr of tasks.
        /// Use `log -j` if you want everything.
        #[structopt(short, long)]
        json: bool,

        #[structopt(short, long)]
        /// Only show tasks of a specific group
        group: Option<String>,
    },

    /// Display the log output of finished tasks.
    /// Prints either all logs or only the logs of specified tasks.
    Log {
        /// Specify for which specific tasks you want to see the output.
        task_ids: Vec<usize>,
        /// Print the current state as json.
        /// Includes EVERYTHING.
        #[structopt(short, long)]
        json: bool,
    },

    /// Follow the output of a currently running task.
    /// This command works like `tail -f`.
    Follow {
        /// The id of the task you want to watch.
        /// If no or multiple tasks are running, you have to specify the id.
        /// If only a single task is running, you can omit the id.
        task_id: Option<usize>,

        /// Show stderr instead of stdout.
        #[structopt(short, long)]
        err: bool,
    },

    /// Remove all finished tasks from the list (also clears logs).
    Clean,

    /// Kill all running tasks, remove all tasks and reset max_task_id.
    Reset {
        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[structopt(short, long)]
        children: bool,
    },

    /// Remotely shut down the daemon. Should only be used if the daemon isn't started by a service manager.
    Shutdown,

    /// Set the amount of allowed parallel tasks.
    Parallel {
        /// The amount of allowed parallel tasks.
        #[structopt(validator=min_one)]
        parallel_tasks: usize,

        /// Specify the amount of parallel tasks for a group.
        #[structopt(name = "group", short, long)]
        group: Option<String>,
    },

    /// Generates shell completion files.
    /// This can be ignored during normal operations.
    Completions {
        /// The target shell. Can be `bash`, `fish`, `powershell`, `elvish` and `zsh`.
        shell: Shell,
        /// The output directory to which the file should be written.
        output_directory: PathBuf,
    },
}

#[derive(StructOpt, Debug)]
#[structopt(
    name = "Pueue client",
    about = "Interact with the Pueue daemon",
    author = "Arne Beer <contact@arne.beer>"
)]
pub struct Opt {
    // The number of occurrences of the `v/verbose` flag.
    /// Verbose mode (-v, -vv, -vvv)
    #[structopt(short, long, parse(from_occurrences))]
    pub verbose: u8,

    //    /// The url for the daemon. Overwrites the address in the config file
    //    #[structopt(short, long)]
    //    pub address: Option<String>,
    /// The port for the daemon. Overwrites the port in the config file.
    #[structopt(short, long)]
    pub port: Option<String>,

    #[structopt(subcommand)]
    pub cmd: SubCommand,
}

fn parse_delay_until(src: &str) -> Result<DateTime<Local>, String> {
    if let Ok(seconds) = src.parse::<i64>() {
        let delay_until = Local::now() + Duration::seconds(seconds);
        return Ok(delay_until);
    }

    if let Ok(date_time) = parse_date_string(src, Local::now(), Dialect::Us) {
        return Ok(date_time);
    }

    Err(String::from(
        "could not parse as seconds or date expression",
    ))
}

/// Validator function. The input string has to be parsable as int and bigger than 0
fn min_one(value: String) -> Result<(), String> {
    match value.parse::<usize>() {
        Ok(value) => {
            if value < 1 {
                return Err("You must provide a value that's bigger than 0".into());
            }
            Ok(())
        }
        Err(_) => Err("Failed to parse integer".into()),
    }
}
<commit_msg>Fix typo<commit_after>use std::path::PathBuf;

use ::chrono::prelude::*;
use ::chrono::Duration;
use ::chrono_english::*;
use ::structopt::clap::Shell;
use ::structopt::StructOpt;

#[derive(StructOpt, Debug)]
pub enum SubCommand {
    /// Enqueue a task for execution.
    Add {
        /// The command that should be added.
        command: Vec<String>,

        /// Start the task immediately.
        #[structopt(name = "immediate", short, long, conflicts_with = "stash")]
        start_immediately: bool,

        /// Create the task in stashed state.
        /// Useful to avoid immediate execution if the queue is empty.
        #[structopt(name = "stashed", short, long, conflicts_with = "immediate")]
        stashed: bool,

        /// Delays enqueueing the task until <delay> elapses. See enqueue for accepted formats.
        #[structopt(name = "delay", short, long, conflicts_with = "immediate", parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,

        /// Assign the task to a group. Groups kind of act as separate queues.
        /// I.e. all groups run in parallel and you can specify the amount of parallel tasks for each group.
        /// If no group is specified, the default group will be used.
        #[structopt(name = "group", short, long)]
        group: Option<String>,

        /// Start the task once all specified tasks have successfully finished.
        /// As soon as one of the dependencies fails, this task will fail as well.
        #[structopt(name = "after", short, long)]
        dependencies: Vec<usize>,
    },
    /// Remove tasks from the list.
    /// Running or paused tasks need to be killed first.
    Remove {
        /// The task ids to be removed.
        #[structopt(required = true)]
        task_ids: Vec<usize>,
    },
    /// Switches the queue position of two commands. Only works on queued and stashed commands.
    Switch {
        /// The first task id.
        task_id_1: usize,
        /// The second task id.
        task_id_2: usize,
    },
    /// Stashed tasks won't be automatically started.
    /// Either `enqueue` them, to be normally handled or explicitly `start` them.
    Stash {
        /// The id(s) of the tasks you want to stash.
        #[structopt(required = true)]
        task_ids: Vec<usize>,
    },
    /// Enqueue stashed tasks. They'll be handled normally afterwards.
    #[structopt(after_help = "DELAY FORMAT:

    The --delay argument must be either a number of seconds or a \"date expression\" similar to GNU \
    `date -d` with some extensions. It does not attempt to parse all natural language, but is \
    incredibly flexible. Here are some supported examples.

    2020-04-01T18:30:00   // RFC 3339 timestamp
    2020-4-1 18:2:30      // Optional leading zeros
    2020-4-1 5:30pm       // Informal am/pm time
    2020-4-1 5pm          // Optional minutes and seconds
    April 1 2020 18:30:00 // English months
    1 Apr 8:30pm          // Implies current year
    4/1                   // American form date
    wednesday 10:30pm     // The closest wednesday in the future at 22:30
    wednesday             // The closest wednesday in the future
    4 months              // 4 months from today at 00:00:00
    1 week                // 1 week at the current time
    1days                 // 1 day from today at the current time
    1d 03:00              // The closest 3:00 after 1 day (24 hours)
    3h                    // 3 hours from now
    3600s                 // 3600 seconds from now
")]
    Enqueue {
        /// The id(s) of the tasks you want to enqueue.
        task_ids: Vec<usize>,

        /// Delay enqueuing the tasks until <delay> elapses. See DELAY FORMAT below.
        #[structopt(name = "delay", short, long, parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,
    },

    /// Resume operation of specific tasks or groups of tasks.
    /// By default, this resumes the default queue and all it's tasks.
    /// Can also be used force specific tasks to start.
    #[structopt(verbatim_doc_comment)]
    Start {
        /// Enforce starting these tasks. Paused tasks will be started again.
        /// This doesn't affect anything other than these tasks.
        task_ids: Vec<usize>,

        /// Start a specific group and all paused tasks in it.
        #[structopt(short, long, group("start"))]
        group: Option<String>,

        /// Start a everything (Default queue and all groups)!
        /// All groups will be set to `running` and all paused tasks will be resumed.
        #[structopt(short, long, group("start"))]
        all: bool,

        /// Also resume direct child processes of your paused tasks.
        /// By default only the main process will get a SIGSTART.
        #[structopt(short, long, group("start"))]
        children: bool,
    },

    /// Restart task(s).
    /// Identical tasks will be created and by default enqueued.
    Restart {
        /// The tasks you want to restart.
        #[structopt(required = true)]
        task_ids: Vec<usize>,

        /// Immediately start the task(s).
        #[structopt(name = "immediate", short, long)]
        start_immediately: bool,

        /// Create the task in stashed state.
        /// Useful to avoid immediate execution.
        #[structopt(short, long, conflicts_with = "immediate")]
        stashed: bool,

        /// Edit the command of the task before restarting
        #[structopt(short, long)]
        edit: bool,

        /// Edit the path of the task before restarting
        #[structopt(short, long)]
        path: bool,
    },

    /// Pause either running tasks or specific groups of tasks.
    /// By default, pauses the default queue and all it's tasks.
    /// A paused queue (group) won't start any new tasks.
    /// Everything can be resumed with `start`.
    #[structopt(verbatim_doc_comment)]
    Pause {
        /// Pause these specific tasks.
        /// Doesn't affect the default queue, groups or any other tasks.
        task_ids: Vec<usize>,

        /// Pause a specific group.
        #[structopt(short, long, group("pause"))]
        group: Option<String>,

        /// Pause everything (Default queue and all groups)!
        #[structopt(short, long, group("pause"))]
        all: bool,

        /// Don't pause already running tasks and let them finish by themselves,
        ///  when pausing with `default`, `all` or `group`.
        #[structopt(short, long, group("pause"))]
        wait: bool,

        /// Also pause direct child processes of a task's main process.
        /// By default only the main process will get a SIGSTOP.
        /// This is useful when calling bash scripts, which start other processes themselves.
        /// This operation is not recursive!
        #[structopt(short, long, group("pause"))]
        children: bool,
    },

    /// Kill specific running tasks or various groups of tasks.
    Kill {
        /// The tasks that should be killed.
        task_ids: Vec<usize>,

        /// Kill all running tasks in the default queue. Pause the default queue.
        #[structopt(short, long, group("kill"))]
        default: bool,

        /// Kill all running in a group. Pauses the group.
        #[structopt(short, long, group("kill"))]
        group: Option<String>,

        /// Kill ALL running tasks. This also pauses everything
        #[structopt(short, long, group("kill"))]
        all: bool,

        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[structopt(short, long, group("kill"))]
        children: bool,
    },

    /// Send something to a task. Useful for sending confirmations such as 'y\n'.
    Send {
        /// The id of the task.
        task_id: usize,

        /// The input that should be sent to the process.
        input: String,
    },

    /// Edit the command or path of a stashed or queued task.
    /// This edits the command of the task by default.
    #[structopt(verbatim_doc_comment)]
    Edit {
        /// The id of the task.
        task_id: usize,

        /// Edit the path of the task.
        #[structopt(short, long)]
        path: bool,
    },

    /// Manage groups.
    /// By default, this will simply display all known groups.
    Group {
        /// Add a group
        #[structopt(short, long)]
        add: Option<String>,

        /// Remove a group.
        /// This will move all tasks in this group to the default group!
        #[structopt(short, long)]
        remove: Option<String>,
    },

    /// Display the current status of all tasks.
    Status {
        /// Print the current state as json to stdout.
        /// This doesn't include stdout/stderr of tasks.
        /// Use `log -j` if you want everything.
        #[structopt(short, long)]
        json: bool,

        #[structopt(short, long)]
        /// Only show tasks of a specific group
        group: Option<String>,
    },

    /// Display the log output of finished tasks.
    /// Prints either all logs or only the logs of specified tasks.
    Log {
        /// Specify for which specific tasks you want to see the output.
        task_ids: Vec<usize>,
        /// Print the current state as json.
        /// Includes EVERYTHING.
        #[structopt(short, long)]
        json: bool,
    },

    /// Follow the output of a currently running task.
    /// This command works like `tail -f`.
    Follow {
        /// The id of the task you want to watch.
        /// If no or multiple tasks are running, you have to specify the id.
        /// If only a single task is running, you can omit the id.
        task_id: Option<usize>,

        /// Show stderr instead of stdout.
        #[structopt(short, long)]
        err: bool,
    },

    /// Remove all finished tasks from the list (also clears logs).
    Clean,

    /// Kill all running tasks, remove all tasks and reset max_task_id.
    Reset {
        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[structopt(short, long)]
        children: bool,
    },

    /// Remotely shut down the daemon. Should only be used if the daemon isn't started by a service manager.
    Shutdown,

    /// Set the amount of allowed parallel tasks.
    Parallel {
        /// The amount of allowed parallel tasks.
        #[structopt(validator=min_one)]
        parallel_tasks: usize,

        /// Specify the amount of parallel tasks for a group.
        #[structopt(name = "group", short, long)]
        group: Option<String>,
    },

    /// Generates shell completion files.
    /// This can be ignored during normal operations.
    Completions {
        /// The target shell. Can be `bash`, `fish`, `powershell`, `elvish` and `zsh`.
        shell: Shell,
        /// The output directory to which the file should be written.
        output_directory: PathBuf,
    },
}

#[derive(StructOpt, Debug)]
#[structopt(
    name = "Pueue client",
    about = "Interact with the Pueue daemon",
    author = "Arne Beer <contact@arne.beer>"
)]
pub struct Opt {
    // The number of occurrences of the `v/verbose` flag.
    /// Verbose mode (-v, -vv, -vvv)
    #[structopt(short, long, parse(from_occurrences))]
    pub verbose: u8,

    //    /// The url for the daemon. Overwrites the address in the config file
    //    #[structopt(short, long)]
    //    pub address: Option<String>,
    /// The port for the daemon. Overwrites the port in the config file.
    #[structopt(short, long)]
    pub port: Option<String>,

    #[structopt(subcommand)]
    pub cmd: SubCommand,
}

fn parse_delay_until(src: &str) -> Result<DateTime<Local>, String> {
    if let Ok(seconds) = src.parse::<i64>() {
        let delay_until = Local::now() + Duration::seconds(seconds);
        return Ok(delay_until);
    }

    if let Ok(date_time) = parse_date_string(src, Local::now(), Dialect::Us) {
        return Ok(date_time);
    }

    Err(String::from(
        "could not parse as seconds or date expression",
    ))
}

/// Validator function. The input string has to be parsable as int and bigger than 0
fn min_one(value: String) -> Result<(), String> {
    match value.parse::<usize>() {
        Ok(value) => {
            if value < 1 {
                return Err("You must provide a value that's bigger than 0".into());
            }
            Ok(())
        }
        Err(_) => Err("Failed to parse integer".into()),
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/tokio-macros/0.3.1")]
#![allow(clippy::needless_doctest_main)]
#![warn(
    missing_debug_implementations,
    missing_docs,
    rust_2018_idioms,
    unreachable_pub
)]
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]

//! Macros for use with Tokio

// This `extern` is required for older `rustc` versions but newer `rustc`
// versions warn about the unused `extern crate`.
#[allow(unused_extern_crates)]
extern crate proc_macro;

mod entry;
mod select;

use proc_macro::TokenStream;

/// Marks async function to be executed by the selected runtime. This macro helps
/// set up a `Runtime` without requiring the user to use
/// [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.Builder.html) directly.
///
/// Note: This macro is designed to be simplistic and targets applications that
/// do not require a complex setup. If the provided functionality is not
/// sufficient, you may be interested in using
/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
/// powerful interface.
///
/// # Multi-threaded runtime
///
/// To use the multi-threaded runtime, the macro can be configured using
///
/// ```
/// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
/// # async fn main() {}
/// ```
///
/// The `worker_threads` option configures the number of worker threads, and
/// defaults to the number of cpus on the system. This is the default flavor.
///
/// # Current thread runtime
///
/// To use the single-threaded runtime known as the `current_thread` runtime,
/// the macro can be configured using
///
/// ```
/// #[tokio::main(flavor = "current_thread")]
/// # async fn main() {}
/// ```
///
/// ## Function arguments:
///
/// Arguments are allowed for any functions aside from `main` which is special
///
/// ## Usage
///
/// ### Using the multi-thread runtime
///
/// ```rust
/// #[tokio::main]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_multi_thread()
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### Using current thread runtime
///
/// The basic scheduler is single-threaded.
///
/// ```rust
/// #[tokio::main(flavor = "current_thread")]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_current_thread()
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### Set number of worker threads
///
/// ```rust
/// #[tokio::main(worker_threads = 2)]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_multi_thread()
///         .worker_threads(2)
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro will not work.
/// If you must rename the 0.3 version of tokio because you're also using the
/// 0.1 version of tokio, you _must_ make the tokio 0.3 crate available as
/// `tokio` in the module where this macro is expanded.
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::main(args, item, true)
}

/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.builder.html) directly.
///
/// ## Function arguments:
///
/// Arguments are allowed for any functions aside from `main` which is special
///
/// ## Usage
///
/// ### Using default
///
/// ```rust
/// #[tokio::main(flavor = "current_thread")]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_current_thread()
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro
/// will not work. If you must rename the 0.3 version of tokio because
/// you're also using the 0.1 version of tokio, you _must_ make the
/// tokio 0.3 crate available as `tokio` in the module where this
/// macro is expanded.
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::main(args, item, false)
}

/// Marks async function to be executed by runtime, suitable to test environment
///
/// ## Usage
///
/// ### Multi-thread runtime
///
/// ```no_run
/// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
///
/// ### Using default
///
/// The default test runtime is single-threaded.
///
/// ```no_run
/// #[tokio::test]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro
/// will not work. If you must rename the 0.3 version of tokio because
/// you're also using the 0.1 version of tokio, you _must_ make the
/// tokio 0.3 crate available as `tokio` in the module where this
/// macro is expanded.
#[proc_macro_attribute]
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::test(args, item, true)
}

/// Marks async function to be executed by runtime, suitable to test environment
///
/// ## Usage
///
/// ```no_run
/// #[tokio::test]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro
/// will not work. If you must rename the 0.3 version of tokio because
/// you're also using the 0.1 version of tokio, you _must_ make the
/// tokio 0.3 crate available as `tokio` in the module where this
/// macro is expanded.
#[proc_macro_attribute]
pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::test(args, item, false)
}

/// Always fails with the error message below.
/// ```text
/// The #[tokio::main] macro requires rt or rt-multi-thread.
/// ```
#[proc_macro_attribute]
pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
    syn::Error::new(
        proc_macro2::Span::call_site(),
        "The #[tokio::main] macro requires rt or rt-multi-thread.",
    )
    .to_compile_error()
    .into()
}

/// Always fails with the error message below.
/// ```text
/// The #[tokio::test] macro requires rt or rt-multi-thread.
/// ```
#[proc_macro_attribute]
pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
    syn::Error::new(
        proc_macro2::Span::call_site(),
        "The #[tokio::test] macro requires rt or rt-multi-thread.",
    )
    .to_compile_error()
    .into()
}

/// Implementation detail of the `select!` macro. This macro is **not** intended
/// to be used as part of the public API and is permitted to change.
#[proc_macro]
#[doc(hidden)]
pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
    select::declare_output_enum(input)
}
<commit_msg>macros: #[tokio::main] can be used on non-main (#3199)<commit_after>#![doc(html_root_url = "https://docs.rs/tokio-macros/0.3.1")]
#![allow(clippy::needless_doctest_main)]
#![warn(
    missing_debug_implementations,
    missing_docs,
    rust_2018_idioms,
    unreachable_pub
)]
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]

//! Macros for use with Tokio

// This `extern` is required for older `rustc` versions but newer `rustc`
// versions warn about the unused `extern crate`.
#[allow(unused_extern_crates)]
extern crate proc_macro;

mod entry;
mod select;

use proc_macro::TokenStream;

/// Marks async function to be executed by the selected runtime. This macro helps
/// set up a `Runtime` without requiring the user to use
/// [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.Builder.html) directly.
///
/// Note: This macro is designed to be simplistic and targets applications that
/// do not require a complex setup. If the provided functionality is not
/// sufficient, you may be interested in using
/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
/// powerful interface.
///
/// Note: This macro can be used on any function and not just the `main`
/// function. Using it on a non-main function makes the function behave
/// as if it was synchronous by starting a new runtime each time it is called.
/// If the function is called often, it is preferable to create the runtime using
/// the runtime builder so the runtime can be reused across calls.
///
/// # Multi-threaded runtime
///
/// To use the multi-threaded runtime, the macro can be configured using
///
/// ```
/// #[tokio::main(flavor = "multi_thread", worker_threads = 10)]
/// # async fn main() {}
/// ```
///
/// The `worker_threads` option configures the number of worker threads, and
/// defaults to the number of cpus on the system. This is the default flavor.
///
/// # Current thread runtime
///
/// To use the single-threaded runtime known as the `current_thread` runtime,
/// the macro can be configured using
///
/// ```
/// #[tokio::main(flavor = "current_thread")]
/// # async fn main() {}
/// ```
///
/// ## Function arguments:
///
/// Arguments are allowed for any functions aside from `main` which is special
///
/// ## Usage
///
/// ### Using the multi-thread runtime
///
/// ```rust
/// #[tokio::main]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_multi_thread()
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### Using current thread runtime
///
/// The basic scheduler is single-threaded.
///
/// ```rust
/// #[tokio::main(flavor = "current_thread")]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_current_thread()
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### Set number of worker threads
///
/// ```rust
/// #[tokio::main(worker_threads = 2)]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_multi_thread()
///         .worker_threads(2)
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro will not work.
/// If you must rename the 0.3 version of tokio because you're also using the
/// 0.1 version of tokio, you _must_ make the tokio 0.3 crate available as
/// `tokio` in the module where this macro is expanded.
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::main(args, item, true)
}

/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.builder.html) directly.
///
/// ## Function arguments:
///
/// Arguments are allowed for any functions aside from `main` which is special
///
/// ## Usage
///
/// ### Using default
///
/// ```rust
/// #[tokio::main(flavor = "current_thread")]
/// async fn main() {
///     println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// fn main() {
///     tokio::runtime::Builder::new_current_thread()
///         .enable_all()
///         .build()
///         .unwrap()
///         .block_on(async {
///             println!("Hello world");
///         })
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro
/// will not work. If you must rename the 0.3 version of tokio because
/// you're also using the 0.1 version of tokio, you _must_ make the
/// tokio 0.3 crate available as `tokio` in the module where this
/// macro is expanded.
#[proc_macro_attribute]
#[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::main(args, item, false)
}

/// Marks async function to be executed by runtime, suitable to test environment
///
/// ## Usage
///
/// ### Multi-thread runtime
///
/// ```no_run
/// #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
///
/// ### Using default
///
/// The default test runtime is single-threaded.
///
/// ```no_run
/// #[tokio::test]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro
/// will not work. If you must rename the 0.3 version of tokio because
/// you're also using the 0.1 version of tokio, you _must_ make the
/// tokio 0.3 crate available as `tokio` in the module where this
/// macro is expanded.
#[proc_macro_attribute]
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::test(args, item, true)
}

/// Marks async function to be executed by runtime, suitable to test environment
///
/// ## Usage
///
/// ```no_run
/// #[tokio::test]
/// async fn my_test() {
///     assert!(true);
/// }
/// ```
///
/// ### NOTE:
///
/// If you rename the tokio crate in your dependencies this macro
/// will not work. If you must rename the 0.3 version of tokio because
/// you're also using the 0.1 version of tokio, you _must_ make the
/// tokio 0.3 crate available as `tokio` in the module where this
/// macro is expanded.
#[proc_macro_attribute]
pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream {
    entry::test(args, item, false)
}

/// Always fails with the error message below.
/// ```text
/// The #[tokio::main] macro requires rt or rt-multi-thread.
/// ```
#[proc_macro_attribute]
pub fn main_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
    syn::Error::new(
        proc_macro2::Span::call_site(),
        "The #[tokio::main] macro requires rt or rt-multi-thread.",
    )
    .to_compile_error()
    .into()
}

/// Always fails with the error message below.
/// ```text
/// The #[tokio::test] macro requires rt or rt-multi-thread.
/// ```
#[proc_macro_attribute]
pub fn test_fail(_args: TokenStream, _item: TokenStream) -> TokenStream {
    syn::Error::new(
        proc_macro2::Span::call_site(),
        "The #[tokio::test] macro requires rt or rt-multi-thread.",
    )
    .to_compile_error()
    .into()
}

/// Implementation detail of the `select!` macro. This macro is **not** intended
/// to be used as part of the public API and is permitted to change.
#[proc_macro]
#[doc(hidden)]
pub fn select_priv_declare_output_enum(input: TokenStream) -> TokenStream {
    select::declare_output_enum(input)
}
<|endoftext|>


<commit_before>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cargo;
mod error;
mod gen;
mod out;
mod paths;
mod syntax;

use crate::error::Result;
use crate::gen::error::report;
use crate::gen::{fs, Opt};
use crate::paths::{PathExt, TargetDir};
use cc::Build;
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

struct Project {
    out_dir: PathBuf,
    target_dir: TargetDir,
}

impl Project {
    fn init() -> Result<Self> {
        let out_dir = paths::out_dir()?;

        let target_dir = match cargo::target_dir(&out_dir) {
            target_dir @ TargetDir::Path(_) => target_dir,
            // Fallback if Cargo did not work.
            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
        };

        Ok(Project {
            out_dir,
            target_dir,
        })
    }
}

fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref prj = Project::init()?;
    let mut build = Build::new();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    build.include(paths::include_dir(prj));
    write_header(prj);
    symlink_crate(prj, &mut build);

    for path in rust_source_files {
        generate_bridge(prj, &mut build, path.as_ref())?;
    }

    Ok(build)
}

fn write_header(prj: &Project) {
    let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
    let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
    if let TargetDir::Path(target_dir) = &prj.target_dir {
        let ref header_dir = target_dir.join("cxxbridge").join("rust");
        let _ = fs::create_dir_all(header_dir);
        let ref cxx_h = header_dir.join("cxx.h");
        let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
    }
}

fn symlink_crate(prj: &Project, build: &mut Build) {
    let manifest_dir = match paths::manifest_dir() {
        Some(manifest_dir) => manifest_dir,
        None => return,
    };
    let package_name = match paths::package_name() {
        Some(package_name) => package_name,
        None => return,
    };

    let mut link = paths::include_dir(prj);
    link.push("CRATE");
    let _ = out::symlink_dir(manifest_dir, link.join(package_name));
    build.include(link);
}

fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);
    let ref rel_path = paths::local_relative_path(rust_source_file);

    let ref rel_path_h = rel_path.with_appended_extension(".h");
    let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
    out::write(header_path, &generated.header)?;

    let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
    let _ = out::symlink_file(header_path, link_path);
    if let TargetDir::Path(target_dir) = &prj.target_dir {
        let ref link_path = paths::namespaced(target_dir, rel_path);
        let _ = out::symlink_file(header_path, link_path);
        let _ = out::symlink_file(header_path, link_path.with_appended_extension(".h"));
    }

    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
    let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
    out::write(implementation_path, &generated.implementation)?;
    build.file(implementation_path);
    Ok(())
}
<commit_msg>Log the include directories<commit_after>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cargo;
mod error;
mod gen;
mod out;
mod paths;
mod syntax;

use crate::error::Result;
use crate::gen::error::report;
use crate::gen::{fs, Opt};
use crate::paths::{PathExt, TargetDir};
use cc::Build;
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

struct Project {
    out_dir: PathBuf,
    target_dir: TargetDir,
}

impl Project {
    fn init() -> Result<Self> {
        let out_dir = paths::out_dir()?;

        let target_dir = match cargo::target_dir(&out_dir) {
            target_dir @ TargetDir::Path(_) => target_dir,
            // Fallback if Cargo did not work.
            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
        };

        Ok(Project {
            out_dir,
            target_dir,
        })
    }
}

fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref prj = Project::init()?;
    let include_dir = paths::include_dir(prj);

    let mut build = Build::new();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    build.include(&include_dir);
    write_header(prj);
    let crate_dir = symlink_crate(prj, &mut build);

    for path in rust_source_files {
        generate_bridge(prj, &mut build, path.as_ref())?;
    }

    eprintln!("\nCXX include path:");
    eprintln!("  {}", include_dir.display());
    if let Some(crate_dir) = crate_dir {
        eprintln!("  {}", crate_dir.display());
    }
    Ok(build)
}

fn write_header(prj: &Project) {
    let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
    let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
    if let TargetDir::Path(target_dir) = &prj.target_dir {
        let ref header_dir = target_dir.join("cxxbridge").join("rust");
        let _ = fs::create_dir_all(header_dir);
        let ref cxx_h = header_dir.join("cxx.h");
        let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
    }
}

fn symlink_crate(prj: &Project, build: &mut Build) -> Option<PathBuf> {
    let manifest_dir = match paths::manifest_dir() {
        Some(manifest_dir) => manifest_dir,
        None => return None,
    };
    let package_name = match paths::package_name() {
        Some(package_name) => package_name,
        None => return None,
    };

    let mut link = paths::include_dir(prj);
    link.push("CRATE");
    let _ = out::symlink_dir(manifest_dir, link.join(package_name));
    build.include(&link);
    Some(link)
}

fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);
    let ref rel_path = paths::local_relative_path(rust_source_file);

    let ref rel_path_h = rel_path.with_appended_extension(".h");
    let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
    out::write(header_path, &generated.header)?;

    let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
    let _ = out::symlink_file(header_path, link_path);
    if let TargetDir::Path(target_dir) = &prj.target_dir {
        let ref link_path = paths::namespaced(target_dir, rel_path);
        let _ = out::symlink_file(header_path, link_path);
        let _ = out::symlink_file(header_path, link_path.with_appended_extension(".h"));
    }

    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
    let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
    out::write(implementation_path, &generated.implementation)?;
    build.file(implementation_path);
    Ok(())
}
<|endoftext|>


<commit_before>use num::traits::One;
use std::ops::Add;

extern crate num;

struct TwoNums<T> {
  a: T,
  b: T
}

// You implement function for struct TwuNums which accept type T with following traits: Add and One
impl<T> TwoNums<T> where T: Add<Output=T> + One {
  fn new(a: T, b: T) -> TwoNums<T> {
    TwoNums {a: a, b: b}
  }
}

// inside your funcion which accepts type your type T Rust expects that you pass to add() the variable
// with the same Type
impl<T> TwoNums<T> where T: Add<Output=T> + One {
  fn succ(self) -> TwoNums<T> {
    let a = self.a.add(One::one());
    let b = self.b.add(One::one());
    TwoNums::new(a, b)
  }
}

fn main() {
  let num: TwoNums<f64> = TwoNums::new(1.0, 2.0);
  let snum: TwoNums<f64> = num.succ();
  println!("{}", snum.a);
  println!("{}", snum.b);
}
<commit_msg>updated code<commit_after>use num::traits::One;
use std::ops::Add;

extern crate num;

struct TwoNums<T> {
  a: T,
  b: T
}

// You implement function for struct TwuNums which accept type T with following traits: Add and One
impl<T> TwoNums<T> where T: Add<Output=T> {
  fn new(a: T, b: T) -> TwoNums<T> {
    TwoNums {a: a, b: b}
  }
}

// inside your funcion which accepts type your type T Rust expects that you pass to add() the variable
// with the same Type
impl<T> TwoNums<T> where T: Add<Output=T> + One {
  fn succ(self) -> TwoNums<T> {
    let a = self.a.add(One::one());
    let b = self.b.add(One::one());
    TwoNums::new(a, b)
  }
}

fn main() {
  let num: TwoNums<f64> = TwoNums::new(1.0, 2.0);
  let snum: TwoNums<f64> = num.succ();
  println!("{}", snum.a);
  println!("{}", snum.b);
}
<|endoftext|>


<commit_before>use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{any_parent_is_automatically_derived, contains_name, match_def_path, paths};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for literal calls to `Default::default()`.
    ///
    /// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
    /// being gotten than the generic `Default`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// // Bad
    /// let s: String = Default::default();
    ///
    /// // Good
    /// let s = String::default();
    /// ```
    pub DEFAULT_TRAIT_ACCESS,
    pedantic,
    "checks for literal calls to `Default::default()`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for immediate reassignment of fields initialized
    /// with Default::default().
    ///
    /// **Why is this bad?**It's more idiomatic to use the [functional update syntax](https://doc.rust-lang.org/reference/expressions/struct-expr.html#functional-update-syntax).
    ///
    /// **Known problems:** Assignments to patterns that are of tuple type are not linted.
    ///
    /// **Example:**
    /// Bad:
    /// ```
    /// # #[derive(Default)]
    /// # struct A { i: i32 }
    /// let mut a: A = Default::default();
    /// a.i = 42;
    /// ```
    /// Use instead:
    /// ```
    /// # #[derive(Default)]
    /// # struct A { i: i32 }
    /// let a = A {
    ///     i: 42,
    ///     .. Default::default()
    /// };
    /// ```
    pub FIELD_REASSIGN_WITH_DEFAULT,
    style,
    "binding initialized with Default should have its fields set in the initializer"
}

#[derive(Default)]
pub struct Default {
    // Spans linted by `field_reassign_with_default`.
    reassigned_linted: FxHashSet<Span>,
}

impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]);

impl LateLintPass<'_> for Default {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if_chain! {
            // Avoid cases already linted by `field_reassign_with_default`
            if !self.reassigned_linted.contains(&expr.span);
            if let ExprKind::Call(path, ..) = expr.kind;
            if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
            if let ExprKind::Path(ref qpath) = path.kind;
            if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
            // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
            if let QPath::Resolved(None, _path) = qpath;
            let expr_ty = cx.typeck_results().expr_ty(expr);
            if let ty::Adt(def, ..) = expr_ty.kind();
            then {
                // TODO: Work out a way to put "whatever the imported way of referencing
                // this type in this file" rather than a fully-qualified type.
                let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
                span_lint_and_sugg(
                    cx,
                    DEFAULT_TRAIT_ACCESS,
                    expr.span,
                    &format!("calling `{}` is more clear than this expression", replacement),
                    "try",
                    replacement,
                    Applicability::Unspecified, // First resolve the TODO above
                );
            }
        }
    }

    #[allow(clippy::too_many_lines)]
    fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
        // start from the `let mut _ = _::default();` and look at all the following
        // statements, see if they re-assign the fields of the binding
        let stmts_head = match block.stmts {
            // Skip the last statement since there cannot possibly be any following statements that re-assign fields.
            [head @ .., _] if !head.is_empty() => head,
            _ => return,
        };
        for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
            // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
            // `default` method of the `Default` trait, and store statement index in current block being
            // checked and the name of the bound variable
            let (local, variant, binding_name, binding_type, span) = if_chain! {
                // only take `let ...` statements
                if let StmtKind::Local(local) = stmt.kind;
                if let Some(expr) = local.init;
                if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
                if !in_external_macro(cx.tcx.sess, expr.span);
                // only take bindings to identifiers
                if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
                // only when assigning `... = Default::default()`
                if is_expr_default(expr, cx);
                let binding_type = cx.typeck_results().node_type(binding_id);
                if let Some(adt) = binding_type.ty_adt_def();
                if adt.is_struct();
                let variant = adt.non_enum_variant();
                if adt.did.is_local() || !variant.is_field_list_non_exhaustive();
                let module_did = cx.tcx.parent_module(stmt.hir_id).to_def_id();
                if variant
                    .fields
                    .iter()
                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx));
                then {
                    (local, variant, ident.name, binding_type, expr.span)
                } else {
                    continue;
                }
            };

            // find all "later statement"'s where the fields of the binding set as
            // Default::default() get reassigned, unless the reassignment refers to the original binding
            let mut first_assign = None;
            let mut assigned_fields = Vec::new();
            let mut cancel_lint = false;
            for consecutive_statement in &block.stmts[stmt_idx + 1..] {
                // find out if and which field was set by this `consecutive_statement`
                if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
                    // interrupt and cancel lint if assign_rhs references the original binding
                    if contains_name(binding_name, assign_rhs) {
                        cancel_lint = true;
                        break;
                    }

                    // if the field was previously assigned, replace the assignment, otherwise insert the assignment
                    if let Some(prev) = assigned_fields
                        .iter_mut()
                        .find(|(field_name, _)| field_name == &field_ident.name)
                    {
                        *prev = (field_ident.name, assign_rhs);
                    } else {
                        assigned_fields.push((field_ident.name, assign_rhs));
                    }

                    // also set first instance of error for help message
                    if first_assign.is_none() {
                        first_assign = Some(consecutive_statement);
                    }
                }
                // interrupt if no field was assigned, since we only want to look at consecutive statements
                else {
                    break;
                }
            }

            // if there are incorrectly assigned fields, do a span_lint_and_note to suggest
            // construction using `Ty { fields, ..Default::default() }`
            if !assigned_fields.is_empty() && !cancel_lint {
                // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
                let ext_with_default = !variant
                    .fields
                    .iter()
                    .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.ident.name));

                let field_list = assigned_fields
                    .into_iter()
                    .map(|(field, rhs)| {
                        // extract and store the assigned value for help message
                        let value_snippet = snippet_with_macro_callsite(cx, rhs.span, "..");
                        format!("{}: {}", field, value_snippet)
                    })
                    .collect::<Vec<String>>()
                    .join(", ");

                // give correct suggestion if generics are involved (see #6944)
                let binding_type = if_chain! {
                    if let ty::Adt(adt_def, substs) = binding_type.kind();
                    if !substs.is_empty();
                    then {
                        let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
                        let generic_args = substs.iter().collect::<Vec<_>>();
                        let tys_str = generic_args
                            .iter()
                            .map(ToString::to_string)
                            .collect::<Vec<_>>()
                            .join(", ");
                        format!("{}::<{}>", adt_def_ty_name, &tys_str)
                    } else {
                        binding_type.to_string()
                    }
                };

                let sugg = if ext_with_default {
                    if field_list.is_empty() {
                        format!("{}::default()", binding_type)
                    } else {
                        format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
                    }
                } else {
                    format!("{} {{ {} }}", binding_type, field_list)
                };

                // span lint once per statement that binds default
                span_lint_and_note(
                    cx,
                    FIELD_REASSIGN_WITH_DEFAULT,
                    first_assign.unwrap().span,
                    "field assignment outside of initializer for an instance created with Default::default()",
                    Some(local.span),
                    &format!(
                        "consider initializing the variable with `{}` and removing relevant reassignments",
                        sugg
                    ),
                );
                self.reassigned_linted.insert(span);
            }
        }
    }
}

/// Checks if the given expression is the `default` method belonging to the `Default` trait.
fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
    if_chain! {
        if let ExprKind::Call(fn_expr, _) = &expr.kind;
        if let ExprKind::Path(qpath) = &fn_expr.kind;
        if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
        then {
            // right hand side of assignment is `Default::default`
            match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD)
        } else {
            false
        }
    }
}

/// Returns the reassigned field and the assigning expression (right-hand side of assign).
fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
    if_chain! {
        // only take assignments
        if let StmtKind::Semi(later_expr) = this.kind;
        if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind;
        // only take assignments to fields where the left-hand side field is a field of
        // the same binding as the previous statement
        if let ExprKind::Field(binding, field_ident) = assign_lhs.kind;
        if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind;
        if let Some(second_binding_name) = path.segments.last();
        if second_binding_name.ident.name == binding_name;
        then {
            Some((field_ident, assign_rhs))
        } else {
            None
        }
    }
}
<commit_msg>Disable default_trait_access in macros<commit_after>use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{any_parent_is_automatically_derived, contains_name, in_macro, match_def_path, paths};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for literal calls to `Default::default()`.
    ///
    /// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
    /// being gotten than the generic `Default`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// // Bad
    /// let s: String = Default::default();
    ///
    /// // Good
    /// let s = String::default();
    /// ```
    pub DEFAULT_TRAIT_ACCESS,
    pedantic,
    "checks for literal calls to `Default::default()`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for immediate reassignment of fields initialized
    /// with Default::default().
    ///
    /// **Why is this bad?**It's more idiomatic to use the [functional update syntax](https://doc.rust-lang.org/reference/expressions/struct-expr.html#functional-update-syntax).
    ///
    /// **Known problems:** Assignments to patterns that are of tuple type are not linted.
    ///
    /// **Example:**
    /// Bad:
    /// ```
    /// # #[derive(Default)]
    /// # struct A { i: i32 }
    /// let mut a: A = Default::default();
    /// a.i = 42;
    /// ```
    /// Use instead:
    /// ```
    /// # #[derive(Default)]
    /// # struct A { i: i32 }
    /// let a = A {
    ///     i: 42,
    ///     .. Default::default()
    /// };
    /// ```
    pub FIELD_REASSIGN_WITH_DEFAULT,
    style,
    "binding initialized with Default should have its fields set in the initializer"
}

#[derive(Default)]
pub struct Default {
    // Spans linted by `field_reassign_with_default`.
    reassigned_linted: FxHashSet<Span>,
}

impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]);

impl LateLintPass<'_> for Default {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if_chain! {
            if !in_macro(expr.span);
            // Avoid cases already linted by `field_reassign_with_default`
            if !self.reassigned_linted.contains(&expr.span);
            if let ExprKind::Call(path, ..) = expr.kind;
            if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
            if let ExprKind::Path(ref qpath) = path.kind;
            if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
            // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
            if let QPath::Resolved(None, _path) = qpath;
            let expr_ty = cx.typeck_results().expr_ty(expr);
            if let ty::Adt(def, ..) = expr_ty.kind();
            then {
                // TODO: Work out a way to put "whatever the imported way of referencing
                // this type in this file" rather than a fully-qualified type.
                let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
                span_lint_and_sugg(
                    cx,
                    DEFAULT_TRAIT_ACCESS,
                    expr.span,
                    &format!("calling `{}` is more clear than this expression", replacement),
                    "try",
                    replacement,
                    Applicability::Unspecified, // First resolve the TODO above
                );
            }
        }
    }

    #[allow(clippy::too_many_lines)]
    fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
        // start from the `let mut _ = _::default();` and look at all the following
        // statements, see if they re-assign the fields of the binding
        let stmts_head = match block.stmts {
            // Skip the last statement since there cannot possibly be any following statements that re-assign fields.
            [head @ .., _] if !head.is_empty() => head,
            _ => return,
        };
        for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
            // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
            // `default` method of the `Default` trait, and store statement index in current block being
            // checked and the name of the bound variable
            let (local, variant, binding_name, binding_type, span) = if_chain! {
                // only take `let ...` statements
                if let StmtKind::Local(local) = stmt.kind;
                if let Some(expr) = local.init;
                if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
                if !in_external_macro(cx.tcx.sess, expr.span);
                // only take bindings to identifiers
                if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
                // only when assigning `... = Default::default()`
                if is_expr_default(expr, cx);
                let binding_type = cx.typeck_results().node_type(binding_id);
                if let Some(adt) = binding_type.ty_adt_def();
                if adt.is_struct();
                let variant = adt.non_enum_variant();
                if adt.did.is_local() || !variant.is_field_list_non_exhaustive();
                let module_did = cx.tcx.parent_module(stmt.hir_id).to_def_id();
                if variant
                    .fields
                    .iter()
                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx));
                then {
                    (local, variant, ident.name, binding_type, expr.span)
                } else {
                    continue;
                }
            };

            // find all "later statement"'s where the fields of the binding set as
            // Default::default() get reassigned, unless the reassignment refers to the original binding
            let mut first_assign = None;
            let mut assigned_fields = Vec::new();
            let mut cancel_lint = false;
            for consecutive_statement in &block.stmts[stmt_idx + 1..] {
                // find out if and which field was set by this `consecutive_statement`
                if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
                    // interrupt and cancel lint if assign_rhs references the original binding
                    if contains_name(binding_name, assign_rhs) {
                        cancel_lint = true;
                        break;
                    }

                    // if the field was previously assigned, replace the assignment, otherwise insert the assignment
                    if let Some(prev) = assigned_fields
                        .iter_mut()
                        .find(|(field_name, _)| field_name == &field_ident.name)
                    {
                        *prev = (field_ident.name, assign_rhs);
                    } else {
                        assigned_fields.push((field_ident.name, assign_rhs));
                    }

                    // also set first instance of error for help message
                    if first_assign.is_none() {
                        first_assign = Some(consecutive_statement);
                    }
                }
                // interrupt if no field was assigned, since we only want to look at consecutive statements
                else {
                    break;
                }
            }

            // if there are incorrectly assigned fields, do a span_lint_and_note to suggest
            // construction using `Ty { fields, ..Default::default() }`
            if !assigned_fields.is_empty() && !cancel_lint {
                // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
                let ext_with_default = !variant
                    .fields
                    .iter()
                    .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.ident.name));

                let field_list = assigned_fields
                    .into_iter()
                    .map(|(field, rhs)| {
                        // extract and store the assigned value for help message
                        let value_snippet = snippet_with_macro_callsite(cx, rhs.span, "..");
                        format!("{}: {}", field, value_snippet)
                    })
                    .collect::<Vec<String>>()
                    .join(", ");

                // give correct suggestion if generics are involved (see #6944)
                let binding_type = if_chain! {
                    if let ty::Adt(adt_def, substs) = binding_type.kind();
                    if !substs.is_empty();
                    then {
                        let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
                        let generic_args = substs.iter().collect::<Vec<_>>();
                        let tys_str = generic_args
                            .iter()
                            .map(ToString::to_string)
                            .collect::<Vec<_>>()
                            .join(", ");
                        format!("{}::<{}>", adt_def_ty_name, &tys_str)
                    } else {
                        binding_type.to_string()
                    }
                };

                let sugg = if ext_with_default {
                    if field_list.is_empty() {
                        format!("{}::default()", binding_type)
                    } else {
                        format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
                    }
                } else {
                    format!("{} {{ {} }}", binding_type, field_list)
                };

                // span lint once per statement that binds default
                span_lint_and_note(
                    cx,
                    FIELD_REASSIGN_WITH_DEFAULT,
                    first_assign.unwrap().span,
                    "field assignment outside of initializer for an instance created with Default::default()",
                    Some(local.span),
                    &format!(
                        "consider initializing the variable with `{}` and removing relevant reassignments",
                        sugg
                    ),
                );
                self.reassigned_linted.insert(span);
            }
        }
    }
}

/// Checks if the given expression is the `default` method belonging to the `Default` trait.
fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
    if_chain! {
        if let ExprKind::Call(fn_expr, _) = &expr.kind;
        if let ExprKind::Path(qpath) = &fn_expr.kind;
        if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
        then {
            // right hand side of assignment is `Default::default`
            match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD)
        } else {
            false
        }
    }
}

/// Returns the reassigned field and the assigning expression (right-hand side of assign).
fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
    if_chain! {
        // only take assignments
        if let StmtKind::Semi(later_expr) = this.kind;
        if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind;
        // only take assignments to fields where the left-hand side field is a field of
        // the same binding as the previous statement
        if let ExprKind::Field(binding, field_ident) = assign_lhs.kind;
        if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind;
        if let Some(second_binding_name) = path.segments.last();
        if second_binding_name.ident.name == binding_name;
        then {
            Some((field_ident, assign_rhs))
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#![crate_name="calculator"]
#![crate_type="bin"]

extern crate thrift;

use std::io::net::ip;
use thrift::TResult;
use thrift::ThriftErr;
use thrift::ThriftErr::*;
use thrift::protocol::{MessageType, Type};
use thrift::transport::Transport;
use thrift::protocol::Protocol;
use thrift::protocol::{Readable, Writeable};
use thrift::protocol::binary_protocol::BinaryProtocol;

mod tutorial;

struct CalculatorClient<T: Transport, P: Protocol> {
    transport: T,
    protocol: P,
}

impl <T: Transport, P: Protocol> CalculatorClient<T, P> {

    fn ping(& mut self) -> TResult<()> {
        try!(self.send("ping", MessageType::MtCall, &tutorial::CalculatorPingArgs));
        self.receive_ping()
    }

    #[allow(unused_variables)]
    fn receive_ping(& mut self) -> TResult<()> {
        let mut result = tutorial::CalculatorPingResult;
        try!(self.receive("ping", &mut result));
        Ok(())
    }

    fn add(& mut self, num1: i32, num2: i32) -> TResult<i32> {
        let args = tutorial::CalculatorAddArgs { num1: num1, num2: num2 };
        try!(self.send("add", MessageType::MtCall, &args));
        self.receive_add()
    }

    fn receive_add(& mut self) -> TResult<i32> {
        let mut result = tutorial::CalculatorAddResult  { success: 0 };
        try!(self.receive("add", &mut result));
        Ok(result.success)
    }

    fn calculate(& mut self, logid: i32, w: tutorial::Work) -> TResult<i32> {
        let args = tutorial::CalculatorCalculateArgs { logid: logid, w: w };
        try!(self.send("calculate", MessageType::MtCall, &args));
        self.receive_calculate()
    }

    fn receive_calculate(& mut self) -> TResult<i32> {
        let mut result = tutorial::CalculatorCalculateResult { success: 0, ouch: None };
        try!(self.receive("calculate", &mut result));
        Ok(result.success)
    }

    fn send<W: Writeable>(&mut self, name: &str, _type: MessageType, args: &W) -> TResult<()> {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(&mut self.transport, name, _type, cseqid);

        try!(args.write(&self.protocol, &mut self.transport));

        self.protocol.write_message_end(&mut self.transport);

        //self.transport.write_end();
        try!(self.transport.flush());

        Ok(())
    }

    #[allow(unused_variables)]
    fn receive<R: Readable>(& mut self, op: &'static str, result: &mut R) -> TResult<()> {

        match try!(self.protocol.read_message_begin(& mut self.transport)) {
          (_, MessageType::MtException, _) => {
              // TODO
              //let x = ApplicationException;
              //x.read(& mut self protocol)
              //self.protocol.read_message_end();
              //transport.read_end();
              //throw x
              Err(ThriftErr::Exception)
          }
          (fname, MessageType::MtReply, _) => {
              if fname.as_slice() == op {
                  try!(result.read(&self.protocol, & mut self.transport));
                  try!(self.protocol.read_message_end(& mut self.transport));
                  Ok(())
               }
              else {
                // FIXME: shall we err in this case?
                  try!(self.protocol.skip(& mut self.transport, Type::TStruct));
                  try!(self.protocol.read_message_end(& mut self.transport));
                  Err(ThriftErr::ProtocolError)
              }
          }
          (_, _, _) => {
              try!(self.protocol.skip(& mut self.transport, Type::TStruct));
              try!(self.protocol.read_message_end(& mut self.transport));
              Err(ThriftErr::ProtocolError)
          }
        }
    }
}

pub fn main() {
    let server_address = "127.0.0.1:9090";
    let addr: ip::SocketAddr = std::str::FromStr::from_str(server_address)
        .expect("bad server address");
    let tcp = std::io::TcpStream::connect(addr).unwrap();

    let mut client = CalculatorClient{ protocol: BinaryProtocol, transport: tcp };

    // Ping
    client.ping().unwrap();
    println!("ping()");

    // Add
    println!("1 + 1 = {}", client.add(1, 1).unwrap());

    // Work: divide
    let work = tutorial::Work { op: tutorial::Operation::DIVIDE, num1: 1, num2: 0, comment: None };

    match client.calculate(1, work) {
      Ok(_) => {
        println!("Whoa? We can divide by zero!");
      }
      Err(_) => {
        // FIXME: use thrift exceptions
        println!("Invalid operation")
      }
    }

    // Work: subtract
    let work = tutorial::Work { op: tutorial::Operation::SUBTRACT, num1: 15, num2: 10, comment: None };
    println!("15 - 10 = {}", client.calculate(2, work).unwrap());

    println!("PASS");
}

<commit_msg>Simplified client code<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#![crate_name="calculator"]
#![crate_type="bin"]

extern crate thrift;

use std::io::net::ip;
use thrift::TResult;
use thrift::ThriftErr;
use thrift::ThriftErr::*;
use thrift::protocol::{MessageType, Type};
use thrift::transport::Transport;
use thrift::protocol::Protocol;
use thrift::protocol::{Readable, Writeable};
use thrift::protocol::binary_protocol::BinaryProtocol;

mod tutorial;

struct CalculatorClient<T: Transport, P: Protocol> {
    transport: T,
    protocol: P,
}

impl <T: Transport, P: Protocol> CalculatorClient<T, P> {

    fn ping(& mut self) -> TResult<()> {
        try!(self.send("ping", MessageType::MtCall, &tutorial::CalculatorPingArgs));

        let mut result = tutorial::CalculatorPingResult;
        try!(self.receive("ping", &mut result));
        Ok(())
    }

    fn add(& mut self, num1: i32, num2: i32) -> TResult<i32> {
        let args = tutorial::CalculatorAddArgs { num1: num1, num2: num2 };
        try!(self.send("add", MessageType::MtCall, &args));

        let mut result = tutorial::CalculatorAddResult  { success: 0 };
        try!(self.receive("add", &mut result));
        Ok(result.success)
    }

    fn calculate(& mut self, logid: i32, w: tutorial::Work) -> TResult<i32> {
        let args = tutorial::CalculatorCalculateArgs { logid: logid, w: w };
        try!(self.send("calculate", MessageType::MtCall, &args));

        let mut result = tutorial::CalculatorCalculateResult { success: 0, ouch: None };
        try!(self.receive("calculate", &mut result));
        Ok(result.success)
    }

    fn send<W: Writeable>(&mut self, name: &str, _type: MessageType, args: &W) -> TResult<()> {
        let cseqid: i32 = 0;
        self.protocol.write_message_begin(&mut self.transport, name, _type, cseqid);

        try!(args.write(&self.protocol, &mut self.transport));

        self.protocol.write_message_end(&mut self.transport);

        //self.transport.write_end();
        try!(self.transport.flush());

        Ok(())
    }

    #[allow(unused_variables)]
    fn receive<R: Readable>(& mut self, op: &'static str, result: &mut R) -> TResult<()> {

        match try!(self.protocol.read_message_begin(& mut self.transport)) {
          (_, MessageType::MtException, _) => {
              // TODO
              //let x = ApplicationException;
              //x.read(& mut self protocol)
              //self.protocol.read_message_end();
              //transport.read_end();
              //throw x
              Err(ThriftErr::Exception)
          }
          (fname, MessageType::MtReply, _) => {
              if fname.as_slice() == op {
                  try!(result.read(&self.protocol, & mut self.transport));
                  try!(self.protocol.read_message_end(& mut self.transport));
                  Ok(())
               }
              else {
                // FIXME: shall we err in this case?
                  try!(self.protocol.skip(& mut self.transport, Type::TStruct));
                  try!(self.protocol.read_message_end(& mut self.transport));
                  Err(ThriftErr::ProtocolError)
              }
          }
          (_, _, _) => {
              try!(self.protocol.skip(& mut self.transport, Type::TStruct));
              try!(self.protocol.read_message_end(& mut self.transport));
              Err(ThriftErr::ProtocolError)
          }
        }
    }
}

pub fn main() {
    let server_address = "127.0.0.1:9090";
    let addr: ip::SocketAddr = std::str::FromStr::from_str(server_address)
        .expect("bad server address");
    let tcp = std::io::TcpStream::connect(addr).unwrap();

    let mut client = CalculatorClient{ protocol: BinaryProtocol, transport: tcp };

    // Ping
    client.ping().unwrap();
    println!("ping()");

    // Add
    println!("1 + 1 = {}", client.add(1, 1).unwrap());

    // Work: divide
    let work = tutorial::Work { op: tutorial::Operation::DIVIDE, num1: 1, num2: 0, comment: None };

    match client.calculate(1, work) {
      Ok(_) => {
        println!("Whoa? We can divide by zero!");
      }
      Err(_) => {
        // FIXME: use thrift exceptions
        println!("Invalid operation")
      }
    }

    // Work: subtract
    let work = tutorial::Work { op: tutorial::Operation::SUBTRACT, num1: 15, num2: 10, comment: None };
    println!("15 - 10 = {}", client.calculate(2, work).unwrap());

    println!("PASS");
}

<|endoftext|>