<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::CString;
use std::io::{self, BufRead, BufReader, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::mpsc::sync_channel;
use std::sync::Once;
use std::thread;
use std::time::Duration;
use std::{env, process::Child};
use std::{fs::File, process::Stdio};

use anyhow::{anyhow, Result};
use base::syslog;
use tempfile::TempDir;

const PREBUILT_URL: &str = "https://storage.googleapis.com/chromeos-localmirror/distfiles";

#[cfg(target_arch = "x86_64")]
const ARCH: &str = "x86_64";
#[cfg(target_arch = "arm")]
const ARCH: &str = "arm";
#[cfg(target_arch = "aarch64")]
const ARCH: &str = "aarch64";

/// Timeout for communicating with the VM. If we do not hear back, panic so we
/// do not block the tests.
const VM_COMMUNICATION_TIMEOUT: Duration = Duration::from_secs(10);

fn prebuilt_version() -> &'static str {
    include_str!("../guest_under_test/PREBUILT_VERSION").trim()
}

fn kernel_prebuilt_url() -> String {
    format!(
        "{}/crosvm-testing-bzimage-{}-{}",
        PREBUILT_URL,
        ARCH,
        prebuilt_version()
    )
}

fn rootfs_prebuilt_url() -> String {
    format!(
        "{}/crosvm-testing-rootfs-{}-{}",
        PREBUILT_URL,
        ARCH,
        prebuilt_version()
    )
}

/// The kernel bzImage is stored next to the test executable, unless overridden by
/// CROSVM_CARGO_TEST_KERNEL_BINARY
fn kernel_path() -> PathBuf {
    match env::var("CROSVM_CARGO_TEST_KERNEL_BINARY") {
        Ok(value) => PathBuf::from(value),
        Err(_) => env::current_exe()
            .unwrap()
            .parent()
            .unwrap()
            .join("bzImage"),
    }
}

/// The rootfs image is stored next to the test executable, unless overridden by
/// CROSVM_CARGO_TEST_ROOTFS_IMAGE
fn rootfs_path() -> PathBuf {
    match env::var("CROSVM_CARGO_TEST_ROOTFS_IMAGE") {
        Ok(value) => PathBuf::from(value),
        Err(_) => env::current_exe().unwrap().parent().unwrap().join("rootfs"),
    }
}

/// The crosvm binary is expected to be alongside to the integration tests
/// binary. Alternatively in the parent directory (cargo will put the
/// test binary in target/debug/deps/ but the crosvm binary in target/debug).
fn find_crosvm_binary() -> PathBuf {
    let exe_dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
    let first = exe_dir.join("crosvm");
    if first.exists() {
        return first;
    }
    let second = exe_dir.parent().unwrap().join("crosvm");
    if second.exists() {
        return second;
    }
    panic!("Cannot find ./crosvm or ../crosvm alongside test binary.");
}

/// Safe wrapper for libc::mkfifo
fn mkfifo(path: &Path) -> io::Result<()> {
    let cpath = CString::new(path.to_str().unwrap()).unwrap();
    let result = unsafe { libc::mkfifo(cpath.as_ptr(), 0o777) };
    if result == 0 {
        Ok(())
    } else {
        Err(io::Error::last_os_error())
    }
}

/// Run the provided closure, but panic if it does not complete until the timeout has passed.
/// We should panic here, as we cannot gracefully stop the closure from running.
fn panic_on_timeout<F, U>(closure: F, timeout: Duration) -> U
where
    F: FnOnce() -> U + Send + 'static,
    U: Send + 'static,
{
    let (tx, rx) = sync_channel::<()>(1);
    let handle = thread::spawn(move || {
        let result = closure();
        tx.send(()).unwrap();
        result
    });
    rx.recv_timeout(timeout)
        .expect("Operation timed out or closure paniced.");
    handle.join().unwrap()
}

fn download_file(url: &str, destination: &Path) -> Result<()> {
    let status = Command::new("curl")
        .arg("--fail")
        .arg("--location")
        .args(&["--output", destination.to_str().unwrap()])
        .arg(url)
        .status();
    match status {
        Ok(exit_code) => {
            if !exit_code.success() {
                Err(anyhow!("Cannot download {}", url))
            } else {
                Ok(())
            }
        }
        Err(error) => Err(anyhow!(error)),
    }
}

fn crosvm_command(command: &str, args: &[&str]) -> Result<()> {
    println!("$ crosvm {} {:?}", command, &args.join(" "));
    let status = Command::new(find_crosvm_binary())
        .arg(command)
        .args(args)
        .status()?;

    if !status.success() {
        Err(anyhow!("Command failed with exit code {}", status))
    } else {
        Ok(())
    }
}

/// Test fixture to spin up a VM running a guest that can be communicated with.
///
/// After creation, commands can be sent via exec_in_guest. The VM is stopped
/// when this instance is dropped.
pub struct TestVm {
    /// Maintain ownership of test_dir until the vm is destroyed.
    #[allow(dead_code)]
    test_dir: TempDir,
    from_guest_reader: BufReader<File>,
    to_guest: File,
    control_socket_path: PathBuf,
    process: Child,
    debug: bool,
}

impl TestVm {
    /// Magic line sent by the delegate binary when the guest is ready.
    const MAGIC_LINE: &'static str = "\x05Ready";

    /// Downloads prebuilts if needed.
    fn initialize_once() {
        if let Err(e) = syslog::init() {
            panic!("failed to initiailize syslog: {}", e);
        }

        // It's possible the prebuilts downloaded by crosvm-9999.ebuild differ
        // from the version that crosvm was compiled for.
        if let Ok(value) = env::var("CROSVM_CARGO_TEST_PREBUILT_VERSION") {
            if value != prebuilt_version() {
                panic!(
                    "Environment provided prebuilts are version {}, but crosvm was compiled \
                    for prebuilt version {}. Did you update PREBUILT_VERSION everywhere?",
                    value,
                    prebuilt_version()
                );
            }
        }

        let kernel_path = kernel_path();
        if env::var("CROSVM_CARGO_TEST_KERNEL_BINARY").is_err() {
            if !kernel_path.exists() {
                println!("Downloading kernel prebuilt:");
                download_file(&kernel_prebuilt_url(), &kernel_path).unwrap();
            }
        }
        assert!(kernel_path.exists(), "{:?} does not exist", kernel_path);

        let rootfs_path = rootfs_path();
        if env::var("CROSVM_CARGO_TEST_ROOTFS_IMAGE").is_err() {
            if !rootfs_path.exists() {
                println!("Downloading rootfs prebuilt:");
                download_file(&rootfs_prebuilt_url(), &rootfs_path).unwrap();
            }
        }
        assert!(rootfs_path.exists(), "{:?} does not exist", rootfs_path);
    }

    // Adds 2 serial devices:
    // - ttyS0: Console device which prints kernel log / debug output of the
    //          delegate binary.
    // - ttyS1: Serial device attached to the named pipes.
    fn configure_serial_devices(
        command: &mut Command,
        from_guest_pipe: &Path,
        to_guest_pipe: &Path,
    ) {
        command.args(&["--serial", "type=syslog"]);

        // Setup channel for communication with the delegate.
        let serial_params = format!(
            "type=file,path={},input={},num=2",
            from_guest_pipe.display(),
            to_guest_pipe.display()
        );
        command.args(&["--serial", &serial_params]);
    }

    /// Configures the VM kernel and rootfs to load from the guest_under_test assets.
    fn configure_kernel(command: &mut Command, o_direct: bool) {
        let rootfs_and_option = format!(
            "{}{}",
            rootfs_path().to_str().unwrap(),
            if o_direct { ",o_direct=true" } else { "" }
        );
        command
            .args(&["--root", &rootfs_and_option])
            .args(&["--params", "init=/bin/delegate"])
            .arg(kernel_path());
    }

    /// Instanciate a new crosvm instance. The first call will trigger the download of prebuilt
    /// files if necessary.
    pub fn new(additional_arguments: &[&str], debug: bool, o_direct: bool) -> Result<TestVm> {
        static PREP_ONCE: Once = Once::new();
        PREP_ONCE.call_once(|| TestVm::initialize_once());

        // Create two named pipes to communicate with the guest.
        let test_dir = TempDir::new()?;
        let from_guest_pipe = test_dir.path().join("from_guest");
        let to_guest_pipe = test_dir.path().join("to_guest");
        mkfifo(&from_guest_pipe)?;
        mkfifo(&to_guest_pipe)?;

        let control_socket_path = test_dir.path().join("control");

        let mut command = Command::new(find_crosvm_binary());
        command.args(&["run", "--disable-sandbox"]);
        TestVm::configure_serial_devices(&mut command, &from_guest_pipe, &to_guest_pipe);
        command.args(&["--socket", &control_socket_path.to_str().unwrap()]);
        command.args(additional_arguments);

        TestVm::configure_kernel(&mut command, o_direct);

        println!("$ {:?}", command);
        if !debug {
            command.stdout(Stdio::null());
            command.stderr(Stdio::null());
        }
        let process = command.spawn()?;

        // Open pipes. Panic if we cannot connect after a timeout.
        let (to_guest, from_guest) = panic_on_timeout(
            move || (File::create(to_guest_pipe), File::open(from_guest_pipe)),
            VM_COMMUNICATION_TIMEOUT,
        );

        // Wait for magic line to be received, indicating the delegate is ready.
        let mut from_guest_reader = BufReader::new(from_guest?);
        let mut magic_line = String::new();
        from_guest_reader.read_line(&mut magic_line)?;
        assert_eq!(magic_line.trim(), TestVm::MAGIC_LINE);

        Ok(TestVm {
            test_dir,
            from_guest_reader,
            to_guest: to_guest?,
            control_socket_path,
            process,
            debug,
        })
    }

    /// Executes the shell command `command` and returns the programs stdout.
    pub fn exec_in_guest(&mut self, command: &str) -> Result<String> {
        // Write command to serial port.
        writeln!(&mut self.to_guest, "{}", command)?;

        // We will receive an echo of what we have written on the pipe.
        let mut echo = String::new();
        self.from_guest_reader.read_line(&mut echo)?;
        assert_eq!(echo.trim(), command);

        // Return all remaining lines until we receive the MAGIC_LINE
        let mut output = String::new();
        loop {
            let mut line = String::new();
            self.from_guest_reader.read_line(&mut line)?;
            if line.trim() == TestVm::MAGIC_LINE {
                break;
            }
            output.push_str(&line);
        }
        let trimmed = output.trim();
        if self.debug {
            println!("<- {:?}", trimmed);
        }
        Ok(trimmed.to_string())
    }

    pub fn stop(&self) -> Result<()> {
        crosvm_command("stop", &[self.control_socket_path.to_str().unwrap()])
    }

    pub fn suspend(&self) -> Result<()> {
        crosvm_command("suspend", &[self.control_socket_path.to_str().unwrap()])
    }

    pub fn resume(&self) -> Result<()> {
        crosvm_command("resume", &[self.control_socket_path.to_str().unwrap()])
    }
}

impl Drop for TestVm {
    fn drop(&mut self) {
        self.stop().unwrap();
        self.process.wait().unwrap();
    }
}
<commit_msg>integration_test: Do not throw away stdout/stderr.<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::CString;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::mpsc::sync_channel;
use std::sync::Once;
use std::thread;
use std::time::Duration;
use std::{env, process::Child};

use anyhow::{anyhow, Result};
use base::syslog;
use tempfile::TempDir;

const PREBUILT_URL: &str = "https://storage.googleapis.com/chromeos-localmirror/distfiles";

#[cfg(target_arch = "x86_64")]
const ARCH: &str = "x86_64";
#[cfg(target_arch = "arm")]
const ARCH: &str = "arm";
#[cfg(target_arch = "aarch64")]
const ARCH: &str = "aarch64";

/// Timeout for communicating with the VM. If we do not hear back, panic so we
/// do not block the tests.
const VM_COMMUNICATION_TIMEOUT: Duration = Duration::from_secs(10);

fn prebuilt_version() -> &'static str {
    include_str!("../guest_under_test/PREBUILT_VERSION").trim()
}

fn kernel_prebuilt_url() -> String {
    format!(
        "{}/crosvm-testing-bzimage-{}-{}",
        PREBUILT_URL,
        ARCH,
        prebuilt_version()
    )
}

fn rootfs_prebuilt_url() -> String {
    format!(
        "{}/crosvm-testing-rootfs-{}-{}",
        PREBUILT_URL,
        ARCH,
        prebuilt_version()
    )
}

/// The kernel bzImage is stored next to the test executable, unless overridden by
/// CROSVM_CARGO_TEST_KERNEL_BINARY
fn kernel_path() -> PathBuf {
    match env::var("CROSVM_CARGO_TEST_KERNEL_BINARY") {
        Ok(value) => PathBuf::from(value),
        Err(_) => env::current_exe()
            .unwrap()
            .parent()
            .unwrap()
            .join("bzImage"),
    }
}

/// The rootfs image is stored next to the test executable, unless overridden by
/// CROSVM_CARGO_TEST_ROOTFS_IMAGE
fn rootfs_path() -> PathBuf {
    match env::var("CROSVM_CARGO_TEST_ROOTFS_IMAGE") {
        Ok(value) => PathBuf::from(value),
        Err(_) => env::current_exe().unwrap().parent().unwrap().join("rootfs"),
    }
}

/// The crosvm binary is expected to be alongside to the integration tests
/// binary. Alternatively in the parent directory (cargo will put the
/// test binary in target/debug/deps/ but the crosvm binary in target/debug).
fn find_crosvm_binary() -> PathBuf {
    let exe_dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
    let first = exe_dir.join("crosvm");
    if first.exists() {
        return first;
    }
    let second = exe_dir.parent().unwrap().join("crosvm");
    if second.exists() {
        return second;
    }
    panic!("Cannot find ./crosvm or ../crosvm alongside test binary.");
}

/// Safe wrapper for libc::mkfifo
fn mkfifo(path: &Path) -> io::Result<()> {
    let cpath = CString::new(path.to_str().unwrap()).unwrap();
    let result = unsafe { libc::mkfifo(cpath.as_ptr(), 0o777) };
    if result == 0 {
        Ok(())
    } else {
        Err(io::Error::last_os_error())
    }
}

/// Run the provided closure, but panic if it does not complete until the timeout has passed.
/// We should panic here, as we cannot gracefully stop the closure from running.
fn panic_on_timeout<F, U>(closure: F, timeout: Duration) -> U
where
    F: FnOnce() -> U + Send + 'static,
    U: Send + 'static,
{
    let (tx, rx) = sync_channel::<()>(1);
    let handle = thread::spawn(move || {
        let result = closure();
        tx.send(()).unwrap();
        result
    });
    rx.recv_timeout(timeout)
        .expect("Operation timed out or closure paniced.");
    handle.join().unwrap()
}

fn download_file(url: &str, destination: &Path) -> Result<()> {
    let status = Command::new("curl")
        .arg("--fail")
        .arg("--location")
        .args(&["--output", destination.to_str().unwrap()])
        .arg(url)
        .status();
    match status {
        Ok(exit_code) => {
            if !exit_code.success() {
                Err(anyhow!("Cannot download {}", url))
            } else {
                Ok(())
            }
        }
        Err(error) => Err(anyhow!(error)),
    }
}

fn crosvm_command(command: &str, args: &[&str]) -> Result<()> {
    println!("$ crosvm {} {:?}", command, &args.join(" "));
    let status = Command::new(find_crosvm_binary())
        .arg(command)
        .args(args)
        .status()?;

    if !status.success() {
        Err(anyhow!("Command failed with exit code {}", status))
    } else {
        Ok(())
    }
}

/// Test fixture to spin up a VM running a guest that can be communicated with.
///
/// After creation, commands can be sent via exec_in_guest. The VM is stopped
/// when this instance is dropped.
pub struct TestVm {
    /// Maintain ownership of test_dir until the vm is destroyed.
    #[allow(dead_code)]
    test_dir: TempDir,
    from_guest_reader: BufReader<File>,
    to_guest: File,
    control_socket_path: PathBuf,
    process: Child,
    debug: bool,
}

impl TestVm {
    /// Magic line sent by the delegate binary when the guest is ready.
    const MAGIC_LINE: &'static str = "\x05Ready";

    /// Downloads prebuilts if needed.
    fn initialize_once() {
        if let Err(e) = syslog::init() {
            panic!("failed to initiailize syslog: {}", e);
        }

        // It's possible the prebuilts downloaded by crosvm-9999.ebuild differ
        // from the version that crosvm was compiled for.
        if let Ok(value) = env::var("CROSVM_CARGO_TEST_PREBUILT_VERSION") {
            if value != prebuilt_version() {
                panic!(
                    "Environment provided prebuilts are version {}, but crosvm was compiled \
                    for prebuilt version {}. Did you update PREBUILT_VERSION everywhere?",
                    value,
                    prebuilt_version()
                );
            }
        }

        let kernel_path = kernel_path();
        if env::var("CROSVM_CARGO_TEST_KERNEL_BINARY").is_err() {
            if !kernel_path.exists() {
                println!("Downloading kernel prebuilt:");
                download_file(&kernel_prebuilt_url(), &kernel_path).unwrap();
            }
        }
        assert!(kernel_path.exists(), "{:?} does not exist", kernel_path);

        let rootfs_path = rootfs_path();
        if env::var("CROSVM_CARGO_TEST_ROOTFS_IMAGE").is_err() {
            if !rootfs_path.exists() {
                println!("Downloading rootfs prebuilt:");
                download_file(&rootfs_prebuilt_url(), &rootfs_path).unwrap();
            }
        }
        assert!(rootfs_path.exists(), "{:?} does not exist", rootfs_path);
    }

    // Adds 2 serial devices:
    // - ttyS0: Console device which prints kernel log / debug output of the
    //          delegate binary.
    // - ttyS1: Serial device attached to the named pipes.
    fn configure_serial_devices(
        command: &mut Command,
        from_guest_pipe: &Path,
        to_guest_pipe: &Path,
    ) {
        command.args(&["--serial", "type=syslog"]);

        // Setup channel for communication with the delegate.
        let serial_params = format!(
            "type=file,path={},input={},num=2",
            from_guest_pipe.display(),
            to_guest_pipe.display()
        );
        command.args(&["--serial", &serial_params]);
    }

    /// Configures the VM kernel and rootfs to load from the guest_under_test assets.
    fn configure_kernel(command: &mut Command, o_direct: bool) {
        let rootfs_and_option = format!(
            "{}{}",
            rootfs_path().to_str().unwrap(),
            if o_direct { ",o_direct=true" } else { "" }
        );
        command
            .args(&["--root", &rootfs_and_option])
            .args(&["--params", "init=/bin/delegate"])
            .arg(kernel_path());
    }

    /// Instanciate a new crosvm instance. The first call will trigger the download of prebuilt
    /// files if necessary.
    pub fn new(additional_arguments: &[&str], debug: bool, o_direct: bool) -> Result<TestVm> {
        static PREP_ONCE: Once = Once::new();
        PREP_ONCE.call_once(|| TestVm::initialize_once());

        // Create two named pipes to communicate with the guest.
        let test_dir = TempDir::new()?;
        let from_guest_pipe = test_dir.path().join("from_guest");
        let to_guest_pipe = test_dir.path().join("to_guest");
        mkfifo(&from_guest_pipe)?;
        mkfifo(&to_guest_pipe)?;

        let control_socket_path = test_dir.path().join("control");

        let mut command = Command::new(find_crosvm_binary());
        command.args(&["run", "--disable-sandbox"]);
        TestVm::configure_serial_devices(&mut command, &from_guest_pipe, &to_guest_pipe);
        command.args(&["--socket", &control_socket_path.to_str().unwrap()]);
        command.args(additional_arguments);

        TestVm::configure_kernel(&mut command, o_direct);

        println!("$ {:?}", command);

        let process = command.spawn()?;

        // Open pipes. Panic if we cannot connect after a timeout.
        let (to_guest, from_guest) = panic_on_timeout(
            move || (File::create(to_guest_pipe), File::open(from_guest_pipe)),
            VM_COMMUNICATION_TIMEOUT,
        );

        // Wait for magic line to be received, indicating the delegate is ready.
        let mut from_guest_reader = BufReader::new(from_guest?);
        let mut magic_line = String::new();
        from_guest_reader.read_line(&mut magic_line)?;
        assert_eq!(magic_line.trim(), TestVm::MAGIC_LINE);

        Ok(TestVm {
            test_dir,
            from_guest_reader,
            to_guest: to_guest?,
            control_socket_path,
            process,
            debug,
        })
    }

    /// Executes the shell command `command` and returns the programs stdout.
    pub fn exec_in_guest(&mut self, command: &str) -> Result<String> {
        // Write command to serial port.
        writeln!(&mut self.to_guest, "{}", command)?;

        // We will receive an echo of what we have written on the pipe.
        let mut echo = String::new();
        self.from_guest_reader.read_line(&mut echo)?;
        assert_eq!(echo.trim(), command);

        // Return all remaining lines until we receive the MAGIC_LINE
        let mut output = String::new();
        loop {
            let mut line = String::new();
            self.from_guest_reader.read_line(&mut line)?;
            if line.trim() == TestVm::MAGIC_LINE {
                break;
            }
            output.push_str(&line);
        }
        let trimmed = output.trim();
        if self.debug {
            println!("<- {:?}", trimmed);
        }
        Ok(trimmed.to_string())
    }

    pub fn stop(&self) -> Result<()> {
        crosvm_command("stop", &[self.control_socket_path.to_str().unwrap()])
    }

    pub fn suspend(&self) -> Result<()> {
        crosvm_command("suspend", &[self.control_socket_path.to_str().unwrap()])
    }

    pub fn resume(&self) -> Result<()> {
        crosvm_command("resume", &[self.control_socket_path.to_str().unwrap()])
    }
}

impl Drop for TestVm {
    fn drop(&mut self) {
        self.stop().unwrap();
        self.process.wait().unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    compiletest::run_tests(&config);
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for target in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let target = target.unwrap().file_name().into_string().unwrap();
        if !target.contains("-") { continue; }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    run_pass();
    for_all_targets(&sysroot, |target| {
        miri_pass("tests/run-pass", &target);
        if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            miri_pass(&path, &target);
        }
    });
    compile_fail(&sysroot);
}
<commit_msg>Improve compiletest target detection.<commit_after>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    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 for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for entry in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    run_pass();
    for_all_targets(&sysroot, |target| {
        miri_pass("tests/run-pass", &target);
        if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            miri_pass(&path, &target);
        }
    });
    compile_fail(&sysroot);
}
<|endoftext|>


<commit_before>extern crate ldap3;
extern crate native_tls;
extern crate env_logger;

use std::error::Error;

use ldap3::{LdapConn, LdapConnSettings, Scope, SearchEntry};
use native_tls::TlsConnector;

fn main() {
    drop(env_logger::init());
    match do_tls_conn() {
        Ok(_) => (),
        Err(e) => println!("{:?}", e),
    }
}

#[cfg(all(unix, not(target_os = "macos")))]
fn custom_connector() -> Result<TlsConnector, Box<Error>> {
    let mut builder = TlsConnector::builder();
    builder.danger_accept_invalid_certs(true);
    Ok(builder.build()?)
}

#[cfg(any(not(unix), target_os = "macos"))]
fn custom_connector() -> Result<TlsConnector, Box<Error>> {
    Ok(TlsConnector::builder()?.build()?)
}

fn do_tls_conn() -> Result<(), Box<Error>> {
    let settings = LdapConnSettings::new()
        .set_no_tls_verify(true)
        .set_connector(custom_connector()?);
    let ldap = LdapConn::with_settings(settings, "ldaps://127.0.0.1")?;
    let (rs, _) = ldap.search(
        "",
        Scope::Base,
        "objectClass=*",
        vec!["+"]
    )?.success()?;
    for entry in rs {
        println!("{:?}", SearchEntry::construct(entry));
    }
    Ok(())
}
<commit_msg>Simplify connect_tls_ipaddr example<commit_after>extern crate ldap3;
extern crate native_tls;
extern crate env_logger;

use std::error::Error;

use ldap3::{LdapConn, LdapConnSettings, Scope, SearchEntry};
use native_tls::TlsConnector;

fn main() {
    drop(env_logger::init());
    match do_tls_conn() {
        Ok(_) => (),
        Err(e) => println!("{:?}", e),
    }
}

fn custom_connector() -> Result<TlsConnector, Box<Error>> {
    let mut builder = TlsConnector::builder();
    builder.danger_accept_invalid_certs(true);
    Ok(builder.build()?)
}

fn do_tls_conn() -> Result<(), Box<Error>> {
    let settings = LdapConnSettings::new()
        .set_no_tls_verify(true)
        .set_connector(custom_connector()?);
    let ldap = LdapConn::with_settings(settings, "ldaps://127.0.0.1")?;
    let (rs, _) = ldap.search(
        "",
        Scope::Base,
        "objectClass=*",
        vec!["+"]
    )?.success()?;
    for entry in rs {
        println!("{:?}", SearchEntry::construct(entry));
    }
    Ok(())
}
<|endoftext|>


<commit_before>use reqwest;
use std::error::Error as StdError;
use std::io;
use std::string::FromUtf8Error;
use toml::de::Error as TomlDeserializeError;

/// The error type for the program's every operations, such as TOML Parsing
/// or IO-related errors. Wherever there's an error, it _should_ be wrapped
/// into this type.
pub enum PackageError {
    Download(String),
    Parsing(String),
    Utf8(String),
    IO(String),
}

impl From<io::Error> for PackageError {
    /// Converts an `io::Error` into this type.
    fn from(err: io::Error) -> Self {
        PackageError::IO(String::from("An IO error occured:") + err.description())
    }
}

impl From<TomlDeserializeError> for PackageError {
    /// Converts a `toml::de:Error` into this type.
    fn from(err: TomlDeserializeError) -> Self {
        let err_location =
            err
                // Get the position of the error
                .line_col()
                // If it's not available, return a empty string.
                // If it is, then convert the position into a string.
                .map_or(String::from(""), |(line, col)| {
                    format!("in Line: {}, Col: {}",
                        line,
                        col
                    )
                });

        let err_description = err.description();

        PackageError::Parsing(
            format!(
                "An error occured while parsing a TOML, {} due to: {}.",
                err_location,
                err_description
            )
        )
    }
}

impl From<reqwest::Error> for PackageError {
    fn from(err: reqwest::Error) -> PackageError {
        let related_url =
            err
                // Try to retrieve the final stop if an error occured.
                .url()
                // If there's none, return "none"
                .map_or("none", |url| {
                    url.as_str()
                });

        let status_code =
            &err
                // Try to retrieve the status code if the error was generated
                // from an response.
                .status()
                // If there's none, return "none"
                .map_or(String::from("none"), |code| {
                    code.as_u16().to_string()
                });

        PackageError::Download(
            String::new() +
            "related url:           " + related_url +
            "http related:          " + &err.is_http().to_string() +
            "serialization related: " + &err.is_serialization().to_string() +
            "redirect related:      " + &err.is_redirect().to_string() +
            "client related:        " + &err.is_client_error().to_string() +
            "server related:        " + &err.is_server_error().to_string() +
            "status code:           " + status_code +
            "other messages:        " + err.description()
        )
    }
}

impl From<FromUtf8Error> for PackageError {
    fn from(err: FromUtf8Error) -> Self {
        let utf8_error = err.utf8_error();
        let errored_bytes =
            err
            // Gets the invalid bytes of the string
            .as_bytes()
            // Convert the bytes into an iterator.
            .iter()
            // Reduce the array of bytes into a string.
            .fold(String::from("invalid bytes: "), |acc, cur| {
                acc + ", " + &cur.to_string()
            });

        PackageError::Utf8(
            String::new() +
            "description:           " + err.description() +
            "further description:   " + utf8_error.description() +
            "bytes are valid up to: " + &utf8_error.valid_up_to().to_string() +
            /* invalid bytes:      */   &errored_bytes
        )
    }
}<commit_msg>Improve error formatting<commit_after>use reqwest;
use std::error::Error as StdError;
use std::io;
use std::string::FromUtf8Error;
use toml::de::Error as TomlDeserializeError;

/// The error type for the program's every operations, such as TOML Parsing
/// or IO-related errors. Wherever there's an error, it _should_ be wrapped
/// into this type.
pub enum PackageError {
    Download(String),
    Parsing(String),
    Utf8(String),
    IO(String),
}

impl From<io::Error> for PackageError {
    /// Converts an `io::Error` into this type.
    fn from(err: io::Error) -> Self {
        PackageError::IO(String::from("An IO error occured:") + err.description())
    }
}

impl From<TomlDeserializeError> for PackageError {
    /// Converts a `toml::de:Error` into this type.
    fn from(err: TomlDeserializeError) -> Self {
        let err_location =
            err
                // Get the position of the error
                .line_col()
                // If it's not available, return a empty string.
                // If it is, then convert the position into a string.
                .map_or(String::from(""), |(line, col)| {
                    format!("in Line: {}, Col: {}",
                        line,
                        col
                    )
                });

        let err_description = err.description();

        PackageError::Parsing(
            format!(
                "An error occured while parsing a TOML, {} due to: {}.",
                err_location,
                err_description
            )
        )
    }
}

impl From<reqwest::Error> for PackageError {
    fn from(err: reqwest::Error) -> PackageError {
        let related_url =
            err
                // Try to retrieve the final stop if an error occured.
                .url()
                // If there's none, return "none"
                .map_or("none", |url| {
                    url.as_str()
                });

        let status_code =
            &err
                // Try to retrieve the status code if the error was generated
                // from an response.
                .status()
                // If there's none, return "none"
                .map_or(String::from("none"), |code| {
                    code.as_u16().to_string()
                });

        PackageError::Download(
            String::new() +
            "related url:           " + related_url +
            "http related:          " + &err.is_http().to_string() +
            "serialization related: " + &err.is_serialization().to_string() +
            "redirect related:      " + &err.is_redirect().to_string() +
            "client related:        " + &err.is_client_error().to_string() +
            "server related:        " + &err.is_server_error().to_string() +
            "status code:           " + status_code +
            "other messages:        " + err.description()
        )
    }
}

impl From<FromUtf8Error> for PackageError {
    fn from(err: FromUtf8Error) -> Self {
        let utf8_error = err.utf8_error();
        let errored_bytes =
            err
            // Gets the invalid bytes of the string
            .as_bytes()
            // Convert the bytes into an iterator.
            .iter()
            // Reduce the array of bytes into a string.
            // Example output: `152, 84, 156, 78`
            .fold(String::from(""), |acc, cur| {
                acc + ", " + &cur.to_string()
            });

        PackageError::Utf8(
            String::new() +
            "description:         " + err.description() +
            "further description: " + utf8_error.description() +
            "bytes valid up to:   " + &utf8_error.valid_up_to().to_string() +
            "invalid bytes:       " + &errored_bytes
        )
    }
}<|endoftext|>


<commit_before>//! jsonrpc errors
use serde::{Serialize, Serializer};
use super::Value;

#[derive(Debug, PartialEq)]
pub enum ErrorCode {
	/// Invalid JSON was received by the server.
	/// An error occurred on the server while parsing the JSON text.
	ParseError,
	/// The JSON sent is not a valid Request object.
	InvalidRequest,
	/// The method does not exist / is not available.
	MethodNotFound,
	/// Invalid method parameter(s).
	InvalidParams,
	/// Internal JSON-RPC error.
	InternalError,
	/// Reserved for implementation-defined server-errors.
	ServerError(i64)
}

impl ErrorCode {
	pub fn code(&self) -> i64 {
		match *self {
			ErrorCode::ParseError => -32700,
			ErrorCode::InvalidRequest => -32600,
			ErrorCode::MethodNotFound => -32601,
			ErrorCode::InvalidParams => -32602,
			ErrorCode::InternalError => -32603,
			ErrorCode::ServerError(code) => code
		}
	}

	pub fn description(&self) -> String {
		let desc = match *self {
			ErrorCode::ParseError => "Parse error.",
			ErrorCode::InvalidRequest => "Invalid request.",
			ErrorCode::MethodNotFound => "Method not found.",
			ErrorCode::InvalidParams => "Invalid params.",
			ErrorCode::InternalError => "Internal error.",
			ErrorCode::ServerError(_) => "Server error.",
		};
		desc.to_string()
	}
}

impl Serialize for ErrorCode {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		serializer.serialize_i64(self.code())
	}
}

#[derive(Debug, PartialEq, Serialize)]
pub struct Error {
	pub code: ErrorCode,
	pub message: String,
	pub data: Option<Value>
}

impl Error {
	pub fn new(code: ErrorCode) -> Self {
		Error {
			message: code.description(),
			code: code,
			data: None
		}
	}

	pub fn parse_error() -> Self {
		Self::new(ErrorCode::ParseError)
	}

	pub fn invalid_request() -> Self {
		Self::new(ErrorCode::InvalidRequest)
	}

	pub fn method_not_found() -> Self {
		Self::new(ErrorCode::MethodNotFound)
	}

	pub fn invalid_params() -> Self {
		Self::new(ErrorCode::InvalidParams)
	}

	pub fn internal_error() -> Self {
		Self::new(ErrorCode::InternalError)
	}
}
<commit_msg>Impl Deserialize for ErrorCode and Error<commit_after>//! jsonrpc errors
use serde::de::{Deserialize, Deserializer, SeqVisitor, MapVisitor, Error as DeError};
use serde::ser::{Serialize, Serializer};
use serde_json::value;
use super::Value;

#[derive(Debug, PartialEq)]
pub enum ErrorCode {
	/// Invalid JSON was received by the server.
	/// An error occurred on the server while parsing the JSON text.
	ParseError,
	/// The JSON sent is not a valid Request object.
	InvalidRequest,
	/// The method does not exist / is not available.
	MethodNotFound,
	/// Invalid method parameter(s).
	InvalidParams,
	/// Internal JSON-RPC error.
	InternalError,
	/// Reserved for implementation-defined server-errors.
	ServerError(i64)
}

impl ErrorCode {
	pub fn code(&self) -> i64 {
		match *self {
			ErrorCode::ParseError => -32700,
			ErrorCode::InvalidRequest => -32600,
			ErrorCode::MethodNotFound => -32601,
			ErrorCode::InvalidParams => -32602,
			ErrorCode::InternalError => -32603,
			ErrorCode::ServerError(code) => code
		}
	}

	pub fn description(&self) -> String {
		let desc = match *self {
			ErrorCode::ParseError => "Parse error.",
			ErrorCode::InvalidRequest => "Invalid request.",
			ErrorCode::MethodNotFound => "Method not found.",
			ErrorCode::InvalidParams => "Invalid params.",
			ErrorCode::InternalError => "Internal error.",
			ErrorCode::ServerError(_) => "Server error.",
		};
		desc.to_string()
	}
}

impl Deserialize for ErrorCode {
	fn deserialize<D>(deserializer: &mut D) -> Result<ErrorCode, D::Error>
	where D: Deserializer {
		let v = try!(Value::deserialize(deserializer));
		match v.as_i64() {
			Some(-32700) => Ok(ErrorCode::ParseError),
			Some(-32600) => Ok(ErrorCode::InvalidRequest),
			Some(-32601) => Ok(ErrorCode::MethodNotFound),
			Some(-32602) => Ok(ErrorCode::InvalidParams),
			Some(-32603) => Ok(ErrorCode::InternalError),
			Some(code) => Ok(ErrorCode::ServerError(code)),
			_ => unreachable!()
		}

	}
}

impl Serialize for ErrorCode {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		serializer.serialize_i64(self.code())
	}
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Error {
	pub code: ErrorCode,
	pub message: String,
	pub data: Option<Value>
}

impl Error {
	pub fn new(code: ErrorCode) -> Self {
		Error {
			message: code.description(),
			code: code,
			data: None
		}
	}

	pub fn parse_error() -> Self {
		Self::new(ErrorCode::ParseError)
	}

	pub fn invalid_request() -> Self {
		Self::new(ErrorCode::InvalidRequest)
	}

	pub fn method_not_found() -> Self {
		Self::new(ErrorCode::MethodNotFound)
	}

	pub fn invalid_params() -> Self {
		Self::new(ErrorCode::InvalidParams)
	}

	pub fn internal_error() -> Self {
		Self::new(ErrorCode::InternalError)
	}
}
<|endoftext|>


<commit_before>//! Error types and conversions.

use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt::Error as FmtError;
use std::io::Error as IoError;
use std::string::FromUtf8Error;

use base64::Base64Error;
use diesel::result::{TransactionError, Error as DieselError};
use iron::{IronError, Response};
use iron::modifier::Modifier;
use iron::status::Status;
use persistent::PersistentError;
use r2d2::GetTimeout;
use serde::ser::{Serialize, Serializer};
use serde_json;

/// A client-facing error.
#[derive(Clone, Debug, Serialize)]
pub struct APIError {
    errcode: APIErrorCode,
    error: String,
}

impl APIError {
    /// Create an error for invalid or incomplete JSON in request bodies.
    pub fn bad_json() -> APIError {
        APIError {
            errcode: APIErrorCode::BadJson,
            error: "Invalid or missing key-value pairs in JSON.".to_string(),
        }
    }

    /// Create an error for endpoints where guest accounts are not supported.
    pub fn guest_forbidden() -> APIError {
        APIError {
            errcode: APIErrorCode::GuestAccessForbidden,
            error: "Guest accounts are forbidden.".to_string(),
        }
    }

    /// Create an error for requests without JSON bodies.
    pub fn not_json() -> APIError {
        APIError {
            errcode: APIErrorCode::NotJson,
            error: "No JSON found in request body.".to_string(),
        }
    }

    /// Create an error for requests that are not marked as containing JSON.
    pub fn wrong_content_type() -> APIError {
        APIError {
            errcode: APIErrorCode::NotJson,
            error: "Request's Content-Type header must be application/json.".to_string(),
        }
    }

    /// Create an error for requests that did not provide required authentication parameters.
    pub fn unauthorized() -> APIError {
        APIError {
            errcode: APIErrorCode::Forbidden,
            error: "Authentication is required.".to_string(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    pub fn unknown<E>(error: &E) -> APIError where E: Error {
        debug!("APIError::unknown: {:?}", error);

        APIError {
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_string(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    ///
    /// Like `unknown`, but uses a `String` instead of an `Error` to create the value.
    pub fn unknown_from_string(message: String) -> APIError {
        debug!("APIError::unknown_from_string: {}", message);

        APIError {
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_string(),
        }
    }
}

impl Display for APIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl Error for APIError {
    fn description(&self) -> &str {
        &self.error
    }
}

impl From<IoError> for APIError {
    fn from(error: IoError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<Base64Error> for APIError {
    fn from(error: Base64Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<DieselError> for APIError {
    fn from(error: DieselError) -> APIError {
        APIError::unknown(&error)
    }
}

impl<T> From<TransactionError<T>> for APIError where T: Error {
    fn from(error: TransactionError<T>) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<PersistentError> for APIError {
    fn from(error: PersistentError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<GetTimeout> for APIError {
    fn from(error: GetTimeout) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<FromUtf8Error> for APIError {
    fn from(error: FromUtf8Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<APIError> for IronError {
    fn from(error: APIError) -> IronError {
        IronError::new(error.clone(), error)
    }
}

impl Modifier<Response> for APIError {
    fn modify(self, response: &mut Response) {
        response.status = Some(self.errcode.status_code());
        response.body = Some(Box::new(serde_json::to_string(&self).expect("APIError should always serialize")));
    }
}

/// The error code for a client-facing error.
#[derive(Clone, Debug)]
pub enum APIErrorCode {
    /// The request contained valid JSON, but it was malformed in some way,
    /// e.g. missing required keys, invalid values for keys.
    BadJson,
    /// Forbidden access, e.g. joining a room without permission, failed login.
    Forbidden,
    /// Guests are not allowed to perform the requested operation.
    GuestAccessForbidden,
    /// Too many requests have been sent in a short period of time. Wait a while then try again.
    LimitExceeded,
    /// No resource was found for this request.
    NotFound,
    /// Request did not contain valid JSON.
    NotJson,
    /// Errors not fitting into another category.
    Unknown,
    /// The access token specified was not recognised.
    UnknownToken,
}

impl APIErrorCode {
    /// The HTTP status code that should be used to represent the `APIErrorCode`.
    pub fn status_code(&self) -> Status {
        match *self {
            APIErrorCode::BadJson => Status::UnprocessableEntity,
            APIErrorCode::Forbidden => Status::Forbidden,
            APIErrorCode::GuestAccessForbidden => Status::Forbidden,
            APIErrorCode::LimitExceeded => Status::TooManyRequests,
            APIErrorCode::NotFound => Status::NotFound,
            APIErrorCode::NotJson => Status::BadRequest,
            APIErrorCode::Unknown => Status::InternalServerError,
            APIErrorCode::UnknownToken => Status::Unauthorized,
        }
    }
}

impl Serialize for APIErrorCode {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
        let value = match *self {
            APIErrorCode::BadJson => "M_BAD_JSON",
            APIErrorCode::Forbidden => "M_FORBIDDEN",
            APIErrorCode::GuestAccessForbidden => "M_GUEST_ACCESS_FORBIDDEN",
            APIErrorCode::LimitExceeded => "M_LIMIT_EXCEEDED",
            APIErrorCode::NotFound => "M_NOT_FOUND",
            APIErrorCode::NotJson => "M_NOT_JSON",
            APIErrorCode::Unknown => "M_UNKNOWN",
            APIErrorCode::UnknownToken => "M_UNKNOWN_TOKEN",
        };

        serializer.serialize_str(value)
    }
}

/// An operator-facing error.
pub struct CLIError {
    error: String,
}

impl CLIError {
    /// Create a new `CLIError` from any `Error` type.
    pub fn new<E>(error: E) -> CLIError where E: Into<String> {
        CLIError {
            error: error.into(),
        }
    }
}

impl<E> From<E> for CLIError where E: Error {
    fn from(error: E) -> CLIError {
        CLIError::new(error.description())
    }
}

impl Display for CLIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}
<commit_msg>Add constructor for M_NOT_FOUND API error<commit_after>//! Error types and conversions.

use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt::Error as FmtError;
use std::io::Error as IoError;
use std::string::FromUtf8Error;

use base64::Base64Error;
use diesel::result::{TransactionError, Error as DieselError};
use iron::{IronError, Response};
use iron::modifier::Modifier;
use iron::status::Status;
use persistent::PersistentError;
use r2d2::GetTimeout;
use serde::ser::{Serialize, Serializer};
use serde_json;

/// A client-facing error.
#[derive(Clone, Debug, Serialize)]
pub struct APIError {
    errcode: APIErrorCode,
    error: String,
}

impl APIError {
    /// Create an error for invalid or incomplete JSON in request bodies.
    pub fn bad_json() -> APIError {
        APIError {
            errcode: APIErrorCode::BadJson,
            error: "Invalid or missing key-value pairs in JSON.".to_string(),
        }
    }

    /// Create an error for endpoints where guest accounts are not supported.
    pub fn guest_forbidden() -> APIError {
        APIError {
            errcode: APIErrorCode::GuestAccessForbidden,
            error: "Guest accounts are forbidden.".to_string(),
        }
    }

    /// Create an error for requests that do not map to a resource.
    pub fn not_found() -> APIError {
        APIError {
            errcode: APIErrorCode::NotFound,
            error: "No resource was found for this request.".to_string(),
        }
    }

    /// Create an error for requests without JSON bodies.
    pub fn not_json() -> APIError {
        APIError {
            errcode: APIErrorCode::NotJson,
            error: "No JSON found in request body.".to_string(),
        }
    }

    /// Create an error for requests that are not marked as containing JSON.
    pub fn wrong_content_type() -> APIError {
        APIError {
            errcode: APIErrorCode::NotJson,
            error: "Request's Content-Type header must be application/json.".to_string(),
        }
    }

    /// Create an error for requests that did not provide required authentication parameters.
    pub fn unauthorized() -> APIError {
        APIError {
            errcode: APIErrorCode::Forbidden,
            error: "Authentication is required.".to_string(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    pub fn unknown<E>(error: &E) -> APIError where E: Error {
        debug!("APIError::unknown: {:?}", error);

        APIError {
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_string(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    ///
    /// Like `unknown`, but uses a `String` instead of an `Error` to create the value.
    pub fn unknown_from_string(message: String) -> APIError {
        debug!("APIError::unknown_from_string: {}", message);

        APIError {
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_string(),
        }
    }
}

impl Display for APIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl Error for APIError {
    fn description(&self) -> &str {
        &self.error
    }
}

impl From<IoError> for APIError {
    fn from(error: IoError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<Base64Error> for APIError {
    fn from(error: Base64Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<DieselError> for APIError {
    fn from(error: DieselError) -> APIError {
        APIError::unknown(&error)
    }
}

impl<T> From<TransactionError<T>> for APIError where T: Error {
    fn from(error: TransactionError<T>) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<PersistentError> for APIError {
    fn from(error: PersistentError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<GetTimeout> for APIError {
    fn from(error: GetTimeout) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<FromUtf8Error> for APIError {
    fn from(error: FromUtf8Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<APIError> for IronError {
    fn from(error: APIError) -> IronError {
        IronError::new(error.clone(), error)
    }
}

impl Modifier<Response> for APIError {
    fn modify(self, response: &mut Response) {
        response.status = Some(self.errcode.status_code());
        response.body = Some(Box::new(serde_json::to_string(&self).expect("APIError should always serialize")));
    }
}

/// The error code for a client-facing error.
#[derive(Clone, Debug)]
pub enum APIErrorCode {
    /// The request contained valid JSON, but it was malformed in some way,
    /// e.g. missing required keys, invalid values for keys.
    BadJson,
    /// Forbidden access, e.g. joining a room without permission, failed login.
    Forbidden,
    /// Guests are not allowed to perform the requested operation.
    GuestAccessForbidden,
    /// Too many requests have been sent in a short period of time. Wait a while then try again.
    LimitExceeded,
    /// No resource was found for this request.
    NotFound,
    /// Request did not contain valid JSON.
    NotJson,
    /// Errors not fitting into another category.
    Unknown,
    /// The access token specified was not recognised.
    UnknownToken,
}

impl APIErrorCode {
    /// The HTTP status code that should be used to represent the `APIErrorCode`.
    pub fn status_code(&self) -> Status {
        match *self {
            APIErrorCode::BadJson => Status::UnprocessableEntity,
            APIErrorCode::Forbidden => Status::Forbidden,
            APIErrorCode::GuestAccessForbidden => Status::Forbidden,
            APIErrorCode::LimitExceeded => Status::TooManyRequests,
            APIErrorCode::NotFound => Status::NotFound,
            APIErrorCode::NotJson => Status::BadRequest,
            APIErrorCode::Unknown => Status::InternalServerError,
            APIErrorCode::UnknownToken => Status::Unauthorized,
        }
    }
}

impl Serialize for APIErrorCode {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
        let value = match *self {
            APIErrorCode::BadJson => "M_BAD_JSON",
            APIErrorCode::Forbidden => "M_FORBIDDEN",
            APIErrorCode::GuestAccessForbidden => "M_GUEST_ACCESS_FORBIDDEN",
            APIErrorCode::LimitExceeded => "M_LIMIT_EXCEEDED",
            APIErrorCode::NotFound => "M_NOT_FOUND",
            APIErrorCode::NotJson => "M_NOT_JSON",
            APIErrorCode::Unknown => "M_UNKNOWN",
            APIErrorCode::UnknownToken => "M_UNKNOWN_TOKEN",
        };

        serializer.serialize_str(value)
    }
}

/// An operator-facing error.
pub struct CLIError {
    error: String,
}

impl CLIError {
    /// Create a new `CLIError` from any `Error` type.
    pub fn new<E>(error: E) -> CLIError where E: Into<String> {
        CLIError {
            error: error.into(),
        }
    }
}

impl<E> From<E> for CLIError where E: Error {
    fn from(error: E) -> CLIError {
        CLIError::new(error.description())
    }
}

impl Display for CLIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}
<|endoftext|>


<commit_before>//! Error handling facilities.
use std::error::Error;
use std::fmt;

#[cfg(feature = "chrono")]
use time;

#[derive(Debug, Clone)]
pub struct OutOfRangeError {}

impl OutOfRangeError {
    pub fn new() -> OutOfRangeError {
        OutOfRangeError {}
    }
}

impl Error for OutOfRangeError {
    fn description(&self) -> &str {
        "The conversion between duration representations yielded
        produced an out-of-range value"
    }
}

impl fmt::Display for OutOfRangeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

#[cfg(feature = "chrono")]
impl From<time::OutOfRangeError> for OutOfRangeError {
    fn from(_: time::OutOfRangeError) -> OutOfRangeError {
        OutOfRangeError {}
    }
}
<commit_msg>Made the OutOfRangeError description better.<commit_after>//! Error handling facilities.
use std::error::Error;
use std::fmt;

#[cfg(feature = "chrono")]
use time;

#[derive(Debug, Clone)]
pub struct OutOfRangeError {}

impl OutOfRangeError {
    pub fn new() -> OutOfRangeError {
        OutOfRangeError {}
    }
}

impl Error for OutOfRangeError {
    fn description(&self) -> &str {
        "The converted duration value is out of range."
    }
}

impl fmt::Display for OutOfRangeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

#[cfg(feature = "chrono")]
impl From<time::OutOfRangeError> for OutOfRangeError {
    fn from(_: time::OutOfRangeError) -> OutOfRangeError {
        OutOfRangeError {}
    }
}
<|endoftext|>


<commit_before>extern crate thoughtfuck;
mod common;

use common::FauxStdout;
use thoughtfuck::vm::*;
use thoughtfuck::program::*;
use thoughtfuck::parse::parse;

#[test]
fn hello_world () {
    const SOURCE: &str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
    let commands = parse(SOURCE);

    let mut program = Program::new();
    program.append(&commands);

    let mut stdout = FauxStdout::new();
    {
        let mut vm = VM::new(&mut stdout);
        program.execute(&mut vm);
    }
    assert_eq!(stdout.buffer, "Hello World!\n");
}
<commit_msg>Add "correct" whitespacing<commit_after>extern crate thoughtfuck;

mod common;

use common::FauxStdout;
use thoughtfuck::vm::*;
use thoughtfuck::program::*;
use thoughtfuck::parse::parse;

#[test]
fn hello_world () {
    const SOURCE: &str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
    let commands = parse(SOURCE);

    let mut program = Program::new();
    program.append(&commands);

    let mut stdout = FauxStdout::new();
    {
        let mut vm = VM::new(&mut stdout);
        program.execute(&mut vm);
    }
    assert_eq!(stdout.buffer, "Hello World!\n");
}
<|endoftext|>


<commit_before>use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::{size_of, uninitialized};
use std::ptr::read;
use std::ops::{Deref, DerefMut};
use std::slice::{self, from_raw_parts, from_raw_parts_mut};
use std::iter::FromIterator;
use vector::Vector;
use array::{Array, ArrayIndex};
use util::PointerExt;
use nodrop::NoDrop;

pub struct ArrayVec<T: Array> {
    array: NoDrop<T>,
    len: T::Index,
}

impl<T: Array> fmt::Debug for ArrayVec<T> where T::Item: fmt::Debug {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self[..], fmt)
    }
}

impl<T: Array> Hash for ArrayVec<T> where T::Item: Hash {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self[..].hash(h)
    }
}

impl<T: Array> ArrayVec<T> {
    pub fn into_inner(mut self) -> Result<T, Self> {
        if self.len() == self.capacity() {
            self.len = Default::default();
            Ok(unsafe { read(&*self.array) })
        } else {
            Err(self)
        }
    }
}

impl<T: Array> Vector for ArrayVec<T> {
    type Item = T::Item;

    #[inline]
    fn with_capacity(cap: usize) -> Self {
        assert!(cap <= T::len());

        ArrayVec {
            array: NoDrop::new(unsafe { T::uninitialized() }),
            len: Default::default(),
        }
    }

    #[inline]
    fn capacity(&self) -> usize { T::len() }
    #[inline]
    fn reserve(&mut self, additional: usize) { self.reserve_exact(additional); }
    #[inline]
    fn reserve_exact(&mut self, additional: usize) { assert!(T::len() - self.len() >= additional) }
    #[inline]
    fn shrink_to_fit(&mut self) { }

    fn into_boxed_slice(self) -> Box<[T::Item]> { unimplemented!() }

    #[inline]
    unsafe fn set_len(&mut self, len: usize) { self.len = ArrayIndex::from_usize(len); }

    #[inline]
    fn len(&self) -> usize { ArrayIndex::to_usize(self.len) }

    #[inline]
    fn as_ptr(&self) -> *const T::Item {
        self.array.as_ptr()
    }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T::Item {
        self.array.as_mut_ptr()
    }
}

impl<T: Array> Drop for ArrayVec<T> {
    fn drop(&mut self) {
        let len = ArrayIndex::to_usize(self.len);
        if len > 0 {
            let ptr = self.array.as_ptr();

            unsafe {
                self.set_len(0);
                for i in 0..len {
                    read(ptr.uoffset(i));
                }
            }
        }
    }
}

impl<T: Array> From<T> for ArrayVec<T> {
    fn from(array: T) -> Self {
        ArrayVec {
            array: NoDrop::new(array),
            len: ArrayIndex::from_usize(T::len()),
        }
    }
}

pub struct ArrayVecIntoIter<T: Array> {
    inner: ArrayVec<T>,
    start: T::Index,
    end: T::Index,
}

impl<T: Array> ArrayVecIntoIter<T> {
    fn new(mut inner: ArrayVec<T>) -> Self {
        let (start, end) = unsafe {
            let len = inner.len();
            inner.set_len(0);
            (ArrayIndex::from_usize(0), ArrayIndex::from_usize(len))
        };

        ArrayVecIntoIter {
            inner: inner,
            start: start,
            end: end,
        }
    }

    fn ptr_size() -> usize {
        let size = size_of::<<Self as Iterator>::Item>();
        if size == 0 {
            1
        } else {
            size
        }
    }

    fn ptr(&mut self, index: T::Index) -> *mut <Self as Iterator>::Item {
        (self.inner.as_mut_ptr() as usize + ArrayIndex::to_usize(index) * Self::ptr_size()) as *mut _
    }
}

impl<T: Array> Iterator for ArrayVecIntoIter<T> {
    type Item = <ArrayVec<T> as Vector>::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.start < self.end {
            unsafe {
                let start = self.start;
                self.start = ArrayIndex::from_usize(ArrayIndex::to_usize(start) + 1);
                Some(read(self.ptr(start)))
            }
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = ArrayIndex::to_usize(self.end) - ArrayIndex::to_usize(self.start);
        (len, Some(len))
    }

    #[inline]
    fn count(self) -> usize {
        self.size_hint().0
    }
}

impl<T: Array> DoubleEndedIterator for ArrayVecIntoIter<T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.start < self.end {
            unsafe {
                self.end = ArrayIndex::from_usize(ArrayIndex::to_usize(self.end) - 1);
                let end = self.end;
                Some(read(self.ptr(end)))
            }
        } else {
            None
        }
    }
}

impl<T: Array> ExactSizeIterator for ArrayVecIntoIter<T> { }

impl<T: Array> IntoIterator for ArrayVec<T> {
    type Item = T::Item;
    type IntoIter = ArrayVecIntoIter<T>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        ArrayVecIntoIter::new(self)
    }
}

impl<T: Array, R, RHS: Deref<Target=[R]>> PartialEq<RHS> for ArrayVec<T> where T::Item: PartialEq<R>
{
    fn eq(&self, other: &RHS) -> bool {
        **self == *other.deref()
    }
}

impl<T: Array> Eq for ArrayVec<T> where T::Item: Eq { }

impl<T: Array> Drop for ArrayVecIntoIter<T> {
    fn drop(&mut self) {
        for _ in self { }
    }
}

impl<T: Array> Clone for ArrayVec<T> where T::Item: Clone {
    fn clone(&self) -> Self {
        self.iter().cloned().collect()
    }
}

impl<T: Array> Default for ArrayVec<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T: Array> Extend<T::Item> for ArrayVec<T> {
    fn extend<I: IntoIterator<Item=T::Item>>(&mut self, iter: I) {
        let iter = iter.into_iter();
        self.reserve(iter.size_hint().0);
        for v in iter {
            self.push(v);
        }
    }
}

impl<T: Array> FromIterator<T::Item> for ArrayVec<T> {
    fn from_iter<I: IntoIterator<Item=T::Item>>(iter: I) -> Self {
        let mut s = Self::new();
        s.extend(iter);
        s
    }
}

impl<'a, T: Array> IntoIterator for &'a ArrayVec<T> {
    type Item = &'a T::Item;
    type IntoIter = slice::Iter<'a, T::Item>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T: Array> IntoIterator for &'a mut ArrayVec<T> {
    type Item = &'a mut T::Item;
    type IntoIter = slice::IterMut<'a, T::Item>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<T: Array> Deref for ArrayVec<T> {
    type Target = [T::Item];

    fn deref(&self) -> &Self::Target {
        unsafe { from_raw_parts(self.array.as_ptr(), ArrayIndex::to_usize(self.len)) }
    }
}

impl<T: Array> DerefMut for ArrayVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { from_raw_parts_mut(self.array.as_mut_ptr(), ArrayIndex::to_usize(self.len)) }
    }
}
<commit_msg>Remove unused import<commit_after>use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::size_of;
use std::ptr::read;
use std::ops::{Deref, DerefMut};
use std::slice::{self, from_raw_parts, from_raw_parts_mut};
use std::iter::FromIterator;
use vector::Vector;
use array::{Array, ArrayIndex};
use util::PointerExt;
use nodrop::NoDrop;

pub struct ArrayVec<T: Array> {
    array: NoDrop<T>,
    len: T::Index,
}

impl<T: Array> fmt::Debug for ArrayVec<T> where T::Item: fmt::Debug {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self[..], fmt)
    }
}

impl<T: Array> Hash for ArrayVec<T> where T::Item: Hash {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self[..].hash(h)
    }
}

impl<T: Array> ArrayVec<T> {
    pub fn into_inner(mut self) -> Result<T, Self> {
        if self.len() == self.capacity() {
            self.len = Default::default();
            Ok(unsafe { read(&*self.array) })
        } else {
            Err(self)
        }
    }
}

impl<T: Array> Vector for ArrayVec<T> {
    type Item = T::Item;

    #[inline]
    fn with_capacity(cap: usize) -> Self {
        assert!(cap <= T::len());

        ArrayVec {
            array: NoDrop::new(unsafe { T::uninitialized() }),
            len: Default::default(),
        }
    }

    #[inline]
    fn capacity(&self) -> usize { T::len() }
    #[inline]
    fn reserve(&mut self, additional: usize) { self.reserve_exact(additional); }
    #[inline]
    fn reserve_exact(&mut self, additional: usize) { assert!(T::len() - self.len() >= additional) }
    #[inline]
    fn shrink_to_fit(&mut self) { }

    fn into_boxed_slice(self) -> Box<[T::Item]> { unimplemented!() }

    #[inline]
    unsafe fn set_len(&mut self, len: usize) { self.len = ArrayIndex::from_usize(len); }

    #[inline]
    fn len(&self) -> usize { ArrayIndex::to_usize(self.len) }

    #[inline]
    fn as_ptr(&self) -> *const T::Item {
        self.array.as_ptr()
    }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T::Item {
        self.array.as_mut_ptr()
    }
}

impl<T: Array> Drop for ArrayVec<T> {
    fn drop(&mut self) {
        let len = ArrayIndex::to_usize(self.len);
        if len > 0 {
            let ptr = self.array.as_ptr();

            unsafe {
                self.set_len(0);
                for i in 0..len {
                    read(ptr.uoffset(i));
                }
            }
        }
    }
}

impl<T: Array> From<T> for ArrayVec<T> {
    fn from(array: T) -> Self {
        ArrayVec {
            array: NoDrop::new(array),
            len: ArrayIndex::from_usize(T::len()),
        }
    }
}

pub struct ArrayVecIntoIter<T: Array> {
    inner: ArrayVec<T>,
    start: T::Index,
    end: T::Index,
}

impl<T: Array> ArrayVecIntoIter<T> {
    fn new(mut inner: ArrayVec<T>) -> Self {
        let (start, end) = unsafe {
            let len = inner.len();
            inner.set_len(0);
            (ArrayIndex::from_usize(0), ArrayIndex::from_usize(len))
        };

        ArrayVecIntoIter {
            inner: inner,
            start: start,
            end: end,
        }
    }

    fn ptr_size() -> usize {
        let size = size_of::<<Self as Iterator>::Item>();
        if size == 0 {
            1
        } else {
            size
        }
    }

    fn ptr(&mut self, index: T::Index) -> *mut <Self as Iterator>::Item {
        (self.inner.as_mut_ptr() as usize + ArrayIndex::to_usize(index) * Self::ptr_size()) as *mut _
    }
}

impl<T: Array> Iterator for ArrayVecIntoIter<T> {
    type Item = <ArrayVec<T> as Vector>::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.start < self.end {
            unsafe {
                let start = self.start;
                self.start = ArrayIndex::from_usize(ArrayIndex::to_usize(start) + 1);
                Some(read(self.ptr(start)))
            }
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = ArrayIndex::to_usize(self.end) - ArrayIndex::to_usize(self.start);
        (len, Some(len))
    }

    #[inline]
    fn count(self) -> usize {
        self.size_hint().0
    }
}

impl<T: Array> DoubleEndedIterator for ArrayVecIntoIter<T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.start < self.end {
            unsafe {
                self.end = ArrayIndex::from_usize(ArrayIndex::to_usize(self.end) - 1);
                let end = self.end;
                Some(read(self.ptr(end)))
            }
        } else {
            None
        }
    }
}

impl<T: Array> ExactSizeIterator for ArrayVecIntoIter<T> { }

impl<T: Array> IntoIterator for ArrayVec<T> {
    type Item = T::Item;
    type IntoIter = ArrayVecIntoIter<T>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        ArrayVecIntoIter::new(self)
    }
}

impl<T: Array, R, RHS: Deref<Target=[R]>> PartialEq<RHS> for ArrayVec<T> where T::Item: PartialEq<R>
{
    fn eq(&self, other: &RHS) -> bool {
        **self == *other.deref()
    }
}

impl<T: Array> Eq for ArrayVec<T> where T::Item: Eq { }

impl<T: Array> Drop for ArrayVecIntoIter<T> {
    fn drop(&mut self) {
        for _ in self { }
    }
}

impl<T: Array> Clone for ArrayVec<T> where T::Item: Clone {
    fn clone(&self) -> Self {
        self.iter().cloned().collect()
    }
}

impl<T: Array> Default for ArrayVec<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T: Array> Extend<T::Item> for ArrayVec<T> {
    fn extend<I: IntoIterator<Item=T::Item>>(&mut self, iter: I) {
        let iter = iter.into_iter();
        self.reserve(iter.size_hint().0);
        for v in iter {
            self.push(v);
        }
    }
}

impl<T: Array> FromIterator<T::Item> for ArrayVec<T> {
    fn from_iter<I: IntoIterator<Item=T::Item>>(iter: I) -> Self {
        let mut s = Self::new();
        s.extend(iter);
        s
    }
}

impl<'a, T: Array> IntoIterator for &'a ArrayVec<T> {
    type Item = &'a T::Item;
    type IntoIter = slice::Iter<'a, T::Item>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T: Array> IntoIterator for &'a mut ArrayVec<T> {
    type Item = &'a mut T::Item;
    type IntoIter = slice::IterMut<'a, T::Item>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<T: Array> Deref for ArrayVec<T> {
    type Target = [T::Item];

    fn deref(&self) -> &Self::Target {
        unsafe { from_raw_parts(self.array.as_ptr(), ArrayIndex::to_usize(self.len)) }
    }
}

impl<T: Array> DerefMut for ArrayVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { from_raw_parts_mut(self.array.as_mut_ptr(), ArrayIndex::to_usize(self.len)) }
    }
}
<|endoftext|>


<commit_before>#![crate_id = "azure#0"]
#![desc = "Azure BlobStorage"]
#![license = "BSD"]
#![crate_type = "lib"]

#![feature(globs)]

extern crate serialize;
extern crate http;
extern crate openssl;
extern crate time;

pub mod blobstorage {
  use http::client::RequestWriter;
  use http::headers::HeaderConvertible;
  use http::headers::HeaderEnum;
  use http::headers::request::ExtensionHeader;
  use http::headers::test_utils::to_stream_into_str;
  use http::method::Get;
  use openssl::crypto::hash::*;
  use openssl::crypto::hmac::*;
  use std::ascii::OwnedStrAsciiExt;
  use std::path::BytesContainer;
  use serialize::base64::*;
  use serialize::base64::FromBase64;
  use time;

  pub struct BlobStorageClient {
    pub account_name: String,
    pub key: Vec<u8>
  }

  pub fn extract<T: HeaderConvertible>(element: Option<T>) -> String {
    match element {
      None => "".to_str(),
      Some(ref x) => to_stream_into_str(x)
    }
  }

  pub fn new_client(account_name: &str, account_key: &str) -> BlobStorageClient {
    let key = account_key.as_slice().from_base64().unwrap();
    BlobStorageClient{
      account_name: account_name.to_str(),
      key: key
    }
  }

  impl BlobStorageClient {
    pub fn new_list_blob_req(&self, containerName: &str) -> RequestWriter {
      let url = format!("https://{}.blob.core.windows.net/{}?restype=container", self.account_name, containerName);

      let mut rw = RequestWriter::new(
          Get,
          from_str(url.as_slice()).expect("Invalid URL :-(")
      ).unwrap();

      // TODO(colemick): this is common to all reqs, extract
      rw.headers.date = Some(time::now_utc());
      rw.headers.extensions.insert("x-ms-version".to_str(), "2009-09-19".to_str());
      rw
    }

    pub fn sign_request(&self, rw: &mut RequestWriter) {
      let hdrs = rw.headers.clone();

      let strToSign = format!("{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}",
        rw.method.to_str(),
        extract(hdrs.content_encoding),
        extract(hdrs.content_language),
        extract(hdrs.content_length),
        extract(hdrs.content_md5),
        extract(hdrs.content_type),
        extract(hdrs.date),
        extract(hdrs.if_modified_since),
        extract(hdrs.if_match),
        extract(hdrs.if_none_match),
        extract(hdrs.if_unmodified_since),
        extract(hdrs.range),
        self.canonicalized_headers(rw),
        self.canonicalized_resource(rw),
      );

      //println!(">>>>>{}<<<<<<", strToSign);

      let _ = hdrs;

      let mut hmac = HMAC(SHA256, self.key.container_as_bytes());
      hmac.update(strToSign.as_bytes());
      let shared_key = hmac.final().as_slice().to_base64(STANDARD);

      rw.headers.authorization = Some(format!("SharedKey {:s}:{:s}", self.account_name, shared_key));
    }

    pub fn canonicalized_headers(&self, rw: &RequestWriter) -> String {
      let mut headers: Vec<String> = rw.headers.iter()
        .filter_map(|h| {
          let lower_key = h.header_name().into_ascii_lower();
          if lower_key.as_slice().starts_with("x-ms-".as_slice()) {
            let hdr_line = format!("{:s}:{:s}", lower_key, h.header_value());
            return Some(hdr_line)
          }
          return None
        })
        .collect();

      headers.sort();
      headers.connect("\n")
    }

    pub fn canonicalized_resource(&self, rw: &RequestWriter) -> String {
      let mut res_str = format!("/{:s}{:s}", self.account_name, rw.url.path);
      for &(ref k, ref v) in rw.url.query.iter() {
        let lower_key = k.to_str().into_ascii_lower();
        res_str = res_str.append(
          format!("\n{:s}:{:s}", lower_key, v.to_str()).as_slice()
        );
      }

      /*
        TODO(review):
        If I use the following, instead of the line that actually appears:
          let mut lines = res_str.as_slice().split('\n').collect();

        Then I get:
          lib.rs:100:7: 100:19 error: the type of this value must be known in this context
          lib.rs:100       lines.sort();
                           ^~~~~~~~~~~~
          error: aborting due to previous error
      */
      let mut lines: Vec<&str> = res_str.as_slice().split('\n').collect();
      lines.sort();
      lines.connect("\n")
    }
  }
}<commit_msg>one last todo<commit_after>#![crate_id = "azure#0"]
#![desc = "Azure BlobStorage"]
#![license = "BSD"]
#![crate_type = "lib"]

#![feature(globs)]

extern crate serialize;
extern crate http;
extern crate openssl;
extern crate time;

pub mod blobstorage {
  use http::client::RequestWriter;
  use http::headers::HeaderConvertible;
  use http::headers::HeaderEnum;
  use http::headers::request::ExtensionHeader;
  use http::headers::test_utils::to_stream_into_str;
  use http::method::Get;
  use openssl::crypto::hash::*;
  use openssl::crypto::hmac::*;
  use std::ascii::OwnedStrAsciiExt;
  use std::path::BytesContainer;
  use serialize::base64::*;
  use serialize::base64::FromBase64;
  use time;

  pub struct BlobStorageClient {
    pub account_name: String,
    pub key: Vec<u8>
  }

  pub fn extract<T: HeaderConvertible>(element: Option<T>) -> String {
    match element {
      None => "".to_str(),
      Some(ref x) => to_stream_into_str(x)
    }
  }

  pub fn new_client(account_name: &str, account_key: &str) -> BlobStorageClient {
    let key = account_key.as_slice().from_base64().unwrap();
    BlobStorageClient{
      account_name: account_name.to_str(),
      key: key
    }
  }

  impl BlobStorageClient {
    pub fn new_list_blob_req(&self, containerName: &str) -> RequestWriter {
      let url = format!("https://{}.blob.core.windows.net/{}?restype=container", self.account_name, containerName);

      let mut rw = RequestWriter::new(
          Get,
          from_str(url.as_slice()).expect("Invalid URL :-(")
      ).unwrap();

      // TODO(colemick): this is common to all reqs, extract
      rw.headers.date = Some(time::now_utc());
      rw.headers.extensions.insert("x-ms-version".to_str(), "2009-09-19".to_str());
      rw
    }

    pub fn sign_request(&self, rw: &mut RequestWriter) {
      let hdrs = rw.headers.clone();

      let strToSign = format!("{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}\n{:s}",
        rw.method.to_str(),
        extract(hdrs.content_encoding),
        extract(hdrs.content_language),
        extract(hdrs.content_length),
        extract(hdrs.content_md5),
        extract(hdrs.content_type),
        extract(hdrs.date),
        extract(hdrs.if_modified_since),
        extract(hdrs.if_match),
        extract(hdrs.if_none_match),
        extract(hdrs.if_unmodified_since),
        extract(hdrs.range),
        self.canonicalized_headers(rw),
        self.canonicalized_resource(rw),
      );

      //println!(">>>>>{}<<<<<<", strToSign);

      let _ = hdrs;

      let mut hmac = HMAC(SHA256, self.key.container_as_bytes());
      hmac.update(strToSign.as_bytes());
      let shared_key = hmac.final().as_slice().to_base64(STANDARD);

      rw.headers.authorization = Some(format!("SharedKey {:s}:{:s}", self.account_name, shared_key));
    }

    pub fn canonicalized_headers(&self, rw: &RequestWriter) -> String {
      let mut headers: Vec<String> = rw.headers.iter()
        .filter_map(|h| {
          let lower_key = h.header_name().into_ascii_lower();
          if lower_key.as_slice().starts_with("x-ms-".as_slice()) {
            let hdr_line = format!("{:s}:{:s}", lower_key, h.header_value());
            return Some(hdr_line)
          }
          return None
        })
        .collect();

      headers.sort();
      headers.connect("\n")
    }

    pub fn canonicalized_resource(&self, rw: &RequestWriter) -> String {
      // TODO(colemickens):
      // make this map the query params into a vec with the first line
      // collect() once, then sort & connect with ("\n") (like canoniclized_headers)

      let mut res_str = format!("/{:s}{:s}", self.account_name, rw.url.path);
      for &(ref k, ref v) in rw.url.query.iter() {
        let lower_key = k.to_str().into_ascii_lower();
        res_str = res_str.append(
          format!("\n{:s}:{:s}", lower_key, v.to_str()).as_slice()
        );
      }

      /*
        TODO(review):
        If I use the following, instead of the line that actually appears:
          let mut lines = res_str.as_slice().split('\n').collect();

        Then I get:
          lib.rs:100:7: 100:19 error: the type of this value must be known in this context
          lib.rs:100       lines.sort();
                           ^~~~~~~~~~~~
          error: aborting due to previous error
      */
      let mut lines: Vec<&str> = res_str.as_slice().split('\n').collect();
      lines.sort();
      lines.connect("\n")
    }
  }
}<|endoftext|>


<commit_before>use failure::Error;
use std::io;

pub fn read_line() -> Result<String, Error> {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer)?;

    Ok(buffer[..buffer.len() - 1].to_string())
}

pub fn read_usize_range(min: usize, max: usize) -> Result<usize, Error> {
    loop {
        let input = read_line()?.parse()?;

        if input >= min && input <= max {
            return Ok(input);
        } else {
            println!("input must be between {}-{}", min, max);
        }
    }
}

#[derive(Debug)]
pub enum Answer {
    Yes,
    No,
}

impl Into<bool> for Answer {
    fn into(self) -> bool {
        match self {
            Answer::Yes => true,
            Answer::No => false,
        }
    }
}

pub fn read_yn(default: Answer) -> Result<bool, Error> {
    let line = read_line()?;

    let answer = match line.as_str() {
        "Y" | "y" => true,
        "N" | "n" => false,
        _ => default.into(),
    };

    Ok(answer)
}<commit_msg>Return io::Result for appropriate input functions Explain why the buffer is trimmed in read_line()<commit_after>use failure::Error;
use std::io;

pub fn read_line() -> io::Result<String> {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer)?;

    // We trim the end of the buffer to remove the newline character
    Ok(buffer[..buffer.len() - 1].to_string())
}

pub fn read_usize_range(min: usize, max: usize) -> Result<usize, Error> {
    loop {
        let input = read_line()?.parse()?;

        if input >= min && input <= max {
            return Ok(input);
        } else {
            println!("input must be between {}-{}", min, max);
        }
    }
}

#[derive(Debug)]
pub enum Answer {
    Yes,
    No,
}

impl Into<bool> for Answer {
    fn into(self) -> bool {
        match self {
            Answer::Yes => true,
            Answer::No => false,
        }
    }
}

pub fn read_yn(default: Answer) -> io::Result<bool> {
    let line = read_line()?;

    let answer = match line.as_str() {
        "y" | "Y" => true,
        "n" | "N" => false,
        _ => default.into(),
    };

    Ok(answer)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](http://kentonv.github.io/capnproto/) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![feature(io, core, unsafe_destructor)]
#![allow(raw_pointer_derive)]

#![crate_name="capnp"]
#![crate_type = "lib"]

extern crate libc;

// reexports
pub use blob::{text, data};
pub use common::{MessageSize};
pub use list::{primitive_list, enum_list, struct_list, text_list, data_list, list_list};
pub use message::{MessageBuilder, BuilderOptions, MessageReader, ReaderOptions};
pub use message::MallocMessageBuilder;
pub use serialize::OwnedSpaceMessageReader;

pub mod any_pointer;
pub mod arena;
pub mod blob;
pub mod capability;
pub mod common;
pub mod endian;
pub mod io;
pub mod layout;
pub mod list;
pub mod mask;
pub mod message;
pub mod serialize;
pub mod serialize_packed;
pub mod traits;

#[cfg(test)]
pub mod layout_test;
#[cfg(test)]
pub mod serialize_packed_test;

<commit_msg>hide some things. reexport Word<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](http://kentonv.github.io/capnproto/) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![feature(io, core, unsafe_destructor)]
#![allow(raw_pointer_derive)]

#![crate_name="capnp"]
#![crate_type = "lib"]

extern crate libc;

// reexports
pub use blob::{text, data};
pub use common::{MessageSize, Word};
pub use list::{primitive_list, enum_list, struct_list, text_list, data_list, list_list};
pub use message::{MessageBuilder, BuilderOptions, MessageReader, ReaderOptions};
pub use message::MallocMessageBuilder;
pub use serialize::OwnedSpaceMessageReader;

pub mod any_pointer;
pub mod arena;
pub mod blob;
pub mod capability;
pub mod common;
mod endian;
pub mod io;
pub mod layout;
pub mod list;
mod mask;
pub mod message;
pub mod serialize;
pub mod serialize_packed;
pub mod traits;

#[cfg(test)]
pub mod layout_test;
#[cfg(test)]
pub mod serialize_packed_test;

<|endoftext|>