<commit_before>use std::env;
use std::fs;
use std::io;
use std::process;
use std::process::{Command, Stdio};
use num_cpus;
use kuchiki;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::{Client, Url};
use config::Config;
use extractor;
use downloader;
use profile;
use build_conf;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    fs::create_dir_all(&config.versions_dir).expect("Could not create versions directory.");
    build_conf::write_conf(&config);
    if !env::home_dir()
        .unwrap_or_else(|| panic!("Cound not found homedir."))
        .join(".profile")
        .exists() {
        println!(r#"Write the following thing:

. $HOME\.groonga\shims\bin\source-groonga.sh
"#)
    }
}

pub fn install(m: &ArgMatches) {
    extern crate env_proxy;

    const BASE_URL: &'static str = "http://packages.groonga.org/source/groonga";
    let maybe_proxy = env_proxy::for_url(&Url::parse(BASE_URL).unwrap());
    let config = Config::from_matches(m);
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}", config.version.unwrap());
    let groonga_source = format!("{}.tar.gz", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = match maybe_proxy {
        None => Client::new(),
        Some(host_port) => Client::with_http_proxy(host_port.0, host_port.1),
    };
    let targz = downloader::file_download(&client,
                                          &*format!("{}/{}", BASE_URL, groonga_source),
                                          download_dir.clone(),
                                          "groonga.tar.gz")
        .expect("Failed to download");
    assert!(extractor::extract_targz(&targz, &download_dir).is_ok());
    assert!(env::set_current_dir(&download_dir.join(groonga_dir.clone())).is_ok());

    // TODO: Should specify on Linux?
    match inner_autoreconf() {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not execute autoreconf -v.");
            process::exit(1);
        }
    }

    match inner_configure(&config, groonga_dir.clone()) {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not configure.");
            process::exit(1);
        }
    }

    match inner_build() {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not build.");
            process::exit(1);
        }
    }

    match inner_install() {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not install.");
            process::exit(1);
        }
    }

    #[cfg(target_os = "macos")]
    fn inner_autoreconf() -> Result<process::ExitStatus, io::Error> {
        let mut cmd = Command::new("autoreconf")
            .args(&["-v"])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }

    #[cfg(not(target_os = "macos"))]
    fn inner_autoreconf() -> Result<u32, io::Error> {
        Ok(0)
    }

    fn inner_configure(config: &Config,
                       groonga_dir: String)
                       -> Result<process::ExitStatus, io::Error> {
        let args = build_conf::build_args(config, groonga_dir)?;
        let mut cmd = Command::new("./configure")
            .args(&*args)
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }

    fn inner_build() -> Result<process::ExitStatus, io::Error> {
        let make = build_conf::make()
            .ok_or(io::Error::new(io::ErrorKind::NotFound, "make kind command is not found"))?;
        let mut cmd = Command::new(make)
            .args(&["-j", &*format!("{}", num_cpus::get())])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }

    fn inner_install() -> Result<process::ExitStatus, io::Error> {
        let make = build_conf::make()
            .ok_or(io::Error::new(io::ErrorKind::NotFound, "make kind command is not found"))?;
        let mut cmd = Command::new(make)
            .args(&["install"])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}", config.version.unwrap());
    match config.version {
        Some("system") => {
            profile::unix::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::unix::create_profile_source(&config.shim_dir,
                                                 &groonga_dir,
                                                 &config.versions_dir)
                .expect("Could not create source-groonga.sh")
        }
        None => unreachable!(),
    }
}

pub fn uninstall(m: &ArgMatches) {
    let config = Config::from_matches(m);
    let groonga_dir = format!("groonga-{}", config.version.unwrap());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Removing {}....", groonga_dir.clone());
        fs::remove_dir_all(&config.versions_dir.join(groonga_dir))
            .expect("Could not remove specified directory.");
    } else {
        println!("{} is not installed!", groonga_dir.clone());
        process::exit(1);
    }
}

pub fn list() {
    use kuchiki::traits::*;
    use command::common::MaybeProxyUrl;

    let base_url: &'static str = "http://packages.groonga.org/source/groonga";
    let maybe_proxy_url = MaybeProxyUrl { url: Url::parse(base_url).unwrap() };
    if let Ok(doc) = kuchiki::parse_html().from_http(maybe_proxy_url) {
        let docs = doc.select("tr")
            .unwrap_or_else(|e| panic!("failed to find tr elements: {:?}", e))
            .collect::<Vec<_>>();
        println!("Installable Groonga:");
        for handle in &docs {
            let texts = handle.as_node().descendants().text_nodes().collect::<Vec<_>>();
            if let Some(text) = texts.first() {
                let package = text.as_node().text_contents();
                if package.contains("groonga") && package.contains("zip") &&
                   !package.contains("asc") {
                    let package = package.split(".zip").collect::<Vec<_>>();
                    let pkg =
                        package.first().unwrap_or(&"").to_owned().split("-").collect::<Vec<_>>();
                    println!("\t{}", pkg.get(1).unwrap_or(&""));
                }
            }
        }
    } else {
        println!("{}", "The page couldn't be fetched");
    }
}
<commit_msg>unix: Confirm uninstallation<commit_after>use std::env;
use std::fs;
use std::io;
use std::process;
use std::process::{Command, Stdio};
use num_cpus;
use kuchiki;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::{Client, Url};
use config::Config;
use extractor;
use downloader;
use profile;
use build_conf;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    fs::create_dir_all(&config.versions_dir).expect("Could not create versions directory.");
    build_conf::write_conf(&config);
    if !env::home_dir()
        .unwrap_or_else(|| panic!("Cound not found homedir."))
        .join(".profile")
        .exists() {
        println!(r#"Write the following thing:

. $HOME\.groonga\shims\bin\source-groonga.sh
"#)
    }
}

pub fn install(m: &ArgMatches) {
    extern crate env_proxy;

    const BASE_URL: &'static str = "http://packages.groonga.org/source/groonga";
    let maybe_proxy = env_proxy::for_url(&Url::parse(BASE_URL).unwrap());
    let config = Config::from_matches(m);
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}", config.version.unwrap());
    let groonga_source = format!("{}.tar.gz", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = match maybe_proxy {
        None => Client::new(),
        Some(host_port) => Client::with_http_proxy(host_port.0, host_port.1),
    };
    let targz = downloader::file_download(&client,
                                          &*format!("{}/{}", BASE_URL, groonga_source),
                                          download_dir.clone(),
                                          "groonga.tar.gz")
        .expect("Failed to download");
    assert!(extractor::extract_targz(&targz, &download_dir).is_ok());
    assert!(env::set_current_dir(&download_dir.join(groonga_dir.clone())).is_ok());

    // TODO: Should specify on Linux?
    match inner_autoreconf() {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not execute autoreconf -v.");
            process::exit(1);
        }
    }

    match inner_configure(&config, groonga_dir.clone()) {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not configure.");
            process::exit(1);
        }
    }

    match inner_build() {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not build.");
            process::exit(1);
        }
    }

    match inner_install() {
        Ok(o) => println!("{}", o),
        Err(_) => {
            println!("Could not install.");
            process::exit(1);
        }
    }

    #[cfg(target_os = "macos")]
    fn inner_autoreconf() -> Result<process::ExitStatus, io::Error> {
        let mut cmd = Command::new("autoreconf")
            .args(&["-v"])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }

    #[cfg(not(target_os = "macos"))]
    fn inner_autoreconf() -> Result<u32, io::Error> {
        Ok(0)
    }

    fn inner_configure(config: &Config,
                       groonga_dir: String)
                       -> Result<process::ExitStatus, io::Error> {
        let args = build_conf::build_args(config, groonga_dir)?;
        let mut cmd = Command::new("./configure")
            .args(&*args)
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }

    fn inner_build() -> Result<process::ExitStatus, io::Error> {
        let make = build_conf::make()
            .ok_or(io::Error::new(io::ErrorKind::NotFound, "make kind command is not found"))?;
        let mut cmd = Command::new(make)
            .args(&["-j", &*format!("{}", num_cpus::get())])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }

    fn inner_install() -> Result<process::ExitStatus, io::Error> {
        let make = build_conf::make()
            .ok_or(io::Error::new(io::ErrorKind::NotFound, "make kind command is not found"))?;
        let mut cmd = Command::new(make)
            .args(&["install"])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .unwrap_or_else(|e| panic!("failed to execute child: {}", e));
        let status = cmd.wait();
        status
    }
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}", config.version.unwrap());
    match config.version {
        Some("system") => {
            profile::unix::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::unix::create_profile_source(&config.shim_dir,
                                                 &groonga_dir,
                                                 &config.versions_dir)
                .expect("Could not create source-groonga.sh")
        }
        None => unreachable!(),
    }
}

pub fn uninstall(m: &ArgMatches) {
    let config = Config::from_matches(m);
    let mut choice = String::new();
    let groonga_dir = format!("groonga-{}", config.version.unwrap());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Uninstall Groonga version {}? [y/N]", config.version.unwrap());
        io::stdin().read_line(&mut choice).expect("Failed to read line");
        if choice == "y".to_owned() || choice == "Y".to_owned() {
            println!("Removing {}....", groonga_dir.clone());
            fs::remove_dir_all(&config.versions_dir.join(groonga_dir))
                .expect("Could not remove specified directory.");
        }
    } else {
        println!("{} is not installed!", groonga_dir.clone());
        process::exit(1);
    }
}

pub fn list() {
    use kuchiki::traits::*;
    use command::common::MaybeProxyUrl;

    let base_url: &'static str = "http://packages.groonga.org/source/groonga";
    let maybe_proxy_url = MaybeProxyUrl { url: Url::parse(base_url).unwrap() };
    if let Ok(doc) = kuchiki::parse_html().from_http(maybe_proxy_url) {
        let docs = doc.select("tr")
            .unwrap_or_else(|e| panic!("failed to find tr elements: {:?}", e))
            .collect::<Vec<_>>();
        println!("Installable Groonga:");
        for handle in &docs {
            let texts = handle.as_node().descendants().text_nodes().collect::<Vec<_>>();
            if let Some(text) = texts.first() {
                let package = text.as_node().text_contents();
                if package.contains("groonga") && package.contains("zip") &&
                   !package.contains("asc") {
                    let package = package.split(".zip").collect::<Vec<_>>();
                    let pkg =
                        package.first().unwrap_or(&"").to_owned().split("-").collect::<Vec<_>>();
                    println!("\t{}", pkg.get(1).unwrap_or(&""));
                }
            }
        }
    } else {
        println!("{}", "The page couldn't be fetched");
    }
}
<|endoftext|>


<commit_before>// API Methods: Accounts
#[test]
fn client_fetches_account() {
    unimplemented!()
}

#[test]
fn client_gets_current_user() {
    unimplemented!()
}

#[test]
fn client_update_current_user() {
    unimplemented!()
}

#[test]
fn client_get_account_followers() {
    unimplemented!()
}

#[test]
fn client_get_who_account_is_following() {
    unimplemented!()
}

#[test]
fn client_get_account_statuses() {
    unimplemented!()
}

#[test]
fn client_follow_account() {
    unimplemented!()
}

#[test]
fn client_unfullow_account() {
    unimplemented!()
}

#[test]
fn client_mute_account() {
    unimplemented!()
}

#[test]
fn client_unmute_account() {
    unimplemented!()
}

#[test]
fn client_get_account_relationships() {
    unimplemented!()
}

#[test]
fn client_search_accounts() {
    unimplemented!()
}

// API Methods: Apps
#[test]
fn client_registering_an_application() {
    unimplemented!()
}

// API Methods: Blocks
#[test]
fn client_fetching_users_blocks() {
    unimplemented!()
}

// API Methods: Favourites
fn client_fetching_users_favourites() {
    unimplemented!()
}

// API Methods: FollowRequests
fn client_fetching_follow_requests() {
    unimplemented!()
}

fn client_authorizing_follow_requests() {
    unimplemented!()
}

fn client_rejecting_follow_requests() {
    unimplemented!()
}

// API Methods: Follows
fn client_following_a_remote_user() {
    unimplemented!()
}

// API Methods: Instances
fn client_getting_instance_information() {
    unimplemented!()
}

// API Methods: Media
fn client_uploading_a_media_attachment() {
    unimplemented!()
}

// API Methods: Mutes
fn client_fetchin_a_users_mutes() {
    unimplemented!()
}

// API Methods: Notifications
fn client_fetching_users_notifications() {
    unimplemented!()
}

fn client_getting_single_notification() {
    unimplemented!()
}

fn client_clearing_notifications() {
    unimplemented!()
}

// API Methods: Reports
fn client_fetching_users_reports() {
    unimplemented!()
}

fn client_reporting_user() {
    unimplemented!()
}

// API Methods: Search
fn client_searching_for_content() {
    unimplemented!()
}

// API Methods: Statuses
fn client_fetching_a_status() {
    unimplemented!()
}

fn client_getting_status_context() {
    unimplemented!()
}

fn client_getting_card_associated_with_status() {
    unimplemented!()
}

fn client_getting_who_reblogged_status() {
    unimplemented!()
}

fn client_getting_who_favourited_status() {
    unimplemented!()
}

fn client_posting_new_status() {
    unimplemented!()
}

fn client_deleting_a_status() {
    unimplemented!()
}

fn client_reblogging_status() {
    unimplemented!()
}

fn client_unreblogging_status() {
    unimplemented!()
}

fn client_favouriting_status() {
    unimplemented!()
}

fn client_unfavouriting_status() {
    unimplemented!()
}

// API Methods: Timelines
fn client_retrieving_a_timeline() {
    unimplemented!()
}
<commit_msg>missing test flags<commit_after>// API Methods: Accounts
#[test]
fn client_fetches_account() {
    unimplemented!()
}

#[test]
fn client_gets_current_user() {
    unimplemented!()
}

#[test]
fn client_update_current_user() {
    unimplemented!()
}

#[test]
fn client_get_account_followers() {
    unimplemented!()
}

#[test]
fn client_get_who_account_is_following() {
    unimplemented!()
}

#[test]
fn client_get_account_statuses() {
    unimplemented!()
}

#[test]
fn client_follow_account() {
    unimplemented!()
}

#[test]
fn client_unfullow_account() {
    unimplemented!()
}

#[test]
fn client_mute_account() {
    unimplemented!()
}

#[test]
fn client_unmute_account() {
    unimplemented!()
}

#[test]
fn client_get_account_relationships() {
    unimplemented!()
}

#[test]
fn client_search_accounts() {
    unimplemented!()
}

// API Methods: Apps
#[test]
fn client_registering_an_application() {
    unimplemented!()
}

// API Methods: Blocks
#[test]
fn client_fetching_users_blocks() {
    unimplemented!()
}

// API Methods: Favourites
#[test]
fn client_fetching_users_favourites() {
    unimplemented!()
}

// API Methods: FollowRequests
#[test]
fn client_fetching_follow_requests() {
    unimplemented!()
}

#[test]
fn client_authorizing_follow_requests() {
    unimplemented!()
}

#[test]
fn client_rejecting_follow_requests() {
    unimplemented!()
}

// API Methods: Follows
#[test]
fn client_following_a_remote_user() {
    unimplemented!()
}

// API Methods: Instances
#[test]
fn client_getting_instance_information() {
    unimplemented!()
}

// API Methods: Media
#[test]
fn client_uploading_a_media_attachment() {
    unimplemented!()
}

// API Methods: Mutes
#[test]
fn client_fetchin_a_users_mutes() {
    unimplemented!()
}

// API Methods: Notifications
#[test]
fn client_fetching_users_notifications() {
    unimplemented!()
}

#[test]
fn client_getting_single_notification() {
    unimplemented!()
}

#[test]
fn client_clearing_notifications() {
    unimplemented!()
}

// API Methods: Reports
#[test]
fn client_fetching_users_reports() {
    unimplemented!()
}

#[test]
fn client_reporting_user() {
    unimplemented!()
}

// API Methods: Search
#[test]
fn client_searching_for_content() {
    unimplemented!()
}

// API Methods: Statuses
#[test]
fn client_fetching_a_status() {
    unimplemented!()
}

#[test]
fn client_getting_status_context() {
    unimplemented!()
}

#[test]
fn client_getting_card_associated_with_status() {
    unimplemented!()
}

#[test]
fn client_getting_who_reblogged_status() {
    unimplemented!()
}

#[test]
fn client_getting_who_favourited_status() {
    unimplemented!()
}

#[test]
fn client_posting_new_status() {
    unimplemented!()
}

#[test]
fn client_deleting_a_status() {
    unimplemented!()
}

#[test]
fn client_reblogging_status() {
    unimplemented!()
}

#[test]
fn client_unreblogging_status() {
    unimplemented!()
}

#[test]
fn client_favouriting_status() {
    unimplemented!()
}

#[test]
fn client_unfavouriting_status() {
    unimplemented!()
}

// API Methods: Timelines
#[test]
fn client_retrieving_a_timeline() {
    unimplemented!()
}
<|endoftext|>


<commit_before>//! ARM C Language Extensions (ACLE)
//!
//! # Developer notes
//!
//! Below is a list of built-in targets that are representative of the different ARM
//! architectures; the list includes the `target_feature`s they possess.
//!
//! - `armv4t-unknown-linux-gnueabi` - **ARMv4** - `+v4t`
//! - `armv5te-unknown-linux-gnueabi` - **ARMv5TE** - `+v4t +v5te`
//! - `arm-unknown-linux-gnueabi` - **ARMv6** - `+v4t +v5te +v6`
//! - `thumbv6m-none-eabi` - **ARMv6-M** - `+v4t +v5te +v6 +thumb-mode +mclass`
//! - `armv7-unknown-linux-gnueabihf` - **ARMv7-A** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +aclass`
//! - `armv7r-none-eabi` - **ARMv7-R** - `+v4t +v5te +v6 +v6k +v6t2  +v7 +dsp +thumb2 +rclass`
//! - `thumbv7m-none-eabi` - **ARMv7-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +thumb2 +thumb-mode +mclass`
//! - `thumbv7em-none-eabi` - **ARMv7E-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +thumb-mode +mclass`
//! - `aarch64-unknown-linux-gnu` - **ARMv8-A (AArch64)** - `+fp +neon`
//!
//! Section 10.1 of ACLE says:
//!
//! - "In the sequence of Arm architectures { v5, v5TE, v6, v6T2, v7 } each architecture includes
//! its predecessor instruction set."
//!
//! - "In the sequence of Thumb-only architectures { v6-M, v7-M, v7E-M } each architecture includes
//! its predecessor instruction set."
//!
//! From that info and from looking at how LLVM features work (using custom targets) we can identify
//! features that are subsets of others:
//!
//! Legend: `a < b` reads as "`a` is a subset of `b`"; this means that if `b` is enabled then `a` is
//! enabled as well.
//!
//! - `v4t < v5te < v6 < v6k < v6t2 < v7 < v8`
//! - `v6 < v8m < v6t2`
//! - `v7 < v8m.main`
//!
//! *NOTE*: Section 5.4.7 of ACLE says:
//!
//! - "__ARM_FEATURE_DSP is defined to 1 if the DSP (v5E) instructions are supported and the
//! intrinsics defined in Saturating intrinsics are available."
//!
//! This does *not* match how LLVM uses the '+dsp' feature; this feature is not set for v5te
//! targets so we have to work around this difference.
//!
//! # References
//!
//! - [ACLE Q2 2018](https://developer.arm.com/docs/101028/latest)

// 8, 7 and 6-M are supported via dedicated instructions like DMB. All other arches are supported
// via CP15 instructions. See Section 10.1 of ACLE
mod barrier;

pub use self::barrier::*;

mod hints;

pub use self::hints::*;

mod registers;

pub use self::registers::*;

mod ex;

pub use self::ex::*;

// Supported arches: 5TE, 7E-M. See Section 10.1 of ACLE (e.g. QADD)
// We also include the A profile even though DSP is deprecated on that profile as of ACLE 2.0 (see
// section 5.4.7)
// Here we workaround the difference between LLVM's +dsp and ACLE's __ARM_FEATURE_DSP by gating on
// '+v5te' rather than on '+dsp'
#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        // >= v5TE but excludes v7-M
        all(target_feature = "v5te", not(target_feature = "mclass")),
        // v7E-M
        all(target_feature = "mclass", target_feature = "dsp"),
    )
))]
mod dsp;

#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        all(target_feature = "v5te", not(target_feature = "mclass")),
        all(target_feature = "mclass", target_feature = "dsp"),
    )
))]
pub use self::dsp::*;

// Supported arches: 6, 7-M. See Section 10.1 of ACLE (e.g. SSAT)
#[cfg(all(
    not(target_arch = "aarch64"),
    target_feature = "v6",
))]
mod sat;

#[cfg(all(
    not(target_arch = "aarch64"),
    target_feature = "v6",
))]
pub use self::sat::*;

// Deprecated in ACLE 2.0 for the A profile but fully supported on the M and R profiles, says
// Section 5.4.9 of ACLE. We'll expose these for the A profile even if deprecated
#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        // v7-A, v7-R
        all(target_feature = "v6", not(target_feature = "mclass")),
        // v7E-M
        all(target_feature = "mclass", target_feature = "dsp")
    )
))]
mod simd32;

#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        all(target_feature = "v6", not(target_feature = "mclass")),
        all(target_feature = "mclass", target_feature = "dsp")
    )
))]
pub use self::simd32::*;

mod sealed {
    pub trait Dmb {
        unsafe fn __dmb(&self);
    }

    pub trait Dsb {
        unsafe fn __dsb(&self);
    }

    pub trait Isb {
        unsafe fn __isb(&self);
    }

    pub trait Rsr {
        unsafe fn __rsr(&self) -> u32;
    }

    pub trait Rsr64 {
        unsafe fn __rsr64(&self) -> u64;
    }

    pub trait Rsrp {
        unsafe fn __rsrp(&self) -> *const u8;
    }

    pub trait Wsr {
        unsafe fn __wsr(&self, value: u32);
    }

    pub trait Wsr64 {
        unsafe fn __wsr64(&self, value: u64);
    }

    pub trait Wsrp {
        unsafe fn __wsrp(&self, value: *const u8);
    }
}
<commit_msg>acle/docs: add armv8-m and armv8-r to the list of rustc targets & llvm features<commit_after>//! ARM C Language Extensions (ACLE)
//!
//! # Developer notes
//!
//! Below is a list of built-in targets that are representative of the different ARM
//! architectures; the list includes the `target_feature`s they possess.
//!
//! - `armv4t-unknown-linux-gnueabi` - **ARMv4** - `+v4t`
//! - `armv5te-unknown-linux-gnueabi` - **ARMv5TE** - `+v4t +v5te`
//! - `arm-unknown-linux-gnueabi` - **ARMv6** - `+v4t +v5te +v6`
//! - `thumbv6m-none-eabi` - **ARMv6-M** - `+v4t +v5te +v6 +thumb-mode +mclass`
//! - `armv7-unknown-linux-gnueabihf` - **ARMv7-A** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +aclass`
//! - `armv7r-none-eabi` - **ARMv7-R** - `+v4t +v5te +v6 +v6k +v6t2  +v7 +dsp +thumb2 +rclass`
//! - `thumbv7m-none-eabi` - **ARMv7-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +thumb2 +thumb-mode +mclass`
//! - `thumbv7em-none-eabi` - **ARMv7E-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +dsp +thumb2 +thumb-mode +mclass`
//! - `thumbv8m.main-none-eabi` - **ARMv8-M** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +thumb2 +thumb-mode +mclass`
//! - `armv8r-none-eabi` - **ARMv8-R** - `+v4t +v5te +v6 +v6k +v6t2 +v7 +v8 +thumb2 +rclass`
//! - `aarch64-unknown-linux-gnu` - **ARMv8-A (AArch64)** - `+fp +neon`
//!
//! Section 10.1 of ACLE says:
//!
//! - "In the sequence of Arm architectures { v5, v5TE, v6, v6T2, v7 } each architecture includes
//! its predecessor instruction set."
//!
//! - "In the sequence of Thumb-only architectures { v6-M, v7-M, v7E-M } each architecture includes
//! its predecessor instruction set."
//!
//! From that info and from looking at how LLVM features work (using custom targets) we can identify
//! features that are subsets of others:
//!
//! Legend: `a < b` reads as "`a` is a subset of `b`"; this means that if `b` is enabled then `a` is
//! enabled as well.
//!
//! - `v4t < v5te < v6 < v6k < v6t2 < v7 < v8`
//! - `v6 < v8m < v6t2`
//! - `v7 < v8m.main`
//!
//! *NOTE*: Section 5.4.7 of ACLE says:
//!
//! - "__ARM_FEATURE_DSP is defined to 1 if the DSP (v5E) instructions are supported and the
//! intrinsics defined in Saturating intrinsics are available."
//!
//! This does *not* match how LLVM uses the '+dsp' feature; this feature is not set for v5te
//! targets so we have to work around this difference.
//!
//! # References
//!
//! - [ACLE Q2 2018](https://developer.arm.com/docs/101028/latest)

// 8, 7 and 6-M are supported via dedicated instructions like DMB. All other arches are supported
// via CP15 instructions. See Section 10.1 of ACLE
mod barrier;

pub use self::barrier::*;

mod hints;

pub use self::hints::*;

mod registers;

pub use self::registers::*;

mod ex;

pub use self::ex::*;

// Supported arches: 5TE, 7E-M. See Section 10.1 of ACLE (e.g. QADD)
// We also include the A profile even though DSP is deprecated on that profile as of ACLE 2.0 (see
// section 5.4.7)
// Here we workaround the difference between LLVM's +dsp and ACLE's __ARM_FEATURE_DSP by gating on
// '+v5te' rather than on '+dsp'
#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        // >= v5TE but excludes v7-M
        all(target_feature = "v5te", not(target_feature = "mclass")),
        // v7E-M
        all(target_feature = "mclass", target_feature = "dsp"),
    )
))]
mod dsp;

#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        all(target_feature = "v5te", not(target_feature = "mclass")),
        all(target_feature = "mclass", target_feature = "dsp"),
    )
))]
pub use self::dsp::*;

// Supported arches: 6, 7-M. See Section 10.1 of ACLE (e.g. SSAT)
#[cfg(all(
    not(target_arch = "aarch64"),
    target_feature = "v6",
))]
mod sat;

#[cfg(all(
    not(target_arch = "aarch64"),
    target_feature = "v6",
))]
pub use self::sat::*;

// Deprecated in ACLE 2.0 for the A profile but fully supported on the M and R profiles, says
// Section 5.4.9 of ACLE. We'll expose these for the A profile even if deprecated
#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        // v7-A, v7-R
        all(target_feature = "v6", not(target_feature = "mclass")),
        // v7E-M
        all(target_feature = "mclass", target_feature = "dsp")
    )
))]
mod simd32;

#[cfg(all(
    not(target_arch = "aarch64"),
    any(
        all(target_feature = "v6", not(target_feature = "mclass")),
        all(target_feature = "mclass", target_feature = "dsp")
    )
))]
pub use self::simd32::*;

mod sealed {
    pub trait Dmb {
        unsafe fn __dmb(&self);
    }

    pub trait Dsb {
        unsafe fn __dsb(&self);
    }

    pub trait Isb {
        unsafe fn __isb(&self);
    }

    pub trait Rsr {
        unsafe fn __rsr(&self) -> u32;
    }

    pub trait Rsr64 {
        unsafe fn __rsr64(&self) -> u64;
    }

    pub trait Rsrp {
        unsafe fn __rsrp(&self) -> *const u8;
    }

    pub trait Wsr {
        unsafe fn __wsr(&self, value: u32);
    }

    pub trait Wsr64 {
        unsafe fn __wsr64(&self, value: u64);
    }

    pub trait Wsrp {
        unsafe fn __wsrp(&self, value: *const u8);
    }
}
<|endoftext|>


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

#![feature(async_await)]

#[macro_use]
extern crate failure;

#[derive(Fail, Debug)]
#[fail(display = "command failed: {}", command)]
pub struct CommandFailed {
    command: String,
}

mod git;
mod github;

pub mod api;
pub mod load;
pub mod server;
pub mod util;
<commit_msg>Remove async_await feature gate<commit_after>// Copyright 2016 The rustc-perf Project Developers. See the COPYRIGHT
// file at the top-level directory.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_use]
extern crate failure;

#[derive(Fail, Debug)]
#[fail(display = "command failed: {}", command)]
pub struct CommandFailed {
    command: String,
}

mod git;
mod github;

pub mod api;
pub mod load;
pub mod server;
pub mod util;
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;

use std::hash::Hash;
use test::Bencher;

use hashbrown::HashMap;
//use rustc_hash::FxHashMap as HashMap;
//use std::collections::HashMap;

fn new_map<K: Eq + Hash, V>() -> HashMap<K, V> {
    HashMap::default()
}

#[bench]
fn new_drop(b: &mut Bencher) {
    b.iter(|| {
        let m: HashMap<i32, i32> = new_map();
        assert_eq!(m.len(), 0);
    })
}

#[bench]
fn new_insert_drop(b: &mut Bencher) {
    b.iter(|| {
        let mut m = new_map();
        m.insert(0, 0);
        assert_eq!(m.len(), 1);
    })
}

#[bench]
fn grow_by_insertion(b: &mut Bencher) {
    let mut m = new_map();

    for i in 1..1001 {
        m.insert(i, i);
    }

    let mut k = 1001;

    b.iter(|| {
        m.insert(k, k);
        k += 1;
    });
}

#[bench]
fn grow_by_insertion_kb(b: &mut Bencher) {
    let mut m = new_map();
    let kb = 1024;
    for i in 1..1001 {
        m.insert(i * kb, i);
    }

    let mut k = 1001 * kb;

    b.iter(|| {
        m.insert(k, k);
        k += kb;
    });
}

#[bench]
fn find_existing(b: &mut Bencher) {
    let mut m = new_map();

    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in 1..1001 {
            m.contains_key(&i);
        }
    });
}

#[bench]
fn find_existing_high_bits(b: &mut Bencher) {
    let mut m = new_map();

    for i in 1..1001_u64 {
        m.insert(i << 32, i);
    }

    b.iter(|| {
        for i in 1..1001_u64 {
            m.contains_key(&(i << 32));
        }
    });
}

#[bench]
fn find_nonexisting(b: &mut Bencher) {
    let mut m = new_map();

    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in 1001..2001 {
            m.contains_key(&i);
        }
    });
}

#[bench]
fn hashmap_as_queue(b: &mut Bencher) {
    let mut m = new_map();

    for i in 1..1001 {
        m.insert(i, i);
    }

    let mut k = 1;

    b.iter(|| {
        m.remove(&k);
        m.insert(k + 1000, k + 1000);
        k += 1;
    });
}

#[bench]
fn get_remove_insert(b: &mut Bencher) {
    let mut m = new_map();

    for i in 1..1001 {
        m.insert(i, i);
    }

    let mut k = 1;

    b.iter(|| {
        m.get(&(k + 400));
        m.get(&(k + 2000));
        m.remove(&k);
        m.insert(k + 1000, k + 1000);
        k += 1;
    })
}

#[bench]
fn insert_8_char_string(b: &mut Bencher) {
    let mut strings: Vec<_> = Vec::new();
    for i in 1..1001 {
        strings.push(format!("{:x}", -i));
    }

    let mut m = new_map();
    b.iter(|| {
        for key in &strings {
            m.insert(key, key);
        }
    })
}
<commit_msg>Replace benchmarks with (slightly) better ones<commit_after>#![feature(test)]

extern crate test;

use std::hash::Hash;
use test::{black_box, Bencher};

use hashbrown::HashMap;
//use rustc_hash::FxHashMap as HashMap;
//use std::collections::HashMap;

fn new_map<K: Eq + Hash, V>() -> HashMap<K, V> {
    HashMap::default()
}

#[bench]
fn insert_i32(b: &mut Bencher) {
    b.iter(|| {
        let mut m: HashMap<i32, i32> = new_map();
        for i in 1..1001 {
            m.insert(i, i);
        }
        black_box(m);
    })
}

#[bench]
fn insert_i64(b: &mut Bencher) {
    b.iter(|| {
        let mut m: HashMap<i64, i64> = new_map();
        for i in 1..1001 {
            m.insert(i, i);
        }
        black_box(m);
    })
}

#[bench]
fn insert_erase_i32(b: &mut Bencher) {
    b.iter(|| {
        let mut m: HashMap<i32, i32> = new_map();
        for i in 1..1001 {
            m.insert(i, i);
        }
        black_box(&mut m);
        for i in 1..1001 {
            m.remove(&i);
        }
        black_box(m);
    })
}

#[bench]
fn insert_erase_i64(b: &mut Bencher) {
    b.iter(|| {
        let mut m: HashMap<i64, i64> = new_map();
        for i in 1..1001 {
            m.insert(i, i);
        }
        black_box(&mut m);
        for i in 1..1001 {
            m.remove(&i);
        }
        black_box(m);
    })
}

#[bench]
fn lookup_i32(b: &mut Bencher) {
    let mut m: HashMap<i32, i32> = new_map();
    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in 1..1001 {
            black_box(m.get(&i));
        }
    })
}

#[bench]
fn lookup_i64(b: &mut Bencher) {
    let mut m: HashMap<i64, i64> = new_map();
    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in 1..1001 {
            black_box(m.get(&i));
        }
    })
}

#[bench]
fn lookup_fail_i32(b: &mut Bencher) {
    let mut m: HashMap<i32, i32> = new_map();
    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in 1001..2001 {
            black_box(m.get(&i));
        }
    })
}

#[bench]
fn lookup_fail_i64(b: &mut Bencher) {
    let mut m: HashMap<i64, i64> = new_map();
    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in 1001..2001 {
            black_box(m.get(&i));
        }
    })
}

#[bench]
fn iter_i32(b: &mut Bencher) {
    let mut m: HashMap<i32, i32> = new_map();
    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in &m {
            black_box(i);
        }
    })
}

#[bench]
fn iter_i64(b: &mut Bencher) {
    let mut m: HashMap<i64, i64> = new_map();
    for i in 1..1001 {
        m.insert(i, i);
    }

    b.iter(|| {
        for i in &m {
            black_box(i);
        }
    })
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint, RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float, FromPrimitive};
use rand::{task_rng, Rng};
use rand::distributions::range::SampleRange;
use std::vec::Vec;
use std::iter;
use std::clone::Clone;
use std::ops::{Shr, BitAnd};

static pow_offsets : &'static[uint] = &[0u, 4u, 6u, 10u, 12u, 16u];

#[inline]
fn big<T: ToBigUint>(i : T) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint,T> + BitAnd<T,T>>
    (base: &T, exponent: &T, modulus: &T) -> T {

    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result

}

// Rabin-Miller primality test, probabilistic
fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {

    let one : BigUint = One::one();
    if mod_exp(a, d, n) == one {
        return false
    }
    let mut i = 0u;
    loop {
        if big(i) == *s {
            break
        }
        if mod_exp(a, &(pow(one+one, i) * *d), n) == *n-one {
            return false
        }
        i += 1;
    }
    true

}
fn rm_is_prime(n : &BigUint) -> bool {

    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    assert!(n >= &two);

    let mut s = zero.clone();
    let mut d = *n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true

}

fn fermat_is_prime(n : &BigUint) -> bool {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    if n == &two {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&two, &(n-one), n) == one {
        true
    } else {
        false
    }
}

fn is_valid_pow(prime : &BigUint) -> bool {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !fermat_is_prime(&(*prime + *offset)) {
            return false;
        }
    }
    true
}

// Source: http://rosettacode.org/wiki/Sieve_of_Eratosthenes#Rust
fn simple_sieve(limit: uint) -> ~[uint] {

    #[inline]
    fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

    if limit < 2 {
        return ~[];
    }

    let mut primes = Vec::from_elem(limit + 1, true);

    for prime in iter::range_inclusive(2, int_sqrt(limit) + 1) {
        if *primes.get(prime) {
            for multiple in iter::range_step(prime * prime, limit + 1, prime) {
                *primes.get_mut(multiple) = false
            }
        }
    }
    iter::range_inclusive(2, limit).filter(|&n| *primes.get(n)).collect()

}

fn gen_prime(max_val : &BigUint, verbose : bool) -> uint {

    fn candidate_killed_by(candidate : &BigUint, prime : &BigUint) -> bool {
        let zero : BigUint = Zero::zero();
        for &offset in pow_offsets.iter() {
            let o : BigUint = FromPrimitive::from_uint(offset).unwrap();
            if (*candidate + o) % *prime == zero {
                return true;
            }
        }
        false
    }

    fn add_next_prime (max_val : &BigUint, offsets : Vec<BigUint>, prime : BigUint, primorial : BigUint) -> Vec<BigUint> {
        let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
        let mut base : BigUint = Zero::zero();
        let mut new_offsets : Vec<BigUint> = Vec::new();
        let mut counter = zero.clone();
        while counter < prime {
            if base > *max_val {
                break
            }
            for o in offsets.iter() {
                    let val = base + *o;
                    if val > *max_val {
                        break
                    }
                    if !candidate_killed_by(&val, &prime) {
                        new_offsets.push(val);
                    }
            }
            base = base + primorial;
            counter = counter + one;
        }
        return new_offsets
    }
    let primorial_max : uint = 29u;
    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<BigUint> = Vec::from_slice([big(97u)]);
    for i in simple_sieve(primorial_max).iter() {
        if *i <= primorial_start {
            continue
        }
        offsets = add_next_prime(max_val, offsets, big(*i), big(primorial));
        primorial = primorial * *i;
    }
    let mut count : uint = 0;
    for o in offsets.iter() {
        if is_valid_pow(o) {
            count = count + 1;
            if verbose { println!("prime: {}", o) }
        }
    }
    count
}

#[cfg(test)]
mod test_primes {
    use super::{big, gen_prime};

    #[test]
    fn gen_prime_is_correct() {
        let v = gen_prime(&big(1000000000), false);
        println!("{}", v);
        assert!(v == 81u);
    }
}

fn main() {
    println!("{}", gen_prime(&big(1000000000000), true));
}<commit_msg>Faster sieve using mutable global memory<commit_after>extern crate num;
extern crate rand;
extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint, RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float, FromPrimitive};
use rand::{task_rng, Rng};
use rand::distributions::range::SampleRange;
use std::vec::Vec;
use std::iter;
use std::clone::Clone;
use std::ops::{Shr, BitAnd};
use std::bool;

static pow_offsets : &'static[uint] = &[0u, 4u, 6u, 10u, 12u, 16u];

#[inline]
fn big<T: ToBigUint>(i : T) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint,T> + BitAnd<T,T>>
    (base: &T, exponent: &T, modulus: &T) -> T {

    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result

}

// Rabin-Miller primality test, probabilistic
fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {

    let one : BigUint = One::one();
    if mod_exp(a, d, n) == one {
        return false
    }
    let mut i = 0u;
    loop {
        if big(i) == *s {
            break
        }
        if mod_exp(a, &(pow(one+one, i) * *d), n) == *n-one {
            return false
        }
        i += 1;
    }
    true

}
fn rm_is_prime(n : &BigUint) -> bool {

    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    assert!(n >= &two);

    let mut s = zero.clone();
    let mut d = *n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true

}

fn fermat_is_prime(n : &BigUint) -> bool {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    if n == &two {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&two, &(n-one), n) == one {
        true
    } else {
        false
    }
}

fn is_valid_pow(prime : &BigUint) -> bool {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !fermat_is_prime(&(*prime + *offset)) {
            return false;
        }
    }
    true
}

static mut primes : [bool, ..500000001] = [true, ..500000001];
static mut already_sieved : uint = 0;

// Simple sieve
fn simple_sieve(primorial_max : uint, verbose : bool) -> ~[uint] {
    assert!(primorial_max <= 500000000);
    #[inline]
    fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }
    unsafe {
        if already_sieved < primorial_max {
            for prime in range(2, int_sqrt(primorial_max) + 1) {
                if primes[prime] {
                    for multiple in iter::range_step(prime * prime, primorial_max + 1, prime) {
                        primes[multiple] = false
                    }
                    if verbose { println!("Sieved {}", prime) }
                }
            }
            already_sieved = primorial_max;
            if verbose { println!("Finished sieving") }
        }
        range(2, primorial_max+1).filter(|&n| primes[n]).collect()
    }
}

fn gen_prime(max_val : &BigUint, max_sieve : uint, verbose : bool) -> uint {

    fn candidate_killed_by(candidate : &BigUint, prime : &BigUint) -> bool {
        let zero : BigUint = Zero::zero();
        for &offset in pow_offsets.iter() {
            let o : BigUint = FromPrimitive::from_uint(offset).unwrap();
            if (*candidate + o) % *prime == zero {
                return true;
            }
        }
        false
    }

    fn add_next_prime (max_val : &BigUint, offsets : Vec<BigUint>, prime : BigUint, primorial : BigUint) -> Vec<BigUint> {
        let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
        let mut base : BigUint = Zero::zero();
        let mut new_offsets : Vec<BigUint> = Vec::new();
        let mut counter = zero.clone();
        while counter < prime {
            if base > *max_val {
                break
            }
            for o in offsets.iter() {
                    let val = base + *o;
                    if val > *max_val {
                        break
                    }
                    if !candidate_killed_by(&val, &prime) {
                        new_offsets.push(val);
                    }
            }
            base = base + primorial;
            counter = counter + one;
        }
        return new_offsets
    }
    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<BigUint> = Vec::from_slice([big(97u)]);

    for &i in simple_sieve(max_sieve, verbose).iter() {
        if i <= primorial_start {
            continue
        }
        offsets = add_next_prime(max_val, offsets, big(i), big(primorial));
        primorial = primorial * i;
    }
    let mut count : uint = 0;
    for o in offsets.iter() {
        if is_valid_pow(o) {
            count = count + 1;
            if verbose { println!("prime: {}", o) }
        }
    }
    count
}

#[cfg(test)]
mod test_primes {
    use super::{big, gen_prime, simple_sieve};

    #[test]
    fn gen_prime_is_correct() {
        assert!(gen_prime(&big(100000000), 10000, false) == 80u);
    }

    #[test]
    fn simple_sieve_is_correct() {
        assert!(simple_sieve(5000000, false).len() == 348513);
    }
}

fn main() {
    println!("{}", gen_prime(&big(100000000), 10000, true));
}<|endoftext|>


<commit_before>use crate::iter::LoopState;
use crate::ops::Try;

/// An iterator able to yield elements from both ends.
///
/// Something that implements `DoubleEndedIterator` has one extra capability
/// over something that implements [`Iterator`]: the ability to also take
/// `Item`s from the back, as well as the front.
///
/// It is important to note that both back and forth work on the same range,
/// and do not cross: iteration is over when they meet in the middle.
///
/// In a similar fashion to the [`Iterator`] protocol, once a
/// `DoubleEndedIterator` returns `None` from a `next_back()`, calling it again
/// may or may not ever return `Some` again. `next()` and `next_back()` are
/// interchangeable for this purpose.
///
/// [`Iterator`]: trait.Iterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let numbers = vec![1, 2, 3, 4, 5, 6];
///
/// let mut iter = numbers.iter();
///
/// assert_eq!(Some(&1), iter.next());
/// assert_eq!(Some(&6), iter.next_back());
/// assert_eq!(Some(&5), iter.next_back());
/// assert_eq!(Some(&2), iter.next());
/// assert_eq!(Some(&3), iter.next());
/// assert_eq!(Some(&4), iter.next());
/// assert_eq!(None, iter.next());
/// assert_eq!(None, iter.next_back());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DoubleEndedIterator: Iterator {
    /// Removes and returns an element from the end of the iterator.
    ///
    /// Returns `None` when there are no more elements.
    ///
    /// The [trait-level] docs contain more details.
    ///
    /// [trait-level]: trait.DoubleEndedIterator.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let numbers = vec![1, 2, 3, 4, 5, 6];
    ///
    /// let mut iter = numbers.iter();
    ///
    /// assert_eq!(Some(&1), iter.next());
    /// assert_eq!(Some(&6), iter.next_back());
    /// assert_eq!(Some(&5), iter.next_back());
    /// assert_eq!(Some(&2), iter.next());
    /// assert_eq!(Some(&3), iter.next());
    /// assert_eq!(Some(&4), iter.next());
    /// assert_eq!(None, iter.next());
    /// assert_eq!(None, iter.next_back());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn next_back(&mut self) -> Option<Self::Item>;

    /// Returns the `n`th element from the end of the iterator.
    ///
    /// This is essentially the reversed version of [`nth`]. Although like most indexing
    /// operations, the count starts from zero, so `nth_back(0)` returns the first value from
    /// the end, `nth_back(1)` the second, and so on.
    ///
    /// Note that all elements between the end and the returned element will be
    /// consumed, including the returned element. This also means that calling
    /// `nth_back(0)` multiple times on the same iterator will return different
    /// elements.
    ///
    /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the
    /// iterator.
    ///
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(2), Some(&1));
    /// ```
    ///
    /// Calling `nth_back()` multiple times doesn't rewind the iterator:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.nth_back(1), Some(&2));
    /// assert_eq!(iter.nth_back(1), None);
    /// ```
    ///
    /// Returning `None` if there are less than `n + 1` elements:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(10), None);
    /// ```
    #[inline]
    #[stable(feature = "iter_nth_back", since = "1.37.0")]
    fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
        for x in self.rev() {
            if n == 0 {
                return Some(x);
            }
            n -= 1;
        }
        None
    }

    /// This is the reverse version of [`try_fold()`]: it takes elements
    /// starting from the back of the iterator.
    ///
    /// [`try_fold()`]: trait.Iterator.html#method.try_fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = ["1", "2", "3"];
    /// let sum = a.iter()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert_eq!(sum, Ok(6));
    /// ```
    ///
    /// Short-circuiting:
    ///
    /// ```
    /// let a = ["1", "rust", "3"];
    /// let mut it = a.iter();
    /// let sum = it
    ///     .by_ref()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert!(sum.is_err());
    ///
    /// // Because it short-circuited, the remaining elements are still
    /// // available through the iterator.
    /// assert_eq!(it.next_back(), Some(&"1"));
    /// ```
    #[inline]
    #[stable(feature = "iterator_try_fold", since = "1.27.0")]
    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> R,
        R: Try<Ok = B>,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x)?;
        }
        Try::from_ok(accum)
    }

    /// An iterator method that reduces the iterator's elements to a single,
    /// final value, starting from the back.
    ///
    /// This is the reverse version of [`fold()`]: it takes elements starting from
    /// the back of the iterator.
    ///
    /// `rfold()` takes two arguments: an initial value, and a closure with two
    /// arguments: an 'accumulator', and an element. The closure returns the value that
    /// the accumulator should have for the next iteration.
    ///
    /// The initial value is the value the accumulator will have on the first
    /// call.
    ///
    /// After applying this closure to every element of the iterator, `rfold()`
    /// returns the accumulator.
    ///
    /// This operation is sometimes called 'reduce' or 'inject'.
    ///
    /// Folding is useful whenever you have a collection of something, and want
    /// to produce a single value from it.
    ///
    /// [`fold()`]: trait.Iterator.html#method.fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// // the sum of all of the elements of a
    /// let sum = a.iter()
    ///            .rfold(0, |acc, &x| acc + x);
    ///
    /// assert_eq!(sum, 6);
    /// ```
    ///
    /// This example builds a string, starting with an initial value
    /// and continuing with each element from the back until the front:
    ///
    /// ```
    /// let numbers = [1, 2, 3, 4, 5];
    ///
    /// let zero = "0".to_string();
    ///
    /// let result = numbers.iter().rfold(zero, |acc, &x| {
    ///     format!("({} + {})", x, acc)
    /// });
    ///
    /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
    /// ```
    #[inline]
    #[stable(feature = "iter_rfold", since = "1.27.0")]
    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> B,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x);
        }
        accum
    }

    /// Searches for an element of an iterator from the back that satisfies a predicate.
    ///
    /// `rfind()` takes a closure that returns `true` or `false`. It applies
    /// this closure to each element of the iterator, starting at the end, and if any
    /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return
    /// `false`, it returns [`None`].
    ///
    /// `rfind()` is short-circuiting; in other words, it will stop processing
    /// as soon as the closure returns `true`.
    ///
    /// Because `rfind()` takes a reference, and many iterators iterate over
    /// references, this leads to a possibly confusing situation where the
    /// argument is a double reference. You can see this effect in the
    /// examples below, with `&&x`.
    ///
    /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2));
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 5), None);
    /// ```
    ///
    /// Stopping at the first `true`:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2));
    ///
    /// // we can still use `iter`, as there are more elements.
    /// assert_eq!(iter.next_back(), Some(&1));
    /// ```
    #[inline]
    #[stable(feature = "iter_rfind", since = "1.27.0")]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        Self: Sized,
        P: FnMut(&Self::Item) -> bool,
    {
        #[inline]
        fn check<T>(
            mut predicate: impl FnMut(&T) -> bool,
        ) -> impl FnMut((), T) -> LoopState<(), T> {
            move |(), x| {
                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
            }
        }

        self.try_rfold((), check(predicate)).break_value()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
    fn next_back(&mut self) -> Option<I::Item> {
        (**self).next_back()
    }
    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
        (**self).nth_back(n)
    }
}
<commit_msg>Rollup merge of #72626 - phimuemue:doubleendediter_doc, r=dtolnay<commit_after>use crate::iter::LoopState;
use crate::ops::Try;

/// An iterator able to yield elements from both ends.
///
/// Something that implements `DoubleEndedIterator` has one extra capability
/// over something that implements [`Iterator`]: the ability to also take
/// `Item`s from the back, as well as the front.
///
/// It is important to note that both back and forth work on the same range,
/// and do not cross: iteration is over when they meet in the middle.
///
/// In a similar fashion to the [`Iterator`] protocol, once a
/// `DoubleEndedIterator` returns `None` from a `next_back()`, calling it again
/// may or may not ever return `Some` again. `next()` and `next_back()` are
/// interchangeable for this purpose.
///
/// [`Iterator`]: trait.Iterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let numbers = vec![1, 2, 3, 4, 5, 6];
///
/// let mut iter = numbers.iter();
///
/// assert_eq!(Some(&1), iter.next());
/// assert_eq!(Some(&6), iter.next_back());
/// assert_eq!(Some(&5), iter.next_back());
/// assert_eq!(Some(&2), iter.next());
/// assert_eq!(Some(&3), iter.next());
/// assert_eq!(Some(&4), iter.next());
/// assert_eq!(None, iter.next());
/// assert_eq!(None, iter.next_back());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DoubleEndedIterator: Iterator {
    /// Removes and returns an element from the end of the iterator.
    ///
    /// Returns `None` when there are no more elements.
    ///
    /// The [trait-level] docs contain more details.
    ///
    /// [trait-level]: trait.DoubleEndedIterator.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let numbers = vec![1, 2, 3, 4, 5, 6];
    ///
    /// let mut iter = numbers.iter();
    ///
    /// assert_eq!(Some(&1), iter.next());
    /// assert_eq!(Some(&6), iter.next_back());
    /// assert_eq!(Some(&5), iter.next_back());
    /// assert_eq!(Some(&2), iter.next());
    /// assert_eq!(Some(&3), iter.next());
    /// assert_eq!(Some(&4), iter.next());
    /// assert_eq!(None, iter.next());
    /// assert_eq!(None, iter.next_back());
    /// ```
    ///
    /// # Remarks
    ///
    /// The elements yielded by `DoubleEndedIterator`'s methods may differ from
    /// the ones yielded by `Iterator`'s methods:
    ///
    /// ```
    /// let vec = vec![(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b')];
    /// let uniq_by_fst_comp = || {
    ///     let mut seen = std::collections::HashSet::new();
    ///     vec.iter().copied().filter(move |x| seen.insert(x.0))
    /// };
    ///
    /// assert_eq!(uniq_by_fst_comp().last(), Some((2, 'a')));
    /// assert_eq!(uniq_by_fst_comp().next_back(), Some((2, 'b')));
    ///
    /// assert_eq!(
    ///     uniq_by_fst_comp().fold(vec![], |mut v, x| {v.push(x); v}),
    ///     vec![(1, 'a'), (2, 'a')]
    /// );
    /// assert_eq!(
    ///     uniq_by_fst_comp().rfold(vec![], |mut v, x| {v.push(x); v}),
    ///     vec![(2, 'b'), (1, 'c')]
    /// );
    /// ```
    ///
    #[stable(feature = "rust1", since = "1.0.0")]
    fn next_back(&mut self) -> Option<Self::Item>;

    /// Returns the `n`th element from the end of the iterator.
    ///
    /// This is essentially the reversed version of [`nth`]. Although like most indexing
    /// operations, the count starts from zero, so `nth_back(0)` returns the first value from
    /// the end, `nth_back(1)` the second, and so on.
    ///
    /// Note that all elements between the end and the returned element will be
    /// consumed, including the returned element. This also means that calling
    /// `nth_back(0)` multiple times on the same iterator will return different
    /// elements.
    ///
    /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the
    /// iterator.
    ///
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(2), Some(&1));
    /// ```
    ///
    /// Calling `nth_back()` multiple times doesn't rewind the iterator:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.nth_back(1), Some(&2));
    /// assert_eq!(iter.nth_back(1), None);
    /// ```
    ///
    /// Returning `None` if there are less than `n + 1` elements:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(10), None);
    /// ```
    #[inline]
    #[stable(feature = "iter_nth_back", since = "1.37.0")]
    fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
        for x in self.rev() {
            if n == 0 {
                return Some(x);
            }
            n -= 1;
        }
        None
    }

    /// This is the reverse version of [`try_fold()`]: it takes elements
    /// starting from the back of the iterator.
    ///
    /// [`try_fold()`]: trait.Iterator.html#method.try_fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = ["1", "2", "3"];
    /// let sum = a.iter()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert_eq!(sum, Ok(6));
    /// ```
    ///
    /// Short-circuiting:
    ///
    /// ```
    /// let a = ["1", "rust", "3"];
    /// let mut it = a.iter();
    /// let sum = it
    ///     .by_ref()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert!(sum.is_err());
    ///
    /// // Because it short-circuited, the remaining elements are still
    /// // available through the iterator.
    /// assert_eq!(it.next_back(), Some(&"1"));
    /// ```
    #[inline]
    #[stable(feature = "iterator_try_fold", since = "1.27.0")]
    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> R,
        R: Try<Ok = B>,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x)?;
        }
        Try::from_ok(accum)
    }

    /// An iterator method that reduces the iterator's elements to a single,
    /// final value, starting from the back.
    ///
    /// This is the reverse version of [`fold()`]: it takes elements starting from
    /// the back of the iterator.
    ///
    /// `rfold()` takes two arguments: an initial value, and a closure with two
    /// arguments: an 'accumulator', and an element. The closure returns the value that
    /// the accumulator should have for the next iteration.
    ///
    /// The initial value is the value the accumulator will have on the first
    /// call.
    ///
    /// After applying this closure to every element of the iterator, `rfold()`
    /// returns the accumulator.
    ///
    /// This operation is sometimes called 'reduce' or 'inject'.
    ///
    /// Folding is useful whenever you have a collection of something, and want
    /// to produce a single value from it.
    ///
    /// [`fold()`]: trait.Iterator.html#method.fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// // the sum of all of the elements of a
    /// let sum = a.iter()
    ///            .rfold(0, |acc, &x| acc + x);
    ///
    /// assert_eq!(sum, 6);
    /// ```
    ///
    /// This example builds a string, starting with an initial value
    /// and continuing with each element from the back until the front:
    ///
    /// ```
    /// let numbers = [1, 2, 3, 4, 5];
    ///
    /// let zero = "0".to_string();
    ///
    /// let result = numbers.iter().rfold(zero, |acc, &x| {
    ///     format!("({} + {})", x, acc)
    /// });
    ///
    /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
    /// ```
    #[inline]
    #[stable(feature = "iter_rfold", since = "1.27.0")]
    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> B,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x);
        }
        accum
    }

    /// Searches for an element of an iterator from the back that satisfies a predicate.
    ///
    /// `rfind()` takes a closure that returns `true` or `false`. It applies
    /// this closure to each element of the iterator, starting at the end, and if any
    /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return
    /// `false`, it returns [`None`].
    ///
    /// `rfind()` is short-circuiting; in other words, it will stop processing
    /// as soon as the closure returns `true`.
    ///
    /// Because `rfind()` takes a reference, and many iterators iterate over
    /// references, this leads to a possibly confusing situation where the
    /// argument is a double reference. You can see this effect in the
    /// examples below, with `&&x`.
    ///
    /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2));
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 5), None);
    /// ```
    ///
    /// Stopping at the first `true`:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2));
    ///
    /// // we can still use `iter`, as there are more elements.
    /// assert_eq!(iter.next_back(), Some(&1));
    /// ```
    #[inline]
    #[stable(feature = "iter_rfind", since = "1.27.0")]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        Self: Sized,
        P: FnMut(&Self::Item) -> bool,
    {
        #[inline]
        fn check<T>(
            mut predicate: impl FnMut(&T) -> bool,
        ) -> impl FnMut((), T) -> LoopState<(), T> {
            move |(), x| {
                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
            }
        }

        self.try_rfold((), check(predicate)).break_value()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
    fn next_back(&mut self) -> Option<I::Item> {
        (**self).next_back()
    }
    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
        (**self).nth_back(n)
    }
}
<|endoftext|>


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

use target::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
    TargetOptions {
        linker: "cc".to_string(),
        dynamic_linking: true,
        executables: true,
        linker_is_gnu: true,
        has_rpath: true,
        pre_link_args: vec!(
            // GNU-style linkers will use this to omit linking to libraries
            // which don't actually fulfill any relocations, but only for
            // libraries which follow this flag.  Thus, use it before
            // specifying libraries to link to.
            "-Wl,--as-needed".to_string(),
        ),
        position_independent_executables: true,
        archive_format: "bsd".to_string(),
        .. Default::default()
    }
}
<commit_msg>Auto merge of #27839 - gkoz:netbsd_ar, r=brson<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use target::TargetOptions;
use std::default::Default;

pub fn opts() -> TargetOptions {
    TargetOptions {
        linker: "cc".to_string(),
        dynamic_linking: true,
        executables: true,
        linker_is_gnu: true,
        has_rpath: true,
        pre_link_args: vec!(
            // GNU-style linkers will use this to omit linking to libraries
            // which don't actually fulfill any relocations, but only for
            // libraries which follow this flag.  Thus, use it before
            // specifying libraries to link to.
            "-Wl,--as-needed".to_string(),
        ),
        position_independent_executables: true,
        archive_format: "gnu".to_string(),
        .. Default::default()
    }
}
<|endoftext|>


<commit_before>//! Functions to read the content of a dictionary and checking types.

use std::collections::HashMap;
use std::string::FromUtf8Error;

use value::Value;
use decoder::DecodeError;

#[derive(Debug)]
pub enum HelperDecodeError {
    BencodeDecodeError(DecodeError),
    BadType(String),
    MissingKey(String),
    FromUtf8Error(FromUtf8Error),
}

/// Pops a BValue::Integer from a HashMap.
pub fn pop_value_integer(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<i64, HelperDecodeError> {
    match map.remove(&key.clone().into_bytes()) {
        Some(Value::Integer(value)) => Ok(value),
        Some(v) => Err(HelperDecodeError::BadType(format!("Expected integer string for key '{}', got: {:?}", key, v))),
        None => Err(HelperDecodeError::MissingKey(key)),
    }
}

/// Pops a BValue::String from a HashMap.
pub fn pop_value_bytestring(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Vec<u8>, HelperDecodeError> {
    match map.remove(&key.clone().into_bytes()) {
        Some(Value::String(value)) => Ok(value),
        Some(v) => Err(HelperDecodeError::BadType(format!("Expected UTF8 string for key '{}', got: {:?}", key, v))),
        None => Err(HelperDecodeError::MissingKey(key)),
    }
}

/// Pops an optional BValue::String from a HashMap.
pub fn pop_value_bytestring_option(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Option<Vec<u8>>, HelperDecodeError> {
    let encoded_value = pop_value_bytestring(map, key);
    match String::from_utf8(encoded_value) {
        Ok(decoded_value) => Ok(Some(decoded_value)),
        Err(HelperDecodeError::MissingKey(_)) => Ok(None),
        Err(e) => Err(e),
    }
}

/// Pops a BValue::String from a HashMap and decode it into a Rust String.
pub fn pop_value_utf8_string(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<String, HelperDecodeError> {
    let encoded_value = try!(pop_value_bytestring(map, key));
    match String::from_utf8(encoded_value) {
        Ok(decoded_value) => Ok(decoded_value),
        Err(e) => Err(HelperDecodeError::FromUtf8Error(e)),
    }
}

/// Pops an optional BValue::String from a HashMap and decode it into a Rust String.
pub fn pop_value_utf8_string_option(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Option<String>, HelperDecodeError> {
    let encoded_value = pop_value_utf8_string(map, key);
    match String::from_utf8(encoded_value) {
        Ok(decoded_value) => Ok(Some(decoded_value)),
        Err(HelperDecodeError::MissingKey(_)) => Ok(None),
        Err(e) => Err(e),
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use value::Value;
    use super::*;

    #[test]
    fn test_utf8() {
        let mut map = HashMap::new();
        map.insert(b"foo".to_vec(), Value::String(b"bar".to_vec()));
        map.insert(b"baz".to_vec(), Value::String(b"qux".to_vec()));
        map.insert(b"quux".to_vec(), Value::Integer(42));
        assert_eq!(pop_value_utf8_string(&mut map, "foo".to_owned()).unwrap(), "bar".to_owned());
        assert_eq!(pop_value_utf8_string(&mut map, "baz".to_owned()).unwrap(), "qux".to_owned());
        assert_eq!(pop_value_integer(&mut map, "quux".to_owned()).unwrap(), 42);
        assert_eq!(map, HashMap::new());
    }
}
<commit_msg>Add option helper for integers.<commit_after>//! Functions to read the content of a dictionary and checking types.

use std::collections::HashMap;
use std::string::FromUtf8Error;

use value::Value;
use decoder::DecodeError;

#[derive(Debug)]
pub enum HelperDecodeError {
    BencodeDecodeError(DecodeError),
    BadType(String),
    MissingKey(String),
    FromUtf8Error(FromUtf8Error),
}

/// Pops a BValue::Integer from a HashMap.
pub fn pop_value_integer(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<i64, HelperDecodeError> {
    match map.remove(&key.clone().into_bytes()) {
        Some(Value::Integer(value)) => Ok(value),
        Some(v) => Err(HelperDecodeError::BadType(format!("Expected integer string for key '{}', got: {:?}", key, v))),
        None => Err(HelperDecodeError::MissingKey(key)),
    }
}

/// Pops an optional BValue::Integer from a HashMap.
pub fn pop_value_integer_option(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Option<i64>, HelperDecodeError> {
    let value = pop_value_integer(map, key);
    match value {
        Ok(value) => Ok(Some(value)),
        Err(HelperDecodeError::MissingKey(_)) => Ok(None),
        Err(e) => Err(e),
    }
}

/// Pops a BValue::String from a HashMap.
pub fn pop_value_bytestring(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Vec<u8>, HelperDecodeError> {
    match map.remove(&key.clone().into_bytes()) {
        Some(Value::String(value)) => Ok(value),
        Some(v) => Err(HelperDecodeError::BadType(format!("Expected UTF8 string for key '{}', got: {:?}", key, v))),
        None => Err(HelperDecodeError::MissingKey(key)),
    }
}

/// Pops an optional BValue::String from a HashMap.
pub fn pop_value_bytestring_option(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Option<Vec<u8>>, HelperDecodeError> {
    let value = pop_value_bytestring(map, key);
    match value {
        Ok(value) => Ok(Some(value)),
        Err(HelperDecodeError::MissingKey(_)) => Ok(None),
        Err(e) => Err(e),
    }
}

/// Pops a BValue::String from a HashMap and decode it into a Rust String.
pub fn pop_value_utf8_string(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<String, HelperDecodeError> {
    let encoded_value = try!(pop_value_bytestring(map, key));
    match String::from_utf8(encoded_value) {
        Ok(decoded_value) => Ok(decoded_value),
        Err(e) => Err(HelperDecodeError::FromUtf8Error(e)),
    }
}

/// Pops an optional BValue::String from a HashMap and decode it into a Rust String.
pub fn pop_value_utf8_string_option(map: &mut HashMap<Vec<u8>, Value>, key: String) -> Result<Option<String>, HelperDecodeError> {
    let value = pop_value_utf8_string(map, key);
    match value {
        Ok(value) => Ok(Some(value)),
        Err(HelperDecodeError::MissingKey(_)) => Ok(None),
        Err(e) => Err(e),
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use value::Value;
    use super::*;

    #[test]
    fn test_utf8() {
        let mut map = HashMap::new();
        map.insert(b"foo".to_vec(), Value::String(b"bar".to_vec()));
        map.insert(b"baz".to_vec(), Value::String(b"qux".to_vec()));
        map.insert(b"quux".to_vec(), Value::Integer(42));
        assert_eq!(pop_value_utf8_string(&mut map, "foo".to_owned()).unwrap(), "bar".to_owned());
        assert_eq!(pop_value_utf8_string(&mut map, "baz".to_owned()).unwrap(), "qux".to_owned());
        assert_eq!(pop_value_integer(&mut map, "quux".to_owned()).unwrap(), 42);
        assert_eq!(map, HashMap::new());
    }
}
<|endoftext|>


<commit_before>use std::io;
use super::{Deserialize, Serialize, Error, VarUint32, CountedList, InitExpr, CountedListWriter};

/// Entry in the element section.
#[derive(Debug, Clone)]
pub struct ElementSegment {
	index: u32,
	offset: InitExpr,
	members: Vec<u32>,
}

impl ElementSegment {
	/// New element segment.
	pub fn new(index: u32, offset: InitExpr, members: Vec<u32>) -> Self {
		ElementSegment { index: index, offset: offset, members: members }
	}

	/// Sequence of function indices.
	pub fn members(&self) -> &[u32] { &self.members }

	/// Sequence of function indices (mutable)
	pub fn members_mut(&mut self) -> &mut Vec<u32> { &mut self.members }

	/// Table index (currently valid only value of `0`)
	pub fn index(&self) -> u32 { self.index }

	/// An i32 initializer expression that computes the offset at which to place the elements.
	pub fn offset(&self) -> &InitExpr { &self.offset }

	/// An i32 initializer expression that computes the offset at which to place the elements (mutable)
	pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }
}

impl Deserialize for ElementSegment {
	 type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let index = VarUint32::deserialize(reader)?;
		let offset = InitExpr::deserialize(reader)?;
		let funcs: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
			.into_inner()
			.into_iter()
			.map(Into::into)
			.collect();

		Ok(ElementSegment {
			index: index.into(),
			offset: offset,
			members: funcs,
		})
	}
}

impl Serialize for ElementSegment {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		VarUint32::from(self.index).serialize(writer)?;
		self.offset.serialize(writer)?;
		let data = self.members;
		let counted_list = CountedListWriter::<VarUint32, _>(
			data.len(),
			data.into_iter().map(Into::into),
		);
		counted_list.serialize(writer)?;
		Ok(())
	}
}

/// Data segment definition.
#[derive(Clone, Debug)]
pub struct DataSegment {
	index: u32,
	offset: InitExpr,
	value: Vec<u8>,
}

impl DataSegment {
	/// New data segments.
	pub fn new(index: u32, offset: InitExpr, value: Vec<u8>) -> Self {
		DataSegment {
			index: index,
			offset: offset,
			value: value,
		}
	}

	/// Linear memory index (currently the only valid value is `0`).
	pub fn index(&self) -> u32 { self.index }

	/// An i32 initializer expression that computes the offset at which to place the data.
	pub fn offset(&self) -> &InitExpr { &self.offset }

	/// An i32 initializer expression that computes the offset at which to place the data (mutable)
	pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }

	/// Initial value of the data segment.
	pub fn value(&self) -> &[u8] { &self.value }

	/// Initial value of the data segment (mutable).
	pub fn value_mut(&mut self) -> &mut Vec<u8> { &mut self.value }
}

impl Deserialize for DataSegment {
	 type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let index = VarUint32::deserialize(reader)?;
		let offset = InitExpr::deserialize(reader)?;
		let value_len = u32::from(VarUint32::deserialize(reader)?) as usize;
		let value_buf = buffered_read!(65546, value_len, reader);

		Ok(DataSegment {
			index: index.into(),
			offset: offset,
			value: value_buf,
		})
	}
}

impl Serialize for DataSegment {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		VarUint32::from(self.index).serialize(writer)?;
		self.offset.serialize(writer)?;

		let value = self.value;
		VarUint32::from(value.len()).serialize(writer)?;
		writer.write_all(&value[..])?;
		Ok(())
	}
}
<commit_msg>fix typo in integer<commit_after>use std::io;
use super::{Deserialize, Serialize, Error, VarUint32, CountedList, InitExpr, CountedListWriter};

/// Entry in the element section.
#[derive(Debug, Clone)]
pub struct ElementSegment {
	index: u32,
	offset: InitExpr,
	members: Vec<u32>,
}

impl ElementSegment {
	/// New element segment.
	pub fn new(index: u32, offset: InitExpr, members: Vec<u32>) -> Self {
		ElementSegment { index: index, offset: offset, members: members }
	}

	/// Sequence of function indices.
	pub fn members(&self) -> &[u32] { &self.members }

	/// Sequence of function indices (mutable)
	pub fn members_mut(&mut self) -> &mut Vec<u32> { &mut self.members }

	/// Table index (currently valid only value of `0`)
	pub fn index(&self) -> u32 { self.index }

	/// An i32 initializer expression that computes the offset at which to place the elements.
	pub fn offset(&self) -> &InitExpr { &self.offset }

	/// An i32 initializer expression that computes the offset at which to place the elements (mutable)
	pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }
}

impl Deserialize for ElementSegment {
	 type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let index = VarUint32::deserialize(reader)?;
		let offset = InitExpr::deserialize(reader)?;
		let funcs: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
			.into_inner()
			.into_iter()
			.map(Into::into)
			.collect();

		Ok(ElementSegment {
			index: index.into(),
			offset: offset,
			members: funcs,
		})
	}
}

impl Serialize for ElementSegment {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		VarUint32::from(self.index).serialize(writer)?;
		self.offset.serialize(writer)?;
		let data = self.members;
		let counted_list = CountedListWriter::<VarUint32, _>(
			data.len(),
			data.into_iter().map(Into::into),
		);
		counted_list.serialize(writer)?;
		Ok(())
	}
}

/// Data segment definition.
#[derive(Clone, Debug)]
pub struct DataSegment {
	index: u32,
	offset: InitExpr,
	value: Vec<u8>,
}

impl DataSegment {
	/// New data segments.
	pub fn new(index: u32, offset: InitExpr, value: Vec<u8>) -> Self {
		DataSegment {
			index: index,
			offset: offset,
			value: value,
		}
	}

	/// Linear memory index (currently the only valid value is `0`).
	pub fn index(&self) -> u32 { self.index }

	/// An i32 initializer expression that computes the offset at which to place the data.
	pub fn offset(&self) -> &InitExpr { &self.offset }

	/// An i32 initializer expression that computes the offset at which to place the data (mutable)
	pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }

	/// Initial value of the data segment.
	pub fn value(&self) -> &[u8] { &self.value }

	/// Initial value of the data segment (mutable).
	pub fn value_mut(&mut self) -> &mut Vec<u8> { &mut self.value }
}

impl Deserialize for DataSegment {
	 type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let index = VarUint32::deserialize(reader)?;
		let offset = InitExpr::deserialize(reader)?;
		let value_len = u32::from(VarUint32::deserialize(reader)?) as usize;
		let value_buf = buffered_read!(65536, value_len, reader);

		Ok(DataSegment {
			index: index.into(),
			offset: offset,
			value: value_buf,
		})
	}
}

impl Serialize for DataSegment {
	type Error = Error;

	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
		VarUint32::from(self.index).serialize(writer)?;
		self.offset.serialize(writer)?;

		let value = self.value;
		VarUint32::from(value.len()).serialize(writer)?;
		writer.write_all(&value[..])?;
		Ok(())
	}
}
<|endoftext|>


<commit_before>//! This module contains type aliases for C's fixed-width integer types .
//!
//! These aliases are deprecated: use the Rust types instead.

#[deprecated(since = "0.2.55", note = "Use i8 instead.")]
pub type int8_t = i8;
#[deprecated(since = "0.2.55", note = "Use i16 instead.")]
pub type int16_t = i16;
#[deprecated(since = "0.2.55", note = "Use i32 instead.")]
pub type int32_t = i32;
#[deprecated(since = "0.2.55", note = "Use i64 instead.")]
pub type int64_t = i64;
#[deprecated(since = "0.2.55", note = "Use u8 instead.")]
pub type uint8_t = u8;
#[deprecated(since = "0.2.55", note = "Use u16 instead.")]
pub type uint16_t = u16;
#[deprecated(since = "0.2.55", note = "Use u32 instead.")]
pub type uint32_t = u32;
#[deprecated(since = "0.2.55", note = "Use u64 instead.")]
pub type uint64_t = u64;

cfg_if! {
    if #[cfg(all(libc_int128, target_arch = "aarch64", not(target_os = "windows")))] {
        // This introduces partial support for FFI with __int128 and
        // equivalent types on platforms where Rust's definition is validated
        // to match the standard C ABI of that platform.
        //
        // Rust does not guarantee u128/i128 are sound for FFI, and its
        // definitions are in fact known to be incompatible. [0]
        //
        // However these problems aren't fundamental, and are just platform
        // inconsistencies. Specifically at the time of this writing:
        //
        // * For x64 SysV ABIs (everything but Windows), the types are underaligned.
        // * For all Windows ABIs, Microsoft doesn't actually officially define __int128,
        //   and as a result different implementations don't actually agree on its ABI.
        //
        // But on the other major aarch64 platforms (android, linux, ios, macos) we have
        // validated that rustc has the right ABI for these types. This is important because
        // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct,
        // which represents saved simd registers.
        //
        // Any API which uses these types will need to `#[ignore(improper_ctypes)]`
        // until the upstream rust issue is resolved, but this at least lets us make
        // progress on platforms where this type is important.
        //
        // The supported architectures and OSes is intentionally very restricted,
        // as careful work needs to be done to verify that a particular platform
        // has a conformant ABI.
        //
        // [0]: https://github.com/rust-lang/rust/issues/54341

        /// C `__int128` (a GCC extension that's part of many ABIs)
        pub type __int128 = i128;
        /// C `unsigned __int128` (a GCC extension that's part of many ABIs)
        pub type __uint128 = u128;
        /// C __int128_t (alternate name for [__int128][])
        pub type __int128_t = i128;
        /// C __uint128_t (alternate name for [__uint128][])
        pub type __uint128_t = u128;

        cfg_if! {
            if #[cfg(libc_const_assert)] {
                // NOTE: if you add more platforms to here, you may need to cfg
                // these consts. They should always match the platform's values
                // for `sizeof(__int128)` and `_Alignof(__int128)`.
                const _SIZE_128: usize = 16;
                const _ALIGN_128: usize = 16;

                /// Since Rust doesn't officially guarantee that these types
                /// have compatible ABIs, we const assert that these values have the
                /// known size/align of the target platform's libc. If rustc ever
                /// tries to regress things, it will cause a compilation error.
                ///
                /// This isn't a bullet-proof solution because e.g. it doesn't
                /// catch the fact that llvm and gcc disagree on how x64 __int128
                /// is actually *passed* on the stack (clang underaligns it for
                /// the same reason that rustc *never* properly aligns it).
                const _ASSERT_128_COMPAT: () = {
                    assert!(core::mem::size_of::<__int128>() == _SIZE_128);
                    assert!(core::mem::align_of::<__int128>() == _ALIGN_128);

                    assert!(core::mem::size_of::<__uint128>() == _SIZE_128);
                    assert!(core::mem::align_of::<__uint128>() == _ALIGN_128);

                    assert!(core::mem::size_of::<__int128_t>() == _SIZE_128);
                    assert!(core::mem::align_of::<__int128_t>() == _ALIGN_128);

                    assert!(core::mem::size_of::<__uint128_t>() == _SIZE_128);
                    assert!(core::mem::align_of::<__uint128_t>() == _ALIGN_128);
                };
            }
        }
    }
}
<commit_msg>Typo fix<commit_after>//! This module contains type aliases for C's fixed-width integer types .
//!
//! These aliases are deprecated: use the Rust types instead.

#[deprecated(since = "0.2.55", note = "Use i8 instead.")]
pub type int8_t = i8;
#[deprecated(since = "0.2.55", note = "Use i16 instead.")]
pub type int16_t = i16;
#[deprecated(since = "0.2.55", note = "Use i32 instead.")]
pub type int32_t = i32;
#[deprecated(since = "0.2.55", note = "Use i64 instead.")]
pub type int64_t = i64;
#[deprecated(since = "0.2.55", note = "Use u8 instead.")]
pub type uint8_t = u8;
#[deprecated(since = "0.2.55", note = "Use u16 instead.")]
pub type uint16_t = u16;
#[deprecated(since = "0.2.55", note = "Use u32 instead.")]
pub type uint32_t = u32;
#[deprecated(since = "0.2.55", note = "Use u64 instead.")]
pub type uint64_t = u64;

cfg_if! {
    if #[cfg(all(libc_int128, target_arch = "aarch64", not(target_os = "windows")))] {
        // This introduces partial support for FFI with __int128 and
        // equivalent types on platforms where Rust's definition is validated
        // to match the standard C ABI of that platform.
        //
        // Rust does not guarantee u128/i128 are sound for FFI, and its
        // definitions are in fact known to be incompatible. [0]
        //
        // However these problems aren't fundamental, and are just platform
        // inconsistencies. Specifically at the time of this writing:
        //
        // * For x64 SysV ABIs (everything but Windows), the types are underaligned.
        // * For all Windows ABIs, Microsoft doesn't actually officially define __int128,
        //   and as a result different implementations don't actually agree on its ABI.
        //
        // But on the other major aarch64 platforms (android, linux, ios, macos) we have
        // validated that rustc has the right ABI for these types. This is important because
        // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct,
        // which represents saved simd registers.
        //
        // Any API which uses these types will need to `#[ignore(improper_ctypes)]`
        // until the upstream rust issue is resolved, but this at least lets us make
        // progress on platforms where this type is important.
        //
        // The list of supported architectures and OSes is intentionally very restricted,
        // as careful work needs to be done to verify that a particular platform
        // has a conformant ABI.
        //
        // [0]: https://github.com/rust-lang/rust/issues/54341

        /// C `__int128` (a GCC extension that's part of many ABIs)
        pub type __int128 = i128;
        /// C `unsigned __int128` (a GCC extension that's part of many ABIs)
        pub type __uint128 = u128;
        /// C __int128_t (alternate name for [__int128][])
        pub type __int128_t = i128;
        /// C __uint128_t (alternate name for [__uint128][])
        pub type __uint128_t = u128;

        cfg_if! {
            if #[cfg(libc_const_assert)] {
                // NOTE: if you add more platforms to here, you may need to cfg
                // these consts. They should always match the platform's values
                // for `sizeof(__int128)` and `_Alignof(__int128)`.
                const _SIZE_128: usize = 16;
                const _ALIGN_128: usize = 16;

                /// Since Rust doesn't officially guarantee that these types
                /// have compatible ABIs, we const assert that these values have the
                /// known size/align of the target platform's libc. If rustc ever
                /// tries to regress things, it will cause a compilation error.
                ///
                /// This isn't a bullet-proof solution because e.g. it doesn't
                /// catch the fact that llvm and gcc disagree on how x64 __int128
                /// is actually *passed* on the stack (clang underaligns it for
                /// the same reason that rustc *never* properly aligns it).
                const _ASSERT_128_COMPAT: () = {
                    assert!(core::mem::size_of::<__int128>() == _SIZE_128);
                    assert!(core::mem::align_of::<__int128>() == _ALIGN_128);

                    assert!(core::mem::size_of::<__uint128>() == _SIZE_128);
                    assert!(core::mem::align_of::<__uint128>() == _ALIGN_128);

                    assert!(core::mem::size_of::<__int128_t>() == _SIZE_128);
                    assert!(core::mem::align_of::<__int128_t>() == _ALIGN_128);

                    assert!(core::mem::size_of::<__uint128_t>() == _SIZE_128);
                    assert!(core::mem::align_of::<__uint128_t>() == _ALIGN_128);
                };
            }
        }
    }
}
<|endoftext|>