<commit_before>#![cfg_attr(feature = "fatal_warnings", deny(warnings))]

extern crate atty;
extern crate ansi_term;
extern crate unescape;
#[cfg(test)]
extern crate lazy_static;
extern crate libc;
extern crate linefeed;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate prettytable;
extern crate log4rs;
extern crate indyrs as indy;

#[macro_use]
mod utils;
mod command_executor;
#[macro_use]
mod commands;
mod libindy;

use command_executor::CommandExecutor;

use commands::{common, did, ledger, pool, wallet, payment_address};
use utils::history;

use linefeed::{Reader, ReadResult, Terminal, Signal};
use linefeed::complete::{Completer, Completion};

use std::env;
use std::fs::File;
use std::io::BufReader;
use std::rc::Rc;

fn main() {
    #[cfg(target_os = "windows")]
    ansi_term::enable_ansi_support().is_ok();

    let mut args = env::args();
    args.next(); // skip library

    let command_executor = build_executor();

    while let Some(arg) = args.next() {
        match arg.as_str() {
            "-h" | "--help" => return _print_help(),
            "--config" => {
                let file = unwrap_or_return!(args.next(), println_err!("CLI configuration file is not specified"));

                match CliConfig::read_from_file(&file)
                    .and_then(|config| config.handle(&command_executor)) {
                    Ok(()) => {}
                    Err(err) => return println_err!("{}", err)
                }
            }
            "--logger-config" => {
                let file = unwrap_or_return!(args.next(), println_err!("Logger config file is not specified"));
                match utils::logger::IndyCliLogger::init(&file) {
                    Ok(()) => println_succ!("Logger has been initialized according to the config file: \"{}\"", file),
                    Err(err) => return println_err!("{}", err)
                }
            }
            "--plugins" => {
                let plugins = unwrap_or_return!(args.next(), println_err!("Plugins are not specified"));
                _load_plugins(&command_executor, &plugins)
            }
            _ if args.len() == 0 => {
                execute_batch(&command_executor, Some(&arg));

                if command_executor.ctx().is_exit() {
                    return;
                }
            },
            _ => {
                println_err!("Unknown option");
                return _print_help();
            }
        }
    }
    execute_stdin(command_executor);
}

#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct CliConfig {
    pub logger_config: Option<String>,
    pub plugins: Option<String>,
    pub taa_acceptance_mechanism: Option<String>,
}

impl CliConfig {
    fn read_from_file(file: &str) -> Result<CliConfig, String> {
        let content = utils::file::read_file(file)?;
        let config: CliConfig = serde_json::from_str(&content)
            .map_err(|err| format!("Invalid CLI configuration file: {:?}", err))?;
        Ok(config)
    }

    fn handle(&self, command_executor: &CommandExecutor) -> Result<(), String> {
        if let Some(ref logger_config) = self.logger_config {
            utils::logger::IndyCliLogger::init(logger_config)?;
            println_succ!("Logger has been initialized according to the config file: \"{}\"", logger_config);
        }
        if let Some(ref plugins) = self.plugins {
            _load_plugins(&command_executor, plugins);
        }
        if let Some(ref taa_acceptance_mechanism) = self.taa_acceptance_mechanism {
            command_executor.ctx().set_taa_acceptance_mechanism(taa_acceptance_mechanism);
            println_succ!("\"{}\" is used as transaction author agreement acceptance mechanism", taa_acceptance_mechanism);
        }
        Ok(())
    }
}

fn build_executor() -> CommandExecutor {
    CommandExecutor::build()
        .add_command(common::about_command::new())
        .add_command(common::exit_command::new())
        .add_command(common::prompt_command::new())
        .add_command(common::show_command::new())
        .add_command(common::load_plugin_command::new())
        .add_command(common::init_logger_command::new())
        .add_group(did::group::new())
        .add_command(did::new_command::new())
        .add_command(did::import_command::new())
        .add_command(did::use_command::new())
        .add_command(did::rotate_key_command::new())
        .add_command(did::list_command::new())
        .finalize_group()
        .add_group(pool::group::new())
        .add_command(pool::create_command::new())
        .add_command(pool::connect_command::new())
        .add_command(pool::refresh_command::new())
        .add_command(pool::list_command::new())
        .add_command(pool::disconnect_command::new())
        .add_command(pool::delete_command::new())
        .add_command(pool::show_taa_command::new())
        .finalize_group()
        .add_group(wallet::group::new())
        .add_command(wallet::create_command::new())
        .add_command(wallet::attach_command::new())
        .add_command(wallet::open_command::new())
        .add_command(wallet::list_command::new())
        .add_command(wallet::close_command::new())
        .add_command(wallet::delete_command::new())
        .add_command(wallet::detach_command::new())
        .add_command(wallet::export_command::new())
        .add_command(wallet::import_command::new())
        .finalize_group()
        .add_group(ledger::group::new())
        .add_command(ledger::nym_command::new())
        .add_command(ledger::get_nym_command::new())
        .add_command(ledger::attrib_command::new())
        .add_command(ledger::get_attrib_command::new())
        .add_command(ledger::schema_command::new())
        .add_command(ledger::get_schema_command::new())
        .add_command(ledger::get_validator_info_command::new())
        .add_command(ledger::cred_def_command::new())
        .add_command(ledger::get_cred_def_command::new())
        .add_command(ledger::node_command::new())
        .add_command(ledger::pool_config_command::new())
        .add_command(ledger::pool_restart_command::new())
        .add_command(ledger::pool_upgrade_command::new())
        .add_command(ledger::custom_command::new())
        .add_command(ledger::get_payment_sources_command::new())
        .add_command(ledger::payment_command::new())
        .add_command(ledger::get_fees_command::new())
        .add_command(ledger::mint_prepare_command::new())
        .add_command(ledger::set_fees_prepare_command::new())
        .add_command(ledger::verify_payment_receipt_command::new())
        .add_command(ledger::sign_multi_command::new())
        .add_command(ledger::auth_rule_command::new())
        .add_command(ledger::auth_rules_command::new())
        .add_command(ledger::get_auth_rule_command::new())
        .add_command(ledger::save_transaction_command::new())
        .add_command(ledger::load_transaction_command::new())
        .add_command(ledger::taa_command::new())
        .add_command(ledger::aml_command::new())
        .finalize_group()
        .add_group(payment_address::group::new())
        .add_command(payment_address::create_command::new())
        .add_command(payment_address::list_command::new())
        .finalize_group()
        .finalize()
}

fn execute_stdin(command_executor: CommandExecutor) {
    match Reader::new("indy-cli") {
        Ok(reader) => execute_interactive(command_executor, reader),
        Err(_) => execute_batch(&command_executor, None),
    }
}

fn execute_interactive<T>(command_executor: CommandExecutor, mut reader: Reader<T>)
    where T: Terminal {
    let command_executor = Rc::new(command_executor);
    reader.set_completer(command_executor.clone());
    reader.set_prompt(&command_executor.ctx().get_prompt());
    history::load(&mut reader).ok();

    while let Ok(read_result) = reader.read_line() {
        match read_result {
            ReadResult::Input(line) => {
                let line = line.trim();
                if line.is_empty() {
                    continue;
                }

                if command_executor.execute(&line).is_ok() {
                    reader.add_history(line.to_string());
                };

                reader.set_prompt(&command_executor.ctx().get_prompt());

                if command_executor.ctx().is_exit() {
                    history::persist(&mut reader).ok();
                    break;
                }
            },
            ReadResult::Eof | ReadResult::Signal(Signal::Quit) | ReadResult::Signal(Signal::Break)| ReadResult::Signal(Signal::Interrupt) => {
                history::persist(&mut reader).ok();
                break;
            },
            _ => {break}
        }
    }
}

fn execute_batch(command_executor: &CommandExecutor, script_path: Option<&str>) {
    command_executor.ctx().set_batch_mode();
    if let Some(script_path) = script_path {
        let file = match File::open(script_path) {
            Ok(file) => file,
            Err(err) => return println_err!("Can't open script file {}\nError: {}", script_path, err),
        };
        _iter_batch(command_executor, BufReader::new(file));
    } else {
        let stdin = std::io::stdin();
        _iter_batch(command_executor, stdin.lock());
    };
    command_executor.ctx().set_not_batch_mode();
}

fn _load_plugins(command_executor: &CommandExecutor, plugins_str: &str) {
    for plugin in plugins_str.split(",") {
        let parts: Vec<&str> = plugin.split(":").collect::<Vec<&str>>();

        let name = unwrap_or_return!(parts.get(0), println_err!("Plugin Name not found in {}", plugin));
        let init_func = unwrap_or_return!(parts.get(1), println_err!("Plugin Init function not found in {}", plugin));

        common::load_plugin(command_executor.ctx(), name, init_func).ok();
    }
}

fn _print_help() {
    println_acc!("Hyperledger Indy CLI");
    println!();
    println_acc!("CLI supports 2 execution modes:");
    println_acc!("\tInteractive - reads commands from terminal. To start just run indy-cli without params.");
    println_acc!("\tUsage: indy-cli");
    println!();
    println_acc!("\tBatch - all commands will be read from text file or pipe and executed in series.");
    println_acc!("\tUsage: indy-cli <path-to-text-file>");
    println!();
    println_acc!("Options:");
    println_acc!("\tLoad plugins in Libindy.");
    println_acc!("\tUsage: indy-cli --plugins <lib-1-name>:<init-func-1-name>,...,<lib-n-name>:<init-func-n-name>");
    println!();
    println_acc!("\tInit logger according to a config file. \n\tIndy Cli uses `log4rs` logging framework: https://crates.io/crates/log4rs");
    println_acc!("\tUsage: indy-cli --logger-config <path-to-config-file>");
    println!();
    println_acc!("\tUse config file for CLI initialization. A config file can contain the following fields:");
    println_acc!("\t\tplugins - a list of plugins to load in Libindy (is equal to usage of \"--plugins\" option).");
    println_acc!("\t\tloggerConfig - path to a logger config file (is equal to usage of \"--logger-config\" option).");
    println_acc!("\t\ttaaAcceptanceMechanism - transaction author agreement acceptance mechanism to use for sending write transactions to the Ledger.");
    println_acc!("\tUsage: indy-cli --config <path-to-config-json-file>");
    println!();
}

fn _iter_batch<T>(command_executor: &CommandExecutor, reader: T) where T: std::io::BufRead {
    let mut line_num = 1;
    for line in reader.lines() {
        let line = if let Ok(line) = line { line } else {
            return println_err!("Can't parse line #{}", line_num);
        };

        if line.starts_with("#") || line.is_empty() {
            // Skip blank lines and lines starting with #
            continue;
        }

        println!("{}", line);
        let (line, force) = if line.starts_with("-") {
            (line[1..].as_ref(), true)
        } else {
            (line[0..].as_ref(), false)
        };
        if command_executor.execute(line).is_err() && !force {
            return println_err!("Batch execution failed at line #{}", line_num);
        }
        println!();
        line_num += 1;

        if command_executor.ctx().is_exit() {
            break;
        }
    }
}

impl<Term: Terminal> Completer<Term> for CommandExecutor {
    fn complete(&self, word: &str, reader: &Reader<Term>,
                _start: usize, _end: usize) -> Option<Vec<Completion>> {
        Some(self
            .complete(reader.buffer(),
                      word,
                      reader.cursor())
            .into_iter()
            .map(|c| Completion {
                completion: c.0,
                display: None,
                suffix: linefeed::Suffix::Some(c.1),
            })
            .collect())
    }
}
<commit_msg>Fixed warning in CLI<commit_after>#![cfg_attr(feature = "fatal_warnings", deny(warnings))]

extern crate atty;
extern crate ansi_term;
extern crate unescape;
#[cfg(test)]
extern crate lazy_static;
extern crate libc;
extern crate linefeed;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate prettytable;
extern crate log4rs;
extern crate indyrs as indy;

#[macro_use]
mod utils;
mod command_executor;
#[macro_use]
mod commands;
mod libindy;

use command_executor::CommandExecutor;

use commands::{common, did, ledger, pool, wallet, payment_address};
use utils::history;

use linefeed::{Reader, ReadResult, Terminal, Signal};
use linefeed::complete::{Completer, Completion};

use std::env;
use std::fs::File;
use std::io::BufReader;
use std::rc::Rc;

fn main() {
    #[cfg(target_os = "windows")]
    let _ = ansi_term::enable_ansi_support().is_ok();

    let mut args = env::args();
    args.next(); // skip library

    let command_executor = build_executor();

    while let Some(arg) = args.next() {
        match arg.as_str() {
            "-h" | "--help" => return _print_help(),
            "--config" => {
                let file = unwrap_or_return!(args.next(), println_err!("CLI configuration file is not specified"));

                match CliConfig::read_from_file(&file)
                    .and_then(|config| config.handle(&command_executor)) {
                    Ok(()) => {}
                    Err(err) => return println_err!("{}", err)
                }
            }
            "--logger-config" => {
                let file = unwrap_or_return!(args.next(), println_err!("Logger config file is not specified"));
                match utils::logger::IndyCliLogger::init(&file) {
                    Ok(()) => println_succ!("Logger has been initialized according to the config file: \"{}\"", file),
                    Err(err) => return println_err!("{}", err)
                }
            }
            "--plugins" => {
                let plugins = unwrap_or_return!(args.next(), println_err!("Plugins are not specified"));
                _load_plugins(&command_executor, &plugins)
            }
            _ if args.len() == 0 => {
                execute_batch(&command_executor, Some(&arg));

                if command_executor.ctx().is_exit() {
                    return;
                }
            },
            _ => {
                println_err!("Unknown option");
                return _print_help();
            }
        }
    }
    execute_stdin(command_executor);
}

#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct CliConfig {
    pub logger_config: Option<String>,
    pub plugins: Option<String>,
    pub taa_acceptance_mechanism: Option<String>,
}

impl CliConfig {
    fn read_from_file(file: &str) -> Result<CliConfig, String> {
        let content = utils::file::read_file(file)?;
        let config: CliConfig = serde_json::from_str(&content)
            .map_err(|err| format!("Invalid CLI configuration file: {:?}", err))?;
        Ok(config)
    }

    fn handle(&self, command_executor: &CommandExecutor) -> Result<(), String> {
        if let Some(ref logger_config) = self.logger_config {
            utils::logger::IndyCliLogger::init(logger_config)?;
            println_succ!("Logger has been initialized according to the config file: \"{}\"", logger_config);
        }
        if let Some(ref plugins) = self.plugins {
            _load_plugins(&command_executor, plugins);
        }
        if let Some(ref taa_acceptance_mechanism) = self.taa_acceptance_mechanism {
            command_executor.ctx().set_taa_acceptance_mechanism(taa_acceptance_mechanism);
            println_succ!("\"{}\" is used as transaction author agreement acceptance mechanism", taa_acceptance_mechanism);
        }
        Ok(())
    }
}

fn build_executor() -> CommandExecutor {
    CommandExecutor::build()
        .add_command(common::about_command::new())
        .add_command(common::exit_command::new())
        .add_command(common::prompt_command::new())
        .add_command(common::show_command::new())
        .add_command(common::load_plugin_command::new())
        .add_command(common::init_logger_command::new())
        .add_group(did::group::new())
        .add_command(did::new_command::new())
        .add_command(did::import_command::new())
        .add_command(did::use_command::new())
        .add_command(did::rotate_key_command::new())
        .add_command(did::list_command::new())
        .finalize_group()
        .add_group(pool::group::new())
        .add_command(pool::create_command::new())
        .add_command(pool::connect_command::new())
        .add_command(pool::refresh_command::new())
        .add_command(pool::list_command::new())
        .add_command(pool::disconnect_command::new())
        .add_command(pool::delete_command::new())
        .add_command(pool::show_taa_command::new())
        .finalize_group()
        .add_group(wallet::group::new())
        .add_command(wallet::create_command::new())
        .add_command(wallet::attach_command::new())
        .add_command(wallet::open_command::new())
        .add_command(wallet::list_command::new())
        .add_command(wallet::close_command::new())
        .add_command(wallet::delete_command::new())
        .add_command(wallet::detach_command::new())
        .add_command(wallet::export_command::new())
        .add_command(wallet::import_command::new())
        .finalize_group()
        .add_group(ledger::group::new())
        .add_command(ledger::nym_command::new())
        .add_command(ledger::get_nym_command::new())
        .add_command(ledger::attrib_command::new())
        .add_command(ledger::get_attrib_command::new())
        .add_command(ledger::schema_command::new())
        .add_command(ledger::get_schema_command::new())
        .add_command(ledger::get_validator_info_command::new())
        .add_command(ledger::cred_def_command::new())
        .add_command(ledger::get_cred_def_command::new())
        .add_command(ledger::node_command::new())
        .add_command(ledger::pool_config_command::new())
        .add_command(ledger::pool_restart_command::new())
        .add_command(ledger::pool_upgrade_command::new())
        .add_command(ledger::custom_command::new())
        .add_command(ledger::get_payment_sources_command::new())
        .add_command(ledger::payment_command::new())
        .add_command(ledger::get_fees_command::new())
        .add_command(ledger::mint_prepare_command::new())
        .add_command(ledger::set_fees_prepare_command::new())
        .add_command(ledger::verify_payment_receipt_command::new())
        .add_command(ledger::sign_multi_command::new())
        .add_command(ledger::auth_rule_command::new())
        .add_command(ledger::auth_rules_command::new())
        .add_command(ledger::get_auth_rule_command::new())
        .add_command(ledger::save_transaction_command::new())
        .add_command(ledger::load_transaction_command::new())
        .add_command(ledger::taa_command::new())
        .add_command(ledger::aml_command::new())
        .finalize_group()
        .add_group(payment_address::group::new())
        .add_command(payment_address::create_command::new())
        .add_command(payment_address::list_command::new())
        .finalize_group()
        .finalize()
}

fn execute_stdin(command_executor: CommandExecutor) {
    match Reader::new("indy-cli") {
        Ok(reader) => execute_interactive(command_executor, reader),
        Err(_) => execute_batch(&command_executor, None),
    }
}

fn execute_interactive<T>(command_executor: CommandExecutor, mut reader: Reader<T>)
    where T: Terminal {
    let command_executor = Rc::new(command_executor);
    reader.set_completer(command_executor.clone());
    reader.set_prompt(&command_executor.ctx().get_prompt());
    history::load(&mut reader).ok();

    while let Ok(read_result) = reader.read_line() {
        match read_result {
            ReadResult::Input(line) => {
                let line = line.trim();
                if line.is_empty() {
                    continue;
                }

                if command_executor.execute(&line).is_ok() {
                    reader.add_history(line.to_string());
                };

                reader.set_prompt(&command_executor.ctx().get_prompt());

                if command_executor.ctx().is_exit() {
                    history::persist(&mut reader).ok();
                    break;
                }
            },
            ReadResult::Eof | ReadResult::Signal(Signal::Quit) | ReadResult::Signal(Signal::Break)| ReadResult::Signal(Signal::Interrupt) => {
                history::persist(&mut reader).ok();
                break;
            },
            _ => {break}
        }
    }
}

fn execute_batch(command_executor: &CommandExecutor, script_path: Option<&str>) {
    command_executor.ctx().set_batch_mode();
    if let Some(script_path) = script_path {
        let file = match File::open(script_path) {
            Ok(file) => file,
            Err(err) => return println_err!("Can't open script file {}\nError: {}", script_path, err),
        };
        _iter_batch(command_executor, BufReader::new(file));
    } else {
        let stdin = std::io::stdin();
        _iter_batch(command_executor, stdin.lock());
    };
    command_executor.ctx().set_not_batch_mode();
}

fn _load_plugins(command_executor: &CommandExecutor, plugins_str: &str) {
    for plugin in plugins_str.split(",") {
        let parts: Vec<&str> = plugin.split(":").collect::<Vec<&str>>();

        let name = unwrap_or_return!(parts.get(0), println_err!("Plugin Name not found in {}", plugin));
        let init_func = unwrap_or_return!(parts.get(1), println_err!("Plugin Init function not found in {}", plugin));

        common::load_plugin(command_executor.ctx(), name, init_func).ok();
    }
}

fn _print_help() {
    println_acc!("Hyperledger Indy CLI");
    println!();
    println_acc!("CLI supports 2 execution modes:");
    println_acc!("\tInteractive - reads commands from terminal. To start just run indy-cli without params.");
    println_acc!("\tUsage: indy-cli");
    println!();
    println_acc!("\tBatch - all commands will be read from text file or pipe and executed in series.");
    println_acc!("\tUsage: indy-cli <path-to-text-file>");
    println!();
    println_acc!("Options:");
    println_acc!("\tLoad plugins in Libindy.");
    println_acc!("\tUsage: indy-cli --plugins <lib-1-name>:<init-func-1-name>,...,<lib-n-name>:<init-func-n-name>");
    println!();
    println_acc!("\tInit logger according to a config file. \n\tIndy Cli uses `log4rs` logging framework: https://crates.io/crates/log4rs");
    println_acc!("\tUsage: indy-cli --logger-config <path-to-config-file>");
    println!();
    println_acc!("\tUse config file for CLI initialization. A config file can contain the following fields:");
    println_acc!("\t\tplugins - a list of plugins to load in Libindy (is equal to usage of \"--plugins\" option).");
    println_acc!("\t\tloggerConfig - path to a logger config file (is equal to usage of \"--logger-config\" option).");
    println_acc!("\t\ttaaAcceptanceMechanism - transaction author agreement acceptance mechanism to use for sending write transactions to the Ledger.");
    println_acc!("\tUsage: indy-cli --config <path-to-config-json-file>");
    println!();
}

fn _iter_batch<T>(command_executor: &CommandExecutor, reader: T) where T: std::io::BufRead {
    let mut line_num = 1;
    for line in reader.lines() {
        let line = if let Ok(line) = line { line } else {
            return println_err!("Can't parse line #{}", line_num);
        };

        if line.starts_with("#") || line.is_empty() {
            // Skip blank lines and lines starting with #
            continue;
        }

        println!("{}", line);
        let (line, force) = if line.starts_with("-") {
            (line[1..].as_ref(), true)
        } else {
            (line[0..].as_ref(), false)
        };
        if command_executor.execute(line).is_err() && !force {
            return println_err!("Batch execution failed at line #{}", line_num);
        }
        println!();
        line_num += 1;

        if command_executor.ctx().is_exit() {
            break;
        }
    }
}

impl<Term: Terminal> Completer<Term> for CommandExecutor {
    fn complete(&self, word: &str, reader: &Reader<Term>,
                _start: usize, _end: usize) -> Option<Vec<Completion>> {
        Some(self
            .complete(reader.buffer(),
                      word,
                      reader.cursor())
            .into_iter()
            .map(|c| Completion {
                completion: c.0,
                display: None,
                suffix: linefeed::Suffix::Some(c.1),
            })
            .collect())
    }
}
<|endoftext|>


<commit_before>use crate::model::channel::ChannelType;
use crate::model::id::ChannelId;
use crate::model::Permissions;

/// A container for any partial channel.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct PartialChannel {
    /// The channel Id.
    pub id: ChannelId,
    /// The channel name.
    pub name: String,
    /// The channel type.
    #[serde(rename = "type")]
    pub kind: ChannelType,
    /// The channel permissions.
    pub permissions: Option<Permissions>,
}
<commit_msg>Fix parsing interactions with DM channel argument (#1819)<commit_after>use crate::model::channel::ChannelType;
use crate::model::id::ChannelId;
use crate::model::Permissions;

/// A container for any partial channel.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct PartialChannel {
    /// The channel Id.
    pub id: ChannelId,
    /// The channel name.
    pub name: Option<String>,
    /// The channel type.
    #[serde(rename = "type")]
    pub kind: ChannelType,
    /// The channel permissions.
    pub permissions: Option<Permissions>,
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use syntax::{
    ast::{self, AstNode, AstToken},
    match_ast, NodeOrToken, SyntaxElement, TextSize, T,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: remove_dbg
//
// Removes `dbg!()` macro call.
//
// ```
// fn main() {
//     $0dbg!(92);
// }
// ```
// ->
// ```
// fn main() {
//     92;
// }
// ```
pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
    let tt = macro_call.token_tree()?;
    let r_delim = NodeOrToken::Token(tt.right_delimiter_token()?);
    if macro_call.path()?.segment()?.name_ref()?.text() != "dbg"
        || macro_call.excl_token().is_none()
    {
        return None;
    }

    let mac_input = tt.syntax().children_with_tokens().skip(1).take_while(|it| *it != r_delim);
    let input_expressions = mac_input.group_by(|tok| tok.kind() == T![,]);
    let input_expressions = input_expressions
        .into_iter()
        .filter_map(|(is_sep, group)| (!is_sep).then(|| group))
        .map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join("")))
        .collect::<Option<Vec<ast::Expr>>>()?;

    let macro_expr = ast::MacroExpr::cast(macro_call.syntax().parent()?)?;
    let parent = macro_expr.syntax().parent()?;
    let (range, text) = match &*input_expressions {
        // dbg!()
        [] => {
            match_ast! {
                match parent {
                    ast::StmtList(__) => {
                        let range = macro_expr.syntax().text_range();
                        let range = match whitespace_start(macro_expr.syntax().prev_sibling_or_token()) {
                            Some(start) => range.cover_offset(start),
                            None => range,
                        };
                        (range, String::new())
                    },
                    ast::ExprStmt(it) => {
                        let range = it.syntax().text_range();
                        let range = match whitespace_start(it.syntax().prev_sibling_or_token()) {
                            Some(start) => range.cover_offset(start),
                            None => range,
                        };
                        (range, String::new())
                    },
                    _ => (macro_call.syntax().text_range(), "()".to_owned())
                }
            }
        }
        // dbg!(expr0)
        [expr] => {
            let wrap = match ast::Expr::cast(parent) {
                Some(parent) => match (expr, parent) {
                    (ast::Expr::CastExpr(_), ast::Expr::CastExpr(_)) => false,
                    (
                        ast::Expr::BoxExpr(_) | ast::Expr::PrefixExpr(_) | ast::Expr::RefExpr(_),
                        ast::Expr::AwaitExpr(_)
                        | ast::Expr::CallExpr(_)
                        | ast::Expr::CastExpr(_)
                        | ast::Expr::FieldExpr(_)
                        | ast::Expr::IndexExpr(_)
                        | ast::Expr::MethodCallExpr(_)
                        | ast::Expr::RangeExpr(_)
                        | ast::Expr::TryExpr(_),
                    ) => true,
                    (
                        ast::Expr::BinExpr(_) | ast::Expr::CastExpr(_) | ast::Expr::RangeExpr(_),
                        ast::Expr::AwaitExpr(_)
                        | ast::Expr::BinExpr(_)
                        | ast::Expr::CallExpr(_)
                        | ast::Expr::CastExpr(_)
                        | ast::Expr::FieldExpr(_)
                        | ast::Expr::IndexExpr(_)
                        | ast::Expr::MethodCallExpr(_)
                        | ast::Expr::PrefixExpr(_)
                        | ast::Expr::RangeExpr(_)
                        | ast::Expr::RefExpr(_)
                        | ast::Expr::TryExpr(_),
                    ) => true,
                    _ => false,
                },
                None => false,
            };
            (
                macro_call.syntax().text_range(),
                if wrap { format!("({expr})") } else { expr.to_string() },
            )
        }
        // dbg!(expr0, expr1, ...)
        exprs => (macro_call.syntax().text_range(), format!("({})", exprs.iter().format(", "))),
    };

    acc.add(AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", range, |builder| {
        builder.replace(range, text);
    })
}

fn whitespace_start(it: Option<SyntaxElement>) -> Option<TextSize> {
    Some(it?.into_token().and_then(ast::Whitespace::cast)?.syntax().text_range().start())
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    fn check(ra_fixture_before: &str, ra_fixture_after: &str) {
        check_assist(
            remove_dbg,
            &format!("fn main() {{\n{ra_fixture_before}\n}}"),
            &format!("fn main() {{\n{ra_fixture_after}\n}}"),
        );
    }

    #[test]
    fn test_remove_dbg() {
        check("$0dbg!(1 + 1)", "1 + 1");
        check("dbg!$0(1 + 1)", "1 + 1");
        check("dbg!(1 $0+ 1)", "1 + 1");
        check("dbg![$01 + 1]", "1 + 1");
        check("dbg!{$01 + 1}", "1 + 1");
    }

    #[test]
    fn test_remove_dbg_not_applicable() {
        check_assist_not_applicable(remove_dbg, "fn main() {$0vec![1, 2, 3]}");
        check_assist_not_applicable(remove_dbg, "fn main() {$0dbg(5, 6, 7)}");
        check_assist_not_applicable(remove_dbg, "fn main() {$0dbg!(5, 6, 7}");
    }

    #[test]
    fn test_remove_dbg_keep_semicolon_in_let() {
        // https://github.com/rust-lang/rust-analyzer/issues/5129#issuecomment-651399779
        check(
            r#"let res = $0dbg!(1 * 20); // needless comment"#,
            r#"let res = 1 * 20; // needless comment"#,
        );
        check(r#"let res = $0dbg!(); // needless comment"#, r#"let res = (); // needless comment"#);
        check(
            r#"let res = $0dbg!(1, 2); // needless comment"#,
            r#"let res = (1, 2); // needless comment"#,
        );
    }

    #[test]
    fn test_remove_dbg_cast_cast() {
        check(r#"let res = $0dbg!(x as u32) as u32;"#, r#"let res = x as u32 as u32;"#);
    }

    #[test]
    fn test_remove_dbg_prefix() {
        check(r#"let res = $0dbg!(&result).foo();"#, r#"let res = (&result).foo();"#);
        check(r#"let res = &$0dbg!(&result);"#, r#"let res = &&result;"#);
        check(r#"let res = $0dbg!(!result) && true;"#, r#"let res = !result && true;"#);
    }

    #[test]
    fn test_remove_dbg_post_expr() {
        check(r#"let res = $0dbg!(fut.await).foo();"#, r#"let res = fut.await.foo();"#);
        check(r#"let res = $0dbg!(result?).foo();"#, r#"let res = result?.foo();"#);
        check(r#"let res = $0dbg!(foo as u32).foo();"#, r#"let res = (foo as u32).foo();"#);
        check(r#"let res = $0dbg!(array[3]).foo();"#, r#"let res = array[3].foo();"#);
        check(r#"let res = $0dbg!(tuple.3).foo();"#, r#"let res = tuple.3.foo();"#);
    }

    #[test]
    fn test_remove_dbg_range_expr() {
        check(r#"let res = $0dbg!(foo..bar).foo();"#, r#"let res = (foo..bar).foo();"#);
        check(r#"let res = $0dbg!(foo..=bar).foo();"#, r#"let res = (foo..=bar).foo();"#);
    }

    #[test]
    fn test_remove_empty_dbg() {
        check_assist(remove_dbg, r#"fn foo() { $0dbg!(); }"#, r#"fn foo() { }"#);
        check_assist(
            remove_dbg,
            r#"
fn foo() {
    $0dbg!();
}
"#,
            r#"
fn foo() {
}
"#,
        );
        check_assist(
            remove_dbg,
            r#"
fn foo() {
    let test = $0dbg!();
}"#,
            r#"
fn foo() {
    let test = ();
}"#,
        );
        check_assist(
            remove_dbg,
            r#"
fn foo() {
    let t = {
        println!("Hello, world");
        $0dbg!()
    };
}"#,
            r#"
fn foo() {
    let t = {
        println!("Hello, world");
    };
}"#,
        );
    }

    #[test]
    fn test_remove_multi_dbg() {
        check(r#"$0dbg!(0, 1)"#, r#"(0, 1)"#);
        check(r#"$0dbg!(0, (1, 2))"#, r#"(0, (1, 2))"#);
    }
}
<commit_msg>Auto merge of #13629 - jonas-schievink:remove-dbg-selection, r=jonas-schievink<commit_after>use itertools::Itertools;
use syntax::{
    ast::{self, AstNode, AstToken},
    match_ast, NodeOrToken, SyntaxElement, TextRange, TextSize, T,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: remove_dbg
//
// Removes `dbg!()` macro call.
//
// ```
// fn main() {
//     $0dbg!(92);
// }
// ```
// ->
// ```
// fn main() {
//     92;
// }
// ```
pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
    let macro_calls = if ctx.has_empty_selection() {
        vec![ctx.find_node_at_offset::<ast::MacroCall>()?]
    } else {
        ctx.covering_element()
            .as_node()?
            .descendants()
            .filter(|node| ctx.selection_trimmed().contains_range(node.text_range()))
            .filter_map(ast::MacroCall::cast)
            .collect()
    };

    let replacements =
        macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::<Vec<_>>();
    if replacements.is_empty() {
        return None;
    }

    acc.add(
        AssistId("remove_dbg", AssistKind::Refactor),
        "Remove dbg!()",
        ctx.selection_trimmed(),
        |builder| {
            for (range, text) in replacements {
                builder.replace(range, text);
            }
        },
    )
}

fn compute_dbg_replacement(macro_call: ast::MacroCall) -> Option<(TextRange, String)> {
    let tt = macro_call.token_tree()?;
    let r_delim = NodeOrToken::Token(tt.right_delimiter_token()?);
    if macro_call.path()?.segment()?.name_ref()?.text() != "dbg"
        || macro_call.excl_token().is_none()
    {
        return None;
    }

    let mac_input = tt.syntax().children_with_tokens().skip(1).take_while(|it| *it != r_delim);
    let input_expressions = mac_input.group_by(|tok| tok.kind() == T![,]);
    let input_expressions = input_expressions
        .into_iter()
        .filter_map(|(is_sep, group)| (!is_sep).then(|| group))
        .map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join("")))
        .collect::<Option<Vec<ast::Expr>>>()?;

    let macro_expr = ast::MacroExpr::cast(macro_call.syntax().parent()?)?;
    let parent = macro_expr.syntax().parent()?;
    Some(match &*input_expressions {
        // dbg!()
        [] => {
            match_ast! {
                match parent {
                    ast::StmtList(__) => {
                        let range = macro_expr.syntax().text_range();
                        let range = match whitespace_start(macro_expr.syntax().prev_sibling_or_token()) {
                            Some(start) => range.cover_offset(start),
                            None => range,
                        };
                        (range, String::new())
                    },
                    ast::ExprStmt(it) => {
                        let range = it.syntax().text_range();
                        let range = match whitespace_start(it.syntax().prev_sibling_or_token()) {
                            Some(start) => range.cover_offset(start),
                            None => range,
                        };
                        (range, String::new())
                    },
                    _ => (macro_call.syntax().text_range(), "()".to_owned())
                }
            }
        }
        // dbg!(expr0)
        [expr] => {
            let wrap = match ast::Expr::cast(parent) {
                Some(parent) => match (expr, parent) {
                    (ast::Expr::CastExpr(_), ast::Expr::CastExpr(_)) => false,
                    (
                        ast::Expr::BoxExpr(_) | ast::Expr::PrefixExpr(_) | ast::Expr::RefExpr(_),
                        ast::Expr::AwaitExpr(_)
                        | ast::Expr::CallExpr(_)
                        | ast::Expr::CastExpr(_)
                        | ast::Expr::FieldExpr(_)
                        | ast::Expr::IndexExpr(_)
                        | ast::Expr::MethodCallExpr(_)
                        | ast::Expr::RangeExpr(_)
                        | ast::Expr::TryExpr(_),
                    ) => true,
                    (
                        ast::Expr::BinExpr(_) | ast::Expr::CastExpr(_) | ast::Expr::RangeExpr(_),
                        ast::Expr::AwaitExpr(_)
                        | ast::Expr::BinExpr(_)
                        | ast::Expr::CallExpr(_)
                        | ast::Expr::CastExpr(_)
                        | ast::Expr::FieldExpr(_)
                        | ast::Expr::IndexExpr(_)
                        | ast::Expr::MethodCallExpr(_)
                        | ast::Expr::PrefixExpr(_)
                        | ast::Expr::RangeExpr(_)
                        | ast::Expr::RefExpr(_)
                        | ast::Expr::TryExpr(_),
                    ) => true,
                    _ => false,
                },
                None => false,
            };
            (
                macro_call.syntax().text_range(),
                if wrap { format!("({expr})") } else { expr.to_string() },
            )
        }
        // dbg!(expr0, expr1, ...)
        exprs => (macro_call.syntax().text_range(), format!("({})", exprs.iter().format(", "))),
    })
}

fn whitespace_start(it: Option<SyntaxElement>) -> Option<TextSize> {
    Some(it?.into_token().and_then(ast::Whitespace::cast)?.syntax().text_range().start())
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    fn check(ra_fixture_before: &str, ra_fixture_after: &str) {
        check_assist(
            remove_dbg,
            &format!("fn main() {{\n{ra_fixture_before}\n}}"),
            &format!("fn main() {{\n{ra_fixture_after}\n}}"),
        );
    }

    #[test]
    fn test_remove_dbg() {
        check("$0dbg!(1 + 1)", "1 + 1");
        check("dbg!$0(1 + 1)", "1 + 1");
        check("dbg!(1 $0+ 1)", "1 + 1");
        check("dbg![$01 + 1]", "1 + 1");
        check("dbg!{$01 + 1}", "1 + 1");
    }

    #[test]
    fn test_remove_dbg_not_applicable() {
        check_assist_not_applicable(remove_dbg, "fn main() {$0vec![1, 2, 3]}");
        check_assist_not_applicable(remove_dbg, "fn main() {$0dbg(5, 6, 7)}");
        check_assist_not_applicable(remove_dbg, "fn main() {$0dbg!(5, 6, 7}");
    }

    #[test]
    fn test_remove_dbg_keep_semicolon_in_let() {
        // https://github.com/rust-lang/rust-analyzer/issues/5129#issuecomment-651399779
        check(
            r#"let res = $0dbg!(1 * 20); // needless comment"#,
            r#"let res = 1 * 20; // needless comment"#,
        );
        check(r#"let res = $0dbg!(); // needless comment"#, r#"let res = (); // needless comment"#);
        check(
            r#"let res = $0dbg!(1, 2); // needless comment"#,
            r#"let res = (1, 2); // needless comment"#,
        );
    }

    #[test]
    fn test_remove_dbg_cast_cast() {
        check(r#"let res = $0dbg!(x as u32) as u32;"#, r#"let res = x as u32 as u32;"#);
    }

    #[test]
    fn test_remove_dbg_prefix() {
        check(r#"let res = $0dbg!(&result).foo();"#, r#"let res = (&result).foo();"#);
        check(r#"let res = &$0dbg!(&result);"#, r#"let res = &&result;"#);
        check(r#"let res = $0dbg!(!result) && true;"#, r#"let res = !result && true;"#);
    }

    #[test]
    fn test_remove_dbg_post_expr() {
        check(r#"let res = $0dbg!(fut.await).foo();"#, r#"let res = fut.await.foo();"#);
        check(r#"let res = $0dbg!(result?).foo();"#, r#"let res = result?.foo();"#);
        check(r#"let res = $0dbg!(foo as u32).foo();"#, r#"let res = (foo as u32).foo();"#);
        check(r#"let res = $0dbg!(array[3]).foo();"#, r#"let res = array[3].foo();"#);
        check(r#"let res = $0dbg!(tuple.3).foo();"#, r#"let res = tuple.3.foo();"#);
    }

    #[test]
    fn test_remove_dbg_range_expr() {
        check(r#"let res = $0dbg!(foo..bar).foo();"#, r#"let res = (foo..bar).foo();"#);
        check(r#"let res = $0dbg!(foo..=bar).foo();"#, r#"let res = (foo..=bar).foo();"#);
    }

    #[test]
    fn test_remove_empty_dbg() {
        check_assist(remove_dbg, r#"fn foo() { $0dbg!(); }"#, r#"fn foo() { }"#);
        check_assist(
            remove_dbg,
            r#"
fn foo() {
    $0dbg!();
}
"#,
            r#"
fn foo() {
}
"#,
        );
        check_assist(
            remove_dbg,
            r#"
fn foo() {
    let test = $0dbg!();
}"#,
            r#"
fn foo() {
    let test = ();
}"#,
        );
        check_assist(
            remove_dbg,
            r#"
fn foo() {
    let t = {
        println!("Hello, world");
        $0dbg!()
    };
}"#,
            r#"
fn foo() {
    let t = {
        println!("Hello, world");
    };
}"#,
        );
    }

    #[test]
    fn test_remove_multi_dbg() {
        check(r#"$0dbg!(0, 1)"#, r#"(0, 1)"#);
        check(r#"$0dbg!(0, (1, 2))"#, r#"(0, (1, 2))"#);
    }

    #[test]
    fn test_range() {
        check(
            r#"
fn f() {
    dbg!(0) + $0dbg!(1);
    dbg!(())$0
}
"#,
            r#"
fn f() {
    dbg!(0) + 1;
    ()
}
"#,
        );
    }

    #[test]
    fn test_range_partial() {
        check_assist_not_applicable(remove_dbg, r#"$0dbg$0!(0)"#);
        check_assist_not_applicable(remove_dbg, r#"$0dbg!(0$0)"#);
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a `Waker`, which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless polled"]
#[stable(feature = "futures_api", since = "1.36.0")]
pub trait Future {
    /// The type of value produced on completion.
    #[stable(feature = "futures_api", since = "1.36.0")]
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Context`]: ../task/struct.Context.html
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    #[stable(feature = "futures_api", since = "1.36.0")]
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<commit_msg>Improve the "must use" lint for `Future`<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a `Waker`, which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
pub trait Future {
    /// The type of value produced on completion.
    #[stable(feature = "futures_api", since = "1.36.0")]
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Context`]: ../task/struct.Context.html
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    #[stable(feature = "futures_api", since = "1.36.0")]
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<|endoftext|>


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

use dot;
use rustc::mir::repr::*;
use rustc::middle::ty;
use std::fmt::Debug;
use std::io::{self, Write};

/// Write a graphviz DOT graph for the given MIR.
pub fn write_mir_graphviz<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(writeln!(w, "digraph Mir {{"));

    // Global graph properties
    try!(writeln!(w, r#"    graph [fontname="monospace"];"#));
    try!(writeln!(w, r#"    node [fontname="monospace"];"#));
    try!(writeln!(w, r#"    edge [fontname="monospace"];"#));

    // Graph label
    try!(write_graph_label(mir, w));

    // Nodes
    for block in mir.all_basic_blocks() {
        try!(write_node(block, mir, w));
    }

    // Edges
    for source in mir.all_basic_blocks() {
        try!(write_edges(source, mir, w));
    }

    writeln!(w, "}}")
}

/// Write a graphviz DOT node for the given basic block.
fn write_node<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
    let data = mir.basic_block_data(block);

    // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
    try!(write!(w, r#"    {} [shape="none", label=<"#, node(block)));
    try!(write!(w, r#"
"#));

    // Basic block number at the top.
    try!(write!(w, r#"
{}
"#, block.index()));

    // List of statements in the middle.
    if !data.statements.is_empty() {
        try!(write!(w, r#"
"#));
        for statement in &data.statements {
            try!(write!(w, "{}
", escape(statement)));
        }
        try!(write!(w, "
"));
    }

    // Terminator head at the bottom, not including the list of successor blocks. Those will be
    // displayed as labels on the edges between blocks.
    let mut terminator_head = String::new();
    data.terminator.fmt_head(&mut terminator_head).unwrap();
    try!(write!(w, r#"
{}
"#, dot::escape_html(&terminator_head)));

    // Close the table, node label, and the node itself.
    writeln!(w, "
>];")
}

/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
    let terminator = &mir.basic_block_data(source).terminator;
    let labels = terminator.fmt_successor_labels();

    for (&target, label) in terminator.successors().iter().zip(labels) {
        try!(writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label));
    }

    Ok(())
}

/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn write_graph_label<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(write!(w, "    label=<fn("));

    // fn argument types.
    for (i, arg) in mir.arg_decls.iter().enumerate() {
        if i > 0 {
            try!(write!(w, ", "));
        }
        try!(write!(w, "a{}: {}", i, escape(&arg.ty)));
    }

    try!(write!(w, ") -> "));

    // fn return type.
    match mir.return_ty {
        ty::FnOutput::FnConverging(ty) => try!(write!(w, "{}", escape(ty))),
        ty::FnOutput::FnDiverging => try!(write!(w, "!")),
    }

    try!(write!(w, r#"
"#));

    // User variable types (including the user's name in a comment).
    for (i, var) in mir.var_decls.iter().enumerate() {
        try!(write!(w, "let "));
        if var.mutability == Mutability::Mut {
            try!(write!(w, "mut "));
        }
        try!(write!(w, r#"v{}: {}; // {}
"#, i, escape(&var.ty), var.name));
    }

    // Compiler-introduced temporary types.
    for (i, temp) in mir.temp_decls.iter().enumerate() {
        try!(write!(w, r#"let t{}: {};
"#, i, escape(&temp.ty)));
    }

    writeln!(w, ">;")
}

fn node(block: BasicBlock) -> String {
    format!("bb{}", block.index())
}

fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{:?}", t))
}
<commit_msg>Fix MIR var names and keep them in sync.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use dot;
use rustc::mir::repr::*;
use rustc::middle::ty;
use std::fmt::Debug;
use std::io::{self, Write};

/// Write a graphviz DOT graph for the given MIR.
pub fn write_mir_graphviz<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(writeln!(w, "digraph Mir {{"));

    // Global graph properties
    try!(writeln!(w, r#"    graph [fontname="monospace"];"#));
    try!(writeln!(w, r#"    node [fontname="monospace"];"#));
    try!(writeln!(w, r#"    edge [fontname="monospace"];"#));

    // Graph label
    try!(write_graph_label(mir, w));

    // Nodes
    for block in mir.all_basic_blocks() {
        try!(write_node(block, mir, w));
    }

    // Edges
    for source in mir.all_basic_blocks() {
        try!(write_edges(source, mir, w));
    }

    writeln!(w, "}}")
}

/// Write a graphviz DOT node for the given basic block.
fn write_node<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
    let data = mir.basic_block_data(block);

    // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
    try!(write!(w, r#"    {} [shape="none", label=<"#, node(block)));
    try!(write!(w, r#"
"#));

    // Basic block number at the top.
    try!(write!(w, r#"
{}
"#, block.index()));

    // List of statements in the middle.
    if !data.statements.is_empty() {
        try!(write!(w, r#"
"#));
        for statement in &data.statements {
            try!(write!(w, "{}
", escape(statement)));
        }
        try!(write!(w, "
"));
    }

    // Terminator head at the bottom, not including the list of successor blocks. Those will be
    // displayed as labels on the edges between blocks.
    let mut terminator_head = String::new();
    data.terminator.fmt_head(&mut terminator_head).unwrap();
    try!(write!(w, r#"
{}
"#, dot::escape_html(&terminator_head)));

    // Close the table, node label, and the node itself.
    writeln!(w, "
>];")
}

/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
    let terminator = &mir.basic_block_data(source).terminator;
    let labels = terminator.fmt_successor_labels();

    for (&target, label) in terminator.successors().iter().zip(labels) {
        try!(writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label));
    }

    Ok(())
}

/// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
/// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
/// all the variables and temporaries.
fn write_graph_label<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
    try!(write!(w, "    label=<fn("));

    // fn argument types.
    for (i, arg) in mir.arg_decls.iter().enumerate() {
        if i > 0 {
            try!(write!(w, ", "));
        }
        try!(write!(w, "{:?}: {}", Lvalue::Arg(i as u32), escape(&arg.ty)));
    }

    try!(write!(w, ") -> "));

    // fn return type.
    match mir.return_ty {
        ty::FnOutput::FnConverging(ty) => try!(write!(w, "{}", escape(ty))),
        ty::FnOutput::FnDiverging => try!(write!(w, "!")),
    }

    try!(write!(w, r#"
"#));

    // User variable types (including the user's name in a comment).
    for (i, var) in mir.var_decls.iter().enumerate() {
        try!(write!(w, "let "));
        if var.mutability == Mutability::Mut {
            try!(write!(w, "mut "));
        }
        try!(write!(w, r#"{:?}: {}; // {}
"#,
                    Lvalue::Var(i as u32), escape(&var.ty), var.name));
    }

    // Compiler-introduced temporary types.
    for (i, temp) in mir.temp_decls.iter().enumerate() {
        try!(write!(w, r#"let {:?}: {};
"#,
                    Lvalue::Temp(i as u32), escape(&temp.ty)));
    }

    writeln!(w, ">;")
}

fn node(block: BasicBlock) -> String {
    format!("bb{}", block.index())
}

fn escape<T: Debug>(t: &T) -> String {
    dot::escape_html(&format!("{:?}", t))
}
<|endoftext|>


<commit_before>use std::any::TypeId;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker;

use crate::descriptor::EnumDescriptorProto;
use crate::descriptor::EnumValueDescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::enums::ProtobufEnum;
use crate::enums::ProtobufEnumOrUnknown;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;
use crate::reflect::ProtobufValue;

/// Description for enum variant.
///
/// Used in reflection.
#[derive(Clone)]
pub struct EnumValueDescriptor {
    proto: &'static EnumValueDescriptorProto,
    protobuf_value: &'static dyn ProtobufValue,
    get_descriptor: &'static dyn GetEnumDescriptor,
}

impl PartialEq for EnumValueDescriptor {
    fn eq(&self, other: &EnumValueDescriptor) -> bool {
        self.enum_descriptor() == other.enum_descriptor() && self.value() == other.value()
    }
}

impl Hash for EnumValueDescriptor {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&self.value(), state)
    }
}

fn _assert_send_sync() {
    fn _assert_send_sync<T: Send + Sync>() {}
    _assert_send_sync::<EnumValueDescriptor>();
}

impl fmt::Debug for EnumValueDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumValueDescriptor")
            .field("proto", self.proto)
            .field("value", &"...")
            .finish()
    }
}

impl Copy for EnumValueDescriptor {}

impl EnumValueDescriptor {
    /// Name of enum variant as specified in proto file
    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    /// `i32` value of the enum variant
    pub fn value(&self) -> i32 {
        self.proto.get_number()
    }

    /// Convert to generic `ProtobufValue`
    pub fn protobuf_value(&self) -> &'static dyn ProtobufValue {
        self.protobuf_value
    }

    /// Get descriptor of enum holding this value.
    pub fn enum_descriptor(&self) -> &EnumDescriptor {
        self.get_descriptor.descriptor()
    }

    /// Convert this value descriptor into proper enum object.
    ///
    /// See [`EnumDescriptor::cast`](crate::reflect::EnumDescriptor::cast) for more details.
    pub fn cast<E: ProtobufEnum>(&self) -> Option<E> {
        self.enum_descriptor().cast_to_protobuf_enum(self.value())
    }
}

trait GetEnumDescriptor: Send + Sync + 'static {
    fn descriptor(&self) -> &EnumDescriptor;
    unsafe fn copy_to(&self, value: i32, dest: *mut ());
}

struct GetDescriptorImpl<E: ProtobufEnum>(marker::PhantomData<E>);

impl<E: ProtobufEnum> GetEnumDescriptor for GetDescriptorImpl<E> {
    fn descriptor(&self) -> &EnumDescriptor {
        E::enum_descriptor_static()
    }

    unsafe fn copy_to(&self, value: i32, dest: *mut ()) {
        let e = E::from_i32(value).expect("unknown value");
        (&e as *const E).copy_to(dest as *mut E, 1);
    }
}

/// Dynamic representation of enum type.
///
/// Can be used in reflective operations.
pub struct EnumDescriptor {
    full_name: String,
    proto: &'static EnumDescriptorProto,
    values: Vec<EnumValueDescriptor>,
    /// Type id of `<E>`
    type_id: TypeId,
    /// Type id of `<ProtobufEnumOrUnknown<E>>`
    enum_or_unknown_type_id: TypeId,

    #[cfg(not(rustc_nightly))]
    get_descriptor: &'static dyn GetEnumDescriptor,

    index_by_name: HashMap<String, usize>,
    index_by_number: HashMap<i32, usize>,
}

impl fmt::Debug for EnumDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumDescriptor")
            .field("full_name", &self.full_name)
            .field("..", &"..")
            .finish()
    }
}

/// Identity comparison: message descriptor are equal if their addresses are equal
impl PartialEq for EnumDescriptor {
    fn eq(&self, other: &EnumDescriptor) -> bool {
        self as *const EnumDescriptor == other as *const EnumDescriptor
    }
}

impl EnumDescriptor {
    /// Enum name as given in `.proto` file
    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    /// Fully qualified protobuf name of enum
    pub fn full_name(&self) -> &str {
        &self.full_name[..]
    }

    /// Get `EnumDescriptor` object for given enum type
    pub fn for_type<E: ProtobufEnum>() -> &'static EnumDescriptor {
        E::enum_descriptor_static()
    }

    fn compute_full_name(
        package: &str,
        path_to_package: &str,
        proto: &EnumDescriptorProto,
    ) -> String {
        let mut full_name = package.to_owned();
        if path_to_package.len() != 0 {
            if full_name.len() != 0 {
                full_name.push('.');
            }
            full_name.push_str(path_to_package);
        }
        if full_name.len() != 0 {
            full_name.push('.');
        }
        full_name.push_str(proto.get_name());
        full_name
    }

    /// Separate function to reduce generated code size bloat.
    fn make_indices(proto: &EnumDescriptorProto) -> (HashMap<String, usize>, HashMap<i32, usize>) {
        let mut index_by_name = HashMap::new();
        let mut index_by_number = HashMap::new();
        for (i, v) in proto.value.iter().enumerate() {
            index_by_number.insert(v.get_number(), i);
            index_by_name.insert(v.get_name().to_string(), i);
        }

        (index_by_name, index_by_number)
    }

    /// Construct `EnumDescriptor` given enum name and `FileDescriptorProto`.
    ///
    /// This function is called from generated code, and should rarely be called directly.
    ///
    /// This function is not a part of public API.
    #[doc(hidden)]
    pub fn new<E>(name_in_file: &'static str, file: &'static FileDescriptorProto) -> EnumDescriptor
    where
        E: ProtobufEnum,
    {
        let (path_to_package, proto) = match find_message_or_enum(file, name_in_file) {
            (path_to_package, MessageOrEnum::Enum(e)) => (path_to_package, e),
            (_, MessageOrEnum::Message(_)) => panic!("not an enum"),
        };

        let (index_by_name, index_by_number) = EnumDescriptor::make_indices(proto);

        let proto_values = &proto.value;
        let code_values = E::values();
        assert_eq!(proto_values.len(), code_values.len());

        let get_descriptor = &GetDescriptorImpl(marker::PhantomData::<E>);

        let values = proto_values
            .iter()
            .zip(code_values)
            .map(|(p, c)| EnumValueDescriptor {
                proto: p,
                protobuf_value: c,
                get_descriptor,
            })
            .collect();

        EnumDescriptor {
            full_name: EnumDescriptor::compute_full_name(
                file.get_package(),
                &path_to_package,
                &proto,
            ),
            proto,
            values,
            type_id: TypeId::of::<E>(),
            enum_or_unknown_type_id: TypeId::of::<ProtobufEnumOrUnknown<E>>(),
            #[cfg(not(rustc_nightly))]
            get_descriptor,
            index_by_name,
            index_by_number,
        }
    }

    /// This enum values
    pub fn values(&self) -> &[EnumValueDescriptor] {
        &self.values
    }

    /// Find enum variant by name
    pub fn value_by_name<'a>(&'a self, name: &str) -> Option<&'a EnumValueDescriptor> {
        let &index = self.index_by_name.get(name)?;
        Some(&self.values[index])
    }

    /// Find enum variant by number
    pub fn value_by_number(&self, number: i32) -> Option<&EnumValueDescriptor> {
        let &index = self.index_by_number.get(&number)?;
        Some(&self.values[index])
    }

    pub(crate) fn value_by_number_or_default(&self, number: i32) -> &EnumValueDescriptor {
        match self.value_by_number(number) {
            Some(v) => v,
            None => &self.values()[0],
        }
    }

    /// Check if this enum descriptor corresponds given enum type
    ///
    /// ```
    /// # use protobuf::ProtobufEnum;
    /// # use protobuf::descriptor::field_descriptor_proto::Label;
    /// # use protobuf::reflect::EnumDescriptor;
    ///
    /// let descriptor: &EnumDescriptor = Label::enum_descriptor_static();
    ///
    /// assert!(descriptor.is::<Label>())
    /// ```
    pub fn is<E: ProtobufEnum>(&self) -> bool {
        TypeId::of::<E>() == self.type_id
    }

    /// Create enum object from given value.
    ///
    /// Type parameter `E` can be either [`ProtobufEnum`](crate::ProtobufEnum)
    /// or [`ProtobufEnumOrUnknown`](crate::ProtobufEnumOrUnknown).
    ///
    /// # Panics
    ///
    /// This operation panics of `E` is `ProtobufEnum` and `value` is unknown.
    pub(crate) fn cast<E: 'static>(&self, value: i32) -> Option<E> {
        if TypeId::of::<E>() == self.type_id {
            Some(self.cast_to_protobuf_enum(value))
        } else if TypeId::of::<E>() == self.enum_or_unknown_type_id {
            Some(self.cast_to_protobuf_enum_or_unknown(value))
        } else {
            None
        }
    }

    #[cfg(rustc_nightly)]
    fn cast_to_protobuf_enum<E: 'static>(&self, value: i32) -> E {
        <E as cast_impl::CastValueToProtobufEnum>::cast(value).unwrap()
    }

    #[cfg(not(rustc_nightly))]
    fn cast_to_protobuf_enum<E: 'static>(&self, value: i32) -> E {
        use std::mem;
        unsafe {
            let mut r = mem::uninitialized();
            self.get_descriptor
                .copy_to(value, &mut r as *mut E as *mut ());
            r
        }
    }

    #[cfg(rustc_nightly)]
    fn cast_to_protobuf_enum_or_unknown<E: 'static>(&self, value: i32) -> E {
        <E as cast_impl::CastValueToProtobufEnumOrUnknown>::cast(value).unwrap()
    }

    #[cfg(not(rustc_nightly))]
    fn cast_to_protobuf_enum_or_unknown<E: 'static>(&self, value: i32) -> E {
        use std::mem;
        use std::ptr;
        debug_assert_eq!(mem::size_of::<E>(), mem::size_of::<i32>());
        unsafe {
            // This works because `ProtobufEnumOrUnknown<E>` is `#[repr(transparent)]`
            let mut r = mem::uninitialized();
            ptr::copy(&value, &mut r as *mut E as *mut i32, 1);
            r
        }
    }
}

#[cfg(rustc_nightly)]
mod cast_impl {
    use super::*;

    pub(crate) trait CastValueToProtobufEnumOrUnknown: Sized {
        fn cast(value: i32) -> Option<Self>;
    }

    impl<T> CastValueToProtobufEnumOrUnknown for T {
        default fn cast(_value: i32) -> Option<T> {
            None
        }
    }

    impl<E: ProtobufEnum> CastValueToProtobufEnumOrUnknown for ProtobufEnumOrUnknown<E> {
        fn cast(value: i32) -> Option<ProtobufEnumOrUnknown<E>> {
            Some(ProtobufEnumOrUnknown::from_i32(value))
        }
    }

    pub(crate) trait CastValueToProtobufEnum: Sized {
        fn cast(value: i32) -> Option<Self>;
    }

    impl<T> CastValueToProtobufEnum for T {
        default fn cast(_value: i32) -> Option<T> {
            None
        }
    }

    impl<E: ProtobufEnum> CastValueToProtobufEnum for E {
        fn cast(value: i32) -> Option<E> {
            Some(E::from_i32(value).expect(&format!("unknown enum value: {}", value)))
        }
    }
}
<commit_msg>Remove outdated comment<commit_after>use std::any::TypeId;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker;

use crate::descriptor::EnumDescriptorProto;
use crate::descriptor::EnumValueDescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::enums::ProtobufEnum;
use crate::enums::ProtobufEnumOrUnknown;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;
use crate::reflect::ProtobufValue;

/// Description for enum variant.
///
/// Used in reflection.
#[derive(Clone)]
pub struct EnumValueDescriptor {
    proto: &'static EnumValueDescriptorProto,
    protobuf_value: &'static dyn ProtobufValue,
    get_descriptor: &'static dyn GetEnumDescriptor,
}

impl PartialEq for EnumValueDescriptor {
    fn eq(&self, other: &EnumValueDescriptor) -> bool {
        self.enum_descriptor() == other.enum_descriptor() && self.value() == other.value()
    }
}

impl Hash for EnumValueDescriptor {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&self.value(), state)
    }
}

fn _assert_send_sync() {
    fn _assert_send_sync<T: Send + Sync>() {}
    _assert_send_sync::<EnumValueDescriptor>();
}

impl fmt::Debug for EnumValueDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumValueDescriptor")
            .field("proto", self.proto)
            .field("value", &"...")
            .finish()
    }
}

impl Copy for EnumValueDescriptor {}

impl EnumValueDescriptor {
    /// Name of enum variant as specified in proto file
    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    /// `i32` value of the enum variant
    pub fn value(&self) -> i32 {
        self.proto.get_number()
    }

    /// Convert to generic `ProtobufValue`
    pub fn protobuf_value(&self) -> &'static dyn ProtobufValue {
        self.protobuf_value
    }

    /// Get descriptor of enum holding this value.
    pub fn enum_descriptor(&self) -> &EnumDescriptor {
        self.get_descriptor.descriptor()
    }

    /// Convert this value descriptor into proper enum object.
    pub fn cast<E: ProtobufEnum>(&self) -> Option<E> {
        self.enum_descriptor().cast_to_protobuf_enum(self.value())
    }
}

trait GetEnumDescriptor: Send + Sync + 'static {
    fn descriptor(&self) -> &EnumDescriptor;
    unsafe fn copy_to(&self, value: i32, dest: *mut ());
}

struct GetDescriptorImpl<E: ProtobufEnum>(marker::PhantomData<E>);

impl<E: ProtobufEnum> GetEnumDescriptor for GetDescriptorImpl<E> {
    fn descriptor(&self) -> &EnumDescriptor {
        E::enum_descriptor_static()
    }

    unsafe fn copy_to(&self, value: i32, dest: *mut ()) {
        let e = E::from_i32(value).expect("unknown value");
        (&e as *const E).copy_to(dest as *mut E, 1);
    }
}

/// Dynamic representation of enum type.
///
/// Can be used in reflective operations.
pub struct EnumDescriptor {
    full_name: String,
    proto: &'static EnumDescriptorProto,
    values: Vec<EnumValueDescriptor>,
    /// Type id of `<E>`
    type_id: TypeId,
    /// Type id of `<ProtobufEnumOrUnknown<E>>`
    enum_or_unknown_type_id: TypeId,

    #[cfg(not(rustc_nightly))]
    get_descriptor: &'static dyn GetEnumDescriptor,

    index_by_name: HashMap<String, usize>,
    index_by_number: HashMap<i32, usize>,
}

impl fmt::Debug for EnumDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumDescriptor")
            .field("full_name", &self.full_name)
            .field("..", &"..")
            .finish()
    }
}

/// Identity comparison: message descriptor are equal if their addresses are equal
impl PartialEq for EnumDescriptor {
    fn eq(&self, other: &EnumDescriptor) -> bool {
        self as *const EnumDescriptor == other as *const EnumDescriptor
    }
}

impl EnumDescriptor {
    /// Enum name as given in `.proto` file
    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    /// Fully qualified protobuf name of enum
    pub fn full_name(&self) -> &str {
        &self.full_name[..]
    }

    /// Get `EnumDescriptor` object for given enum type
    pub fn for_type<E: ProtobufEnum>() -> &'static EnumDescriptor {
        E::enum_descriptor_static()
    }

    fn compute_full_name(
        package: &str,
        path_to_package: &str,
        proto: &EnumDescriptorProto,
    ) -> String {
        let mut full_name = package.to_owned();
        if path_to_package.len() != 0 {
            if full_name.len() != 0 {
                full_name.push('.');
            }
            full_name.push_str(path_to_package);
        }
        if full_name.len() != 0 {
            full_name.push('.');
        }
        full_name.push_str(proto.get_name());
        full_name
    }

    /// Separate function to reduce generated code size bloat.
    fn make_indices(proto: &EnumDescriptorProto) -> (HashMap<String, usize>, HashMap<i32, usize>) {
        let mut index_by_name = HashMap::new();
        let mut index_by_number = HashMap::new();
        for (i, v) in proto.value.iter().enumerate() {
            index_by_number.insert(v.get_number(), i);
            index_by_name.insert(v.get_name().to_string(), i);
        }

        (index_by_name, index_by_number)
    }

    /// Construct `EnumDescriptor` given enum name and `FileDescriptorProto`.
    ///
    /// This function is called from generated code, and should rarely be called directly.
    ///
    /// This function is not a part of public API.
    #[doc(hidden)]
    pub fn new<E>(name_in_file: &'static str, file: &'static FileDescriptorProto) -> EnumDescriptor
    where
        E: ProtobufEnum,
    {
        let (path_to_package, proto) = match find_message_or_enum(file, name_in_file) {
            (path_to_package, MessageOrEnum::Enum(e)) => (path_to_package, e),
            (_, MessageOrEnum::Message(_)) => panic!("not an enum"),
        };

        let (index_by_name, index_by_number) = EnumDescriptor::make_indices(proto);

        let proto_values = &proto.value;
        let code_values = E::values();
        assert_eq!(proto_values.len(), code_values.len());

        let get_descriptor = &GetDescriptorImpl(marker::PhantomData::<E>);

        let values = proto_values
            .iter()
            .zip(code_values)
            .map(|(p, c)| EnumValueDescriptor {
                proto: p,
                protobuf_value: c,
                get_descriptor,
            })
            .collect();

        EnumDescriptor {
            full_name: EnumDescriptor::compute_full_name(
                file.get_package(),
                &path_to_package,
                &proto,
            ),
            proto,
            values,
            type_id: TypeId::of::<E>(),
            enum_or_unknown_type_id: TypeId::of::<ProtobufEnumOrUnknown<E>>(),
            #[cfg(not(rustc_nightly))]
            get_descriptor,
            index_by_name,
            index_by_number,
        }
    }

    /// This enum values
    pub fn values(&self) -> &[EnumValueDescriptor] {
        &self.values
    }

    /// Find enum variant by name
    pub fn value_by_name<'a>(&'a self, name: &str) -> Option<&'a EnumValueDescriptor> {
        let &index = self.index_by_name.get(name)?;
        Some(&self.values[index])
    }

    /// Find enum variant by number
    pub fn value_by_number(&self, number: i32) -> Option<&EnumValueDescriptor> {
        let &index = self.index_by_number.get(&number)?;
        Some(&self.values[index])
    }

    pub(crate) fn value_by_number_or_default(&self, number: i32) -> &EnumValueDescriptor {
        match self.value_by_number(number) {
            Some(v) => v,
            None => &self.values()[0],
        }
    }

    /// Check if this enum descriptor corresponds given enum type
    ///
    /// ```
    /// # use protobuf::ProtobufEnum;
    /// # use protobuf::descriptor::field_descriptor_proto::Label;
    /// # use protobuf::reflect::EnumDescriptor;
    ///
    /// let descriptor: &EnumDescriptor = Label::enum_descriptor_static();
    ///
    /// assert!(descriptor.is::<Label>())
    /// ```
    pub fn is<E: ProtobufEnum>(&self) -> bool {
        TypeId::of::<E>() == self.type_id
    }

    /// Create enum object from given value.
    ///
    /// Type parameter `E` can be either [`ProtobufEnum`](crate::ProtobufEnum)
    /// or [`ProtobufEnumOrUnknown`](crate::ProtobufEnumOrUnknown).
    ///
    /// # Panics
    ///
    /// This operation panics of `E` is `ProtobufEnum` and `value` is unknown.
    pub(crate) fn cast<E: 'static>(&self, value: i32) -> Option<E> {
        if TypeId::of::<E>() == self.type_id {
            Some(self.cast_to_protobuf_enum(value))
        } else if TypeId::of::<E>() == self.enum_or_unknown_type_id {
            Some(self.cast_to_protobuf_enum_or_unknown(value))
        } else {
            None
        }
    }

    #[cfg(rustc_nightly)]
    fn cast_to_protobuf_enum<E: 'static>(&self, value: i32) -> E {
        <E as cast_impl::CastValueToProtobufEnum>::cast(value).unwrap()
    }

    #[cfg(not(rustc_nightly))]
    fn cast_to_protobuf_enum<E: 'static>(&self, value: i32) -> E {
        use std::mem;
        unsafe {
            let mut r = mem::uninitialized();
            self.get_descriptor
                .copy_to(value, &mut r as *mut E as *mut ());
            r
        }
    }

    #[cfg(rustc_nightly)]
    fn cast_to_protobuf_enum_or_unknown<E: 'static>(&self, value: i32) -> E {
        <E as cast_impl::CastValueToProtobufEnumOrUnknown>::cast(value).unwrap()
    }

    #[cfg(not(rustc_nightly))]
    fn cast_to_protobuf_enum_or_unknown<E: 'static>(&self, value: i32) -> E {
        use std::mem;
        use std::ptr;
        debug_assert_eq!(mem::size_of::<E>(), mem::size_of::<i32>());
        unsafe {
            // This works because `ProtobufEnumOrUnknown<E>` is `#[repr(transparent)]`
            let mut r = mem::uninitialized();
            ptr::copy(&value, &mut r as *mut E as *mut i32, 1);
            r
        }
    }
}

#[cfg(rustc_nightly)]
mod cast_impl {
    use super::*;

    pub(crate) trait CastValueToProtobufEnumOrUnknown: Sized {
        fn cast(value: i32) -> Option<Self>;
    }

    impl<T> CastValueToProtobufEnumOrUnknown for T {
        default fn cast(_value: i32) -> Option<T> {
            None
        }
    }

    impl<E: ProtobufEnum> CastValueToProtobufEnumOrUnknown for ProtobufEnumOrUnknown<E> {
        fn cast(value: i32) -> Option<ProtobufEnumOrUnknown<E>> {
            Some(ProtobufEnumOrUnknown::from_i32(value))
        }
    }

    pub(crate) trait CastValueToProtobufEnum: Sized {
        fn cast(value: i32) -> Option<Self>;
    }

    impl<T> CastValueToProtobufEnum for T {
        default fn cast(_value: i32) -> Option<T> {
            None
        }
    }

    impl<E: ProtobufEnum> CastValueToProtobufEnum for E {
        fn cast(value: i32) -> Option<E> {
            Some(E::from_i32(value).expect(&format!("unknown enum value: {}", value)))
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate names;

use clap::{AppSettings, Arg};

use names::{Generator, Name};

fn main() {
    let (naming, amount) = parse_cli_args();
    let mut generator = Generator::with_naming(naming);
    for _ in 0..amount {
        println!("{}", generator.next().unwrap());
    }
}

fn parse_cli_args() -> (Name, usize) {
    const FLAG_NUMBER: &str = "number";
    const ARG_AMOUNT: &str = "amount";

    let app = app_from_crate!()
        .name("names")
        .setting(AppSettings::ColoredHelp)
        .arg(
            Arg::with_name(FLAG_NUMBER)
                .short("n")
                .long(FLAG_NUMBER)
                .help("Adds a random number to the name(s)"),
        ).arg(
            Arg::with_name(ARG_AMOUNT)
                .help("Number of names to generate")
                .default_value("1"),
        );

    let matches = app.get_matches();
    let amount = value_t_or_exit!(matches.value_of(ARG_AMOUNT), usize);
    let naming: Name = if matches.is_present(FLAG_NUMBER) {
        Name::Numbered
    } else {
        Default::default()
    };

    (naming, amount)
}
<commit_msg>[lint] Source formatting due to Rustfmt.<commit_after>#[macro_use]
extern crate clap;
extern crate names;

use clap::{AppSettings, Arg};

use names::{Generator, Name};

fn main() {
    let (naming, amount) = parse_cli_args();
    let mut generator = Generator::with_naming(naming);
    for _ in 0..amount {
        println!("{}", generator.next().unwrap());
    }
}

fn parse_cli_args() -> (Name, usize) {
    const FLAG_NUMBER: &str = "number";
    const ARG_AMOUNT: &str = "amount";

    let app = app_from_crate!()
        .name("names")
        .setting(AppSettings::ColoredHelp)
        .arg(
            Arg::with_name(FLAG_NUMBER)
                .short("n")
                .long(FLAG_NUMBER)
                .help("Adds a random number to the name(s)"),
        )
        .arg(
            Arg::with_name(ARG_AMOUNT)
                .help("Number of names to generate")
                .default_value("1"),
        );

    let matches = app.get_matches();
    let amount = value_t_or_exit!(matches.value_of(ARG_AMOUNT), usize);
    let naming: Name = if matches.is_present(FLAG_NUMBER) {
        Name::Numbered
    } else {
        Default::default()
    };

    (naming, amount)
}
<|endoftext|>


<commit_before>use std::io::IoResult;

use collections::HashMap;
use serialize::{json, Encodable, Encoder};

use backend::Backend;

pub struct JsonBackend {
    pretty: bool,

    entries: Vec<Entry>,
}

#[deriving(Encodable)]
struct Entry {
    ty: ~str,
    value: ~str,
}

impl JsonBackend {
    pub fn new() -> JsonBackend {
        JsonBackend {
            pretty: false,

            entries: Vec::new(),
        }
    }
}

impl Backend for JsonBackend {
    fn configure(&mut self, vars: &HashMap<~str, ~str>) -> Result<(), ~str> {
        match vars.find(&~"pretty") {
            Some(ref value) => {
                self.pretty = match from_str(value.as_slice()) {
                    Some(b) => b,
                    None => {
                        return Err(format!("Bad value for pretty: {}", value));
                    }
                }
            }
            None => {}
        }

        Ok(())
    }

    fn header(&mut self, _w: &mut Writer) -> IoResult<()> {
        Ok(())
    }

    fn code_start(&mut self, _w: &mut Writer) -> IoResult<()> {
        Ok(())
    }

    fn code_end(&mut self, w: &mut Writer) -> IoResult<()> {
        if self.pretty {
            let mut encoder = json::PrettyEncoder::new(w);
            self.entries.encode(&mut encoder);
        } else {
            let mut encoder = json::Encoder::new(w);
            self.entries.encode(&mut encoder);
        }

        Ok(())
    }

    fn start(&mut self, _w: &mut Writer, ty: &str) -> IoResult<()> {
        self.entries.push(Entry {
            ty: ~"start",
            value: ty.to_owned(),
        });

        Ok(())
    }

    fn end(&mut self, _w: &mut Writer, ty: &str) -> IoResult<()> {
        self.entries.push(Entry {
            ty: ~"end",
            value: ty.to_owned(),
        });

        Ok(())
    }

    fn text(&mut self, _w: &mut Writer, text: &str) -> IoResult<()> {
        self.entries.push(Entry {
            ty: ~"text",
            value: text.to_owned(),
        });

        Ok(())
    }
}
<commit_msg>Add JSON header: The output is the map associating colors name and value.<commit_after>use std::io::IoResult;

use collections::HashMap;
use serialize::{json, Encodable, Encoder};

use backend::Backend;
use colors;

pub struct JsonBackend {
    pretty: bool,

    entries: Vec<Entry>,
}

#[deriving(Encodable)]
struct Entry {
    ty: ~str,
    value: ~str,
}

impl JsonBackend {
    pub fn new() -> JsonBackend {
        JsonBackend {
            pretty: false,

            entries: Vec::new(),
        }
    }
}

impl Backend for JsonBackend {
    fn configure(&mut self, vars: &HashMap<~str, ~str>) -> Result<(), ~str> {
        match vars.find(&~"pretty") {
            Some(ref value) => {
                self.pretty = match from_str(value.as_slice()) {
                    Some(b) => b,
                    None => {
                        return Err(format!("Bad value for pretty: {}", value));
                    }
                }
            }
            None => {}
        }

        Ok(())
    }

    fn header(&mut self, w: &mut Writer) -> IoResult<()> {
        let colors = colors::get_colors();

        if self.pretty {
            let mut encoder = json::PrettyEncoder::new(w);
            colors.encode(&mut encoder);
        } else {
            let mut encoder = json::Encoder::new(w);
            colors.encode(&mut encoder);
        }

        Ok(())
    }

    fn code_start(&mut self, _w: &mut Writer) -> IoResult<()> {
        Ok(())
    }

    fn code_end(&mut self, w: &mut Writer) -> IoResult<()> {
        if self.pretty {
            let mut encoder = json::PrettyEncoder::new(w);
            self.entries.encode(&mut encoder);
        } else {
            let mut encoder = json::Encoder::new(w);
            self.entries.encode(&mut encoder);
        }

        Ok(())
    }

    fn start(&mut self, _w: &mut Writer, ty: &str) -> IoResult<()> {
        self.entries.push(Entry {
            ty: ~"start",
            value: ty.to_owned(),
        });

        Ok(())
    }

    fn end(&mut self, _w: &mut Writer, ty: &str) -> IoResult<()> {
        self.entries.push(Entry {
            ty: ~"end",
            value: ty.to_owned(),
        });

        Ok(())
    }

    fn text(&mut self, _w: &mut Writer, text: &str) -> IoResult<()> {
        self.entries.push(Entry {
            ty: ~"text",
            value: text.to_owned(),
        });

        Ok(())
    }
}
<|endoftext|>