<commit_before>
use ffi;
use num_traits::{One, Zero};
use std::ops::*;

#[allow(non_camel_case_types)]
#[derive(Clone, Debug, Copy)]
pub struct c64(ffi::fftw_complex);

impl Deref for c64 {
    type Target = ffi::fftw_complex;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for c64 {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl c64 {
    pub fn re(&self) -> f64 {
        self[0]
    }
    pub fn im(&self) -> f64 {
        self[1]
    }
    pub fn new(re: f64, im: f64) -> Self {
        c64([re, im])
    }
    pub fn abs(&self) -> f64 {
        (self.re() * self.re() + self.im() * self.im()).sqrt()
    }
}

impl Add for c64 {
    type Output = c64;
    fn add(self, other: Self) -> Self {
        c64([self.re() + other.re(), self.im() + other.im()])
    }
}

impl Sub for c64 {
    type Output = c64;
    fn sub(self, other: Self) -> Self {
        c64([self.re() - other.re(), self.im() - other.im()])
    }
}

impl Neg for c64 {
    type Output = c64;
    fn neg(self) -> Self {
        c64([-self[0], -self[1]])
    }
}

impl Mul for c64 {
    type Output = c64;
    fn mul(self, other: Self) -> Self {
        c64([self.re() * other.re() - self.im() * other.im(),
             self.re() * other.im() + self.im() * other.re()])
    }
}

impl Add<f64> for c64 {
    type Output = c64;
    fn add(self, other: f64) -> Self {
        c64([self.re() + other, self.im()])
    }
}

impl AddAssign<f64> for c64 {
    fn add_assign(&mut self, rhs: f64) {
        self[0] += rhs;
    }
}

impl Mul<f64> for c64 {
    type Output = c64;
    fn mul(self, other: f64) -> Self {
        c64([self.re() * other, self.im() * other])
    }
}

impl MulAssign<f64> for c64 {
    fn mul_assign(&mut self, rhs: f64) {
        self[0] *= rhs;
        self[1] *= rhs;
    }
}

impl Div<f64> for c64 {
    type Output = c64;
    fn div(self, rhs: f64) -> Self {
        c64([self.re() / rhs, self.im() / rhs])
    }
}

impl One for c64 {
    fn one() -> Self {
        c64([1.0, 0.0])
    }
}

impl Zero for c64 {
    fn zero() -> Self {
        c64([0.0, 0.0])
    }
    fn is_zero(&self) -> bool {
        self.re().is_zero() && self.im().is_zero()
    }
}
<commit_msg>Add operations into complex<commit_after>
use ffi;
use num_traits::{One, Zero};
use std::ops::*;

#[allow(non_camel_case_types)]
#[derive(Clone, Debug, Copy)]
pub struct c64(ffi::fftw_complex);

impl Deref for c64 {
    type Target = ffi::fftw_complex;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for c64 {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl c64 {
    pub fn re(&self) -> f64 {
        self[0]
    }
    pub fn im(&self) -> f64 {
        self[1]
    }
    pub fn new(re: f64, im: f64) -> Self {
        c64([re, im])
    }
    pub fn abs(&self) -> f64 {
        (self.re() * self.re() + self.im() * self.im()).sqrt()
    }
}

impl Add for c64 {
    type Output = c64;
    fn add(self, other: Self) -> Self {
        c64([self.re() + other.re(), self.im() + other.im()])
    }
}

impl AddAssign for c64 {
    fn add_assign(&mut self, other: Self) {
        self[0] += other[0];
        self[1] += other[1];
    }
}

impl Sub for c64 {
    type Output = c64;
    fn sub(self, other: Self) -> Self {
        c64([self.re() - other.re(), self.im() - other.im()])
    }
}

impl SubAssign for c64 {
    fn sub_assign(&mut self, other: Self) {
        self[0] -= other[0];
        self[1] -= other[1];
    }
}

impl Neg for c64 {
    type Output = c64;
    fn neg(self) -> Self {
        c64([-self[0], -self[1]])
    }
}

impl Mul for c64 {
    type Output = c64;
    fn mul(self, other: Self) -> Self {
        c64([self.re() * other.re() - self.im() * other.im(),
             self.re() * other.im() + self.im() * other.re()])
    }
}

impl MulAssign for c64 {
    fn mul_assign(&mut self, other: Self) {
        let a = self.re();
        let b = self.im();
        self[0] = a * other.re() - b * other.im();
        self[1] = a * other.im() + b * other.re();
    }
}

impl Div for c64 {
    type Output = c64;
    fn div(self, other: Self) -> Self {
        let a = other.re();
        let b = other.im();
        let c = self.re();
        let d = self.im();
        let abs = a * a + b * b;
        c64([(a * c + b * d) / abs, (a * d - b * c) / abs])
    }
}

impl Add<f64> for c64 {
    type Output = c64;
    fn add(self, other: f64) -> Self {
        c64([self.re() + other, self.im()])
    }
}

impl AddAssign<f64> for c64 {
    fn add_assign(&mut self, rhs: f64) {
        self[0] += rhs;
    }
}

impl Mul<f64> for c64 {
    type Output = c64;
    fn mul(self, other: f64) -> Self {
        c64([self.re() * other, self.im() * other])
    }
}

impl MulAssign<f64> for c64 {
    fn mul_assign(&mut self, rhs: f64) {
        self[0] *= rhs;
        self[1] *= rhs;
    }
}

impl Div<f64> for c64 {
    type Output = c64;
    fn div(self, rhs: f64) -> Self {
        c64([self.re() / rhs, self.im() / rhs])
    }
}

impl One for c64 {
    fn one() -> Self {
        c64([1.0, 0.0])
    }
}

impl Zero for c64 {
    fn zero() -> Self {
        c64([0.0, 0.0])
    }
    fn is_zero(&self) -> bool {
        self.re().is_zero() && self.im().is_zero()
    }
}
<|endoftext|>


<commit_before>extern crate etcd;

use etcd::{Client, Error};

#[test]
fn lifecycle() {
    let client = Client::new("http://etcd:2379").unwrap();

    // Creating a key

    let create_response = client.create("/foo", "bar", Some(60)).ok().unwrap();

    assert_eq!(create_response.action, "create".to_string());
    assert_eq!(create_response.node.value.unwrap(), "bar".to_string());
    assert_eq!(create_response.node.ttl.unwrap(), 60);

    // Getting a key

    let get_response = client.get("/foo", false, false).ok().unwrap();

    assert_eq!(get_response.action, "get".to_string());
    assert_eq!(get_response.node.value.unwrap(), "bar".to_string());
    assert_eq!(get_response.node.ttl.unwrap(), 60);

    // Creating a key fails if it already exists

    match client.create("/foo", "bar", None).err().unwrap() {
        Error::Etcd(error) => assert_eq!(error.message, "Key already exists".to_string()),
        _ => panic!("expected EtcdError due to pre-existing key"),
    };

    // Setting a key

    let set_response = client.set("/foo", "baz", None).ok().unwrap();

    assert_eq!(set_response.action, "set".to_string());
    assert_eq!(set_response.node.value.unwrap(), "baz".to_string());
    assert!(set_response.node.ttl.is_none());

    // Updating a key

    let update_response = client.update("/foo", "blah", Some(30)).ok().unwrap();

    assert_eq!(update_response.action, "update".to_string());
    assert_eq!(update_response.node.value.unwrap(), "blah".to_string());
    assert_eq!(update_response.node.ttl.unwrap(), 30);

    // Deleting a key

    let delete_response = client.delete("/foo", false).ok().unwrap();

    assert_eq!(delete_response.action, "delete");

    // Updating a key fails if it doesn't exist

    match client.update("/foo", "bar", None).err().unwrap() {
        Error::Etcd(error) => assert_eq!(error.message, "Key not found".to_string()),
        _ => panic!("expected EtcdError due to missing key"),
    };

    // Creating a directory

    let create_dir_response = client.create_dir("/dir", None).ok().unwrap();

    assert_eq!(create_dir_response.action, "create".to_string());
    assert!(create_dir_response.node.dir.unwrap());
    assert!(create_dir_response.node.value.is_none());

    // Deleting an empty directory

    let delete_dir_response = client.delete_dir("/dir").ok().unwrap();

    assert_eq!(delete_dir_response.action, "delete");

    // Getting keys within directories (recursive listing)

    client.set("/foo", "bar", None).ok();
    client.set("/dir/baz", "blah", None).ok();

    let non_recursive_get_response = client.get("/", false, false).ok().unwrap();

    assert_eq!(non_recursive_get_response.node.dir.unwrap(), true);

    let nodes = non_recursive_get_response.node.nodes.unwrap();

    assert_eq!(nodes[0].clone().key.unwrap(), "/foo".to_string());
    assert_eq!(nodes[0].clone().value.unwrap(), "bar".to_string());
    assert_eq!(nodes[1].clone().key.unwrap(), "/dir".to_string());
    assert_eq!(nodes[1].clone().dir.unwrap(), true);

    client.delete("/foo", false).ok();
    client.delete("/dir/baz", false).ok();
    client.delete_dir("/dir").ok();
}
<commit_msg>Test listing recursively.<commit_after>extern crate etcd;

use etcd::{Client, Error};

#[test]
fn lifecycle() {
    let client = Client::new("http://etcd:2379").unwrap();

    // Creating a key

    let create_response = client.create("/foo", "bar", Some(60)).ok().unwrap();

    assert_eq!(create_response.action, "create".to_string());
    assert_eq!(create_response.node.value.unwrap(), "bar".to_string());
    assert_eq!(create_response.node.ttl.unwrap(), 60);

    // Getting a key

    let get_response = client.get("/foo", false, false).ok().unwrap();

    assert_eq!(get_response.action, "get".to_string());
    assert_eq!(get_response.node.value.unwrap(), "bar".to_string());
    assert_eq!(get_response.node.ttl.unwrap(), 60);

    // Creating a key fails if it already exists

    match client.create("/foo", "bar", None).err().unwrap() {
        Error::Etcd(error) => assert_eq!(error.message, "Key already exists".to_string()),
        _ => panic!("expected EtcdError due to pre-existing key"),
    };

    // Setting a key

    let set_response = client.set("/foo", "baz", None).ok().unwrap();

    assert_eq!(set_response.action, "set".to_string());
    assert_eq!(set_response.node.value.unwrap(), "baz".to_string());
    assert!(set_response.node.ttl.is_none());

    // Updating a key

    let update_response = client.update("/foo", "blah", Some(30)).ok().unwrap();

    assert_eq!(update_response.action, "update".to_string());
    assert_eq!(update_response.node.value.unwrap(), "blah".to_string());
    assert_eq!(update_response.node.ttl.unwrap(), 30);

    // Deleting a key

    let delete_response = client.delete("/foo", false).ok().unwrap();

    assert_eq!(delete_response.action, "delete");

    // Updating a key fails if it doesn't exist

    match client.update("/foo", "bar", None).err().unwrap() {
        Error::Etcd(error) => assert_eq!(error.message, "Key not found".to_string()),
        _ => panic!("expected EtcdError due to missing key"),
    };

    // Creating a directory

    let create_dir_response = client.create_dir("/dir", None).ok().unwrap();

    assert_eq!(create_dir_response.action, "create".to_string());
    assert!(create_dir_response.node.dir.unwrap());
    assert!(create_dir_response.node.value.is_none());

    // Deleting an empty directory

    let delete_dir_response = client.delete_dir("/dir").ok().unwrap();

    assert_eq!(delete_dir_response.action, "delete");

    // Getting keys within directories (recursive listing)

    client.set("/foo", "bar", None).ok();
    client.set("/dir/baz", "blah", None).ok();

    let non_recursive_get_response = client.get("/", false, false).ok().unwrap();

    assert_eq!(non_recursive_get_response.node.dir.unwrap(), true);

    let non_recursive_nodes = non_recursive_get_response.node.nodes.unwrap();

    assert_eq!(non_recursive_nodes[0].clone().key.unwrap(), "/foo".to_string());
    assert_eq!(non_recursive_nodes[0].clone().value.unwrap(), "bar".to_string());
    assert_eq!(non_recursive_nodes[1].clone().key.unwrap(), "/dir".to_string());
    assert_eq!(non_recursive_nodes[1].clone().dir.unwrap(), true);

    let recursive_get_response = client.get("/", false, true).ok().unwrap();
    let recursive_nodes = recursive_get_response.node.nodes.unwrap();

    assert_eq!(
        recursive_nodes[1].clone().nodes.unwrap()[0].clone().value.unwrap(),
        "blah".to_string()
    );

    client.delete("/foo", false).ok();
    client.delete("/dir/baz", false).ok();
    client.delete_dir("/dir").ok();
}
<|endoftext|>


<commit_before>#![feature(slice_concat_ext, custom_test_frameworks)]
// Custom test runner, to avoid libtest being wrapped around compiletest which wraps libtest.
#![test_runner(test_runner)]

use std::slice::SliceConcatExt;
use std::path::{PathBuf, Path};
use std::env;

use compiletest_rs as compiletest;
use colored::*;

fn miri_path() -> PathBuf {
    if rustc_test_suite().is_some() {
        PathBuf::from(option_env!("MIRI_PATH").unwrap())
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/miri"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn mk_config(mode: &str) -> compiletest::common::ConfigWithTemp {
    let mut config = compiletest::Config::default().tempdir();
    config.mode = mode.parse().expect("Invalid mode");
    config.rustc_path = miri_path();
    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.filter = env::args().nth(1);
    config
}

fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running compile-fail tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    flags.push(format!("--sysroot {}", sysroot.display()));
    flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    flags.push("--edition 2018".to_owned());
    if opt {
        // Optimizing too aggressivley makes UB detection harder, but test at least
        // the default value.
        // FIXME: Opt level 3 ICEs during stack trace generation.
        flags.push("-Zmir-opt-level=1".to_owned());
    }

    let mut config = mk_config("compile-fail");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.target_rustcflags = Some(flags.join(" "));
    compiletest::run_tests(&config);
}

fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running run-pass tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    flags.push(format!("--sysroot {}", sysroot.display()));
    flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    flags.push("--edition 2018".to_owned());
    if opt {
        // FIXME: We use opt level 1 because MIR inlining defeats the validation
        // whitelist.
        flags.push("-Zmir-opt-level=1".to_owned());
    }

    let mut config = mk_config("ui");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.target_rustcflags = Some(flags.join(" "));
    compiletest::run_tests(&config);
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn target_has_std<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    std::fs::read_dir(path)
        .expect("invalid target")
        .map(|entry| entry.unwrap())
        .filter(|entry| entry.file_type().unwrap().is_file())
        .filter_map(|entry| entry.file_name().into_string().ok())
        .any(|file_name| file_name == "libstd.rlib")
}

fn for_all_targets<F: FnMut(String)>(sysroot: &Path, f: F) {
    let target_dir = sysroot.join("lib").join("rustlib");
    let mut targets = std::fs::read_dir(target_dir)
        .expect("invalid sysroot")
        .map(|entry| entry.unwrap())
        .filter(|entry| is_target_dir(entry.path()))
        .filter(|entry| target_has_std(entry.path()))
        .map(|entry| entry.file_name().into_string().unwrap())
        .peekable();

    if targets.peek().is_none() {
        panic!("No valid targets found");
    }

    targets.for_each(f);
}

fn get_sysroot() -> PathBuf {
    let sysroot = std::env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
        let sysroot = std::process::Command::new("rustc")
            .arg("--print")
            .arg("sysroot")
            .output()
            .expect("rustc not found")
            .stdout;
        String::from_utf8(sysroot).expect("sysroot is not utf8")
    });
    PathBuf::from(sysroot.trim())
}

fn get_host() -> String {
    let rustc = rustc_test_suite().unwrap_or(PathBuf::from("rustc"));
    let host = std::process::Command::new(rustc)
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let host = std::str::from_utf8(&host).expect("sysroot is not utf8");
    let host = host.split("\nhost: ").nth(1).expect(
        "no host: part in rustc -vV",
    );
    let host = host.split('\n').next().expect("no \n after host");
    String::from(host)
}

fn run_pass_miri(opt: bool) {
    let sysroot = get_sysroot();
    let host = get_host();

    for_all_targets(&sysroot, |target| {
        miri_pass(&sysroot, "tests/run-pass", &target, &host, opt);
    });
}

fn compile_fail_miri(opt: bool) {
    let sysroot = get_sysroot();
    let host = get_host();

    for_all_targets(&sysroot, |target| {
        compile_fail(&sysroot, "tests/compile-fail", &target, &host, opt);
    });
}

fn test_runner(_tests: &[&()]) {
    // We put everything into a single test to avoid the parallelism `cargo test`
    // introduces.  We still get parallelism within our tests because `compiletest`
    // uses `libtest` which runs jobs in parallel.

    run_pass_miri(false);
    run_pass_miri(true);

    compile_fail_miri(false);
    compile_fail_miri(true);
}
<commit_msg>use rustc_version also to parse host in compiletest<commit_after>#![feature(slice_concat_ext, custom_test_frameworks)]
// Custom test runner, to avoid libtest being wrapped around compiletest which wraps libtest.
#![test_runner(test_runner)]

use std::slice::SliceConcatExt;
use std::path::{PathBuf, Path};
use std::env;

use compiletest_rs as compiletest;
use colored::*;

fn miri_path() -> PathBuf {
    if rustc_test_suite().is_some() {
        PathBuf::from(option_env!("MIRI_PATH").unwrap())
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/miri"))
    }
}

fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn mk_config(mode: &str) -> compiletest::common::ConfigWithTemp {
    let mut config = compiletest::Config::default().tempdir();
    config.mode = mode.parse().expect("Invalid mode");
    config.rustc_path = miri_path();
    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }
    config.filter = env::args().nth(1);
    config
}

fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running compile-fail tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    flags.push(format!("--sysroot {}", sysroot.display()));
    flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    flags.push("--edition 2018".to_owned());
    if opt {
        // Optimizing too aggressivley makes UB detection harder, but test at least
        // the default value.
        // FIXME: Opt level 3 ICEs during stack trace generation.
        flags.push("-Zmir-opt-level=1".to_owned());
    }

    let mut config = mk_config("compile-fail");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.target_rustcflags = Some(flags.join(" "));
    compiletest::run_tests(&config);
}

fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
    let opt_str = if opt { " with optimizations" } else { "" };
    eprintln!("{}", format!(
        "## Running run-pass tests in {} against miri for target {}{}",
        path,
        target,
        opt_str
    ).green().bold());

    let mut flags = Vec::new();
    flags.push(format!("--sysroot {}", sysroot.display()));
    flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
    flags.push("--edition 2018".to_owned());
    if opt {
        // FIXME: We use opt level 1 because MIR inlining defeats the validation
        // whitelist.
        flags.push("-Zmir-opt-level=1".to_owned());
    }

    let mut config = mk_config("ui");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.target_rustcflags = Some(flags.join(" "));
    compiletest::run_tests(&config);
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn target_has_std<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    std::fs::read_dir(path)
        .expect("invalid target")
        .map(|entry| entry.unwrap())
        .filter(|entry| entry.file_type().unwrap().is_file())
        .filter_map(|entry| entry.file_name().into_string().ok())
        .any(|file_name| file_name == "libstd.rlib")
}

fn for_all_targets<F: FnMut(String)>(sysroot: &Path, f: F) {
    let target_dir = sysroot.join("lib").join("rustlib");
    let mut targets = std::fs::read_dir(target_dir)
        .expect("invalid sysroot")
        .map(|entry| entry.unwrap())
        .filter(|entry| is_target_dir(entry.path()))
        .filter(|entry| target_has_std(entry.path()))
        .map(|entry| entry.file_name().into_string().unwrap())
        .peekable();

    if targets.peek().is_none() {
        panic!("No valid targets found");
    }

    targets.for_each(f);
}

fn get_sysroot() -> PathBuf {
    let sysroot = std::env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
        let sysroot = std::process::Command::new("rustc")
            .arg("--print")
            .arg("sysroot")
            .output()
            .expect("rustc not found")
            .stdout;
        String::from_utf8(sysroot).expect("sysroot is not utf8")
    });
    PathBuf::from(sysroot.trim())
}

fn get_host() -> String {
    let rustc = rustc_test_suite().unwrap_or(PathBuf::from("rustc"));
    let rustc_version = std::process::Command::new(rustc)
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let rustc_version = std::str::from_utf8(&rustc_version).expect("rustc -vV is not utf8");
    let version_meta = rustc_version::version_meta_for(&rustc_version)
        .expect("failed to parse rustc version info");
    version_meta.host
}

fn run_pass_miri(opt: bool) {
    let sysroot = get_sysroot();
    let host = get_host();

    for_all_targets(&sysroot, |target| {
        miri_pass(&sysroot, "tests/run-pass", &target, &host, opt);
    });
}

fn compile_fail_miri(opt: bool) {
    let sysroot = get_sysroot();
    let host = get_host();

    for_all_targets(&sysroot, |target| {
        compile_fail(&sysroot, "tests/compile-fail", &target, &host, opt);
    });
}

fn test_runner(_tests: &[&()]) {
    // We put everything into a single test to avoid the parallelism `cargo test`
    // introduces.  We still get parallelism within our tests because `compiletest`
    // uses `libtest` which runs jobs in parallel.

    run_pass_miri(false);
    run_pass_miri(true);

    compile_fail_miri(false);
    compile_fail_miri(true);
}
<|endoftext|>


<commit_before>use ideal::{Id, IdVec};
use ideal::vec::IdsIter;
use point::{Point, Position};

pub struct VertexData {
    position: Position,
    edges: Vec<Edge>,
    cells: Vec<Cell>,
}

pub struct EdgeData {
    vertices: (Vertex, Vertex),
    cells: (Cell, Cell),
}

pub struct CellData {
    point: Point,
    vertices: Vec<Vertex>,
    edges: Vec<Edge>,
}

#[derive(Default)]
pub struct Diagram {
    vertices: IdVec<VertexData>,
    edges: IdVec<EdgeData>,
    cells: IdVec<CellData>,
}

impl Diagram {
    pub fn add_vertex(&mut self, position: Position, cells: &[Cell]) -> Vertex {
        let vertex = self.vertices.push(VertexData {
            position: position,
            edges: Vec::new(),
            cells: Vec::from(cells),
        });
        for &cell in cells {
            self.cells[cell].vertices.push(vertex);
        }
        vertex
    }

    pub fn vertices(&self) -> IdsIter<VertexData> {
        self.vertices.ids()
    }

    pub fn vertex_position(&self, vertex: Vertex) -> Position {
        self.vertices[vertex].position
    }

    pub fn vertex_edges(&self, vertex: Vertex) -> &[Edge] {
        &self.vertices[vertex].edges
    }

    pub fn vertex_cells(&self, vertex: Vertex) -> &[Cell] {
        &self.vertices[vertex].cells
    }

    pub fn vertex_neighbors(&self, vertex: Vertex) -> Vec<Vertex> {
        self.vertex_edges(vertex)
            .iter()
            .map(|&edge| self.other_edge_vertex(edge, vertex))
            .collect()
    }

    pub fn add_edge(&mut self, vertex0: Vertex, vertex1: Vertex) -> Edge {
        self.edges.push(EdgeData {
            vertices: (vertex0, vertex1),
            cells: (Cell::invalid(), Cell::invalid())
        })
    }

    pub fn edges(&self) -> IdsIter<EdgeData> {
        self.edges.ids()
    }

    pub fn edge_vertices(&self, edge: Edge) -> (Vertex, Vertex) {
        self.edges[edge].vertices
    }

    pub fn edge_cells(&self, edge: Edge) -> (Cell, Cell) {
        self.edges[edge].cells
    }

    pub fn set_edge_cells(&mut self, edge: Edge, cell0: Cell, cell1: Cell) {
        self.edges[edge].cells = (cell0, cell1);
        self.cells[cell0].edges.push(edge);
        self.cells[cell1].edges.push(edge);
    }

    pub fn other_edge_vertex(&self, edge: Edge, vertex: Vertex) -> Vertex {
        let (vertex0, vertex1) = self.edge_vertices(edge);
        if vertex == vertex0 {
            vertex1
        } else if vertex == vertex1 {
            vertex0
        } else {
            Vertex::invalid()
        }
    }

    pub fn other_edge_cell(&self, edge: Edge, cell: Cell) -> Cell {
        let (cell0, cell1) = self.edge_cells(edge);
        if cell == cell0 {
            cell1
        } else if cell == cell1 {
            cell0
        } else {
            Cell::invalid()
        }
    }

    pub fn add_cell(&mut self, point: Point) -> Cell {
        self.cells.push(CellData {
            point: point,
            vertices: Vec::new(),
            edges: Vec::new(),
        })
    }

    pub fn cells(&self) -> IdsIter<CellData> {
        self.cells.ids()
    }

    pub fn compute_centers(&mut self) {
        for cell in self.cells() {
            let mut position = Position::new(0.0, 0.0, 0.0);
            for vertex in self.cell_vertices(cell) {
                position += self.vertex_position(*vertex);
            }
            self.cells[cell].point = Point::from(position / (self.vertices.len() as f64));
        }
    }

    pub fn reset(&mut self) {
        self.compute_centers();
        self.vertices.clear();
        self.edges.clear();
        for cell in self.cells() {
            self.cells[cell].vertices.clear();
        }
    }

    pub fn cell_point(&self, cell: Cell) -> &Point {
        &self.cells[cell].point
    }

    pub fn cell_vertices(&self, cell: Cell) -> &[Vertex] {
        &self.cells[cell].vertices
    }

    pub fn cell_edges(&self, cell: Cell) -> &[Edge] {
        &self.cells[cell].edges
    }

    pub fn cell_neighbors(&self, cell: Cell) -> Vec<Cell> {
        self.cell_edges(cell)
            .iter()
            .map(|&edge| self.other_edge_cell(edge, cell))
            .collect()
    }
}

pub type Vertex = Id<VertexData>;
pub type Edge = Id<EdgeData>;
pub type Cell = Id<CellData>;<commit_msg>Fix edges of vertices<commit_after>use ideal::{Id, IdVec};
use ideal::vec::IdsIter;
use point::{Point, Position};

pub struct VertexData {
    position: Position,
    edges: Vec<Edge>,
    cells: Vec<Cell>,
}

pub struct EdgeData {
    vertices: (Vertex, Vertex),
    cells: (Cell, Cell),
}

pub struct CellData {
    point: Point,
    vertices: Vec<Vertex>,
    edges: Vec<Edge>,
}

#[derive(Default)]
pub struct Diagram {
    vertices: IdVec<VertexData>,
    edges: IdVec<EdgeData>,
    cells: IdVec<CellData>,
}

impl Diagram {
    pub fn add_vertex(&mut self, position: Position, cells: &[Cell]) -> Vertex {
        let vertex = self.vertices.push(VertexData {
            position: position,
            edges: Vec::new(),
            cells: Vec::from(cells),
        });
        for &cell in cells {
            self.cells[cell].vertices.push(vertex);
        }
        vertex
    }

    pub fn vertices(&self) -> IdsIter<VertexData> {
        self.vertices.ids()
    }

    pub fn vertex_position(&self, vertex: Vertex) -> Position {
        self.vertices[vertex].position
    }

    pub fn vertex_edges(&self, vertex: Vertex) -> &[Edge] {
        &self.vertices[vertex].edges
    }

    pub fn vertex_cells(&self, vertex: Vertex) -> &[Cell] {
        &self.vertices[vertex].cells
    }

    pub fn vertex_neighbors(&self, vertex: Vertex) -> Vec<Vertex> {
        self.vertex_edges(vertex)
            .iter()
            .map(|&edge| self.other_edge_vertex(edge, vertex))
            .collect()
    }

    pub fn add_edge(&mut self, vertex0: Vertex, vertex1: Vertex) -> Edge {
        let edge = self.edges.push(EdgeData {
            vertices: (vertex0, vertex1),
            cells: (Cell::invalid(), Cell::invalid())
        });
        self.vertices[vertex0].edges.push(edge);
        self.vertices[vertex1].edges.push(edge);
        edge
    }

    pub fn edges(&self) -> IdsIter<EdgeData> {
        self.edges.ids()
    }

    pub fn edge_vertices(&self, edge: Edge) -> (Vertex, Vertex) {
        self.edges[edge].vertices
    }

    pub fn edge_cells(&self, edge: Edge) -> (Cell, Cell) {
        self.edges[edge].cells
    }

    pub fn set_edge_cells(&mut self, edge: Edge, cell0: Cell, cell1: Cell) {
        self.edges[edge].cells = (cell0, cell1);
        self.cells[cell0].edges.push(edge);
        self.cells[cell1].edges.push(edge);
    }

    pub fn other_edge_vertex(&self, edge: Edge, vertex: Vertex) -> Vertex {
        let (vertex0, vertex1) = self.edge_vertices(edge);
        if vertex == vertex0 {
            vertex1
        } else if vertex == vertex1 {
            vertex0
        } else {
            Vertex::invalid()
        }
    }

    pub fn other_edge_cell(&self, edge: Edge, cell: Cell) -> Cell {
        let (cell0, cell1) = self.edge_cells(edge);
        if cell == cell0 {
            cell1
        } else if cell == cell1 {
            cell0
        } else {
            Cell::invalid()
        }
    }

    pub fn add_cell(&mut self, point: Point) -> Cell {
        self.cells.push(CellData {
            point: point,
            vertices: Vec::new(),
            edges: Vec::new(),
        })
    }

    pub fn cells(&self) -> IdsIter<CellData> {
        self.cells.ids()
    }

    pub fn compute_centers(&mut self) {
        for cell in self.cells() {
            let mut position = Position::new(0.0, 0.0, 0.0);
            for vertex in self.cell_vertices(cell) {
                position += self.vertex_position(*vertex);
            }
            self.cells[cell].point = Point::from(position / (self.vertices.len() as f64));
        }
    }

    pub fn reset(&mut self) {
        self.compute_centers();
        self.vertices.clear();
        self.edges.clear();
        for cell in self.cells() {
            self.cells[cell].vertices.clear();
        }
    }

    pub fn cell_point(&self, cell: Cell) -> &Point {
        &self.cells[cell].point
    }

    pub fn cell_vertices(&self, cell: Cell) -> &[Vertex] {
        &self.cells[cell].vertices
    }

    pub fn cell_edges(&self, cell: Cell) -> &[Edge] {
        &self.cells[cell].edges
    }

    pub fn cell_neighbors(&self, cell: Cell) -> Vec<Cell> {
        self.cell_edges(cell)
            .iter()
            .map(|&edge| self.other_edge_cell(edge, cell))
            .collect()
    }
}

pub type Vertex = Id<VertexData>;
pub type Edge = Id<EdgeData>;
pub type Cell = Id<CellData>;<|endoftext|>


<commit_before>#![crate_name = "shuf"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#![feature(macro_rules)]

extern crate getopts;
extern crate libc;

use std::cmp;
use std::from_str::from_str;
use std::io;
use std::io::IoResult;
use std::iter::{range_inclusive, RangeInclusive};
use std::rand;
use std::uint;

#[path = "../common/util.rs"]
mod util;

enum Mode {
    Default,
    Echo,
    InputRange(RangeInclusive<uint>)
}

static NAME: &'static str = "shuf";
static VERSION: &'static str = "0.0.1";

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();

    let opts = [
        getopts::optflag("e", "echo", "treat each ARG as an input line"),
        getopts::optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"),
        getopts::optopt("n", "head-count", "output at most COUNT lines", "COUNT"),
        getopts::optopt("o", "output", "write result to FILE instead of standard output", "FILE"),
        getopts::optopt("", "random-source", "get random bytes from FILE", "FILE"),
        getopts::optflag("r", "repeat", "output lines can be repeated"),
        getopts::optflag("z", "zero-terminated", "end lines with 0 byte, not newline"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "{}", f)
        }
    };
    if matches.opt_present("help") {
        println!("{name} v{version}

Usage:
  {prog} [OPTION]... [FILE]
  {prog} -e [OPTION]... [ARG]...
  {prog} -i LO-HI [OPTION]...\n
{usage}
With no FILE, or when FILE is -, read standard input.",
                 name = NAME, version = VERSION, prog = program,
                 usage = getopts::usage("Write a random permutation of the input lines to standard output.", opts));
    } else if matches.opt_present("version") {
        println!("{} v{}", NAME, VERSION);
    } else {
        let echo = matches.opt_present("echo");
        let mode = match matches.opt_str("input-range") {
            Some(range) => {
                if echo {
                    show_error!("cannot specify more than one mode");
                    return 1;
                }
                match parse_range(range) {
                    Ok(m) => InputRange(m),
                    Err((msg, code)) => {
                        show_error!("{}", msg);
                        return code;
                    }
                }
            }
            None => if echo { Echo } else { Default }
        };
        let repeat = matches.opt_present("repeat");
        let zero = matches.opt_present("zero-terminated");
        let count = match matches.opt_str("head-count") {
            Some(cnt) => match from_str::<uint>(cnt.as_slice()) {
                Some(val) => val,
                None => {
                    show_error!("'{}' is not a valid count", cnt);
                    return 1;
                }
            },
            None => uint::MAX
        };
        let output = matches.opt_str("output");
        let random = matches.opt_str("random-source");
        match shuf(matches.free, mode, repeat, zero, count, output, random) {
            Err(f) => {
                show_error!("{}", f);
                return 1;
            },
            _ => {}
        }
    }

    0
}

fn shuf(input: Vec<String>, mode: Mode, repeat: bool, zero: bool, count: uint, output: Option<String>, random: Option<String>) -> IoResult<()> {
    match mode {
        Echo => shuf_lines(input, repeat, zero, count, output, random),
        InputRange(range) => shuf_lines(range.map(|num| num.to_string()).collect(), repeat, zero, count, output, random),
        Default => {
            let lines: Vec<String> = input.move_iter().flat_map(|filename| {
                let mut file = io::BufferedReader::new(crash_if_err!(1, io::File::open(&Path::new(filename.as_slice()))));
                let mut lines = vec!();
                for line in file.lines() {
                    let mut line = crash_if_err!(1, line);
                    line.pop_char();
                    lines.push(line);
                }
                lines.move_iter()
            }).collect();
            shuf_lines(lines, repeat, zero, count, output, random)
        }
    }
}

fn shuf_lines(mut lines: Vec<String>, repeat: bool, zero: bool, count: uint, outname: Option<String>, random: Option<String>) -> IoResult<()> {
    let mut output = match outname {
        Some(name) => box io::BufferedWriter::new(try!(io::File::create(&Path::new(name)))) as Box<Writer>,
        None => box io::stdout() as Box<Writer>
    };
    let mut rng = match random {
        Some(name) => box rand::reader::ReaderRng::new(try!(io::File::open(&Path::new(name)))) as Box<rand::Rng>,
        None => box rand::task_rng() as Box<rand::Rng>
    };
    let mut len = lines.len();
    let max = if repeat { count } else { cmp::min(count, len) };
    for _ in range(0, max) {
        let idx = rng.next_u32() as uint % len;
        try!(write!(output, "{}{}", lines.get(idx), if zero { '\0' } else { '\n' }));
        if !repeat {
            lines.remove(idx);
            len -= 1;
        }
    }
    Ok(())
}

fn parse_range(input_range: String) -> Result<RangeInclusive<uint>, (String, int)> {
    let split: Vec<&str> = input_range.as_slice().split('-').collect();
    if split.len() != 2 {
        Err(("invalid range format".to_string(), 1))
    } else {
        let begin = match from_str::<uint>(*split.get(0)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(0)), 1))
        };
        let end = match from_str::<uint>(*split.get(1)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(1)), 1))
        };
        Ok(range_inclusive(begin, end))
    }
}

<commit_msg>shuf: handle stdin<commit_after>#![crate_name = "shuf"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#![feature(macro_rules)]

extern crate getopts;
extern crate libc;

use std::cmp;
use std::from_str::from_str;
use std::io;
use std::io::IoResult;
use std::iter::{range_inclusive, RangeInclusive};
use std::rand;
use std::uint;

#[path = "../common/util.rs"]
mod util;

enum Mode {
    Default,
    Echo,
    InputRange(RangeInclusive<uint>)
}

static NAME: &'static str = "shuf";
static VERSION: &'static str = "0.0.1";

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();

    let opts = [
        getopts::optflag("e", "echo", "treat each ARG as an input line"),
        getopts::optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"),
        getopts::optopt("n", "head-count", "output at most COUNT lines", "COUNT"),
        getopts::optopt("o", "output", "write result to FILE instead of standard output", "FILE"),
        getopts::optopt("", "random-source", "get random bytes from FILE", "FILE"),
        getopts::optflag("r", "repeat", "output lines can be repeated"),
        getopts::optflag("z", "zero-terminated", "end lines with 0 byte, not newline"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let mut matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "{}", f)
        }
    };
    if matches.opt_present("help") {
        println!("{name} v{version}

Usage:
  {prog} [OPTION]... [FILE]
  {prog} -e [OPTION]... [ARG]...
  {prog} -i LO-HI [OPTION]...\n
{usage}
With no FILE, or when FILE is -, read standard input.",
                 name = NAME, version = VERSION, prog = program,
                 usage = getopts::usage("Write a random permutation of the input lines to standard output.", opts));
    } else if matches.opt_present("version") {
        println!("{} v{}", NAME, VERSION);
    } else {
        let echo = matches.opt_present("echo");
        let mode = match matches.opt_str("input-range") {
            Some(range) => {
                if echo {
                    show_error!("cannot specify more than one mode");
                    return 1;
                }
                match parse_range(range) {
                    Ok(m) => InputRange(m),
                    Err((msg, code)) => {
                        show_error!("{}", msg);
                        return code;
                    }
                }
            }
            None => {
                if echo {
                    Echo
                } else {
                    if matches.free.len() == 0 {
                        matches.free.push("-".to_string());
                    }
                    Default
                }
            }
        };
        let repeat = matches.opt_present("repeat");
        let zero = matches.opt_present("zero-terminated");
        let count = match matches.opt_str("head-count") {
            Some(cnt) => match from_str::<uint>(cnt.as_slice()) {
                Some(val) => val,
                None => {
                    show_error!("'{}' is not a valid count", cnt);
                    return 1;
                }
            },
            None => uint::MAX
        };
        let output = matches.opt_str("output");
        let random = matches.opt_str("random-source");
        match shuf(matches.free, mode, repeat, zero, count, output, random) {
            Err(f) => {
                show_error!("{}", f);
                return 1;
            },
            _ => {}
        }
    }

    0
}

fn shuf(input: Vec<String>, mode: Mode, repeat: bool, zero: bool, count: uint, output: Option<String>, random: Option<String>) -> IoResult<()> {
    match mode {
        Echo => shuf_lines(input, repeat, zero, count, output, random),
        InputRange(range) => shuf_lines(range.map(|num| num.to_string()).collect(), repeat, zero, count, output, random),
        Default => {
            let lines: Vec<String> = input.move_iter().flat_map(|filename| {
                let slice = filename.as_slice();
                let mut file_buf;
                let mut stdin_buf;
                let mut file = io::BufferedReader::new(
                    if slice == "-" {
                        stdin_buf = io::stdio::stdin_raw();
                        &mut stdin_buf as &mut Reader
                    } else {
                        file_buf = crash_if_err!(1, io::File::open(&Path::new(slice)));
                        &mut file_buf as &mut Reader
                    }
                );
                let mut lines = vec!();
                for line in file.lines() {
                    let mut line = crash_if_err!(1, line);
                    line.pop_char();
                    lines.push(line);
                }
                lines.move_iter()
            }).collect();
            shuf_lines(lines, repeat, zero, count, output, random)
        }
    }
}

fn shuf_lines(mut lines: Vec<String>, repeat: bool, zero: bool, count: uint, outname: Option<String>, random: Option<String>) -> IoResult<()> {
    let mut output = match outname {
        Some(name) => box io::BufferedWriter::new(try!(io::File::create(&Path::new(name)))) as Box<Writer>,
        None => box io::stdout() as Box<Writer>
    };
    let mut rng = match random {
        Some(name) => box rand::reader::ReaderRng::new(try!(io::File::open(&Path::new(name)))) as Box<rand::Rng>,
        None => box rand::task_rng() as Box<rand::Rng>
    };
    let mut len = lines.len();
    let max = if repeat { count } else { cmp::min(count, len) };
    for _ in range(0, max) {
        let idx = rng.next_u32() as uint % len;
        try!(write!(output, "{}{}", lines.get(idx), if zero { '\0' } else { '\n' }));
        if !repeat {
            lines.remove(idx);
            len -= 1;
        }
    }
    Ok(())
}

fn parse_range(input_range: String) -> Result<RangeInclusive<uint>, (String, int)> {
    let split: Vec<&str> = input_range.as_slice().split('-').collect();
    if split.len() != 2 {
        Err(("invalid range format".to_string(), 1))
    } else {
        let begin = match from_str::<uint>(*split.get(0)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(0)), 1))
        };
        let end = match from_str::<uint>(*split.get(1)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(1)), 1))
        };
        Ok(range_inclusive(begin, end))
    }
}

<|endoftext|>


<commit_before>// Copyright 2012 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 syntax::{ast, codemap};
use syntax::ast::node_id;
use codemap::span;
use syntax::ast::{int_ty, uint_ty, float_ty};
use syntax::parse::parse_sess;
use metadata::filesearch;
use back::target_strs;
use back::link;
use middle::lint;

enum os { os_win32, os_macos, os_linux, os_freebsd, }

impl os : cmp::Eq {
    pure fn eq(&self, other: &os) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &os) -> bool { !(*self).eq(other) }
}

enum arch { arch_x86, arch_x86_64, arch_arm, }

impl arch : cmp::Eq {
    pure fn eq(&self, other: &arch) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &arch) -> bool { !(*self).eq(other) }
}

enum crate_type { bin_crate, lib_crate, unknown_crate, }

type config =
    {os: os,
     arch: arch,
     target_strs: target_strs::t,
     int_type: int_ty,
     uint_type: uint_ty,
     float_type: float_ty};

const verbose: uint = 1 << 0;
const time_passes: uint = 1 << 1;
const count_llvm_insns: uint = 1 << 2;
const time_llvm_passes: uint = 1 << 3;
const trans_stats: uint = 1 << 4;
const no_asm_comments: uint = 1 << 5;
const no_verify: uint = 1 << 6;
const trace: uint = 1 << 7;
const coherence: uint = 1 << 8;
const borrowck_stats: uint = 1 << 9;
const borrowck_note_pure: uint = 1 << 10;
const borrowck_note_loan: uint = 1 << 11;
const no_landing_pads: uint = 1 << 12;
const debug_llvm: uint = 1 << 13;
const count_type_sizes: uint = 1 << 14;
const meta_stats: uint = 1 << 15;
const no_opt: uint = 1 << 16;
const no_monomorphic_collapse: uint = 1 << 17;

fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
    ~[(~"verbose", ~"in general, enable more debug printouts", verbose),
     (~"time-passes", ~"measure time of each rustc pass", time_passes),
     (~"count-llvm-insns", ~"count where LLVM \
                           instrs originate", count_llvm_insns),
     (~"time-llvm-passes", ~"measure time of each LLVM pass",
      time_llvm_passes),
     (~"trans-stats", ~"gather trans statistics", trans_stats),
     (~"no-asm-comments", ~"omit comments when using -S", no_asm_comments),
     (~"no-verify", ~"skip LLVM verification", no_verify),
     (~"trace", ~"emit trace logs", trace),
     (~"coherence", ~"perform coherence checking", coherence),
     (~"borrowck-stats", ~"gather borrowck statistics",  borrowck_stats),
     (~"borrowck-note-pure", ~"note where purity is req'd",
      borrowck_note_pure),
     (~"borrowck-note-loan", ~"note where loans are req'd",
      borrowck_note_loan),
     (~"no-landing-pads", ~"omit landing pads for unwinding",
      no_landing_pads),
     (~"debug-llvm", ~"enable debug output from LLVM", debug_llvm),
     (~"count-type-sizes", ~"count the sizes of aggregate types",
      count_type_sizes),
     (~"meta-stats", ~"gather metadata statistics", meta_stats),
     (~"no-opt", ~"do not optimize, even if -O is passed", no_opt),
     (~"no-monomorphic-collapse", ~"do not collapse template instantiations",
      no_monomorphic_collapse),
    ]
}

enum OptLevel {
    No, // -O0
    Less, // -O1
    Default, // -O2
    Aggressive // -O3
}

impl OptLevel : cmp::Eq {
    pure fn eq(&self, other: &OptLevel) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &OptLevel) -> bool { !(*self).eq(other) }
}

type options =
    // The crate config requested for the session, which may be combined
    // with additional crate configurations during the compile process
    {crate_type: crate_type,
     static: bool,
     gc: bool,
     optimize: OptLevel,
     debuginfo: bool,
     extra_debuginfo: bool,
     lint_opts: ~[(lint::lint, lint::level)],
     save_temps: bool,
     jit: bool,
     output_type: back::link::output_type,
     addl_lib_search_paths: ~[Path],
     maybe_sysroot: Option<Path>,
     target_triple: ~str,
     // User-specified cfg meta items. The compiler itself will add additional
     // items to the crate config, and during parsing the entire crate config
     // will be added to the crate AST node.  This should not be used for
     // anything except building the full crate config prior to parsing.
     cfg: ast::crate_cfg,
     binary: ~str,
     test: bool,
     parse_only: bool,
     no_trans: bool,
     debugging_opts: uint,
    };

type crate_metadata = {name: ~str, data: ~[u8]};

type Session_ = {targ_cfg: @config,
                 opts: @options,
                 cstore: metadata::cstore::CStore,
                 parse_sess: parse_sess,
                 codemap: @codemap::CodeMap,
                 // For a library crate, this is always none
                 mut main_fn: Option<(node_id, codemap::span)>,
                 span_diagnostic: diagnostic::span_handler,
                 filesearch: filesearch::FileSearch,
                 mut building_library: bool,
                 working_dir: Path,
                 lint_settings: lint::lint_settings};

enum Session {
    Session_(@Session_)
}

impl Session {
    fn span_fatal(sp: span, msg: ~str) -> ! {
        self.span_diagnostic.span_fatal(sp, msg)
    }
    fn fatal(msg: ~str) -> ! {
        self.span_diagnostic.handler().fatal(msg)
    }
    fn span_err(sp: span, msg: ~str) {
        self.span_diagnostic.span_err(sp, msg)
    }
    fn err(msg: ~str) {
        self.span_diagnostic.handler().err(msg)
    }
    fn has_errors() -> bool {
        self.span_diagnostic.handler().has_errors()
    }
    fn abort_if_errors() {
        self.span_diagnostic.handler().abort_if_errors()
    }
    fn span_warn(sp: span, msg: ~str) {
        self.span_diagnostic.span_warn(sp, msg)
    }
    fn warn(msg: ~str) {
        self.span_diagnostic.handler().warn(msg)
    }
    fn span_note(sp: span, msg: ~str) {
        self.span_diagnostic.span_note(sp, msg)
    }
    fn note(msg: ~str) {
        self.span_diagnostic.handler().note(msg)
    }
    fn span_bug(sp: span, msg: ~str) -> ! {
        self.span_diagnostic.span_bug(sp, msg)
    }
    fn bug(msg: ~str) -> ! {
        self.span_diagnostic.handler().bug(msg)
    }
    fn span_unimpl(sp: span, msg: ~str) -> ! {
        self.span_diagnostic.span_unimpl(sp, msg)
    }
    fn unimpl(msg: ~str) -> ! {
        self.span_diagnostic.handler().unimpl(msg)
    }
    fn span_lint_level(level: lint::level,
                       sp: span, msg: ~str) {
        match level {
          lint::allow => { },
          lint::warn => self.span_warn(sp, msg),
          lint::deny | lint::forbid => {
            self.span_err(sp, msg);
          }
        }
    }
    fn span_lint(lint_mode: lint::lint,
                 expr_id: ast::node_id, item_id: ast::node_id,
                 span: span, msg: ~str) {
        let level = lint::get_lint_settings_level(
            self.lint_settings, lint_mode, expr_id, item_id);
        self.span_lint_level(level, span, msg);
    }
    fn next_node_id() -> ast::node_id {
        return syntax::parse::next_node_id(self.parse_sess);
    }
    fn diagnostic() -> diagnostic::span_handler {
        self.span_diagnostic
    }
    fn debugging_opt(opt: uint) -> bool {
        (self.opts.debugging_opts & opt) != 0u
    }
    // This exists to help with refactoring to eliminate impossible
    // cases later on
    fn impossible_case(sp: span, msg: &str) -> ! {
        self.span_bug(sp, fmt!("Impossible case reached: %s", msg));
    }
    fn verbose() -> bool { self.debugging_opt(verbose) }
    fn time_passes() -> bool { self.debugging_opt(time_passes) }
    fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) }
    fn count_type_sizes() -> bool { self.debugging_opt(count_type_sizes) }
    fn time_llvm_passes() -> bool { self.debugging_opt(time_llvm_passes) }
    fn trans_stats() -> bool { self.debugging_opt(trans_stats) }
    fn meta_stats() -> bool { self.debugging_opt(meta_stats) }
    fn no_asm_comments() -> bool { self.debugging_opt(no_asm_comments) }
    fn no_verify() -> bool { self.debugging_opt(no_verify) }
    fn trace() -> bool { self.debugging_opt(trace) }
    fn coherence() -> bool { self.debugging_opt(coherence) }
    fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
    fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) }
    fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) }
    fn no_monomorphic_collapse() -> bool {
        self.debugging_opt(no_monomorphic_collapse)
    }

    fn str_of(id: ast::ident) -> ~str {
        *self.parse_sess.interner.get(id)
    }
    fn ident_of(st: ~str) -> ast::ident {
        self.parse_sess.interner.intern(@st)
    }
    fn intr() -> @syntax::parse::token::ident_interner {
        self.parse_sess.interner
    }
}

/// Some reasonable defaults
fn basic_options() -> @options {
    @{
        crate_type: session::lib_crate,
        static: false,
        gc: false,
        optimize: No,
        debuginfo: false,
        extra_debuginfo: false,
        lint_opts: ~[],
        save_temps: false,
        jit: false,
        output_type: link::output_type_exe,
        addl_lib_search_paths: ~[],
        maybe_sysroot: None,
        target_triple: driver::host_triple(),
        cfg: ~[],
        binary: ~"rustc",
        test: false,
        parse_only: false,
        no_trans: false,
        debugging_opts: 0u
    }
}

// Seems out of place, but it uses session, so I'm putting it here
fn expect<T: Copy>(sess: Session, opt: Option<T>, msg: fn() -> ~str) -> T {
    diagnostic::expect(sess.diagnostic(), opt, msg)
}

fn building_library(req_crate_type: crate_type, crate: @ast::crate,
                    testing: bool) -> bool {
    match req_crate_type {
      bin_crate => false,
      lib_crate => true,
      unknown_crate => {
        if testing {
            false
        } else {
            match syntax::attr::first_attr_value_str_by_name(
                crate.node.attrs,
                ~"crate_type") {
              option::Some(~"lib") => true,
              _ => false
            }
        }
      }
    }
}

fn sess_os_to_meta_os(os: os) -> metadata::loader::os {
    use metadata::loader;

    match os {
      os_win32 => loader::os_win32,
      os_linux => loader::os_linux,
      os_macos => loader::os_macos,
      os_freebsd => loader::os_freebsd
    }
}

#[cfg(test)]
mod test {
    #[legacy_exports];
    use syntax::ast_util;

    fn make_crate_type_attr(t: ~str) -> ast::attribute {
        ast_util::respan(ast_util::dummy_sp(), {
            style: ast::attr_outer,
            value: ast_util::respan(ast_util::dummy_sp(),
                ast::meta_name_value(
                    ~"crate_type",
                    ast_util::respan(ast_util::dummy_sp(),
                                     ast::lit_str(@t)))),
            is_sugared_doc: false
        })
    }

    fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate {
        let mut attrs = ~[];
        if with_bin { attrs += ~[make_crate_type_attr(~"bin")]; }
        if with_lib { attrs += ~[make_crate_type_attr(~"lib")]; }
        @ast_util::respan(ast_util::dummy_sp(), {
            module: {view_items: ~[], items: ~[]},
            attrs: attrs,
            config: ~[]
        })
    }

    #[test]
    fn bin_crate_type_attr_results_in_bin_output() {
        let crate = make_crate(true, false);
        assert !building_library(unknown_crate, crate, false);
    }

    #[test]
    fn lib_crate_type_attr_results_in_lib_output() {
        let crate = make_crate(false, true);
        assert building_library(unknown_crate, crate, false);
    }

    #[test]
    fn bin_option_overrides_lib_crate_type() {
        let crate = make_crate(false, true);
        assert !building_library(bin_crate, crate, false);
    }

    #[test]
    fn lib_option_overrides_bin_crate_type() {
        let crate = make_crate(true, false);
        assert building_library(lib_crate, crate, false);
    }

    #[test]
    fn bin_crate_type_is_default() {
        let crate = make_crate(false, false);
        assert !building_library(unknown_crate, crate, false);
    }

    #[test]
    fn test_option_overrides_lib_crate_type() {
        let crate = make_crate(false, true);
        assert !building_library(unknown_crate, crate, true);
    }

    #[test]
    fn test_option_does_not_override_requested_lib_type() {
        let crate = make_crate(false, false);
        assert building_library(lib_crate, crate, true);
    }
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Turn off type_use on x86. #4127<commit_after>// Copyright 2012 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 syntax::{ast, codemap};
use syntax::ast::node_id;
use codemap::span;
use syntax::ast::{int_ty, uint_ty, float_ty};
use syntax::parse::parse_sess;
use metadata::filesearch;
use back::target_strs;
use back::link;
use middle::lint;

enum os { os_win32, os_macos, os_linux, os_freebsd, }

impl os : cmp::Eq {
    pure fn eq(&self, other: &os) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &os) -> bool { !(*self).eq(other) }
}

enum arch { arch_x86, arch_x86_64, arch_arm, }

impl arch : cmp::Eq {
    pure fn eq(&self, other: &arch) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &arch) -> bool { !(*self).eq(other) }
}

enum crate_type { bin_crate, lib_crate, unknown_crate, }

type config =
    {os: os,
     arch: arch,
     target_strs: target_strs::t,
     int_type: int_ty,
     uint_type: uint_ty,
     float_type: float_ty};

const verbose: uint = 1 << 0;
const time_passes: uint = 1 << 1;
const count_llvm_insns: uint = 1 << 2;
const time_llvm_passes: uint = 1 << 3;
const trans_stats: uint = 1 << 4;
const no_asm_comments: uint = 1 << 5;
const no_verify: uint = 1 << 6;
const trace: uint = 1 << 7;
const coherence: uint = 1 << 8;
const borrowck_stats: uint = 1 << 9;
const borrowck_note_pure: uint = 1 << 10;
const borrowck_note_loan: uint = 1 << 11;
const no_landing_pads: uint = 1 << 12;
const debug_llvm: uint = 1 << 13;
const count_type_sizes: uint = 1 << 14;
const meta_stats: uint = 1 << 15;
const no_opt: uint = 1 << 16;
const no_monomorphic_collapse: uint = 1 << 17;

fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
    ~[(~"verbose", ~"in general, enable more debug printouts", verbose),
     (~"time-passes", ~"measure time of each rustc pass", time_passes),
     (~"count-llvm-insns", ~"count where LLVM \
                           instrs originate", count_llvm_insns),
     (~"time-llvm-passes", ~"measure time of each LLVM pass",
      time_llvm_passes),
     (~"trans-stats", ~"gather trans statistics", trans_stats),
     (~"no-asm-comments", ~"omit comments when using -S", no_asm_comments),
     (~"no-verify", ~"skip LLVM verification", no_verify),
     (~"trace", ~"emit trace logs", trace),
     (~"coherence", ~"perform coherence checking", coherence),
     (~"borrowck-stats", ~"gather borrowck statistics",  borrowck_stats),
     (~"borrowck-note-pure", ~"note where purity is req'd",
      borrowck_note_pure),
     (~"borrowck-note-loan", ~"note where loans are req'd",
      borrowck_note_loan),
     (~"no-landing-pads", ~"omit landing pads for unwinding",
      no_landing_pads),
     (~"debug-llvm", ~"enable debug output from LLVM", debug_llvm),
     (~"count-type-sizes", ~"count the sizes of aggregate types",
      count_type_sizes),
     (~"meta-stats", ~"gather metadata statistics", meta_stats),
     (~"no-opt", ~"do not optimize, even if -O is passed", no_opt),
     (~"no-monomorphic-collapse", ~"do not collapse template instantiations",
      no_monomorphic_collapse),
    ]
}

enum OptLevel {
    No, // -O0
    Less, // -O1
    Default, // -O2
    Aggressive // -O3
}

impl OptLevel : cmp::Eq {
    pure fn eq(&self, other: &OptLevel) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &OptLevel) -> bool { !(*self).eq(other) }
}

type options =
    // The crate config requested for the session, which may be combined
    // with additional crate configurations during the compile process
    {crate_type: crate_type,
     static: bool,
     gc: bool,
     optimize: OptLevel,
     debuginfo: bool,
     extra_debuginfo: bool,
     lint_opts: ~[(lint::lint, lint::level)],
     save_temps: bool,
     jit: bool,
     output_type: back::link::output_type,
     addl_lib_search_paths: ~[Path],
     maybe_sysroot: Option<Path>,
     target_triple: ~str,
     // User-specified cfg meta items. The compiler itself will add additional
     // items to the crate config, and during parsing the entire crate config
     // will be added to the crate AST node.  This should not be used for
     // anything except building the full crate config prior to parsing.
     cfg: ast::crate_cfg,
     binary: ~str,
     test: bool,
     parse_only: bool,
     no_trans: bool,
     debugging_opts: uint,
    };

type crate_metadata = {name: ~str, data: ~[u8]};

type Session_ = {targ_cfg: @config,
                 opts: @options,
                 cstore: metadata::cstore::CStore,
                 parse_sess: parse_sess,
                 codemap: @codemap::CodeMap,
                 // For a library crate, this is always none
                 mut main_fn: Option<(node_id, codemap::span)>,
                 span_diagnostic: diagnostic::span_handler,
                 filesearch: filesearch::FileSearch,
                 mut building_library: bool,
                 working_dir: Path,
                 lint_settings: lint::lint_settings};

enum Session {
    Session_(@Session_)
}

impl Session {
    fn span_fatal(sp: span, msg: ~str) -> ! {
        self.span_diagnostic.span_fatal(sp, msg)
    }
    fn fatal(msg: ~str) -> ! {
        self.span_diagnostic.handler().fatal(msg)
    }
    fn span_err(sp: span, msg: ~str) {
        self.span_diagnostic.span_err(sp, msg)
    }
    fn err(msg: ~str) {
        self.span_diagnostic.handler().err(msg)
    }
    fn has_errors() -> bool {
        self.span_diagnostic.handler().has_errors()
    }
    fn abort_if_errors() {
        self.span_diagnostic.handler().abort_if_errors()
    }
    fn span_warn(sp: span, msg: ~str) {
        self.span_diagnostic.span_warn(sp, msg)
    }
    fn warn(msg: ~str) {
        self.span_diagnostic.handler().warn(msg)
    }
    fn span_note(sp: span, msg: ~str) {
        self.span_diagnostic.span_note(sp, msg)
    }
    fn note(msg: ~str) {
        self.span_diagnostic.handler().note(msg)
    }
    fn span_bug(sp: span, msg: ~str) -> ! {
        self.span_diagnostic.span_bug(sp, msg)
    }
    fn bug(msg: ~str) -> ! {
        self.span_diagnostic.handler().bug(msg)
    }
    fn span_unimpl(sp: span, msg: ~str) -> ! {
        self.span_diagnostic.span_unimpl(sp, msg)
    }
    fn unimpl(msg: ~str) -> ! {
        self.span_diagnostic.handler().unimpl(msg)
    }
    fn span_lint_level(level: lint::level,
                       sp: span, msg: ~str) {
        match level {
          lint::allow => { },
          lint::warn => self.span_warn(sp, msg),
          lint::deny | lint::forbid => {
            self.span_err(sp, msg);
          }
        }
    }
    fn span_lint(lint_mode: lint::lint,
                 expr_id: ast::node_id, item_id: ast::node_id,
                 span: span, msg: ~str) {
        let level = lint::get_lint_settings_level(
            self.lint_settings, lint_mode, expr_id, item_id);
        self.span_lint_level(level, span, msg);
    }
    fn next_node_id() -> ast::node_id {
        return syntax::parse::next_node_id(self.parse_sess);
    }
    fn diagnostic() -> diagnostic::span_handler {
        self.span_diagnostic
    }
    fn debugging_opt(opt: uint) -> bool {
        (self.opts.debugging_opts & opt) != 0u
    }
    // This exists to help with refactoring to eliminate impossible
    // cases later on
    fn impossible_case(sp: span, msg: &str) -> ! {
        self.span_bug(sp, fmt!("Impossible case reached: %s", msg));
    }
    fn verbose() -> bool { self.debugging_opt(verbose) }
    fn time_passes() -> bool { self.debugging_opt(time_passes) }
    fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) }
    fn count_type_sizes() -> bool { self.debugging_opt(count_type_sizes) }
    fn time_llvm_passes() -> bool { self.debugging_opt(time_llvm_passes) }
    fn trans_stats() -> bool { self.debugging_opt(trans_stats) }
    fn meta_stats() -> bool { self.debugging_opt(meta_stats) }
    fn no_asm_comments() -> bool { self.debugging_opt(no_asm_comments) }
    fn no_verify() -> bool { self.debugging_opt(no_verify) }
    fn trace() -> bool { self.debugging_opt(trace) }
    fn coherence() -> bool { self.debugging_opt(coherence) }
    fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
    fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) }
    fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) }
    fn no_monomorphic_collapse() -> bool {
        // FIXME #4127: Type use is causing mysterious bustage on 32-bit archs
        let type_use_unreliable = self.targ_cfg.arch == arch_x86;

        self.debugging_opt(no_monomorphic_collapse) || type_use_unreliable
    }

    fn str_of(id: ast::ident) -> ~str {
        *self.parse_sess.interner.get(id)
    }
    fn ident_of(st: ~str) -> ast::ident {
        self.parse_sess.interner.intern(@st)
    }
    fn intr() -> @syntax::parse::token::ident_interner {
        self.parse_sess.interner
    }
}

/// Some reasonable defaults
fn basic_options() -> @options {
    @{
        crate_type: session::lib_crate,
        static: false,
        gc: false,
        optimize: No,
        debuginfo: false,
        extra_debuginfo: false,
        lint_opts: ~[],
        save_temps: false,
        jit: false,
        output_type: link::output_type_exe,
        addl_lib_search_paths: ~[],
        maybe_sysroot: None,
        target_triple: driver::host_triple(),
        cfg: ~[],
        binary: ~"rustc",
        test: false,
        parse_only: false,
        no_trans: false,
        debugging_opts: 0u
    }
}

// Seems out of place, but it uses session, so I'm putting it here
fn expect<T: Copy>(sess: Session, opt: Option<T>, msg: fn() -> ~str) -> T {
    diagnostic::expect(sess.diagnostic(), opt, msg)
}

fn building_library(req_crate_type: crate_type, crate: @ast::crate,
                    testing: bool) -> bool {
    match req_crate_type {
      bin_crate => false,
      lib_crate => true,
      unknown_crate => {
        if testing {
            false
        } else {
            match syntax::attr::first_attr_value_str_by_name(
                crate.node.attrs,
                ~"crate_type") {
              option::Some(~"lib") => true,
              _ => false
            }
        }
      }
    }
}

fn sess_os_to_meta_os(os: os) -> metadata::loader::os {
    use metadata::loader;

    match os {
      os_win32 => loader::os_win32,
      os_linux => loader::os_linux,
      os_macos => loader::os_macos,
      os_freebsd => loader::os_freebsd
    }
}

#[cfg(test)]
mod test {
    #[legacy_exports];
    use syntax::ast_util;

    fn make_crate_type_attr(t: ~str) -> ast::attribute {
        ast_util::respan(ast_util::dummy_sp(), {
            style: ast::attr_outer,
            value: ast_util::respan(ast_util::dummy_sp(),
                ast::meta_name_value(
                    ~"crate_type",
                    ast_util::respan(ast_util::dummy_sp(),
                                     ast::lit_str(@t)))),
            is_sugared_doc: false
        })
    }

    fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate {
        let mut attrs = ~[];
        if with_bin { attrs += ~[make_crate_type_attr(~"bin")]; }
        if with_lib { attrs += ~[make_crate_type_attr(~"lib")]; }
        @ast_util::respan(ast_util::dummy_sp(), {
            module: {view_items: ~[], items: ~[]},
            attrs: attrs,
            config: ~[]
        })
    }

    #[test]
    fn bin_crate_type_attr_results_in_bin_output() {
        let crate = make_crate(true, false);
        assert !building_library(unknown_crate, crate, false);
    }

    #[test]
    fn lib_crate_type_attr_results_in_lib_output() {
        let crate = make_crate(false, true);
        assert building_library(unknown_crate, crate, false);
    }

    #[test]
    fn bin_option_overrides_lib_crate_type() {
        let crate = make_crate(false, true);
        assert !building_library(bin_crate, crate, false);
    }

    #[test]
    fn lib_option_overrides_bin_crate_type() {
        let crate = make_crate(true, false);
        assert building_library(lib_crate, crate, false);
    }

    #[test]
    fn bin_crate_type_is_default() {
        let crate = make_crate(false, false);
        assert !building_library(unknown_crate, crate, false);
    }

    #[test]
    fn test_option_overrides_lib_crate_type() {
        let crate = make_crate(false, true);
        assert !building_library(unknown_crate, crate, true);
    }

    #[test]
    fn test_option_does_not_override_requested_lib_type() {
        let crate = make_crate(false, false);
        assert building_library(lib_crate, crate, true);
    }
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


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

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<WindowPortsMethods>,
    servo: RefCell<Servo<WindowPortsMethods>>,
    browser: RefCell<Browser<WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    fn has_events(&self) -> bool {
        !self.event_queue.borrow().is_empty() || self.window.has_events()
    }

    fn winit_event_to_servo_event(&self, event: glutin::Event) {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    self.window.winit_event_to_servo_event(event);
                }
            },
        }
    }

    fn run_loop(self) {
        loop {
            if !self.window.is_animating()  || self.suspended.get() {
                // If there's no animations running then we block on the window event loop.
                self.events_loop.borrow_mut().run_forever(|e| {
                    self.winit_event_to_servo_event(e);
                    glutin::ControlFlow::Break
                });
            }
            // Grab any other events that may have happened
            self.events_loop.borrow_mut().poll_events(|e| {
                self.winit_event_to_servo_event(e);
            });
            // If animations are running, we block on compositing
            // (self.handle_events() ends up calling swap_buffers)
            let stop = self.handle_events();
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<commit_msg>Handle resize events during run_forever<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<WindowPortsMethods>,
    servo: RefCell<Servo<WindowPortsMethods>>,
    browser: RefCell<Browser<WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    fn has_events(&self) -> bool {
        !self.event_queue.borrow().is_empty() || self.window.has_events()
    }

    // This function decides whether the event should be handled during `run_forever`.
    fn winit_event_to_servo_event(&self, event: glutin::Event) -> glutin::ControlFlow {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    // Resize events need to be handled during run_forever
                    let cont = if let glutin::WindowEvent::Resized(_) = event {
                        glutin::ControlFlow::Continue
                    } else {
                        glutin::ControlFlow::Break
                    };
                    self.window.winit_event_to_servo_event(event);
                    return cont;
                }
            },
        }
        glutin::ControlFlow::Break
    }

    fn run_loop(self) {
        loop {
            if !self.window.is_animating()  || self.suspended.get() {
                // If there's no animations running then we block on the window event loop.
                self.events_loop.borrow_mut().run_forever(|e| {
                    let cont = self.winit_event_to_servo_event(e);
                    if cont == glutin::ControlFlow::Continue {
                        // Note we need to be careful to make sure that any events
                        // that are handled during run_forever aren't re-entrant,
                        // since we are handling them while holding onto a mutable borrow
                        // of the events loop
                        self.handle_events();
                    }
                    cont
                });
            }
            // Grab any other events that may have happened
            self.events_loop.borrow_mut().poll_events(|e| {
                self.winit_event_to_servo_event(e);
            });
            // If animations are running, we block on compositing
            // (self.handle_events() ends up calling swap_buffers)
            let stop = self.handle_events();
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>int module: macro-ify trait impls and add {u,i}128 support<commit_after><|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use serde_json;
use std::ffi::OsStr;
use std::io::{BufReader, ErrorKind as IoErrorKind, Read, Result as IoResult};
use std::process::{Child, Command, Stdio};
use super::{AudioSource, AudioType, DcaError, DcaMetadata, VoiceError};
use internal::prelude::*;

use std::fs::File;
use std::result::Result as StdResult;

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind.clone() }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => {
                if e.kind() == IoErrorKind::UnexpectedEof {
                    Some(Vec::new())
                } else {
                    None
                }
            },
        }
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<AudioSource>> {
    let path = path.as_ref();

    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    let args = [
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ];

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(&args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<AudioSource>, DcaError> {
    let file = File::open(path.as_ref()).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source.
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Opus,
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Pcm,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<AudioSource>> {
    let args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--print-json",
        "--skip-download",
        uri,
    ];

    let out = Command::new("youtube-dl")
        .args(&args)
        .stdin(Stdio::null())
        .output()?;

    if !out.status.success() {
        return Err(Error::Voice(VoiceError::YouTubeDLRun(out)));
    }

    let value = serde_json::from_reader(&out.stdout[..])?;
    let mut obj = match value {
        Value::Object(obj) => obj,
        other => return Err(Error::Voice(VoiceError::YouTubeDLProcessing(other))),
    };

    let uri = match obj.remove("url") {
        Some(v) => {
            match v {
                Value::String(uri) => uri,
                other => return Err(Error::Voice(VoiceError::YouTubeDLUrl(other))),
            }
        },
        None => return Err(Error::Voice(VoiceError::YouTubeDLUrl(Value::Object(obj)))),
    };

    ffmpeg(&uri)
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream.as_object().and_then(|m| {
            m.get("channels").and_then(|v| v.as_i64())
        });

        channels == Some(2)
    });

    Ok(check)
}
<commit_msg>Run clippy<commit_after>use byteorder::{LittleEndian, ReadBytesExt};
use serde_json;
use std::ffi::OsStr;
use std::io::{BufReader, ErrorKind as IoErrorKind, Read, Result as IoResult};
use std::process::{Child, Command, Stdio};
use super::{AudioSource, AudioType, DcaError, DcaMetadata, VoiceError};
use internal::prelude::*;

use std::fs::File;
use std::result::Result as StdResult;

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind.clone() }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => {
                if e.kind() == IoErrorKind::UnexpectedEof {
                    Some(Vec::new())
                } else {
                    None
                }
            },
        }
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<AudioSource>> {
    let path = path.as_ref();

    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    let args = [
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ];

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(&args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<AudioSource>, DcaError> {
    let file = File::open(path.as_ref()).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source.
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Opus,
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Pcm,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<AudioSource>> {
    let args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--print-json",
        "--skip-download",
        uri,
    ];

    let out = Command::new("youtube-dl")
        .args(&args)
        .stdin(Stdio::null())
        .output()?;

    if !out.status.success() {
        return Err(Error::Voice(VoiceError::YouTubeDLRun(out)));
    }

    let value = serde_json::from_reader(&out.stdout[..])?;
    let mut obj = match value {
        Value::Object(obj) => obj,
        other => return Err(Error::Voice(VoiceError::YouTubeDLProcessing(other))),
    };

    let uri = match obj.remove("url") {
        Some(v) => {
            match v {
                Value::String(uri) => uri,
                other => return Err(Error::Voice(VoiceError::YouTubeDLUrl(other))),
            }
        },
        None => return Err(Error::Voice(VoiceError::YouTubeDLUrl(Value::Object(obj)))),
    };

    ffmpeg(&uri)
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream.as_object().and_then(|m| {
            m.get("channels").and_then(|v| v.as_i64())
        });

        channels == Some(2)
    });

    Ok(check)
}
<|endoftext|>