<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")]
    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())
    }
}
<commit_msg>IS-1321: CLI persist all command<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;
                }

                let _ = 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 super::loader::Loader;
use super::util;
use crate::error::{Error, Result};
use std::io::{self, Write};
use std::path::Path;
use std::time::Instant;
use std::{fs, str};
use tree_sitter_tags::TagsContext;

pub fn generate_tags(
    loader: &Loader,
    scope: Option<&str>,
    paths: &[String],
    quiet: bool,
    time: bool,
) -> Result<()> {
    let mut lang = None;
    if let Some(scope) = scope {
        lang = loader.language_configuration_for_scope(scope)?;
        if lang.is_none() {
            return Error::err(format!("Unknown scope '{}'", scope));
        }
    }

    let mut context = TagsContext::new();
    let cancellation_flag = util::cancel_on_stdin();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    for path in paths {
        let path = Path::new(&path);
        let (language, language_config) = match lang {
            Some(v) => v,
            None => match loader.language_configuration_for_file_name(path)? {
                Some(v) => v,
                None => {
                    eprintln!("No language found for path {:?}", path);
                    continue;
                }
            },
        };

        if let Some(tags_config) = language_config.tags_config(language)? {
            let indent;
            if paths.len() > 1 {
                if !quiet {
                    writeln!(&mut stdout, "{}", path.to_string_lossy())?;
                }
                indent = "\t"
            } else {
                indent = "";
            };

            let source = fs::read(path)?;
            let t0 = Instant::now();
            let (tagged, _) = context.generate_tags(tags_config, &source, Some(&cancellation_flag))?;
            for tag in tagged {
                let tag = tag?;
                if !quiet {
                    write!(
                        &mut stdout,
                        "{}{:<10}\t | {:<8}\t{} {} - {} `{}`",
                        indent,
                        str::from_utf8(&source[tag.name_range]).unwrap_or(""),
                        &tags_config.syntax_type_name(tag.syntax_type_id),
                        if tag.is_definition { "def" } else { "ref" },
                        tag.span.start,
                        tag.span.end,
                        str::from_utf8(&source[tag.line_range]).unwrap_or(""),
                    )?;
                    if let Some(docs) = tag.docs {
                        if docs.len() > 120 {
                            write!(&mut stdout, "\t{:?}...", &docs[0..120])?;
                        } else {
                            write!(&mut stdout, "\t{:?}", &docs)?;
                        }
                    }
                    writeln!(&mut stdout, "")?;
                }
            }

            if time {
                writeln!(
                    &mut stdout,
                    "{}time: {}ms",
                    indent,
                    t0.elapsed().as_millis(),
                )?;
            }
        } else {
            eprintln!("No tags config found for path {:?}", path);
        }
    }

    Ok(())
}
<commit_msg>Remove otiose pattern match.<commit_after>use super::loader::Loader;
use super::util;
use crate::error::{Error, Result};
use std::io::{self, Write};
use std::path::Path;
use std::time::Instant;
use std::{fs, str};
use tree_sitter_tags::TagsContext;

pub fn generate_tags(
    loader: &Loader,
    scope: Option<&str>,
    paths: &[String],
    quiet: bool,
    time: bool,
) -> Result<()> {
    let mut lang = None;
    if let Some(scope) = scope {
        lang = loader.language_configuration_for_scope(scope)?;
        if lang.is_none() {
            return Error::err(format!("Unknown scope '{}'", scope));
        }
    }

    let mut context = TagsContext::new();
    let cancellation_flag = util::cancel_on_stdin();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    for path in paths {
        let path = Path::new(&path);
        let (language, language_config) = match lang {
            Some(v) => v,
            None => match loader.language_configuration_for_file_name(path)? {
                Some(v) => v,
                None => {
                    eprintln!("No language found for path {:?}", path);
                    continue;
                }
            },
        };

        if let Some(tags_config) = language_config.tags_config(language)? {
            let indent;
            if paths.len() > 1 {
                if !quiet {
                    writeln!(&mut stdout, "{}", path.to_string_lossy())?;
                }
                indent = "\t"
            } else {
                indent = "";
            };

            let source = fs::read(path)?;
            let t0 = Instant::now();
            for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))?.0 {
                let tag = tag?;
                if !quiet {
                    write!(
                        &mut stdout,
                        "{}{:<10}\t | {:<8}\t{} {} - {} `{}`",
                        indent,
                        str::from_utf8(&source[tag.name_range]).unwrap_or(""),
                        &tags_config.syntax_type_name(tag.syntax_type_id),
                        if tag.is_definition { "def" } else { "ref" },
                        tag.span.start,
                        tag.span.end,
                        str::from_utf8(&source[tag.line_range]).unwrap_or(""),
                    )?;
                    if let Some(docs) = tag.docs {
                        if docs.len() > 120 {
                            write!(&mut stdout, "\t{:?}...", &docs[0..120])?;
                        } else {
                            write!(&mut stdout, "\t{:?}", &docs)?;
                        }
                    }
                    writeln!(&mut stdout, "")?;
                }
            }

            if time {
                writeln!(
                    &mut stdout,
                    "{}time: {}ms",
                    indent,
                    t0.elapsed().as_millis(),
                )?;
            }
        } else {
            eprintln!("No tags config found for path {:?}", path);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! An example of how to use a `SpriteBatch` with a `Canvas`.
//!
//! You really want to run this one in release mode.

use ggez::event;
use ggez::graphics::{self, Color};
use ggez::timer;
use ggez::{Context, GameResult};
use std::env;
use std::path;

type Point2 = glam::Vec2;
type Vector2 = glam::Vec2;

struct MainState {
    spritebatch: graphics::spritebatch::SpriteBatch,
    canvas: graphics::Canvas,
    draw_pt: Point2,
    draw_vec: Vector2,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let image = graphics::Image::new(ctx, "/tile.png").unwrap();
        let spritebatch = graphics::spritebatch::SpriteBatch::new(image);
        let canvas = graphics::Canvas::with_window_size(ctx)?;
        let draw_pt = Point2::new(0.0, 0.0);
        let draw_vec = Vector2::new(1.0, 1.0);
        let s = MainState {
            spritebatch,
            canvas,
            draw_pt,
            draw_vec,
        };
        Ok(s)
    }
}

impl MainState {
    fn draw_spritebatch(&mut self, ctx: &mut Context) -> GameResult {
        graphics::set_canvas(ctx, Some(&self.canvas));
        graphics::clear(ctx, Color::WHITE);

        // Freeze the animation so things are easier to see.
        let time = 2000;
        //let time = (timer::duration_to_f64(timer::time_since_start(ctx)) * 1000.0) as u32;
        let cycle = 10_000;
        for x in 0..150 {
            for y in 0..150 {
                let x = x as f32;
                let y = y as f32;
                let p = graphics::DrawParam::new()
                    .dest(Point2::new(x * 10.0, y * 10.0))
                    // scale: graphics::Point::new(0.0625, 0.0625),
                    .scale(Vector2::new(
                        ((time % cycle * 2) as f32 / cycle as f32 * 6.28)
                            .cos()
                            .abs()
                            * 0.0625,
                        ((time % cycle * 2) as f32 / cycle as f32 * 6.28)
                            .cos()
                            .abs()
                            * 0.0625,
                    ))
                    .rotation(-2.0 * ((time % cycle) as f32 / cycle as f32 * 6.28));
                self.spritebatch.add(p);
            }
        }
        let param = graphics::DrawParam::new()
            .dest(Point2::new(
                ((time % cycle) as f32 / cycle as f32 * 6.28).cos() * 50.0 + 150.0,
                ((time % cycle) as f32 / cycle as f32 * 6.28).sin() * 50.0 + 250.0,
            ))
            .scale(Vector2::new(
                ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0,
                ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0,
            ))
            .rotation((time % cycle) as f32 / cycle as f32 * 6.28)
            // WARNING: Using an offset != (0.,0.) on a spritebatch may come with a significant performance cost.
            // This is due to the fact that the total dimensions of everything drawn by it have to be calculated.
            // See SpriteBatch::draw and SpriteBatch::dimensions for more information.
            .offset(Point2::new(0.5, 0.5));
        graphics::draw(ctx, &self.spritebatch, param)?;
        self.spritebatch.clear();
        graphics::set_canvas(ctx, None);
        Ok(())
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        if timer::ticks(ctx) % 100 == 0 {
            println!("Delta frame time: {:?} ", timer::delta(ctx));
            println!("Average FPS: {}", timer::fps(ctx));
        }

        // Bounce the rect if necessary
        let (w, h) = graphics::size(ctx);
        if self.draw_pt.x + (w as f32 / 2.0) > (w as f32) || self.draw_pt.x < 0.0 {
            self.draw_vec.x *= -1.0;
        }
        if self.draw_pt.y + (h as f32 / 2.0) > (h as f32) || self.draw_pt.y < 0.0
        {
            self.draw_vec.y *= -1.0;
        }
        self.draw_pt += self.draw_vec;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());
        self.draw_spritebatch(ctx)?;
        let dims = self.canvas.dimensions();
        let src_x = self.draw_pt.x / dims.w;
        let src_y = self.draw_pt.y / dims.h;
        graphics::draw(
            ctx,
            &self.canvas,
            graphics::DrawParam::new()
                .dest(self.draw_pt)
                .src(graphics::Rect::new(src_x, src_y, 0.5, 0.5)),
        )?;
        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    if cfg!(debug_assertions) && env::var("yes_i_really_want_debug_mode").is_err() {
        eprintln!(
            "Note: Release mode will improve performance greatly.\n    \
             e.g. use `cargo run --example canvas_subframe --release`"
        );
    }
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("canvas_subframe", "ggez").add_resource_path(resource_dir);

    let (mut ctx, events_loop) = cb.build()?;
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, events_loop, state)
}
<commit_msg>rustfmt<commit_after>//! An example of how to use a `SpriteBatch` with a `Canvas`.
//!
//! You really want to run this one in release mode.

use ggez::event;
use ggez::graphics::{self, Color};
use ggez::timer;
use ggez::{Context, GameResult};
use std::env;
use std::path;

type Point2 = glam::Vec2;
type Vector2 = glam::Vec2;

struct MainState {
    spritebatch: graphics::spritebatch::SpriteBatch,
    canvas: graphics::Canvas,
    draw_pt: Point2,
    draw_vec: Vector2,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let image = graphics::Image::new(ctx, "/tile.png").unwrap();
        let spritebatch = graphics::spritebatch::SpriteBatch::new(image);
        let canvas = graphics::Canvas::with_window_size(ctx)?;
        let draw_pt = Point2::new(0.0, 0.0);
        let draw_vec = Vector2::new(1.0, 1.0);
        let s = MainState {
            spritebatch,
            canvas,
            draw_pt,
            draw_vec,
        };
        Ok(s)
    }
}

impl MainState {
    fn draw_spritebatch(&mut self, ctx: &mut Context) -> GameResult {
        graphics::set_canvas(ctx, Some(&self.canvas));
        graphics::clear(ctx, Color::WHITE);

        // Freeze the animation so things are easier to see.
        let time = 2000;
        //let time = (timer::duration_to_f64(timer::time_since_start(ctx)) * 1000.0) as u32;
        let cycle = 10_000;
        for x in 0..150 {
            for y in 0..150 {
                let x = x as f32;
                let y = y as f32;
                let p = graphics::DrawParam::new()
                    .dest(Point2::new(x * 10.0, y * 10.0))
                    // scale: graphics::Point::new(0.0625, 0.0625),
                    .scale(Vector2::new(
                        ((time % cycle * 2) as f32 / cycle as f32 * 6.28)
                            .cos()
                            .abs()
                            * 0.0625,
                        ((time % cycle * 2) as f32 / cycle as f32 * 6.28)
                            .cos()
                            .abs()
                            * 0.0625,
                    ))
                    .rotation(-2.0 * ((time % cycle) as f32 / cycle as f32 * 6.28));
                self.spritebatch.add(p);
            }
        }
        let param = graphics::DrawParam::new()
            .dest(Point2::new(
                ((time % cycle) as f32 / cycle as f32 * 6.28).cos() * 50.0 + 150.0,
                ((time % cycle) as f32 / cycle as f32 * 6.28).sin() * 50.0 + 250.0,
            ))
            .scale(Vector2::new(
                ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0,
                ((time % cycle) as f32 / cycle as f32 * 6.28).sin().abs() * 2.0 + 1.0,
            ))
            .rotation((time % cycle) as f32 / cycle as f32 * 6.28)
            // WARNING: Using an offset != (0.,0.) on a spritebatch may come with a significant performance cost.
            // This is due to the fact that the total dimensions of everything drawn by it have to be calculated.
            // See SpriteBatch::draw and SpriteBatch::dimensions for more information.
            .offset(Point2::new(0.5, 0.5));
        graphics::draw(ctx, &self.spritebatch, param)?;
        self.spritebatch.clear();
        graphics::set_canvas(ctx, None);
        Ok(())
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        if timer::ticks(ctx) % 100 == 0 {
            println!("Delta frame time: {:?} ", timer::delta(ctx));
            println!("Average FPS: {}", timer::fps(ctx));
        }

        // Bounce the rect if necessary
        let (w, h) = graphics::size(ctx);
        if self.draw_pt.x + (w as f32 / 2.0) > (w as f32) || self.draw_pt.x < 0.0 {
            self.draw_vec.x *= -1.0;
        }
        if self.draw_pt.y + (h as f32 / 2.0) > (h as f32) || self.draw_pt.y < 0.0 {
            self.draw_vec.y *= -1.0;
        }
        self.draw_pt += self.draw_vec;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());
        self.draw_spritebatch(ctx)?;
        let dims = self.canvas.dimensions();
        let src_x = self.draw_pt.x / dims.w;
        let src_y = self.draw_pt.y / dims.h;
        graphics::draw(
            ctx,
            &self.canvas,
            graphics::DrawParam::new()
                .dest(self.draw_pt)
                .src(graphics::Rect::new(src_x, src_y, 0.5, 0.5)),
        )?;
        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    if cfg!(debug_assertions) && env::var("yes_i_really_want_debug_mode").is_err() {
        eprintln!(
            "Note: Release mode will improve performance greatly.\n    \
             e.g. use `cargo run --example canvas_subframe --release`"
        );
    }
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("canvas_subframe", "ggez").add_resource_path(resource_dir);

    let (mut ctx, events_loop) = cb.build()?;
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, events_loop, state)
}
<|endoftext|>


<commit_before>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_sdk_dynamodb::{Client, Error};
use tokio_stream::StreamExt;

// List your tables.
// snippet-start:[dynamodb.rust.list-tables]
pub async fn list_tables(client: &Client) -> Result<(), Error> {
    let paginator = client.list_tables().into_paginator().items().send();
    let table_names = paginator.collect::<Result<Vec<_>, _>>().await?;

    println!("Tables:");

    for name in &table_names {
        println!("  {}", name);
    }

    println!("Found {} tables", table_names.len());
    Ok(())
}
// snippet-end:[dynamodb.rust.list-tables]

// List only 10 of your tables.
// snippet-start:[dynamodb.rust.list10-tables]
pub async fn list_tables_limit_10(
    client: &aws_sdk_dynamodb::Client,
) -> Result<(), aws_sdk_dynamodb::Error> {
    let resp = client.list_tables().limit(10).send().await?;

    println!("Tables:");

    let names = resp.table_names().unwrap_or_default();

    for name in names {
        println!("  {}", name);
    }

    println!();
    println!("Found {} tables", names.len());

    Ok(())
}
// snippet-end:[dynamodb.rust.list10-tables]

// List your tables 10 at a time.
// snippet-start:[dynamodb.rust.list-more-tables]
pub async fn list_tables_iterative(client: &Client) -> Result<(), Error> {
    // snippet-start:[dynamodb.rust.list-more-tables-list]
    let mut resp = client.list_tables().limit(10).send().await?;
    let names = resp.table_names.unwrap_or_default();
    let len = names.len();

    let mut num_tables = len;

    println!("Tables:");

    for name in names {
        println!("  {}", name);
    }

    while resp.last_evaluated_table_name != None {
        println!("-- more --");
        resp = client
            .list_tables()
            .limit(10)
            .exclusive_start_table_name(
                resp.last_evaluated_table_name
                    .as_deref()
                    .unwrap_or_default(),
            )
            .send()
            .await?;

        let names = resp.table_names.unwrap_or_default();
        num_tables += names.len();

        for name in names {
            println!("  {}", name);
        }
    }

    println!();
    println!("Found {} tables", num_tables);

    Ok(())
    // snippet-end:[dynamodb.rust.list-more-tables-list]
}
// snippet-end:[dynamodb.rust.list-more-tables]

// List up to 10 tables and indicates whether there are more.
// snippet-start:[dynamodb.rust.are-more-tables]
pub async fn list_tables_are_more(client: &Client) -> Result<(), Error> {
    // snippet-start:[dynamodb.rust.are-more-tables-limit]
    let resp = client.list_tables().limit(10).send().await?;
    // snippet-end:[dynamodb.rust.are-more-tables-limit]

    println!("Tables:");

    let names = resp.table_names().unwrap_or_default();

    for name in names {
        println!("  {}", name);
    }

    println!();
    println!("Found {} tables", names.len());

    // snippet-start:[dynamodb.rust.are-more-tables-more]
    if resp.last_evaluated_table_name != None {
        println!("There are more tables");
    }
    // snippet-end:[dynamodb.rust.are-more-tables-more]

    Ok(())
}
// snippet-end:[dynamodb.rust.are-more-tables]

// Lists the items in a table.
// snippet-start:[dynamodb.rust.list-items]
pub async fn list_items(client: &Client, table: &str) -> Result<(), Error> {
    let items: Result<Vec<_>, _> = client
        .scan()
        .table_name(table)
        .into_paginator()
        .items()
        .send()
        .collect()
        .await;

    println!("Items in table:");
    for item in items? {
        println!("   {:?}", item);
    }

    Ok(())
}
// snippet-end:[dynamodb.rust.list-items]
<commit_msg>Fix copy paste typo<commit_after>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_sdk_dynamodb::{Client, Error};
use tokio_stream::StreamExt;

// List your tables.
// snippet-start:[dynamodb.rust.list-tables]
pub async fn list_tables(client: &Client) -> Result<(), Error> {
    let paginator = client.list_tables().into_paginator().items().send();
    let table_names = paginator.collect::<Result<Vec<_>, _>>().await?;

    println!("Tables:");

    for name in &table_names {
        println!("  {}", name);
    }

    println!("Found {} tables", table_names.len());
    Ok(())
}
// snippet-end:[dynamodb.rust.list-tables]

// List only 10 of your tables.
// snippet-start:[dynamodb.rust.list10-tables]
pub async fn list_tables_limit_10(
    client: &aws_sdk_dynamodb::Client,
) -> Result<(), aws_sdk_dynamodb::Error> {
    let resp = client.list_tables().limit(10).send().await?;

    println!("Tables:");

    let names = resp.table_names().unwrap_or_default();

    for name in names {
        println!("  {}", name);
    }

    println!();
    println!("Found {} tables", names.len());

    Ok(())
}
// snippet-end:[dynamodb.rust.list10-tables]

// List your tables 10 at a time.
// snippet-start:[dynamodb.rust.list-more-tables]
pub async fn list_tables_iterative(client: &Client) -> Result<(), Error> {
    // snippet-start:[dynamodb.rust.list-more-tables-list]
    let mut resp = client.list_tables().limit(10).send().await?;
    let names = resp.table_names.unwrap_or_default();
    let len = names.len();

    let mut num_tables = len;

    println!("Tables:");

    for name in names {
        println!("  {}", name);
    }

    while resp.last_evaluated_table_name != None {
        println!("-- more --");
        resp = client
            .list_tables()
            .limit(10)
            .exclusive_start_table_name(
                resp.last_evaluated_table_name
                    .as_deref()
                    .unwrap_or_default(),
            )
            .send()
            .await?;

        let names = resp.table_names.unwrap_or_default();
        num_tables += names.len();

        for name in names {
            println!("  {}", name);
        }
    }

    println!();
    println!("Found {} tables", num_tables);

    Ok(())
    // snippet-end:[dynamodb.rust.list-more-tables-list]
}
// snippet-end:[dynamodb.rust.list-more-tables]

// Lists up to 10 tables and indicates whether there are more.
// snippet-start:[dynamodb.rust.are-more-tables]
pub async fn list_tables_are_more(client: &Client) -> Result<(), Error> {
    // snippet-start:[dynamodb.rust.are-more-tables-limit]
    let resp = client.list_tables().limit(10).send().await?;
    // snippet-end:[dynamodb.rust.are-more-tables-limit]

    println!("Tables:");

    let names = resp.table_names().unwrap_or_default();

    for name in names {
        println!("  {}", name);
    }

    println!();
    println!("Found {} tables", names.len());

    // snippet-start:[dynamodb.rust.are-more-tables-more]
    if resp.last_evaluated_table_name != None {
        println!("There are more tables");
    }
    // snippet-end:[dynamodb.rust.are-more-tables-more]

    Ok(())
}
// snippet-end:[dynamodb.rust.are-more-tables]

// Lists the items in a table.
// snippet-start:[dynamodb.rust.list-items]
pub async fn list_items(client: &Client, table: &str) -> Result<(), Error> {
    let items: Result<Vec<_>, _> = client
        .scan()
        .table_name(table)
        .into_paginator()
        .items()
        .send()
        .collect()
        .await;

    println!("Items in table:");
    for item in items? {
        println!("   {:?}", item);
    }

    Ok(())
}
// snippet-end:[dynamodb.rust.list-items]
<|endoftext|>


<commit_before>use bincode::{self, Infinite};
use instruction::Instruction;
use interrupt::InternalInterrupt;
use program::Program;
use target::Target;
use typedef::*;
use value::Value;

pub struct ImageBuilder {
    instructions: Vec<Instruction>,
}

impl ImageBuilder {
    pub fn new() -> ImageBuilder {
        ImageBuilder { instructions: Vec::new() }
    }

    fn add_instruction(&mut self, instruction: Instruction) {
        self.instructions.push(instruction);
    }

    pub fn add(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Add(dest, src));
    }

    pub fn sub(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Sub(dest, src));
    }

    pub fn div(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Div(dest, src));
    }

    pub fn mul(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Mul(dest, src));
    }

    pub fn rem(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Rem(dest, src));
    }

    pub fn cmp(&mut self, target_a: Target, target_b: Target) {
        self.add_instruction(Instruction::Cmp(target_a, target_b));
    }

    pub fn jmp(&mut self, addr: Address) {
        self.add_instruction(Instruction::Jmp(addr));
    }

    pub fn jmp_lt(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpLt(addr));
    }

    pub fn jmp_gt(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpGt(addr));
    }

    pub fn jmp_eq(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpEq(addr));
    }

    pub fn push(&mut self, dest: Target, value: Value) {
        self.add_instruction(Instruction::Push(dest, value));
    }

    pub fn mov(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Mov(dest, src));
    }

    pub fn swp(&mut self, src_a: Target, src_b: Target) {
        self.add_instruction(Instruction::Swp(src_a, src_b));
    }

    pub fn call(&mut self, addr: Address) {
        self.add_instruction(Instruction::Call(addr));
    }

    pub fn ret(&mut self) {
        self.add_instruction(Instruction::Ret);
    }

    pub fn halt(&mut self) {
        self.add_instruction(Instruction::Halt);
    }

    pub fn pause(&mut self) {
        self.add_instruction(Instruction::Pause);
    }

    pub fn int(&mut self, interrupt: InternalInterrupt) {
        self.add_instruction(Instruction::Int(interrupt));
    }

    pub fn gen(self) -> ImageData {
        let program = self.gen_program();

        bincode::serialize(&program, Infinite).expect("unable to encode program")
    }

    pub fn gen_program(&self) -> Program {
        Program {
            instructions: self.instructions.clone(),
            ..Program::default()
        }
    }
}

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

    #[test]
    fn generate() {
        let mut builder = ImageBuilder::new();
        builder.push(Target::Stack, Value::Float(23.0));
        builder.push(Target::ValueIndex(0), Value::Float(35.0));
        builder.add(Target::Stack, Target::ValueIndex(0));
        builder.gen();
    }
}
<commit_msg>Added missing builder methods<commit_after>use bincode::{self, Infinite};
use instruction::Instruction;
use interrupt::InternalInterrupt;
use program::Program;
use target::Target;
use typedef::*;
use value::{Type, Value};

pub struct ImageBuilder {
    instructions: Vec<Instruction>,
}

impl ImageBuilder {
    pub fn new() -> ImageBuilder {
        ImageBuilder { instructions: Vec::new() }
    }

    fn add_instruction(&mut self, instruction: Instruction) {
        self.instructions.push(instruction);
    }

    pub fn add(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Add(dest, src));
    }

    pub fn sub(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Sub(dest, src));
    }

    pub fn div(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Div(dest, src));
    }

    pub fn mul(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Mul(dest, src));
    }

    pub fn rem(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Rem(dest, src));
    }

    pub fn cmp(&mut self, target_a: Target, target_b: Target) {
        self.add_instruction(Instruction::Cmp(target_a, target_b));
    }

    pub fn jmp(&mut self, addr: Address) {
        self.add_instruction(Instruction::Jmp(addr));
    }

    pub fn jmp_lt(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpLt(addr));
    }

    pub fn jmp_gt(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpGt(addr));
    }

    pub fn jmp_eq(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpEq(addr));
    }

    pub fn jmp_lt_eq(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpLtEq(addr));
    }

    pub fn jmp_gt_eq(&mut self, addr: Address) {
        self.add_instruction(Instruction::JmpGtEq(addr));
    }

    pub fn cast(&mut self, target: Target, val_type: Type) {
        self.add_instruction(Instruction::Cast(target, val_type));
    }

    pub fn push(&mut self, dest: Target, value: Value) {
        self.add_instruction(Instruction::Push(dest, value));
    }

    pub fn mov(&mut self, dest: Target, src: Target) {
        self.add_instruction(Instruction::Mov(dest, src));
    }

    pub fn swp(&mut self, src_a: Target, src_b: Target) {
        self.add_instruction(Instruction::Swp(src_a, src_b));
    }

    pub fn call(&mut self, addr: Address) {
        self.add_instruction(Instruction::Call(addr));
    }

    pub fn ret(&mut self) {
        self.add_instruction(Instruction::Ret);
    }

    pub fn halt(&mut self) {
        self.add_instruction(Instruction::Halt);
    }

    pub fn pause(&mut self) {
        self.add_instruction(Instruction::Pause);
    }

    pub fn int(&mut self, interrupt: InternalInterrupt) {
        self.add_instruction(Instruction::Int(interrupt));
    }

    pub fn gen(self) -> ImageData {
        let program = self.gen_program();

        bincode::serialize(&program, Infinite).expect("unable to encode program")
    }

    pub fn gen_program(&self) -> Program {
        Program {
            instructions: self.instructions.clone(),
            ..Program::default()
        }
    }
}

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

    #[test]
    fn generate() {
        let mut builder = ImageBuilder::new();
        builder.push(Target::Stack, Value::Float(23.0));
        builder.push(Target::ValueIndex(0), Value::Float(35.0));
        builder.add(Target::Stack, Target::ValueIndex(0));
        builder.gen();
    }
}
<|endoftext|>


<commit_before>extern crate bit_vec;
extern crate ssz;

use bit_vec::BitVec;

use std::default;

/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
#[derive(Debug, Clone, PartialEq)]
pub struct BooleanBitfield(BitVec);

/// Error represents some reason a request against a bitfield was not satisfied
#[derive(Debug)]
pub enum Error {
    /// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
    OutOfBounds(usize, usize),
}

impl BooleanBitfield {
    /// Create a new bitfield.
    pub fn new() -> Self {
        Default::default()
    }

    /// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
    pub fn from_elem(inital_len: usize, bit: bool) -> Self {
        Self {
            0: BitVec::from_elem(inital_len, bit),
        }
    }

    /// Create a new bitfield using the supplied `bytes` as input
    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self {
            0: BitVec::from_bytes(bytes),
        }
    }

    /// Read the value of a bit.
    ///
    /// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
    /// If the index is out of bounds, we return an error to that extent.
    pub fn get(&self, i: usize) -> Result<bool, Error> {
        match self.0.get(i) {
            Some(value) => Ok(value),
            None => Err(Error::OutOfBounds(i, self.0.len())),
        }
    }

    /// Set the value of a bit.
    ///
    /// If the index is out of bounds, we expand the size of the underlying set to include the new index.
    /// Returns the previous value if there was one.
    pub fn set(&mut self, i: usize, value: bool) -> Option<bool> {
        let previous = match self.get(i) {
            Ok(previous) => Some(previous),
            Err(Error::OutOfBounds(_, len)) => {
                let new_len = i - len + 1;
                self.0.grow(new_len, false);
                None
            }
        };
        self.0.set(i, value);
        previous
    }

    /// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
    pub fn highest_set_bit(&self) -> Option<usize> {
        self.0.iter().rposition(|bit| bit)
    }

    /// Returns the number of bits in this bitfield.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns the number of bytes required to represent this bitfield.
    pub fn num_bytes(&self) -> usize {
        self.to_bytes().len()
    }

    /// Returns the number of `1` bits in the bitfield
    pub fn num_set_bits(&self) -> usize {
        self.0.iter().filter(|&bit| bit).count()
    }

    /// Returns a vector of bytes representing the bitfield
    /// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
    pub fn to_bytes(&self) -> Vec<u8> {
        self.0.to_bytes()
    }
}

impl default::Default for BooleanBitfield {
    /// default provides the "empty" bitfield
    /// Note: the empty bitfield is set to the `0` byte.
    fn default() -> Self {
        Self::from_elem(8, false)
    }
}

// borrowed from bit_vec crate
fn reverse_bits(byte: u8) -> u8 {
    let mut result = 0;
    for i in 0..8 {
        result = result | ((byte >> i) & 1) << (7 - i);
    }
    result
}

impl ssz::Encodable for BooleanBitfield {
    // ssz_append encodes Self according to the `ssz` spec.
    // Note that we have to flip the endianness of the encoding with `reverse_bits` to account for an implementation detail of `bit-vec` crate.
    fn ssz_append(&self, s: &mut ssz::SszStream) {
        let bytes: Vec<u8> = self
            .to_bytes()
            .iter()
            .map(|&byte| reverse_bits(byte))
            .collect();
        s.append_vec(&bytes);
    }
}

impl ssz::Decodable for BooleanBitfield {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
        let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
        if (ssz::LENGTH_BYTES + len) > bytes.len() {
            return Err(ssz::DecodeError::TooShort);
        }

        if len == 0 {
            Ok((BooleanBitfield::new(), index + ssz::LENGTH_BYTES))
        } else {
            let bytes = &bytes[(index + 4)..(index + len + 4)];

            let mut field = BooleanBitfield::from_elem(0, false);
            for (byte_index, byte) in bytes.iter().enumerate() {
                for i in 0..8 {
                    let bit = byte & (1 << i);
                    if bit != 0 {
                        field.set(8 * byte_index + i, true);
                    }
                }
            }

            let index = index + ssz::LENGTH_BYTES + len;
            Ok((field, index))
        }
    }
}

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

    #[test]
    fn test_empty_bitfield() {
        let mut field = BooleanBitfield::new();
        let original_len = field.len();

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }
    }

    const INPUT: &[u8] = &[0b0000_0010, 0b0000_0010];

    #[test]
    fn test_get_from_bitfield() {
        let field = BooleanBitfield::from_bytes(INPUT);
        let unset = field.get(0).unwrap();
        assert!(!unset);
        let set = field.get(6).unwrap();
        assert!(set);
        let set = field.get(14).unwrap();
        assert!(set);
    }

    #[test]
    fn test_set_for_bitfield() {
        let mut field = BooleanBitfield::from_bytes(INPUT);
        let previous = field.set(10, true).unwrap();
        assert!(!previous);
        let previous = field.get(10).unwrap();
        assert!(previous);
        let previous = field.set(6, false).unwrap();
        assert!(previous);
        let previous = field.get(6).unwrap();
        assert!(!previous);
    }

    #[test]
    fn test_highest_set_bit() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.highest_set_bit().unwrap(), 14);

        let field = BooleanBitfield::new();
        assert_eq!(field.highest_set_bit(), None);
    }

    #[test]
    fn test_len() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.len(), 16);

        let field = BooleanBitfield::new();
        assert_eq!(field.len(), 8);
    }

    #[test]
    fn test_num_set_bits() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_set_bits(), 2);

        let field = BooleanBitfield::new();
        assert_eq!(field.num_set_bits(), 0);
    }

    #[test]
    fn test_to_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.to_bytes(), INPUT);

        let field = BooleanBitfield::new();
        assert_eq!(field.to_bytes(), vec![0]);
    }

    #[test]
    fn test_out_of_bounds() {
        let mut field = BooleanBitfield::from_bytes(INPUT);

        let out_of_bounds_index = field.len();
        assert!(field.set(out_of_bounds_index, true).is_none());
        assert!(field.len() == out_of_bounds_index + 1);
        assert!(field.get(out_of_bounds_index).unwrap());

        for i in 0..100 {
            if i <= out_of_bounds_index {
                assert!(field.set(i, true).is_some());
            } else {
                assert!(field.set(i, true).is_none());
            }
        }
    }

    #[test]
    fn test_num_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_bytes(), 2);

        let field = BooleanBitfield::from_elem(2, true);
        assert_eq!(field.num_bytes(), 1);

        let field = BooleanBitfield::from_elem(13, true);
        assert_eq!(field.num_bytes(), 2);
    }

    #[test]
    fn test_ssz_encode() {
        let field = BooleanBitfield::from_elem(5, true);

        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 1, 31]);

        let field = BooleanBitfield::from_elem(18, true);
        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 3]);
    }

    #[test]
    fn test_ssz_decode() {
        let encoded = vec![0, 0, 0, 1, 31];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(5, true);
        assert_eq!(field, expected);

        let encoded = vec![0, 0, 0, 3, 255, 255, 3];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(18, true);
        assert_eq!(field, expected);
    }
}
<commit_msg>Add some extra tests for boolean-bitfield<commit_after>extern crate bit_vec;
extern crate ssz;

use bit_vec::BitVec;

use std::default;

/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
#[derive(Debug, Clone, PartialEq)]
pub struct BooleanBitfield(BitVec);

/// Error represents some reason a request against a bitfield was not satisfied
#[derive(Debug, PartialEq)]
pub enum Error {
    /// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
    OutOfBounds(usize, usize),
}

impl BooleanBitfield {
    /// Create a new bitfield.
    pub fn new() -> Self {
        Default::default()
    }

    /// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
    pub fn from_elem(inital_len: usize, bit: bool) -> Self {
        Self {
            0: BitVec::from_elem(inital_len, bit),
        }
    }

    /// Create a new bitfield using the supplied `bytes` as input
    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self {
            0: BitVec::from_bytes(bytes),
        }
    }

    /// Read the value of a bit.
    ///
    /// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
    /// If the index is out of bounds, we return an error to that extent.
    pub fn get(&self, i: usize) -> Result<bool, Error> {
        match self.0.get(i) {
            Some(value) => Ok(value),
            None => Err(Error::OutOfBounds(i, self.0.len())),
        }
    }

    /// Set the value of a bit.
    ///
    /// If the index is out of bounds, we expand the size of the underlying set to include the new index.
    /// Returns the previous value if there was one.
    pub fn set(&mut self, i: usize, value: bool) -> Option<bool> {
        let previous = match self.get(i) {
            Ok(previous) => Some(previous),
            Err(Error::OutOfBounds(_, len)) => {
                let new_len = i - len + 1;
                self.0.grow(new_len, false);
                None
            }
        };
        self.0.set(i, value);
        previous
    }

    /// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
    pub fn highest_set_bit(&self) -> Option<usize> {
        self.0.iter().rposition(|bit| bit)
    }

    /// Returns the number of bits in this bitfield.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns the number of bytes required to represent this bitfield.
    pub fn num_bytes(&self) -> usize {
        self.to_bytes().len()
    }

    /// Returns the number of `1` bits in the bitfield
    pub fn num_set_bits(&self) -> usize {
        self.0.iter().filter(|&bit| bit).count()
    }

    /// Returns a vector of bytes representing the bitfield
    /// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
    pub fn to_bytes(&self) -> Vec<u8> {
        self.0.to_bytes()
    }
}

impl default::Default for BooleanBitfield {
    /// default provides the "empty" bitfield
    /// Note: the empty bitfield is set to the `0` byte.
    fn default() -> Self {
        Self::from_elem(8, false)
    }
}

// borrowed from bit_vec crate
fn reverse_bits(byte: u8) -> u8 {
    let mut result = 0;
    for i in 0..8 {
        result = result | ((byte >> i) & 1) << (7 - i);
    }
    result
}

impl ssz::Encodable for BooleanBitfield {
    // ssz_append encodes Self according to the `ssz` spec.
    // Note that we have to flip the endianness of the encoding with `reverse_bits` to account for an implementation detail of `bit-vec` crate.
    fn ssz_append(&self, s: &mut ssz::SszStream) {
        let bytes: Vec<u8> = self
            .to_bytes()
            .iter()
            .map(|&byte| reverse_bits(byte))
            .collect();
        s.append_vec(&bytes);
    }
}

impl ssz::Decodable for BooleanBitfield {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
        let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
        if (ssz::LENGTH_BYTES + len) > bytes.len() {
            return Err(ssz::DecodeError::TooShort);
        }

        if len == 0 {
            Ok((BooleanBitfield::new(), index + ssz::LENGTH_BYTES))
        } else {
            let bytes = &bytes[(index + 4)..(index + len + 4)];

            let mut field = BooleanBitfield::from_elem(0, false);
            for (byte_index, byte) in bytes.iter().enumerate() {
                for i in 0..8 {
                    let bit = byte & (1 << i);
                    if bit != 0 {
                        field.set(8 * byte_index + i, true);
                    }
                }
            }

            let index = index + ssz::LENGTH_BYTES + len;
            Ok((field, index))
        }
    }
}

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

    #[test]
    fn test_new_bitfield() {
        let mut field = BooleanBitfield::new();
        let original_len = field.len();

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }
    }

    #[test]
    fn test_empty_bitfield() {
        let mut field = BooleanBitfield::from_elem(0, false);
        let original_len = field.len();

        assert_eq!(original_len, 0);

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }

        assert_eq!(field.len(), 100);
        assert_eq!(field.num_set_bits(), 100);
    }

    const INPUT: &[u8] = &[0b0000_0010, 0b0000_0010];

    #[test]
    fn test_get_from_bitfield() {
        let field = BooleanBitfield::from_bytes(INPUT);
        let unset = field.get(0).unwrap();
        assert!(!unset);
        let set = field.get(6).unwrap();
        assert!(set);
        let set = field.get(14).unwrap();
        assert!(set);
    }

    #[test]
    fn test_set_for_bitfield() {
        let mut field = BooleanBitfield::from_bytes(INPUT);
        let previous = field.set(10, true).unwrap();
        assert!(!previous);
        let previous = field.get(10).unwrap();
        assert!(previous);
        let previous = field.set(6, false).unwrap();
        assert!(previous);
        let previous = field.get(6).unwrap();
        assert!(!previous);
    }

    #[test]
    fn test_highest_set_bit() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.highest_set_bit().unwrap(), 14);

        let field = BooleanBitfield::from_bytes(&[0b0000_0011]);
        assert_eq!(field.highest_set_bit().unwrap(), 7);

        let field = BooleanBitfield::new();
        assert_eq!(field.highest_set_bit(), None);
    }

    #[test]
    fn test_len() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.len(), 16);

        let field = BooleanBitfield::new();
        assert_eq!(field.len(), 8);
    }

    #[test]
    fn test_num_set_bits() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_set_bits(), 2);

        let field = BooleanBitfield::new();
        assert_eq!(field.num_set_bits(), 0);
    }

    #[test]
    fn test_to_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.to_bytes(), INPUT);

        let field = BooleanBitfield::new();
        assert_eq!(field.to_bytes(), vec![0]);
    }

    #[test]
    fn test_out_of_bounds() {
        let mut field = BooleanBitfield::from_bytes(INPUT);

        let out_of_bounds_index = field.len();
        assert!(field.set(out_of_bounds_index, true).is_none());
        assert!(field.len() == out_of_bounds_index + 1);
        assert!(field.get(out_of_bounds_index).unwrap());

        for i in 0..100 {
            if i <= out_of_bounds_index {
                assert!(field.set(i, true).is_some());
            } else {
                assert!(field.set(i, true).is_none());
            }
        }
    }

    #[test]
    fn test_grows_with_false() {
        let input_all_set: &[u8] = &[0b1111_1111, 0b1111_1111];
        let mut field = BooleanBitfield::from_bytes(input_all_set);

        // Define `a` and `b`, where both are out of bounds and `b` is greater than `a`.
        let a = field.len();
        let b = a + 1;

        // Ensure `a` is out-of-bounds for test integrity.
        assert!(field.get(a).is_err());

        // Set `b` to `true`. Also, for test integrity, ensure it was previously out-of-bounds.
        assert!(field.set(b, true).is_none());

        // Ensure that `a` wasn't also set to `true` during the grow.
        assert_eq!(field.get(a), Ok(false));
        assert_eq!(field.get(b), Ok(true));
    }

    #[test]
    fn test_num_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_bytes(), 2);

        let field = BooleanBitfield::from_elem(2, true);
        assert_eq!(field.num_bytes(), 1);

        let field = BooleanBitfield::from_elem(13, true);
        assert_eq!(field.num_bytes(), 2);
    }

    #[test]
    fn test_ssz_encode() {
        let field = BooleanBitfield::from_elem(5, true);

        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 1, 31]);

        let field = BooleanBitfield::from_elem(18, true);
        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 3]);
    }

    #[test]
    fn test_ssz_decode() {
        let encoded = vec![0, 0, 0, 1, 31];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(5, true);
        assert_eq!(field, expected);

        let encoded = vec![0, 0, 0, 3, 255, 255, 3];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_elem(18, true);
        assert_eq!(field, expected);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_list_t,cef_string_t};

//cef_string_list

#[no_mangle]
extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
    unsafe {
         let lt: Box<Vec<*mut cef_string_t>> = box vec!();
         mem::transmute(lt)
    }
}

#[no_mangle]
extern "C" fn cef_string_list_size(lt: *const cef_string_list_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        v.len() as c_int
    }
}

#[no_mangle]
extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *const cef_string_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let cs = cef_string_userfree_utf8_alloc();
        cef_string_utf8_set(mem::transmute((*value).str), (*value).length, cs, 1);
        v.push(cs);
    }
}

#[no_mangle]
extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if index as uint > v.len() - 1 { return 0; }
        let cs = v.get(index as uint);
        cef_string_utf8_set(mem::transmute((**cs).str), (**cs).length, value, 1)
    }
}

#[no_mangle]
extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if v.len() == 0 { return; }
        let mut cs;
        while v.len() != 0 {
            cs = v.pop();
            cef_string_userfree_utf8_free(cs.unwrap());
        }
    }
}

#[no_mangle]
extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        cef_string_list_clear(lt);
        drop(v);
    }
}

#[no_mangle]
extern "C" fn cef_string_list_copy(lt: *mut cef_string_list_t) -> *mut cef_string_list_t {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0 as *mut cef_string_list_t; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let lt2 = cef_string_list_alloc();
        for cs in v.iter() {
            cef_string_list_append(lt2, mem::transmute((*cs)));
        }
        lt2
    }
}
<commit_msg>auto merge of #3775 : zmike/servo/embedding-dead_code, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf8_alloc,cef_string_userfree_utf8_free,cef_string_utf8_set};
use types::{cef_string_list_t,cef_string_t};

//cef_string_list

#[no_mangle]
pub extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
    unsafe {
         let lt: Box<Vec<*mut cef_string_t>> = box vec!();
         mem::transmute(lt)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_size(lt: *const cef_string_list_t) -> c_int {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        v.len() as c_int
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *const cef_string_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let cs = cef_string_userfree_utf8_alloc();
        cef_string_utf8_set(mem::transmute((*value).str), (*value).length, cs, 1);
        v.push(cs);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int, value: *mut cef_string_t) -> c_int {
    unsafe {
        if index < 0 || fptr_is_null(mem::transmute(lt)) { return 0; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if index as uint > v.len() - 1 { return 0; }
        let cs = v.get(index as uint);
        cef_string_utf8_set(mem::transmute((**cs).str), (**cs).length, value, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        if v.len() == 0 { return; }
        let mut cs;
        while v.len() != 0 {
            cs = v.pop();
            cef_string_userfree_utf8_free(cs.unwrap());
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return; }
        let mut v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        cef_string_list_clear(lt);
        drop(v);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_list_copy(lt: *mut cef_string_list_t) -> *mut cef_string_list_t {
    unsafe {
        if fptr_is_null(mem::transmute(lt)) { return 0 as *mut cef_string_list_t; }
        let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
        let lt2 = cef_string_list_alloc();
        for cs in v.iter() {
            cef_string_list_append(lt2, mem::transmute((*cs)));
        }
        lt2
    }
}
<|endoftext|>