<commit_before>use clap::{App, Arg, AppSettings, SubCommand, ArgMatches};
use common;
use multirust::{Result, Cfg, Error};
use multirust_dist::manifest::Component;
use multirust_dist::dist::TargetTriple;
use multirust_utils::utils;
use self_update;
use std::path::Path;

pub fn main() -> Result<()> {
    try!(::self_update::cleanup_self_updater());

    let ref matches = cli().get_matches();
    let verbose = matches.is_present("verbose");
    let ref cfg = try!(common::set_globals(verbose));

    if try!(maybe_upgrade_data(cfg, matches)) {
        return Ok(())
    }

    try!(cfg.check_metadata_version());

    match matches.subcommand() {
        ("default", Some(m)) => try!(default_(cfg, m)),
        ("update", Some(m)) => try!(update(cfg, m)),
        ("run", Some(m)) => try!(run(cfg, m)),
        ("which", Some(m)) => try!(which(cfg, m)),
        ("show", Some(_)) => try!(show(cfg)),
        ("target", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(target_list(cfg)),
                ("add", Some(m)) => try!(target_add(cfg, m)),
                ("remove", Some(m)) => try!(target_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("toolchain", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_toolchains(cfg)),
                ("link", Some(m)) => try!(toolchain_link(cfg, m)),
                ("remove", Some(m)) => try!(toolchain_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("override", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_overrides(cfg)),
                ("add", Some(m)) => try!(override_add(cfg, m)),
                ("remove", Some(_)) => try!(override_remove(cfg)),
                (_ ,_) => unreachable!(),
            }
        }
        ("doc", Some(m)) => try!(doc(cfg, m)),
        ("self", Some(c)) => {
            match c.subcommand() {
                ("update", Some(_)) => try!(self_update::update()),
                ("uninstall", Some(m)) => try!(self_uninstall(m)),
                (_ ,_) => unreachable!(),
            }
        }
        (_, _) => {
            try!(update_all_channels(cfg, &matches));
        }
    }

    Ok(())
}

pub fn cli() -> App<'static, 'static> {
    App::new("rustup")
        .version("0.1.1")
        .about("The Rust toolchain installer")
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::DeriveDisplayOrder)
        .arg(Arg::with_name("verbose")
            .help("Enable verbose output")
            .short("v")
            .long("verbose"))
        .arg(Arg::with_name("no-self-update")
            .help("Don't perform self update when running the `rustup` command")
            .long("no-self-update")
            .takes_value(false)
            .hidden(true))
        .subcommand(SubCommand::with_name("default")
            .about("Set the default toolchain")
            .arg(Arg::with_name("toolchain")
                .required(true)))
        .subcommand(SubCommand::with_name("update")
            .about("Install or update a toolchain from a Rust distribution channel")
            .arg(Arg::with_name("toolchain")
                .required(false)))
        .subcommand(SubCommand::with_name("run")
            .about("Run a command with an environment configured for a given toolchain")
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("toolchain")
                .required(true))
            .arg(Arg::with_name("command")
                .required(true).multiple(true)))
        .subcommand(SubCommand::with_name("which")
            .about("Display which binary will be run for a given command")
            .arg(Arg::with_name("command")
                .required(true)))
        .subcommand(SubCommand::with_name("show")
            .about("Show the active toolchain"))
        .subcommand(SubCommand::with_name("target")
            .about("Modify a toolchain's supported targets")
            .setting(AppSettings::SubcommandRequired)
            .subcommand(SubCommand::with_name("list")
                .about("List installed and available targets"))
            .subcommand(SubCommand::with_name("add")
                .about("Add a target to a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove a target  from a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true))
                .arg(Arg::with_name("toolchain"))))
        .subcommand(SubCommand::with_name("toolchain")
            .about("Modify or query the installed toolchains")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed toolchains"))
            .subcommand(SubCommand::with_name("link")
                .about("Create a custom toolchain by symlinking to a directory")
                .arg(Arg::with_name("toolchain")
                    .required(true))
                .arg(Arg::with_name("path")
                    .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Uninstall a toolchain")
                .arg(Arg::with_name("toolchain")
                     .required(true))))
        .subcommand(SubCommand::with_name("override")
            .about("Modify directory toolchain overrides")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List directory toolchain overrides"))
            .subcommand(SubCommand::with_name("add")
                .about("Set the override toolchain for a directory")
                .arg(Arg::with_name("toolchain")
                     .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove the override toolchain for a directory")))
        .subcommand(SubCommand::with_name("self")
            .about("Modify the rustup installation")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("update")
                .about("Downloadand and install updates to rustup"))
            .subcommand(SubCommand::with_name("uninstall")
                .about("Uninstall rustup.")
                .arg(Arg::with_name("no-prompt")
                     .short("y")))
            .subcommand(SubCommand::with_name("upgrade-data")
                .about("Upgrade the internal data format.")))
}

fn maybe_upgrade_data(cfg: &Cfg, m: &ArgMatches) -> Result<bool> {
    match m.subcommand() {
        ("self", Some(c)) => {
            match c.subcommand() {
                ("upgrade-data", Some(_)) => {
                    try!(cfg.upgrade_data());
                    Ok(true)
                }
                _ => Ok(false),
            }
        }
        _ => Ok(false)
    }
}

fn update_all_channels(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    common::update_all_channels(cfg, !m.is_present("no-self-update"))
}

fn default_(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
    } else {
        None
    };

    try!(toolchain.make_default());

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn update(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = if let Some(name) = m.value_of("toolchain") {
        try!(cfg.get_toolchain(name, false))
    } else {
        let ref cwd = try!(utils::current_dir());
        let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));
        toolchain
    };

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist()))
    } else if !toolchain.exists() {
        return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
    } else {
        None
    };

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn run(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let args = m.values_of("command").unwrap();
    let args: Vec<_> = args.collect();
    let cmd = try!(cfg.create_command_for_toolchain(toolchain, args[0]));

    common::run_inner(cmd, &args)
}

fn which(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let binary = m.value_of("command").expect("");

    let binary_path = try!(cfg.which_binary(&try!(utils::current_dir()), binary))
                          .expect("binary not found");

    try!(utils::assert_is_file(&binary_path));

    println!("{}", binary_path.display());

    Ok(())
}

fn show(cfg: &Cfg) -> Result<()> {
    let ref cwd = try!(utils::current_dir());
    let override_ = try!(cfg.find_override(cwd));
    if let Some((toolchain, reason)) = override_ {
        println!("{} ({})", toolchain.name(), reason);
        return Ok(());
    }

    let toolchain = try!(cfg.find_default());
    if let Some(toolchain) = toolchain {
        println!("{} (default toolchain)", toolchain.name());
        return Ok(());
    }

    println!("no active toolchain");

    Ok(())
}

fn target_list(cfg: &Cfg) -> Result<()> {
    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));

    common::list_targets(&toolchain)
}

fn target_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let target = m.value_of("target").expect("");
    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: try!(TargetTriple::from_str(target)),
    };

    toolchain.add_component(new_component)
}

fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let target = m.value_of("target").expect("");
    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: try!(TargetTriple::from_str(target)),
    };

    toolchain.remove_component(new_component)
}

fn toolchain_link(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref path = m.value_of("path").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, true));

    toolchain.install_from_dir(Path::new(path), true)
}

fn toolchain_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    toolchain.remove()
}

fn override_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
    } else {
        None
    };

    try!(toolchain.make_override(&try!(utils::current_dir())));

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn override_remove(cfg: &Cfg) -> Result<()> {
    let ref path = try!(utils::current_dir());

    let ref override_db = cfg.override_db;
    let notify_handler = cfg.notify_handler.as_ref();

    if try!(override_db.find(path, notify_handler)).is_none() {
        info!("no override toolchain for '{}'", path.display());
        return Ok(());
    }

    try!(override_db.remove(path, &cfg.temp_cfg, notify_handler));
    info!("override toolchain for '{}' removed", path.display());
    Ok(())
}

fn doc(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let doc_url = if m.is_present("book") {
        "book/index.html"
    } else if m.is_present("std") {
        "std/index.html"
    } else {
        "index.html"
    };

    cfg.open_docs_for_dir(&try!(utils::current_dir()), doc_url)
}

fn self_uninstall(m: &ArgMatches) -> Result<()> {
    let no_prompt = m.is_present("no-prompt");

    self_update::uninstall(no_prompt)
}
<commit_msg>Print help when 'target' not given a subcommand<commit_after>use clap::{App, Arg, AppSettings, SubCommand, ArgMatches};
use common;
use multirust::{Result, Cfg, Error};
use multirust_dist::manifest::Component;
use multirust_dist::dist::TargetTriple;
use multirust_utils::utils;
use self_update;
use std::path::Path;

pub fn main() -> Result<()> {
    try!(::self_update::cleanup_self_updater());

    let ref matches = cli().get_matches();
    let verbose = matches.is_present("verbose");
    let ref cfg = try!(common::set_globals(verbose));

    if try!(maybe_upgrade_data(cfg, matches)) {
        return Ok(())
    }

    try!(cfg.check_metadata_version());

    match matches.subcommand() {
        ("default", Some(m)) => try!(default_(cfg, m)),
        ("update", Some(m)) => try!(update(cfg, m)),
        ("run", Some(m)) => try!(run(cfg, m)),
        ("which", Some(m)) => try!(which(cfg, m)),
        ("show", Some(_)) => try!(show(cfg)),
        ("target", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(target_list(cfg)),
                ("add", Some(m)) => try!(target_add(cfg, m)),
                ("remove", Some(m)) => try!(target_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("toolchain", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_toolchains(cfg)),
                ("link", Some(m)) => try!(toolchain_link(cfg, m)),
                ("remove", Some(m)) => try!(toolchain_remove(cfg, m)),
                (_, _) => unreachable!(),
            }
        }
        ("override", Some(c)) => {
            match c.subcommand() {
                ("list", Some(_)) => try!(common::list_overrides(cfg)),
                ("add", Some(m)) => try!(override_add(cfg, m)),
                ("remove", Some(_)) => try!(override_remove(cfg)),
                (_ ,_) => unreachable!(),
            }
        }
        ("doc", Some(m)) => try!(doc(cfg, m)),
        ("self", Some(c)) => {
            match c.subcommand() {
                ("update", Some(_)) => try!(self_update::update()),
                ("uninstall", Some(m)) => try!(self_uninstall(m)),
                (_ ,_) => unreachable!(),
            }
        }
        (_, _) => {
            try!(update_all_channels(cfg, &matches));
        }
    }

    Ok(())
}

pub fn cli() -> App<'static, 'static> {
    App::new("rustup")
        .version("0.1.1")
        .about("The Rust toolchain installer")
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::DeriveDisplayOrder)
        .arg(Arg::with_name("verbose")
            .help("Enable verbose output")
            .short("v")
            .long("verbose"))
        .arg(Arg::with_name("no-self-update")
            .help("Don't perform self update when running the `rustup` command")
            .long("no-self-update")
            .takes_value(false)
            .hidden(true))
        .subcommand(SubCommand::with_name("default")
            .about("Set the default toolchain")
            .arg(Arg::with_name("toolchain")
                .required(true)))
        .subcommand(SubCommand::with_name("update")
            .about("Install or update a toolchain from a Rust distribution channel")
            .arg(Arg::with_name("toolchain")
                .required(false)))
        .subcommand(SubCommand::with_name("run")
            .about("Run a command with an environment configured for a given toolchain")
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("toolchain")
                .required(true))
            .arg(Arg::with_name("command")
                .required(true).multiple(true)))
        .subcommand(SubCommand::with_name("which")
            .about("Display which binary will be run for a given command")
            .arg(Arg::with_name("command")
                .required(true)))
        .subcommand(SubCommand::with_name("show")
            .about("Show the active toolchain"))
        .subcommand(SubCommand::with_name("target")
            .about("Modify a toolchain's supported targets")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed and available targets"))
            .subcommand(SubCommand::with_name("add")
                .about("Add a target to a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove a target  from a Rust toolchain")
                .arg(Arg::with_name("target")
                    .required(true))
                .arg(Arg::with_name("toolchain"))))
        .subcommand(SubCommand::with_name("toolchain")
            .about("Modify or query the installed toolchains")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List installed toolchains"))
            .subcommand(SubCommand::with_name("link")
                .about("Create a custom toolchain by symlinking to a directory")
                .arg(Arg::with_name("toolchain")
                    .required(true))
                .arg(Arg::with_name("path")
                    .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Uninstall a toolchain")
                .arg(Arg::with_name("toolchain")
                     .required(true))))
        .subcommand(SubCommand::with_name("override")
            .about("Modify directory toolchain overrides")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("list")
                .about("List directory toolchain overrides"))
            .subcommand(SubCommand::with_name("add")
                .about("Set the override toolchain for a directory")
                .arg(Arg::with_name("toolchain")
                     .required(true)))
            .subcommand(SubCommand::with_name("remove")
                .about("Remove the override toolchain for a directory")))
        .subcommand(SubCommand::with_name("self")
            .about("Modify the rustup installation")
            .setting(AppSettings::SubcommandRequiredElseHelp)
            .subcommand(SubCommand::with_name("update")
                .about("Downloadand and install updates to rustup"))
            .subcommand(SubCommand::with_name("uninstall")
                .about("Uninstall rustup.")
                .arg(Arg::with_name("no-prompt")
                     .short("y")))
            .subcommand(SubCommand::with_name("upgrade-data")
                .about("Upgrade the internal data format.")))
}

fn maybe_upgrade_data(cfg: &Cfg, m: &ArgMatches) -> Result<bool> {
    match m.subcommand() {
        ("self", Some(c)) => {
            match c.subcommand() {
                ("upgrade-data", Some(_)) => {
                    try!(cfg.upgrade_data());
                    Ok(true)
                }
                _ => Ok(false),
            }
        }
        _ => Ok(false)
    }
}

fn update_all_channels(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    common::update_all_channels(cfg, !m.is_present("no-self-update"))
}

fn default_(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
    } else {
        None
    };

    try!(toolchain.make_default());

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn update(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let toolchain = if let Some(name) = m.value_of("toolchain") {
        try!(cfg.get_toolchain(name, false))
    } else {
        let ref cwd = try!(utils::current_dir());
        let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));
        toolchain
    };

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist()))
    } else if !toolchain.exists() {
        return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
    } else {
        None
    };

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn run(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let args = m.values_of("command").unwrap();
    let args: Vec<_> = args.collect();
    let cmd = try!(cfg.create_command_for_toolchain(toolchain, args[0]));

    common::run_inner(cmd, &args)
}

fn which(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let binary = m.value_of("command").expect("");

    let binary_path = try!(cfg.which_binary(&try!(utils::current_dir()), binary))
                          .expect("binary not found");

    try!(utils::assert_is_file(&binary_path));

    println!("{}", binary_path.display());

    Ok(())
}

fn show(cfg: &Cfg) -> Result<()> {
    let ref cwd = try!(utils::current_dir());
    let override_ = try!(cfg.find_override(cwd));
    if let Some((toolchain, reason)) = override_ {
        println!("{} ({})", toolchain.name(), reason);
        return Ok(());
    }

    let toolchain = try!(cfg.find_default());
    if let Some(toolchain) = toolchain {
        println!("{} (default toolchain)", toolchain.name());
        return Ok(());
    }

    println!("no active toolchain");

    Ok(())
}

fn target_list(cfg: &Cfg) -> Result<()> {
    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));

    common::list_targets(&toolchain)
}

fn target_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let target = m.value_of("target").expect("");
    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: try!(TargetTriple::from_str(target)),
    };

    toolchain.add_component(new_component)
}

fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let target = m.value_of("target").expect("");
    let ref cwd = try!(utils::current_dir());
    let (toolchain, _) = try!(cfg.toolchain_for_dir(cwd));
    let new_component = Component {
        pkg: "rust-std".to_string(),
        target: try!(TargetTriple::from_str(target)),
    };

    toolchain.remove_component(new_component)
}

fn toolchain_link(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let ref path = m.value_of("path").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, true));

    toolchain.install_from_dir(Path::new(path), true)
}

fn toolchain_remove(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    toolchain.remove()
}

fn override_add(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let ref toolchain = m.value_of("toolchain").expect("");
    let toolchain = try!(cfg.get_toolchain(toolchain, false));

    let status = if !toolchain.is_custom() {
        Some(try!(toolchain.install_from_dist_if_not_installed()))
    } else if !toolchain.exists() {
        return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
    } else {
        None
    };

    try!(toolchain.make_override(&try!(utils::current_dir())));

    if let Some(status) = status {
        println!("");
        try!(common::show_channel_update(cfg, toolchain.name(), Ok(status)));
    }

    Ok(())
}

fn override_remove(cfg: &Cfg) -> Result<()> {
    let ref path = try!(utils::current_dir());

    let ref override_db = cfg.override_db;
    let notify_handler = cfg.notify_handler.as_ref();

    if try!(override_db.find(path, notify_handler)).is_none() {
        info!("no override toolchain for '{}'", path.display());
        return Ok(());
    }

    try!(override_db.remove(path, &cfg.temp_cfg, notify_handler));
    info!("override toolchain for '{}' removed", path.display());
    Ok(())
}

fn doc(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
    let doc_url = if m.is_present("book") {
        "book/index.html"
    } else if m.is_present("std") {
        "std/index.html"
    } else {
        "index.html"
    };

    cfg.open_docs_for_dir(&try!(utils::current_dir()), doc_url)
}

fn self_uninstall(m: &ArgMatches) -> Result<()> {
    let no_prompt = m.is_present("no-prompt");

    self_update::uninstall(no_prompt)
}
<|endoftext|>


<commit_before>//! Unsigned 512-bit integer

use std::convert::{From, Into};
use std::ops::{Add, Sub, Mul, Div, Shr, Shl, BitAnd, Rem};
use std::cmp::Ordering;
use std::fmt;

use super::U256;
use super::algorithms::{add2, mac3, from_signed, sub2_sign};

#[repr(C)]
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)]
/// Represents an unsigned 512-bit integer.
pub struct U512([u32; 16]);

impl U512 {
    /// Bits needed to represent this value.
    pub fn bits(&self) -> usize {
        let &U512(ref arr) = self;
        let mut current_bits = 0;
        for i in (0..16).rev() {
            if arr[i] == 0 {
                continue;
            }

            current_bits = (32 - arr[i].leading_zeros() as usize) + ((15 - i) * 32);
        }
        current_bits
    }

    /// Zero value of U512.
    pub fn zero() -> U512 {
        U512([0u32; 16])
    }
}

impl From<U256> for U512 {
    fn from(val: U256) -> U512 {
        let mut ret = [0u32; 16];
        let val: [u32; 8] = val.into();
        for i in 0..8 {
            ret[8 + i] = val[i];
        }
        U512(ret)
    }
}

impl Into<U256> for U512 {
    fn into(self) -> U256 {
        assert!(self.0[0..8].iter().all(|s| *s == 0));
        let mut ret = [0u32; 8];
        for i in 0..8 {
            ret[i] = self.0[8 + i];
        }
        ret.into()
    }
}

impl Ord for U512 {
    fn cmp(&self, other: &U512) -> Ordering {
	let &U512(ref me) = self;
	let &U512(ref you) = other;
	let mut i = 0;
	while i < 16 {
	    if me[i] < you[i] { return Ordering::Less; }
	    if me[i] > you[i] { return Ordering::Greater; }
            i += 1;
	}
	Ordering::Equal
    }
}

impl PartialOrd for U512 {
    fn partial_cmp(&self, other: &U512) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl BitAnd<U512> for U512 {
    type Output = U512;

    fn bitand(self, other: U512) -> U512 {
        let mut r: U512 = self;
        for i in 0..16 {
            r.0[i] = r.0[i] & other.0[i];
        }
        r
    }
}

impl Shl<usize> for U512 {
    type Output = U512;

    fn shl(self, shift: usize) -> U512 {
        let U512(ref original) = self;
        let mut ret = [0u32; 16];
        let word_shift = shift / 32;
        let bit_shift = shift % 32;
        for i in (0..16).rev() {
            // Shift
            if i >= word_shift {
                ret[i - word_shift] += original[i] << bit_shift;
            }
            // Carry
            if bit_shift > 0 && i >= word_shift + 1 {
                ret[i - word_shift - 1] += original[i] >> (32 - bit_shift);
            }
        }
        U512(ret)
    }
}

impl Shr<usize> for U512 {
    type Output = U512;

    fn shr(self, shift: usize) -> U512 {
        let U512(ref original) = self;
        let mut ret = [0u32; 16];
        let word_shift = shift / 32;
        let bit_shift = shift % 32;
        for i in (0..16).rev() {
            // Shift
            if i + word_shift < 16 {
                ret[i + word_shift] += original[i] >> bit_shift;
            }
            // Carry
            if bit_shift > 0 && i > 0 && i + word_shift < 16 {
                ret[i + word_shift] += original[i - 1] << (32 - bit_shift);
            }
        }
        U512(ret)
    }
}

impl Add for U512 {
    type Output = U512;

    fn add(mut self, other: U512) -> U512 {
        let U512(ref mut a) = self;
        let U512(ref b) = other;

        let carry = add2(a, b);
        assert!(carry == 0);
        U512(*a)
    }
}

impl Sub for U512 {
    type Output = U512;

    fn sub(mut self, other: U512) -> U512 {
        let U512(ref mut a) = self;
        let U512(ref b) = other;

        let sign = sub2_sign(a, b);
        from_signed(sign, a);
        U512(*a)
    }
}

impl Mul for U512 {
    type Output = U512;

    fn mul(mut self, other: U512) -> U512 {
        let mut ret = [0u32; 16];
        let U512(ref mut a) = self;
        let U512(ref b) = other;

        let mut carry = 0;

        for (i, bi) in b.iter().rev().enumerate() {
            carry = mac3(&mut ret[0..(16-i)], a, *bi);
        }

        assert!(carry == 0);
        U512(ret)
    }
}

impl Div for U512 {
    type Output = U512;

    fn div(self, other: U512) -> U512 {
        let mut sub_copy = self;
        let mut shift_copy = other;
        let mut ret = [0u32; 16];

        let my_bits = self.bits();
        let your_bits = other.bits();

        // Check for division by 0
        assert!(your_bits != 0);

        // Early return in case we are dividing by a larger number than us
        if my_bits < your_bits {
            return U512(ret);
        }

        // Bitwise long division
        let mut shift = my_bits - your_bits;
        shift_copy = shift_copy << shift;
        loop {
            if sub_copy >= shift_copy {
                ret[15 - shift / 32] |= 1 << (shift % 32);
                sub_copy = sub_copy - shift_copy;
            }
            shift_copy = shift_copy >> 1;
            if shift == 0 { break; }
            shift -= 1;
        }

        U512(ret)
    }
}

impl Rem for U512 {
    type Output = U512;

    fn rem(self, other: U512) -> U512 {
        let d = self / other;
        self - (other * d)
    }
}

impl fmt::LowerHex for U512 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0..16 {
            write!(f, "{:08x}", self.0[i])?;
        }
        Ok(())
    }
}

impl fmt::UpperHex for U512 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0..16 {
            write!(f, "{:08X}", self.0[i])?;
        }
        Ok(())
    }
}
<commit_msg>Problem: U512 might overflow for Sub<commit_after>//! Unsigned 512-bit integer

use std::convert::{From, Into};
use std::ops::{Add, Sub, Mul, Div, Shr, Shl, BitAnd, Rem};
use std::cmp::Ordering;
use std::fmt;

use super::{U256, Sign};
use super::algorithms::{add2, mac3, from_signed, sub2_sign};

#[repr(C)]
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)]
/// Represents an unsigned 512-bit integer.
pub struct U512([u32; 16]);

impl U512 {
    /// Bits needed to represent this value.
    pub fn bits(&self) -> usize {
        let &U512(ref arr) = self;
        let mut current_bits = 0;
        for i in (0..16).rev() {
            if arr[i] == 0 {
                continue;
            }

            current_bits = (32 - arr[i].leading_zeros() as usize) + ((15 - i) * 32);
        }
        current_bits
    }

    /// Zero value of U512.
    pub fn zero() -> U512 {
        U512([0u32; 16])
    }
}

impl From<U256> for U512 {
    fn from(val: U256) -> U512 {
        let mut ret = [0u32; 16];
        let val: [u32; 8] = val.into();
        for i in 0..8 {
            ret[8 + i] = val[i];
        }
        U512(ret)
    }
}

impl Into<U256> for U512 {
    fn into(self) -> U256 {
        assert!(self.0[0..8].iter().all(|s| *s == 0));
        let mut ret = [0u32; 8];
        for i in 0..8 {
            ret[i] = self.0[8 + i];
        }
        ret.into()
    }
}

impl Ord for U512 {
    fn cmp(&self, other: &U512) -> Ordering {
	let &U512(ref me) = self;
	let &U512(ref you) = other;
	let mut i = 0;
	while i < 16 {
	    if me[i] < you[i] { return Ordering::Less; }
	    if me[i] > you[i] { return Ordering::Greater; }
            i += 1;
	}
	Ordering::Equal
    }
}

impl PartialOrd for U512 {
    fn partial_cmp(&self, other: &U512) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl BitAnd<U512> for U512 {
    type Output = U512;

    fn bitand(self, other: U512) -> U512 {
        let mut r: U512 = self;
        for i in 0..16 {
            r.0[i] = r.0[i] & other.0[i];
        }
        r
    }
}

impl Shl<usize> for U512 {
    type Output = U512;

    fn shl(self, shift: usize) -> U512 {
        let U512(ref original) = self;
        let mut ret = [0u32; 16];
        let word_shift = shift / 32;
        let bit_shift = shift % 32;
        for i in (0..16).rev() {
            // Shift
            if i >= word_shift {
                ret[i - word_shift] += original[i] << bit_shift;
            }
            // Carry
            if bit_shift > 0 && i >= word_shift + 1 {
                ret[i - word_shift - 1] += original[i] >> (32 - bit_shift);
            }
        }
        U512(ret)
    }
}

impl Shr<usize> for U512 {
    type Output = U512;

    fn shr(self, shift: usize) -> U512 {
        let U512(ref original) = self;
        let mut ret = [0u32; 16];
        let word_shift = shift / 32;
        let bit_shift = shift % 32;
        for i in (0..16).rev() {
            // Shift
            if i + word_shift < 16 {
                ret[i + word_shift] += original[i] >> bit_shift;
            }
            // Carry
            if bit_shift > 0 && i > 0 && i + word_shift < 16 {
                ret[i + word_shift] += original[i - 1] << (32 - bit_shift);
            }
        }
        U512(ret)
    }
}

impl Add for U512 {
    type Output = U512;

    fn add(mut self, other: U512) -> U512 {
        let U512(ref mut a) = self;
        let U512(ref b) = other;

        let carry = add2(a, b);
        assert!(carry == 0);
        U512(*a)
    }
}

impl Sub for U512 {
    type Output = U512;

    fn sub(mut self, other: U512) -> U512 {
        let U512(ref mut a) = self;
        let U512(ref b) = other;

        let sign = sub2_sign(a, b);
        assert!(sign != Sign::Minus);
        from_signed(sign, a);
        U512(*a)
    }
}

impl Mul for U512 {
    type Output = U512;

    fn mul(mut self, other: U512) -> U512 {
        let mut ret = [0u32; 16];
        let U512(ref mut a) = self;
        let U512(ref b) = other;

        let mut carry = 0;

        for (i, bi) in b.iter().rev().enumerate() {
            carry = mac3(&mut ret[0..(16-i)], a, *bi);
        }

        assert!(carry == 0);
        U512(ret)
    }
}

impl Div for U512 {
    type Output = U512;

    fn div(self, other: U512) -> U512 {
        let mut sub_copy = self;
        let mut shift_copy = other;
        let mut ret = [0u32; 16];

        let my_bits = self.bits();
        let your_bits = other.bits();

        // Check for division by 0
        assert!(your_bits != 0);

        // Early return in case we are dividing by a larger number than us
        if my_bits < your_bits {
            return U512(ret);
        }

        // Bitwise long division
        let mut shift = my_bits - your_bits;
        shift_copy = shift_copy << shift;
        loop {
            if sub_copy >= shift_copy {
                ret[15 - shift / 32] |= 1 << (shift % 32);
                sub_copy = sub_copy - shift_copy;
            }
            shift_copy = shift_copy >> 1;
            if shift == 0 { break; }
            shift -= 1;
        }

        U512(ret)
    }
}

impl Rem for U512 {
    type Output = U512;

    fn rem(self, other: U512) -> U512 {
        let d = self / other;
        self - (other * d)
    }
}

impl fmt::LowerHex for U512 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0..16 {
            write!(f, "{:08x}", self.0[i])?;
        }
        Ok(())
    }
}

impl fmt::UpperHex for U512 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for i in 0..16 {
            write!(f, "{:08X}", self.0[i])?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(lang_items)]

extern crate drivers;
extern crate hil;
extern crate nrf51822;
extern crate support;
extern crate process;
extern crate common;

use drivers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use hil::gpio::GPIOPin;
use drivers::timer::TimerDriver;
use nrf51822::timer::TimerAlarm;
use nrf51822::timer::ALARM1;

pub mod systick;

pub struct Platform {
    chip: nrf51822::chip::Nrf51822,
    gpio: &'static drivers::gpio::GPIO<'static, nrf51822::gpio::GPIOPin>,
    timer: &'static TimerDriver<'static, VirtualMuxAlarm<'static, TimerAlarm>>,
}

pub struct DummyMPU;

impl DummyMPU {
    pub fn set_mpu(&mut self, _: u32, _: u32, _: u32, _: bool, _: u32) {
    }
}

impl Platform {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn mpu(&mut self) -> DummyMPU {
        DummyMPU
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {
        match driver_num {
            1 => f(Some(self.gpio)),
           // 3 => f(Some(self.timer)),
            _ => f(None)
        }
    }
}

macro_rules! static_init {
    ($V:ident : $T:ty = $e:expr, $size:expr) => {
        // Ideally we could use mem::size_of<$T> here instead of $size, however
        // that is not currently possible in rust. Instead we write the size as
        // a constant in the code and use compile-time verification to see that
        // we got it right
        let $V : &'static mut $T = {
            use core::{mem, ptr};
            // This is our compile-time assertion. The optimizer should be able
            // to remove it from the generated code.
            let assert_buf: [u8; $size] = mem::uninitialized();
            let assert_val: $T = mem::transmute(assert_buf);
            mem::forget(assert_val);

            // Statically allocate a read-write buffer for the value, write our
            // initial value into it (without dropping the initial zeros) and
            // return a reference to it.
            static mut BUF: [u8; $size] = [0; $size];
            let mut tmp : &mut $T = mem::transmute(&mut BUF);
            ptr::write(tmp as *mut $T, $e);
            tmp
        };
    }
}

pub unsafe fn init() -> &'static mut Platform {
    use core::mem;
    use nrf51822::gpio::PORT;

    static_init!(gpio_pins : [&'static nrf51822::gpio::GPIOPin; 10] = [
            &nrf51822::gpio::PORT[15], // LED_0
            &nrf51822::gpio::PORT[19], // LED_1
            &nrf51822::gpio::PORT[0], // Top left header on EK board
            &nrf51822::gpio::PORT[1], //   |
            &nrf51822::gpio::PORT[2], //   V
            &nrf51822::gpio::PORT[3], //
            &nrf51822::gpio::PORT[4], //
            &nrf51822::gpio::PORT[5], //
            &nrf51822::gpio::PORT[6], //
            &nrf51822::gpio::PORT[7], //
            ], 4 * 10);
    static_init!(gpio: drivers::gpio::GPIO<'static, nrf51822::gpio::GPIOPin> =
                     drivers::gpio::GPIO::new(gpio_pins), 20);
    for pin in gpio_pins.iter() {
        pin.set_client(gpio);
    }

    let alarm = &nrf51822::timer::ALARM1;
    static_init!(mux_alarm : MuxAlarm<'static, TimerAlarm> = MuxAlarm::new(&ALARM1), 16);
    alarm.set_client(mux_alarm);

    static_init!(virtual_alarm1 : VirtualMuxAlarm<'static, TimerAlarm> =
                                  VirtualMuxAlarm::new(mux_alarm), 24);
    static_init!(timer : TimerDriver<'static, VirtualMuxAlarm<'static, TimerAlarm>> =
                         TimerDriver::new(virtual_alarm1, process::Container::create()), 12);
    virtual_alarm1.set_client(timer);

    nrf51822::clock::CLOCK.low_stop();
    nrf51822::clock::CLOCK.high_stop();

    nrf51822::clock::CLOCK.low_set_source(nrf51822::clock::LowClockSource::RC);
    nrf51822::clock::CLOCK.low_start();
    nrf51822::clock::CLOCK.high_start();
    while !nrf51822::clock::CLOCK.low_started() {}
    while !nrf51822::clock::CLOCK.high_started() {}

    static_init!(platform: Platform = Platform {
        chip: nrf51822::chip::Nrf51822::new(),
        gpio: gpio,
        timer: timer
    }, 8);

    // The systick implementation currently directly accesses the low clock;
    // it should go through clock::CLOCK instead.
    systick::reset();
    systick::enable(true);
    platform
}

use core::fmt::Arguments;
#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    use support::nop;
    use hil::gpio::GPIOPin;

    let led0 = &nrf51822::gpio::PORT[18];
    let led1 = &nrf51822::gpio::PORT[19];

    led0.enable_output();
    led1.enable_output();
    loop {
        for _ in 0..100000 {
            led0.set();
            led1.set();
            nop();
        }
        for _ in 0..100000 {
            led0.clear();
            led1.clear();
            nop();
        }
    }
}
<commit_msg>Revert nrf_pca10001 gpio pin to LED<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(lang_items)]

extern crate drivers;
extern crate hil;
extern crate nrf51822;
extern crate support;
extern crate process;
extern crate common;

use drivers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use hil::gpio::GPIOPin;
use drivers::timer::TimerDriver;
use nrf51822::timer::TimerAlarm;
use nrf51822::timer::ALARM1;

pub mod systick;

pub struct Platform {
    chip: nrf51822::chip::Nrf51822,
    gpio: &'static drivers::gpio::GPIO<'static, nrf51822::gpio::GPIOPin>,
    timer: &'static TimerDriver<'static, VirtualMuxAlarm<'static, TimerAlarm>>,
}

pub struct DummyMPU;

impl DummyMPU {
    pub fn set_mpu(&mut self, _: u32, _: u32, _: u32, _: bool, _: u32) {
    }
}

impl Platform {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn mpu(&mut self) -> DummyMPU {
        DummyMPU
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {
        match driver_num {
            1 => f(Some(self.gpio)),
           // 3 => f(Some(self.timer)),
            _ => f(None)
        }
    }
}

macro_rules! static_init {
    ($V:ident : $T:ty = $e:expr, $size:expr) => {
        // Ideally we could use mem::size_of<$T> here instead of $size, however
        // that is not currently possible in rust. Instead we write the size as
        // a constant in the code and use compile-time verification to see that
        // we got it right
        let $V : &'static mut $T = {
            use core::{mem, ptr};
            // This is our compile-time assertion. The optimizer should be able
            // to remove it from the generated code.
            let assert_buf: [u8; $size] = mem::uninitialized();
            let assert_val: $T = mem::transmute(assert_buf);
            mem::forget(assert_val);

            // Statically allocate a read-write buffer for the value, write our
            // initial value into it (without dropping the initial zeros) and
            // return a reference to it.
            static mut BUF: [u8; $size] = [0; $size];
            let mut tmp : &mut $T = mem::transmute(&mut BUF);
            ptr::write(tmp as *mut $T, $e);
            tmp
        };
    }
}

pub unsafe fn init() -> &'static mut Platform {
    use core::mem;
    use nrf51822::gpio::PORT;

    static_init!(gpio_pins : [&'static nrf51822::gpio::GPIOPin; 10] = [
            &nrf51822::gpio::PORT[18], // LED_0
            &nrf51822::gpio::PORT[19], // LED_1
            &nrf51822::gpio::PORT[0], // Top left header on EK board
            &nrf51822::gpio::PORT[1], //   |
            &nrf51822::gpio::PORT[2], //   V
            &nrf51822::gpio::PORT[3], //
            &nrf51822::gpio::PORT[4], //
            &nrf51822::gpio::PORT[5], //
            &nrf51822::gpio::PORT[6], //
            &nrf51822::gpio::PORT[7], //
            ], 4 * 10);
    static_init!(gpio: drivers::gpio::GPIO<'static, nrf51822::gpio::GPIOPin> =
                     drivers::gpio::GPIO::new(gpio_pins), 20);
    for pin in gpio_pins.iter() {
        pin.set_client(gpio);
    }

    let alarm = &nrf51822::timer::ALARM1;
    static_init!(mux_alarm : MuxAlarm<'static, TimerAlarm> = MuxAlarm::new(&ALARM1), 16);
    alarm.set_client(mux_alarm);

    static_init!(virtual_alarm1 : VirtualMuxAlarm<'static, TimerAlarm> =
                                  VirtualMuxAlarm::new(mux_alarm), 24);
    static_init!(timer : TimerDriver<'static, VirtualMuxAlarm<'static, TimerAlarm>> =
                         TimerDriver::new(virtual_alarm1, process::Container::create()), 12);
    virtual_alarm1.set_client(timer);

    nrf51822::clock::CLOCK.low_stop();
    nrf51822::clock::CLOCK.high_stop();

    nrf51822::clock::CLOCK.low_set_source(nrf51822::clock::LowClockSource::RC);
    nrf51822::clock::CLOCK.low_start();
    nrf51822::clock::CLOCK.high_start();
    while !nrf51822::clock::CLOCK.low_started() {}
    while !nrf51822::clock::CLOCK.high_started() {}

    static_init!(platform: Platform = Platform {
        chip: nrf51822::chip::Nrf51822::new(),
        gpio: gpio,
        timer: timer
    }, 8);

    // The systick implementation currently directly accesses the low clock;
    // it should go through clock::CLOCK instead.
    systick::reset();
    systick::enable(true);
    platform
}

use core::fmt::Arguments;
#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    use support::nop;
    use hil::gpio::GPIOPin;

    let led0 = &nrf51822::gpio::PORT[18];
    let led1 = &nrf51822::gpio::PORT[19];

    led0.enable_output();
    led1.enable_output();
    loop {
        for _ in 0..100000 {
            led0.set();
            led1.set();
            nop();
        }
        for _ in 0..100000 {
            led0.clear();
            led1.clear();
            nop();
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::mem;
use std::ptr;
use libc::{c_int, c_ulong};

use runtime::Class;
use {Id, Message};

#[allow(improper_ctypes)]
#[link(name = "Foundation", kind = "framework")]
extern {
    static _NSConcreteStackBlock: Class;
}

#[repr(C)]
struct Block<C: Clone> {
    isa: *const Class,
    flags: c_int,
    _reserved: c_int,
    pub invoke: unsafe extern fn(&mut Block<C>, ...),
    descriptor: *const BlockDescriptor<C>,
    pub context: C,
}

impl<C: Clone> Block<C> {
    pub fn new(invoke: unsafe extern fn(&mut Block<C>, ...), context: C) -> Block<C> {
        println!("{}", _NSConcreteStackBlock.name());
        Block {
            isa: &_NSConcreteStackBlock,
            // 1 << 25 = BLOCK_HAS_COPY_DISPOSE
            flags: 1 << 25,
            _reserved: 0,
            invoke: invoke,
            // TODO: don't leak memory here
            descriptor: unsafe {
                mem::transmute(box BlockDescriptor::<C>::new())
            },
            context: context,
        }
    }

    pub fn copy(&self) -> Id<Block<C>> {
        unsafe {
            let block = msg_send![self copy] as *mut Block<C>;
            Id::from_retained_ptr(block)
        }
    }
}

impl<C: Clone> Message for Block<C> { }

impl<C: Clone> Clone for Block<C> {
    fn clone(&self) -> Block<C> {
        Block::new(self.invoke, self.context.clone())
    }
}

unsafe extern fn block_context_dispose<C: Clone>(block: &mut Block<C>) {
    let mut context = mem::uninitialized();
    ptr::copy_nonoverlapping_memory(&mut context, &block.context, 1);
    drop(context);
}

unsafe extern fn block_context_copy<C: Clone>(dst: &mut Block<C>, src: &Block<C>) {
    dst.context = src.context.clone();
}

#[repr(C)]
struct BlockDescriptor<C: Clone> {
    _reserved: c_ulong,
    block_size: c_ulong,
    copy_helper: unsafe extern fn(&mut Block<C>, &Block<C>),
    dispose_helper: unsafe extern fn(&mut Block<C>),
}

impl<C: Clone> BlockDescriptor<C> {
    pub fn new() -> BlockDescriptor<C> {
        BlockDescriptor {
            _reserved: 0,
            block_size: mem::size_of::<Block<C>>() as c_ulong,
            copy_helper: block_context_copy::<C>,
            dispose_helper: block_context_dispose::<C>,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use objc_test_utils::invoke_int_block;
    use super::Block;

    #[test]
    fn test_create_block() {
        extern fn block_get_int(block: &Block<int>) -> int {
            block.context
        }

        let result = unsafe {
            let block = Block::new(mem::transmute(block_get_int), 13i);
            invoke_int_block(mem::transmute(&block))
        };
        assert!(result == 13);
    }
}
<commit_msg>Remove debug print.<commit_after>#![allow(dead_code)]

use std::mem;
use std::ptr;
use libc::{c_int, c_ulong};

use runtime::Class;
use {Id, Message};

#[allow(improper_ctypes)]
#[link(name = "Foundation", kind = "framework")]
extern {
    static _NSConcreteStackBlock: Class;
}

#[repr(C)]
struct Block<C: Clone> {
    isa: *const Class,
    flags: c_int,
    _reserved: c_int,
    pub invoke: unsafe extern fn(&mut Block<C>, ...),
    descriptor: *const BlockDescriptor<C>,
    pub context: C,
}

impl<C: Clone> Block<C> {
    pub fn new(invoke: unsafe extern fn(&mut Block<C>, ...), context: C) -> Block<C> {
        Block {
            isa: &_NSConcreteStackBlock,
            // 1 << 25 = BLOCK_HAS_COPY_DISPOSE
            flags: 1 << 25,
            _reserved: 0,
            invoke: invoke,
            // TODO: don't leak memory here
            descriptor: unsafe {
                mem::transmute(box BlockDescriptor::<C>::new())
            },
            context: context,
        }
    }

    pub fn copy(&self) -> Id<Block<C>> {
        unsafe {
            let block = msg_send![self copy] as *mut Block<C>;
            Id::from_retained_ptr(block)
        }
    }
}

impl<C: Clone> Message for Block<C> { }

impl<C: Clone> Clone for Block<C> {
    fn clone(&self) -> Block<C> {
        Block::new(self.invoke, self.context.clone())
    }
}

unsafe extern fn block_context_dispose<C: Clone>(block: &mut Block<C>) {
    let mut context = mem::uninitialized();
    ptr::copy_nonoverlapping_memory(&mut context, &block.context, 1);
    drop(context);
}

unsafe extern fn block_context_copy<C: Clone>(dst: &mut Block<C>, src: &Block<C>) {
    dst.context = src.context.clone();
}

#[repr(C)]
struct BlockDescriptor<C: Clone> {
    _reserved: c_ulong,
    block_size: c_ulong,
    copy_helper: unsafe extern fn(&mut Block<C>, &Block<C>),
    dispose_helper: unsafe extern fn(&mut Block<C>),
}

impl<C: Clone> BlockDescriptor<C> {
    pub fn new() -> BlockDescriptor<C> {
        BlockDescriptor {
            _reserved: 0,
            block_size: mem::size_of::<Block<C>>() as c_ulong,
            copy_helper: block_context_copy::<C>,
            dispose_helper: block_context_dispose::<C>,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use objc_test_utils::invoke_int_block;
    use super::Block;

    #[test]
    fn test_create_block() {
        extern fn block_get_int(block: &Block<int>) -> int {
            block.context
        }

        let result = unsafe {
            let block = Block::new(mem::transmute(block_get_int), 13i);
            invoke_int_block(mem::transmute(&block))
        };
        assert!(result == 13);
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::path::Path;

extern crate chrono;
use self::chrono::{DateTime, Local};

pub struct Options<'a> {
    pub title: &'a str,
    pub tree_name: &'a str,
    pub revision: Option<(&'a str, &'a str)>,
    pub include_date: bool,
}

pub fn choose_icon(path: &str) -> String {
    let ext : &str = match Path::new(path).extension() {
        Some(ext) => ext.to_str().unwrap(),
        None => "",
    };
    if ext == "jsm" {
        return "js".to_string();
    }
    if ["cpp", "h", "c", "js", "py"].iter().any(|x: &&str| *x == ext) {
        return ext.to_string();
    }
    "".to_string()
}

pub fn file_url(opt: &Options, path: &str) -> String {
    format!("/{}/source/{}", opt.tree_name, path)
}

pub fn generate_breadcrumbs(opt: &Options, writer: &mut Write, path: &str) -> Result<(), &'static str>
{
    let mut breadcrumbs = format!("{}", file_url(opt, ""), opt.tree_name);

    let mut path_so_far = "".to_string();
    for name in path.split('/') {
        breadcrumbs.push_str("/");
        path_so_far.push_str(name);
        breadcrumbs.push_str(&format!("{}", file_url(opt, &path_so_far), name));
        path_so_far.push('/');
    }

    try!(write!(*writer, "
{}
\n", breadcrumbs).map_err(|_| "Write err"));

    Ok(())
}

pub enum F {
    Indent(Vec<F>),
    Seq(Vec<F>),
    T(String),
    S(&'static str),
}

pub fn generate_formatted(writer: &mut Write, formatted: &F, indent: u32) -> Result<(), &'static str>
{
    match *formatted {
        F::Indent(ref seq) => {
            for f in seq {
                try!(generate_formatted(writer, &f, indent + 1));
            }
            Ok(())
        },
        F::Seq(ref seq) => {
            for f in seq {
                try!(generate_formatted(writer, &f, indent));
            }
            Ok(())
        },
        F::T(ref text) => {
            for _ in 0 .. indent {
                try!(write!(writer, "  ").map_err(|_| "Write err"));
            }
            try!(write!(writer, "{}\n", text).map_err(|_| "Write err"));
            Ok(())
        },
        F::S(text) => {
            for _ in 0 .. indent {
                try!(write!(writer, "  ").map_err(|_| "Write err"));
            }
            try!(write!(writer, "{}\n", text).map_err(|_| "Write err"));
            Ok(())
        },
    }
}

pub fn generate_header(opt: &Options, writer: &mut Write) -> Result<(), &'static str>
{
    let css = [
        "mozsearch.css",
        "icons.css",
        "selector-common.css",
        "filter.css",
        "xcode.css",
    ];
    let css_tags =
        css.iter().map(|c| {
            F::T(format!("<link href=\"/static/css/{}\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\"/>", c))
        });

    let mut head_seq = vec![
        F::S("<meta charset=\"utf-8\" />"),
        F::S("<link href=\"/static/icons/search.png\" rel=\"shortcut icon\">"),
        F::T(format!("<title>{}</title>", opt.title)),
    ];
    head_seq.extend(css_tags);

    let fieldset = vec![
        F::S("
"),
        F::Indent(vec![
            F::S("
"),
            F::Indent(vec![
                F::S("Find"),
                F::T(format!("<input type=\"text\" name=\"q\" value=\"\" maxlength=\"2048\" id=\"query\" accesskey=\"s\" title=\"Search\" placeholder=\"Search {}\" autocomplete=\"off\" />",
                             opt.tree_name)),
                F::S("
"),
                F::Indent(vec![
                    F::S("
"),
                    F::S("
"),
                ]),
                F::S("
"),
                F::S("

"),
            ]),
            F::S("
"),

            F::S("
"),
            F::Indent(vec![
                F::S(""),
                F::Indent(vec![
                    F::S("<input type=\"checkbox\" name=\"case\" id=\"case\" class=\"option-checkbox\" value=\"true\" accesskey=\"c\"/>Case-sensitive"),
                ]),
                F::S(""),

                F::S(""),
                F::Indent(vec![
                    F::S("<input type=\"checkbox\" name=\"regexp\" id=\"regexp\" class=\"option-checkbox\" value=\"true\" accesskey=\"r\"/>Regexp search"),
                ]),
                F::S(""),
            ]),
            F::S("
"),

            F::S("
"),
            F::Indent(vec![
                F::S("Path"),
                F::S("<input type=\"text\" name=\"path\" value=\"\" maxlength=\"2048\" id=\"path\" accesskey=\"p\" title=\"Path\" placeholder=\"Path filter (supports globbing and ^, $)\" autocomplete=\"off\" />"),
                F::S("
"),
                F::Indent(vec![
                    F::S("
"),
                    F::S("
"),
                ]),
                F::S("
"),
            ]),
            F::S("
"),
        ]),
        F::S("
"),
    ];

    let revision = match opt.revision {
        Some((rev_id, rev_desc)) => vec![
            F::T(format!("Showing {}:",
                         opt.tree_name, rev_id, &rev_id[..8])),
            F::T(format!("{}", rev_desc)),
        ],
        None => vec![],
    };

    let body_class = match opt.revision {
        Some(_) => "old-rev",
        None => "",
    };

    let form = vec![
        F::S("<fieldset>"),
        F::Indent(fieldset),
        F::S("</fieldset>"),
        F::S("<input type=\"submit\" value=\"Search\" class=\"visually-hidden\" />"),
        F::S("
"),
        F::Indent(revision),
        F::S("
"),
    ];

    let f = F::Seq(vec![
        F::S("<!DOCTYPE html>"),
        F::S(""),
        F::S(""),
        F::Indent(head_seq),
        F::S(""),
        F::S(""),
        F::T(format!("", body_class)),
        F::Indent(vec![
            F::T(format!("<form method=\"get\" action=\"/{}/search\" id=\"basic_search\" class=\"search-box\">",
                         opt.tree_name)),
            F::Indent(form),
            F::S("</form>"),

            F::S("
"),
        ]),
    ]);

    try!(generate_formatted(writer, &f, 0));

    Ok(())
}

pub fn generate_footer(opt: &Options, tree_name: &str, path: &str, writer: &mut Write) -> Result<(), &'static str>
{
    let mut date = F::Seq(vec![]);
    if opt.include_date {
        let local: DateTime<Local> = Local::now();
        let time_str = local.to_rfc2822();

        date = F::Seq(vec![
            F::S("
"),
            F::Indent(vec![
                F::T(format!("This page was generated by Searchfox \
                              .", time_str)),
            ]),
            F::S("
"),
        ]);
    }

    let scripts = [
        "libs/jquery-2.1.3.min.js",
        "libs/nunjucks.min.js",
        "utils.js",
        "dxr.js",
        "context-menu.js",
        "filter.js",
        "panel.js",
        "code-highlighter.js",
        "blame.js",
    ];
    let script_tags: Vec<_> =
        scripts.iter().map(|s| F::T(format!("", s))).collect();

    let f = F::Seq(vec![
        F::Indent(vec![
            F::Indent(vec![F::S("
")]),
            date,
            F::T(format!("",
                         tree_name, tree_name, path)),
            F::Seq(script_tags),
            F::S(""),
        ]),
        F::S("")
    ]);

    try!(generate_formatted(writer, &f, 0));

    Ok(())
}

pub struct PanelItem {
    pub title: String,
    pub link: String,
    pub update_link_lineno: bool,
}

pub struct PanelSection {
    pub name: String,
    pub items: Vec<PanelItem>,
}

pub fn generate_panel(writer: &mut Write, sections: &Vec<PanelSection>) -> Result<(), &'static str> {
    let sections = sections.iter().map(|section| {
        let items = section.items.iter().map(|item| {
            let update_attr = if item.update_link_lineno {
                format!(" data-update-link=\"true\" data-link=\"{}\"", item.link)
            } else {
                "".to_owned()
            };
            F::Seq(vec![
                F::S("
"),
                F::T(format!("{}",
                             item.link, item.title, update_attr, item.title)),
                F::S("
"),
            ])
        }).collect::<Vec<_>>();

        F::Seq(vec![
            F::T(format!("
{}
", section.name)),
            F::S("
"),
            F::Seq(items),
            F::S("
"),
        ])
    }).collect::<Vec<_>>();

    let f = F::Seq(vec![
        F::S("
"),
        F::Indent(vec![
            F::S("<button id=\"panel-toggle\">"),
            F::Indent(vec![
                F::S(""),
                F::S("Navigation"),
            ]),
            F::S("</button>"),
            F::S("
"),
            F::Seq(sections),
            F::S("
"),
        ]),
        F::S("
"),
    ]);

    try!(generate_formatted(writer, &f, 0));

    Ok(())
}
<commit_msg>Use Rust raw strings instead of lots of escapes.<commit_after>use std::io::Write;
use std::path::Path;

extern crate chrono;
use self::chrono::{DateTime, Local};

pub struct Options<'a> {
    pub title: &'a str,
    pub tree_name: &'a str,
    pub revision: Option<(&'a str, &'a str)>,
    pub include_date: bool,
}

pub fn choose_icon(path: &str) -> String {
    let ext : &str = match Path::new(path).extension() {
        Some(ext) => ext.to_str().unwrap(),
        None => "",
    };
    if ext == "jsm" {
        return "js".to_string();
    }
    if ["cpp", "h", "c", "js", "py"].iter().any(|x: &&str| *x == ext) {
        return ext.to_string();
    }
    "".to_string()
}

pub fn file_url(opt: &Options, path: &str) -> String {
    format!("/{}/source/{}", opt.tree_name, path)
}

pub fn generate_breadcrumbs(opt: &Options, writer: &mut Write, path: &str) -> Result<(), &'static str>
{
    let mut breadcrumbs = format!("{}", file_url(opt, ""), opt.tree_name);

    let mut path_so_far = "".to_string();
    for name in path.split('/') {
        breadcrumbs.push_str("/");
        path_so_far.push_str(name);
        breadcrumbs.push_str(&format!("{}", file_url(opt, &path_so_far), name));
        path_so_far.push('/');
    }

    try!(write!(*writer, "
{}
\n", breadcrumbs).map_err(|_| "Write err"));

    Ok(())
}

pub enum F {
    Indent(Vec<F>),
    Seq(Vec<F>),
    T(String),
    S(&'static str),
}

pub fn generate_formatted(writer: &mut Write, formatted: &F, indent: u32) -> Result<(), &'static str>
{
    match *formatted {
        F::Indent(ref seq) => {
            for f in seq {
                try!(generate_formatted(writer, &f, indent + 1));
            }
            Ok(())
        },
        F::Seq(ref seq) => {
            for f in seq {
                try!(generate_formatted(writer, &f, indent));
            }
            Ok(())
        },
        F::T(ref text) => {
            for _ in 0 .. indent {
                try!(write!(writer, "  ").map_err(|_| "Write err"));
            }
            try!(write!(writer, "{}\n", text).map_err(|_| "Write err"));
            Ok(())
        },
        F::S(text) => {
            for _ in 0 .. indent {
                try!(write!(writer, "  ").map_err(|_| "Write err"));
            }
            try!(write!(writer, "{}\n", text).map_err(|_| "Write err"));
            Ok(())
        },
    }
}

pub fn generate_header(opt: &Options, writer: &mut Write) -> Result<(), &'static str>
{
    let css = [
        "mozsearch.css",
        "icons.css",
        "selector-common.css",
        "filter.css",
        "xcode.css",
    ];
    let css_tags =
        css.iter().map(|c| {
            F::T(format!(r#"<link href="/static/css/{}" rel="stylesheet" type="text/css" media="screen"/>"#, c))
        });

    let mut head_seq = vec![
        F::S(r#"<meta charset="utf-8" />"#),
        F::S(r#"<link href="/static/icons/search.png" rel="shortcut icon">"#),
        F::T(format!("<title>{}</title>", opt.title)),
    ];
    head_seq.extend(css_tags);

    let fieldset = vec![
        F::S(r#"
"#),
        F::Indent(vec![
            F::S(r#"
"#),
            F::Indent(vec![
                F::S(r#"Find"#),
                F::T(format!(r#"<input type="text" name="q" value="" maxlength="2048" id="query" accesskey="s" title="Search" placeholder="Search {}" autocomplete="off" />"#,
                             opt.tree_name)),
                F::S(r#"
"#),
                F::Indent(vec![
                    F::S(r#"
"#),
                    F::S("
"),
                ]),
                F::S("
"),
                F::S(r#"

"#),
            ]),
            F::S("
"),

            F::S(r#"
"#),
            F::Indent(vec![
                F::S(r#""#),
                F::Indent(vec![
                    F::S(r#"<input type="checkbox" name="case" id="case" class="option-checkbox" value="true" accesskey="c"/>Case-sensitive"#),
                ]),
                F::S(""),

                F::S(r#""#),
                F::Indent(vec![
                    F::S(r#"<input type="checkbox" name="regexp" id="regexp" class="option-checkbox" value="true" accesskey="r"/>Regexp search"#),
                ]),
                F::S(""),
            ]),
            F::S("
"),

            F::S(r#"
"#),
            F::Indent(vec![
                F::S(r#"Path"#),
                F::S(r#"<input type="text" name="path" value="" maxlength="2048" id="path" accesskey="p" title="Path" placeholder="Path filter (supports globbing and ^, $)" autocomplete="off" />"#),
                F::S(r#"
"#),
                F::Indent(vec![
                    F::S(r#"
"#),
                    F::S("
"),
                ]),
                F::S("
"),
            ]),
            F::S("
"),
        ]),
        F::S("
"),
    ];

    let revision = match opt.revision {
        Some((rev_id, rev_desc)) => vec![
            F::T(format!(r#"Showing {}:"#,
                         opt.tree_name, rev_id, &rev_id[..8])),
            F::T(format!(r#"{}"#, rev_desc)),
        ],
        None => vec![],
    };

    let body_class = match opt.revision {
        Some(_) => "old-rev",
        None => "",
    };

    let form = vec![
        F::S("<fieldset>"),
        F::Indent(fieldset),
        F::S("</fieldset>"),
        F::S(r#"<input type="submit" value="Search" class="visually-hidden" />"#),
        F::S(r#"
"#),
        F::Indent(revision),
        F::S("
"),
    ];

    let f = F::Seq(vec![
        F::S("<!DOCTYPE html>"),
        F::S(r#""#),
        F::S(""),
        F::Indent(head_seq),
        F::S(""),
        F::S(""),
        F::T(format!(r#""#, body_class)),
        F::Indent(vec![
            F::T(format!(r#"<form method="get" action="/{}/search" id="basic_search" class="search-box">"#,
                         opt.tree_name)),
            F::Indent(form),
            F::S("</form>"),

            F::S(r#"
"#),
        ]),
    ]);

    try!(generate_formatted(writer, &f, 0));

    Ok(())
}

pub fn generate_footer(opt: &Options, tree_name: &str, path: &str, writer: &mut Write) -> Result<(), &'static str>
{
    let mut date = F::Seq(vec![]);
    if opt.include_date {
        let local: DateTime<Local> = Local::now();
        let time_str = local.to_rfc2822();

        date = F::Seq(vec![
            F::S(r#"
"#),
            F::Indent(vec![
                F::T(format!(r#"This page was generated by Searchfox ."#, time_str)),
            ]),
            F::S("
"),
        ]);
    }

    let scripts = [
        "libs/jquery-2.1.3.min.js",
        "libs/nunjucks.min.js",
        "utils.js",
        "dxr.js",
        "context-menu.js",
        "filter.js",
        "panel.js",
        "code-highlighter.js",
        "blame.js",
    ];
    let script_tags: Vec<_> =
        scripts.iter().map(|s| F::T(format!(r#""#, s))).collect();

    let f = F::Seq(vec![
        F::Indent(vec![
            F::Indent(vec![F::S("
")]),
            date,
            F::T(format!(r#""#,
                         tree_name, tree_name, path)),
            F::Seq(script_tags),
            F::S(""),
        ]),
        F::S("")
    ]);

    try!(generate_formatted(writer, &f, 0));

    Ok(())
}

pub struct PanelItem {
    pub title: String,
    pub link: String,
    pub update_link_lineno: bool,
}

pub struct PanelSection {
    pub name: String,
    pub items: Vec<PanelItem>,
}

pub fn generate_panel(writer: &mut Write, sections: &Vec<PanelSection>) -> Result<(), &'static str> {
    let sections = sections.iter().map(|section| {
        let items = section.items.iter().map(|item| {
            let update_attr = if item.update_link_lineno {
                format!(r#" data-update-link="true" data-link="{}""#, item.link)
            } else {
                "".to_owned()
            };
            F::Seq(vec![
                F::S("
"),
                F::T(format!(r#"{}"#,
                             item.link, item.title, update_attr, item.title)),
                F::S("
"),
            ])
        }).collect::<Vec<_>>();

        F::Seq(vec![
            F::T(format!("
{}
", section.name)),
            F::S("
"),
            F::Seq(items),
            F::S("
"),
        ])
    }).collect::<Vec<_>>();

    let f = F::Seq(vec![
        F::S(r#"
"#),
        F::Indent(vec![
            F::S(r#"<button id="panel-toggle">"#),
            F::Indent(vec![
                F::S(r#""#),
                F::S("Navigation"),
            ]),
            F::S("</button>"),
            F::S(r#"
"#),
            F::Seq(sections),
            F::S("
"),
        ]),
        F::S("
"),
    ]);

    try!(generate_formatted(writer, &f, 0));

    Ok(())
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use crate::{
    server::NebServer,
};

use super::*;

pub struct RangeIndexCost {
    server: Arc<NebServer>,
}

impl CostFunction for RangeIndexCost {
    fn cost(
        &self,
        schema: u32,
        field: Option<u64>,
        range: Option<&ValueRange>,
        projection: Vec<u64>,
    ) -> Option<CostResult> {
        let stat = self.server.chunks.overall_statistics(schema);
        let field = field?;
        let field_histo = stat.histogram.get(&field)?;
        let num_all_rows = stat.count;
        let range = range?;
        let start_index = range.start.pos_of(field_histo).unwrap_or(0);
        let end_index = range.end.pos_of(field_histo).unwrap_or(field_histo.len());
        let width = end_index - start_index;
        let ratio = (width as f64) / (field_histo.len() as f64);
        let row_count = (ratio * (num_all_rows as f64)) as usize;
        let row_bytes = if projection.is_empty() {
            ((stat.bytes as f64) / (stat.count as f64)) as usize
        } else {
            self.server
                .meta
                .schemas
                .fields_size(&schema, projection.as_slice())?
        };
        Some(CostResult {
            row_count,
            row_bytes,
        })
    }
}
<commit_msg>cargo fmt<commit_after>use std::sync::Arc;

use crate::server::NebServer;

use super::*;

pub struct RangeIndexCost {
    server: Arc<NebServer>,
}

impl CostFunction for RangeIndexCost {
    fn cost(
        &self,
        schema: u32,
        field: Option<u64>,
        range: Option<&ValueRange>,
        projection: Vec<u64>,
    ) -> Option<CostResult> {
        let stat = self.server.chunks.overall_statistics(schema);
        let field = field?;
        let field_histo = stat.histogram.get(&field)?;
        let num_all_rows = stat.count;
        let range = range?;
        let start_index = range.start.pos_of(field_histo).unwrap_or(0);
        let end_index = range.end.pos_of(field_histo).unwrap_or(field_histo.len());
        let width = end_index - start_index;
        let ratio = (width as f64) / (field_histo.len() as f64);
        let row_count = (ratio * (num_all_rows as f64)) as usize;
        let row_bytes = if projection.is_empty() {
            ((stat.bytes as f64) / (stat.count as f64)) as usize
        } else {
            self.server
                .meta
                .schemas
                .fields_size(&schema, projection.as_slice())?
        };
        Some(CostResult {
            row_count,
            row_bytes,
        })
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

pub mod api;
mod client;

pub use client::{get, Client};

use derive_more::{Display, Error, From};

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, Display, Error, From)]
pub enum Error {
    #[display("Package's signature validation has failed")]
    InvalidSignature,
    #[display("Http response is missing Content Length")]
    MissingContentLength,

    Io(std::io::Error),
    JsonParsing(serde_json::Error),
    OpenSsl(openssl::error::ErrorStack),
    ParseInt(std::num::ParseIntError),

    Http(#[error(not(source))] surf::Error),
    InvalidStatusResponse(#[error(not(source))] surf::StatusCode),
}
<commit_msg>cloud-sdk: Improve invalid status response error message<commit_after>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

pub mod api;
mod client;

pub use client::{get, Client};

use derive_more::{Display, Error, From};

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, Display, Error, From)]
pub enum Error {
    #[display("Package's signature validation has failed")]
    InvalidSignature,
    #[display("Http response is missing Content Length")]
    MissingContentLength,

    Io(std::io::Error),
    JsonParsing(serde_json::Error),
    OpenSsl(openssl::error::ErrorStack),
    ParseInt(std::num::ParseIntError),

    Http(#[error(not(source))] surf::Error),
    #[display(fmt = "Invalid status response: {}", _0)]
    InvalidStatusResponse(#[error(not(source))] surf::StatusCode),
}
<|endoftext|>


<commit_before>
use {
    AddColor,
    Borrowed,
    Field,
    Line,
    Matrix2d,
    RoundBorderLineColorContext,
    Value,
    View,
};
use vecmath::{
    identity,
};

/// A line context with round border information.
pub struct RoundBorderLineContext<'a> {
    /// Base/original transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current line.
    pub line: Field<'a, Line>,
    /// Current round border.
    pub round_border_radius: Field<'a, f64>,
}

impl<'a> AddColor<'a, RoundBorderLineColorContext<'a>> for RoundBorderLineContext<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RoundBorderLineColorContext<'a> {
        RoundBorderLineColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
            color: Value([r, g, b, a]),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }
}

impl<'a> View<'a> for RoundBorderLineContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }
}

<commit_msg>Implemented `RelativeTransform2D` for `RoundBorderLineContext`<commit_after>
use {
    AddColor,
    Borrowed,
    Field,
    Line,
    Matrix2d,
    RoundBorderLineColorContext,
    Value,
    View,
};
use vecmath::{
    identity,
};
use internal::{
    CanTransform,
    HasTransform,
};

/// A line context with round border information.
pub struct RoundBorderLineContext<'a> {
    /// Base/original transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current line.
    pub line: Field<'a, Line>,
    /// Current round border.
    pub round_border_radius: Field<'a, f64>,
}

impl<'a> HasTransform<'a, Matrix2d> for RoundBorderLineContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, RoundBorderLineContext<'a>, Matrix2d> for RoundBorderLineContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }
}

impl<'a> AddColor<'a, RoundBorderLineColorContext<'a>> for RoundBorderLineContext<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RoundBorderLineColorContext<'a> {
        RoundBorderLineColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
            color: Value([r, g, b, a]),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }
}

impl<'a> View<'a> for RoundBorderLineContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RoundBorderLineContext<'a> {
        RoundBorderLineContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
            round_border_radius: Borrowed(self.round_border_radius.get()),
        }
    }
}

<|endoftext|>


<commit_before>use libc;
use std;
use std::ptr;
use std::rc::Rc;
use std::str;

use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{node_new, Node, NodeType};
use property_bag::PropertyBag;
use structure::NodeSvg;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

struct XmlState {
    tree: Option<Box<Tree>>,
    current_node: Option<Rc<Node>>,

    // Stack of element names while parsing; used to know when to stop
    // parsing the current element.
    element_name_stack: Vec<String>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            current_node: None,
            element_name_stack: Vec::new(),
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    pub fn set_current_node(&mut self, node: Option<Rc<Node>>) {
        self.current_node = node;
    }

    pub fn push_element_name(&mut self, name: &str) {
        self.element_name_stack.push(name.to_string());
    }

    pub fn pop_element_name(&mut self) {
        self.element_name_stack.pop();
    }

    pub fn topmost_element_name_is(&mut self, name: &str) -> bool {
        let len = self.element_name_stack.len();

        if len > 0 {
            self.element_name_stack[len - 1] == name
        } else {
            false
        }
    }

    pub fn free_element_name_stack(&mut self) {
        self.element_name_stack.clear();
    }

    /// Starts a node for an SVG element of type `name` and hooks it to the tree.
    ///
    /// `pbag` is the set of key/value pairs from the element's XML attributes.
    pub fn standard_element_start(
        &mut self,
        handle: *const RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) {
        let mut defs = handle::get_defs(handle);
        let mut is_svg = false;

        let new_node = rsvg_load_new_node(
            name,
            self.current_node.as_ref(),
            pbag,
            &mut defs,
            &mut is_svg,
        );

        self.push_element_name(name);

        if let Some(ref current_node) = self.current_node {
            current_node.add_child(&new_node);
        } else if is_svg {
            self.set_root(&new_node);
        }

        self.set_current_node(Some(new_node.clone()));

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will parse its style attributes
        // until the end, in standard_element_end().
        if new_node.get_type() != NodeType::Svg {
            new_node.parse_style_attributes(handle, name, pbag);
        }

        new_node.set_overridden_properties();
    }

    /// Ends an SVG element for which we create a node.
    pub fn standard_element_end(&mut self, handle: *const RsvgHandle, name: &str) {
        if let Some(ref current_node) = self.current_node.clone() {
            // The "svg" node is special; it parses its style attributes
            // here, not during element creation.
            if current_node.get_type() == NodeType::Svg {
                current_node.with_impl(|svg: &NodeSvg| {
                    svg.parse_style_attributes(current_node, handle);
                });
            }

            if self.topmost_element_name_is(name) {
                let parent = current_node.get_parent();

                self.set_current_node(parent);

                self.pop_element_name();
            }
        }
    }

    pub fn add_characters(&mut self, text: &str) {
        if text.len() == 0 {
            return;
        }

        if let Some(ref current_node) = self.current_node {
            if current_node.accept_chars() {
                let chars_node = if let Some(child) = current_node.find_last_chars_child() {
                    child
                } else {
                    let child = node_new(
                        NodeType::Chars,
                        self.current_node.as_ref(),
                        None,
                        None,
                        Box::new(NodeChars::new()),
                    );
                    current_node.add_child(&child);
                    child
                };

                chars_node.with_impl(|chars: &NodeChars| {
                    chars.append(text);
                });
            }
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free_element_name_stack(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    xml.free_element_name_stack();
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_start(
    xml: *mut RsvgXmlState,
    handle: *const RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.standard_element_start(handle, name, pbag);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_end(
    xml: *mut RsvgXmlState,
    handle: *const RsvgHandle,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    xml.standard_element_end(handle, name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_add_characters(
    xml: *mut RsvgXmlState,
    unterminated_text: *const libc::c_char,
    len: usize,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!unterminated_text.is_null());

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = unsafe { std::slice::from_raw_parts(unterminated_text as *const u8, len) };
    let utf8 = unsafe { str::from_utf8_unchecked(bytes) };

    xml.add_characters(utf8);
}
<commit_msg>XmlContext: new trait for XML parsing contexts<commit_after>use libc;
use std;
use std::ptr;
use std::rc::Rc;
use std::str;

use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{node_new, Node, NodeType};
use property_bag::PropertyBag;
use structure::NodeSvg;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

/// A trait for processing a certain kind of XML subtree
///
/// In the "normal" state of processing, an `XmlContext` may create an RsvgNode
/// for each SVG element it finds, and create NodeChars inside those nodes when it
/// encounters character data.
///
/// There may be other, special contexts for different subtrees, for example,
/// for the `<style>` element.
trait XmlContext {
    /// Called when the XML parser sees the beginning of an element
    fn start_element(&mut self, handle: *mut RsvgHandle, name: &str, pbag: &PropertyBag);

    /// Called when the XML parser sees the end of an element
    fn end_element(&mut self, handle: *mut RsvgHandle, name: &str);

    /// Called when the XML parser sees character data or CDATA
    fn characters(&mut self, text: &str);

    /// Called when the context terminates, i.e. when the parent element
    /// that created this context is closed.
    fn finish(&mut self);
}

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

struct XmlState {
    tree: Option<Box<Tree>>,
    current_node: Option<Rc<Node>>,

    // Stack of element names while parsing; used to know when to stop
    // parsing the current element.
    element_name_stack: Vec<String>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            current_node: None,
            element_name_stack: Vec::new(),
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    pub fn set_current_node(&mut self, node: Option<Rc<Node>>) {
        self.current_node = node;
    }

    pub fn push_element_name(&mut self, name: &str) {
        self.element_name_stack.push(name.to_string());
    }

    pub fn pop_element_name(&mut self) {
        self.element_name_stack.pop();
    }

    pub fn topmost_element_name_is(&mut self, name: &str) -> bool {
        let len = self.element_name_stack.len();

        if len > 0 {
            self.element_name_stack[len - 1] == name
        } else {
            false
        }
    }

    pub fn free_element_name_stack(&mut self) {
        self.element_name_stack.clear();
    }

    /// Starts a node for an SVG element of type `name` and hooks it to the tree.
    ///
    /// `pbag` is the set of key/value pairs from the element's XML attributes.
    pub fn standard_element_start(
        &mut self,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) {
        let mut defs = handle::get_defs(handle);
        let mut is_svg = false;

        let new_node = rsvg_load_new_node(
            name,
            self.current_node.as_ref(),
            pbag,
            &mut defs,
            &mut is_svg,
        );

        self.push_element_name(name);

        if let Some(ref current_node) = self.current_node {
            current_node.add_child(&new_node);
        } else if is_svg {
            self.set_root(&new_node);
        }

        self.set_current_node(Some(new_node.clone()));

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will parse its style attributes
        // until the end, in standard_element_end().
        if new_node.get_type() != NodeType::Svg {
            new_node.parse_style_attributes(handle, name, pbag);
        }

        new_node.set_overridden_properties();
    }

    /// Ends an SVG element for which we create a node.
    pub fn standard_element_end(&mut self, handle: *mut RsvgHandle, name: &str) {
        if let Some(ref current_node) = self.current_node.clone() {
            // The "svg" node is special; it parses its style attributes
            // here, not during element creation.
            if current_node.get_type() == NodeType::Svg {
                current_node.with_impl(|svg: &NodeSvg| {
                    svg.parse_style_attributes(current_node, handle);
                });
            }

            if self.topmost_element_name_is(name) {
                let parent = current_node.get_parent();

                self.set_current_node(parent);

                self.pop_element_name();
            }
        }
    }

    pub fn add_characters(&mut self, text: &str) {
        if text.len() == 0 {
            return;
        }

        if let Some(ref current_node) = self.current_node {
            if current_node.accept_chars() {
                let chars_node = if let Some(child) = current_node.find_last_chars_child() {
                    child
                } else {
                    let child = node_new(
                        NodeType::Chars,
                        self.current_node.as_ref(),
                        None,
                        None,
                        Box::new(NodeChars::new()),
                    );
                    current_node.add_child(&child);
                    child
                };

                chars_node.with_impl(|chars: &NodeChars| {
                    chars.append(text);
                });
            }
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free_element_name_stack(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    xml.free_element_name_stack();
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_start(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.standard_element_start(handle, name, pbag);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_end(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    xml.standard_element_end(handle, name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_add_characters(
    xml: *mut RsvgXmlState,
    unterminated_text: *const libc::c_char,
    len: usize,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!unterminated_text.is_null());

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = unsafe { std::slice::from_raw_parts(unterminated_text as *const u8, len) };
    let utf8 = unsafe { str::from_utf8_unchecked(bytes) };

    xml.add_characters(utf8);
}
<|endoftext|>