<commit_before>#![feature(globs)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;

extern crate time;
extern crate conduit;
extern crate middleware = "conduit-middleware";

use std::fmt::Show;

use conduit::Request;
use middleware::Middleware;

pub struct LogRequests(u32);

impl Middleware for LogRequests {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show>> {
        match *self {
            LogRequests(level) => log!(level, "{}", log_message(req))
        }
        Ok(())
    }
}

fn log_message(req: &mut Request) -> String {
    format!("{} [{}] {} {}",
            req.remote_ip(),
            time::now().rfc3339(),
            req.method(),
            req.path())
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";

    use super::*;
    use std;
    use log;
    use conduit;
    use middleware;

    use std::io::{ChanWriter, ChanReader};
    use log::{Logger, LogRecord};
    use conduit::{Request, Response, Handler};

    struct MyWriter(ChanWriter);

    impl Logger for MyWriter {
        fn log(&mut self, record: &LogRecord) {
            let MyWriter(ref mut inner) = *self;
            (write!(inner, "{}", record.args)).unwrap();
        }
    }

    #[test]
    fn test_log() {
        let (sender, receiver) = channel();
        let mut reader = ChanReader::new(receiver);

        let mut builder = middleware::MiddlewareBuilder::new(handler);
        builder.add(LogRequests(log::ERROR));

        task(builder, sender);

        let result = reader.read_to_str().ok().expect("No response");
        let parts = result.as_slice().split(' ').map(|s| s.to_str()).collect::<Vec<String>>();

        assert_eq!(parts.get(0).as_slice(), "127.0.0.1");
        assert!(parts.get(1).as_slice().len() == "[2014-07-01T22:34:06-07:00]".len());
        assert_eq!(parts.get(2).as_slice(), "Get");
        assert_eq!(parts.get(3).as_slice(), "/foo");
    }

    fn task<H: Handler + 'static + Send>(handler: H, sender: Sender<Vec<u8>>) {
        spawn(proc() {
            log::set_logger(box MyWriter(ChanWriter::new(sender)));
            let mut request = test::MockRequest::new(conduit::Get, "/foo");
            let _ = handler.call(&mut request);
        });
    }

    fn handler(_: &mut Request) -> Result<Response, ()> {
        Ok(Response {
            status: (200, "OK"),
            headers: std::collections::HashMap::new(),
            body: box std::io::util::NullReader
        })
    }
}
<commit_msg>Make the log level field public<commit_after>#![feature(globs)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;

extern crate time;
extern crate conduit;
extern crate middleware = "conduit-middleware";

use std::fmt::Show;

use conduit::Request;
use middleware::Middleware;

pub struct LogRequests(pub u32);

impl Middleware for LogRequests {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show>> {
        match *self {
            LogRequests(level) => log!(level, "{}", log_message(req))
        }
        Ok(())
    }
}

fn log_message(req: &mut Request) -> String {
    format!("{} [{}] {} {}",
            req.remote_ip(),
            time::now().rfc3339(),
            req.method(),
            req.path())
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";

    use super::*;
    use std;
    use log;
    use conduit;
    use middleware;

    use std::io::{ChanWriter, ChanReader};
    use log::{Logger, LogRecord};
    use conduit::{Request, Response, Handler};

    struct MyWriter(ChanWriter);

    impl Logger for MyWriter {
        fn log(&mut self, record: &LogRecord) {
            let MyWriter(ref mut inner) = *self;
            (write!(inner, "{}", record.args)).unwrap();
        }
    }

    #[test]
    fn test_log() {
        let (sender, receiver) = channel();
        let mut reader = ChanReader::new(receiver);

        let mut builder = middleware::MiddlewareBuilder::new(handler);
        builder.add(LogRequests(log::ERROR));

        task(builder, sender);

        let result = reader.read_to_str().ok().expect("No response");
        let parts = result.as_slice().split(' ').map(|s| s.to_str()).collect::<Vec<String>>();

        assert_eq!(parts.get(0).as_slice(), "127.0.0.1");
        assert!(parts.get(1).as_slice().len() == "[2014-07-01T22:34:06-07:00]".len());
        assert_eq!(parts.get(2).as_slice(), "Get");
        assert_eq!(parts.get(3).as_slice(), "/foo");
    }

    fn task<H: Handler + 'static + Send>(handler: H, sender: Sender<Vec<u8>>) {
        spawn(proc() {
            log::set_logger(box MyWriter(ChanWriter::new(sender)));
            let mut request = test::MockRequest::new(conduit::Get, "/foo");
            let _ = handler.call(&mut request);
        });
    }

    fn handler(_: &mut Request) -> Result<Response, ()> {
        Ok(Response {
            status: (200, "OK"),
            headers: std::collections::HashMap::new(),
            body: box std::io::util::NullReader
        })
    }
}
<|endoftext|>


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

use dom::bindings::codegen::BindingDeclarations::HTMLTextAreaElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::{ErrorResult, Fallible};
use dom::document::Document;
use dom::element::HTMLTextAreaElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLTextAreaElement {
    pub htmlelement: HTMLElement,
}

impl HTMLTextAreaElementDerived for EventTarget {
    fn is_htmltextareaelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLTextAreaElementTypeId))
    }
}

impl HTMLTextAreaElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLTextAreaElement {
        HTMLTextAreaElement {
            htmlelement: HTMLElement::new_inherited(HTMLTextAreaElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLTextAreaElement> {
        let element = HTMLTextAreaElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLTextAreaElementBinding::Wrap)
    }
}

pub trait HTMLTextAreaElementMethods {
    fn Autofocus(&self) -> bool;
    fn SetAutofocus(&mut self, _autofocus: bool) -> ErrorResult;
    fn Cols(&self) -> u32;
    fn SetCols(&self, _cols: u32) -> ErrorResult;
    fn Disabled(&self) -> bool;
    fn SetDisabled(&mut self, _disabled: bool) -> ErrorResult;
    fn MaxLength(&self) -> i32;
    fn SetMaxLength(&self, _max_length: i32) -> ErrorResult;
    fn Name(&self) -> DOMString;
    fn SetName(&mut self, _name: DOMString) -> ErrorResult;
    fn Placeholder(&self) -> DOMString;
    fn SetPlaceholder(&mut self, _placeholder: DOMString) -> ErrorResult;
    fn ReadOnly(&self) -> bool;
    fn SetReadOnly(&mut self, _read_only: bool) -> ErrorResult;
    fn Required(&self) -> bool;
    fn SetRequired(&mut self, _required: bool) -> ErrorResult;
    fn Rows(&self) -> u32;
    fn SetRows(&self, _rows: u32) -> ErrorResult;
    fn Wrap(&self) -> DOMString;
    fn SetWrap(&mut self, _wrap: DOMString) -> ErrorResult;
    fn Type(&self) -> DOMString;
    fn SetType(&mut self, _type: DOMString);
    fn DefaultValue(&self) -> DOMString;
    fn SetDefaultValue(&mut self, _default_value: DOMString) -> ErrorResult;
    fn Value(&self) -> DOMString;
    fn SetValue(&mut self, _value: DOMString);
    fn TextLength(&self) -> u32;
    fn SetTextLength(&self, _text_length: u32) -> ErrorResult;
    fn WillValidate(&self) -> bool;
    fn SetWillValidate(&mut self, _will_validate: bool) -> ErrorResult;
    fn ValidationMessage(&self) -> DOMString;
    fn CheckValidity(&self) -> bool;
    fn SetCustomValidity(&self, _error: DOMString);
    fn Select(&self);
    fn GetSelectionStart(&self) -> Fallible<u32>;
    fn SetSelectionStart(&self, _selection_start: u32) -> ErrorResult;
    fn GetSelectionEnd(&self) -> Fallible<u32>;
    fn SetSelectionEnd(&self, _selection_end: u32) -> ErrorResult;
    fn GetSelectionDirection(&self) -> Fallible<DOMString>;
    fn SetSelectionDirection(&self, _selection_direction: DOMString) -> ErrorResult;
    fn SetRangeText(&self, _replacement: DOMString);
}

impl<'a> HTMLTextAreaElementMethods for JSRef<'a, HTMLTextAreaElement> {
    fn Autofocus(&self) -> bool {
        false
    }

    fn SetAutofocus(&mut self, _autofocus: bool) -> ErrorResult {
        Ok(())
    }

    fn Cols(&self) -> u32 {
        0
    }

    fn SetCols(&self, _cols: u32) -> ErrorResult {
        Ok(())
    }

    fn Disabled(&self) -> bool {
        false
    }

    fn SetDisabled(&mut self, _disabled: bool) -> ErrorResult {
        Ok(())
    }

    fn MaxLength(&self) -> i32 {
        0
    }

    fn SetMaxLength(&self, _max_length: i32) -> ErrorResult {
        Ok(())
    }

    fn Name(&self) -> DOMString {
        "".to_owned()
    }

    fn SetName(&mut self, _name: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Placeholder(&self) -> DOMString {
        "".to_owned()
    }

    fn SetPlaceholder(&mut self, _placeholder: DOMString) -> ErrorResult {
        Ok(())
    }

    fn ReadOnly(&self) -> bool {
        false
    }

    fn SetReadOnly(&mut self, _read_only: bool) -> ErrorResult {
        Ok(())
    }

    fn Required(&self) -> bool {
        false
    }

    fn SetRequired(&mut self, _required: bool) -> ErrorResult {
        Ok(())
    }

    fn Rows(&self) -> u32 {
        0
    }

    fn SetRows(&self, _rows: u32) -> ErrorResult {
        Ok(())
    }

    fn Wrap(&self) -> DOMString {
        "".to_owned()
    }

    fn SetWrap(&mut self, _wrap: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Type(&self) -> DOMString {
        "".to_owned()
    }

    fn SetType(&mut self, _type: DOMString) {
    }

    fn DefaultValue(&self) -> DOMString {
        "".to_owned()
    }

    fn SetDefaultValue(&mut self, _default_value: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Value(&self) -> DOMString {
        "".to_owned()
    }

    fn SetValue(&mut self, _value: DOMString) {
    }

    fn TextLength(&self) -> u32 {
        0
    }

    fn SetTextLength(&self, _text_length: u32) -> ErrorResult {
        Ok(())
    }

    fn WillValidate(&self) -> bool {
        false
    }

    fn SetWillValidate(&mut self, _will_validate: bool) -> ErrorResult {
        Ok(())
    }

    fn ValidationMessage(&self) -> DOMString {
        "".to_owned()
    }

    fn CheckValidity(&self) -> bool {
        false
    }

    fn SetCustomValidity(&self, _error: DOMString) {
    }

    fn Select(&self) {
    }

    fn GetSelectionStart(&self) -> Fallible<u32> {
        Ok(0)
    }

    fn SetSelectionStart(&self, _selection_start: u32) -> ErrorResult {
        Ok(())
    }

    fn GetSelectionEnd(&self) -> Fallible<u32> {
        Ok(0)
    }

    fn SetSelectionEnd(&self, _selection_end: u32) -> ErrorResult {
        Ok(())
    }

    fn GetSelectionDirection(&self) -> Fallible<DOMString> {
        Ok("".to_owned())
    }

    fn SetSelectionDirection(&self, _selection_direction: DOMString) -> ErrorResult {
        Ok(())
    }

    fn SetRangeText(&self, _replacement: DOMString) {
    }
}
<commit_msg>Remove needless '&mut self' from HTMLTextAreaElementMethods.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::HTMLTextAreaElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::{ErrorResult, Fallible};
use dom::document::Document;
use dom::element::HTMLTextAreaElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLTextAreaElement {
    pub htmlelement: HTMLElement,
}

impl HTMLTextAreaElementDerived for EventTarget {
    fn is_htmltextareaelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLTextAreaElementTypeId))
    }
}

impl HTMLTextAreaElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLTextAreaElement {
        HTMLTextAreaElement {
            htmlelement: HTMLElement::new_inherited(HTMLTextAreaElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLTextAreaElement> {
        let element = HTMLTextAreaElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLTextAreaElementBinding::Wrap)
    }
}

pub trait HTMLTextAreaElementMethods {
    fn Autofocus(&self) -> bool;
    fn SetAutofocus(&self, _autofocus: bool) -> ErrorResult;
    fn Cols(&self) -> u32;
    fn SetCols(&self, _cols: u32) -> ErrorResult;
    fn Disabled(&self) -> bool;
    fn SetDisabled(&self, _disabled: bool) -> ErrorResult;
    fn MaxLength(&self) -> i32;
    fn SetMaxLength(&self, _max_length: i32) -> ErrorResult;
    fn Name(&self) -> DOMString;
    fn SetName(&self, _name: DOMString) -> ErrorResult;
    fn Placeholder(&self) -> DOMString;
    fn SetPlaceholder(&self, _placeholder: DOMString) -> ErrorResult;
    fn ReadOnly(&self) -> bool;
    fn SetReadOnly(&self, _read_only: bool) -> ErrorResult;
    fn Required(&self) -> bool;
    fn SetRequired(&self, _required: bool) -> ErrorResult;
    fn Rows(&self) -> u32;
    fn SetRows(&self, _rows: u32) -> ErrorResult;
    fn Wrap(&self) -> DOMString;
    fn SetWrap(&self, _wrap: DOMString) -> ErrorResult;
    fn Type(&self) -> DOMString;
    fn SetType(&self, _type: DOMString);
    fn DefaultValue(&self) -> DOMString;
    fn SetDefaultValue(&self, _default_value: DOMString) -> ErrorResult;
    fn Value(&self) -> DOMString;
    fn SetValue(&self, _value: DOMString);
    fn TextLength(&self) -> u32;
    fn SetTextLength(&self, _text_length: u32) -> ErrorResult;
    fn WillValidate(&self) -> bool;
    fn SetWillValidate(&self, _will_validate: bool) -> ErrorResult;
    fn ValidationMessage(&self) -> DOMString;
    fn CheckValidity(&self) -> bool;
    fn SetCustomValidity(&self, _error: DOMString);
    fn Select(&self);
    fn GetSelectionStart(&self) -> Fallible<u32>;
    fn SetSelectionStart(&self, _selection_start: u32) -> ErrorResult;
    fn GetSelectionEnd(&self) -> Fallible<u32>;
    fn SetSelectionEnd(&self, _selection_end: u32) -> ErrorResult;
    fn GetSelectionDirection(&self) -> Fallible<DOMString>;
    fn SetSelectionDirection(&self, _selection_direction: DOMString) -> ErrorResult;
    fn SetRangeText(&self, _replacement: DOMString);
}

impl<'a> HTMLTextAreaElementMethods for JSRef<'a, HTMLTextAreaElement> {
    fn Autofocus(&self) -> bool {
        false
    }

    fn SetAutofocus(&self, _autofocus: bool) -> ErrorResult {
        Ok(())
    }

    fn Cols(&self) -> u32 {
        0
    }

    fn SetCols(&self, _cols: u32) -> ErrorResult {
        Ok(())
    }

    fn Disabled(&self) -> bool {
        false
    }

    fn SetDisabled(&self, _disabled: bool) -> ErrorResult {
        Ok(())
    }

    fn MaxLength(&self) -> i32 {
        0
    }

    fn SetMaxLength(&self, _max_length: i32) -> ErrorResult {
        Ok(())
    }

    fn Name(&self) -> DOMString {
        "".to_owned()
    }

    fn SetName(&self, _name: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Placeholder(&self) -> DOMString {
        "".to_owned()
    }

    fn SetPlaceholder(&self, _placeholder: DOMString) -> ErrorResult {
        Ok(())
    }

    fn ReadOnly(&self) -> bool {
        false
    }

    fn SetReadOnly(&self, _read_only: bool) -> ErrorResult {
        Ok(())
    }

    fn Required(&self) -> bool {
        false
    }

    fn SetRequired(&self, _required: bool) -> ErrorResult {
        Ok(())
    }

    fn Rows(&self) -> u32 {
        0
    }

    fn SetRows(&self, _rows: u32) -> ErrorResult {
        Ok(())
    }

    fn Wrap(&self) -> DOMString {
        "".to_owned()
    }

    fn SetWrap(&self, _wrap: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Type(&self) -> DOMString {
        "".to_owned()
    }

    fn SetType(&self, _type: DOMString) {
    }

    fn DefaultValue(&self) -> DOMString {
        "".to_owned()
    }

    fn SetDefaultValue(&self, _default_value: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Value(&self) -> DOMString {
        "".to_owned()
    }

    fn SetValue(&self, _value: DOMString) {
    }

    fn TextLength(&self) -> u32 {
        0
    }

    fn SetTextLength(&self, _text_length: u32) -> ErrorResult {
        Ok(())
    }

    fn WillValidate(&self) -> bool {
        false
    }

    fn SetWillValidate(&self, _will_validate: bool) -> ErrorResult {
        Ok(())
    }

    fn ValidationMessage(&self) -> DOMString {
        "".to_owned()
    }

    fn CheckValidity(&self) -> bool {
        false
    }

    fn SetCustomValidity(&self, _error: DOMString) {
    }

    fn Select(&self) {
    }

    fn GetSelectionStart(&self) -> Fallible<u32> {
        Ok(0)
    }

    fn SetSelectionStart(&self, _selection_start: u32) -> ErrorResult {
        Ok(())
    }

    fn GetSelectionEnd(&self) -> Fallible<u32> {
        Ok(0)
    }

    fn SetSelectionEnd(&self, _selection_end: u32) -> ErrorResult {
        Ok(())
    }

    fn GetSelectionDirection(&self) -> Fallible<DOMString> {
        Ok("".to_owned())
    }

    fn SetSelectionDirection(&self, _selection_direction: DOMString) -> ErrorResult {
        Ok(())
    }

    fn SetRangeText(&self, _replacement: DOMString) {
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]
#![feature(proc_macro_lib)]
#![recursion_limit = "128"]

#[macro_use] extern crate quote;

extern crate proc_macro;
extern crate syn;

use proc_macro::TokenStream;

// Yield mock generated code for template
//     Hello, {{name}} ({{age}})
#[proc_macro_derive(StacheDisplay)]
pub fn stache_display(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    let gen = quote! {
        impl #impl_generics std::fmt::Display for #name #ty_generics #where_clause {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                use display_html_safe::DisplayHtmlSafe;

                f.write_str("Hello, ")?;
                DisplayHtmlSafe::fmt(&self.name, f)?;
                f.write_str(" (")?;
                DisplayHtmlSafe::fmt(&self.age, f)?;
                f.write_str(")\n")?;
                Ok(())
            }
        }
    };

    gen.parse().unwrap()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Hygiene<commit_after>#![feature(proc_macro)]
#![feature(proc_macro_lib)]
#![recursion_limit = "128"]

#[macro_use] extern crate quote;

extern crate proc_macro;
extern crate syn;

use proc_macro::TokenStream;

// Yield mock generated code for template
//     Hello, {{name}} ({{age}})
#[proc_macro_derive(StacheDisplay)]
pub fn stache_display(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    let gen = quote! {
        impl #impl_generics ::std::fmt::Display for #name #ty_generics #where_clause {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                use display_html_safe::DisplayHtmlSafe;

                f.write_str("Hello, ")?;
                DisplayHtmlSafe::fmt(&self.name, f)?;
                f.write_str(" (")?;
                DisplayHtmlSafe::fmt(&self.age, f)?;
                f.write_str(")\n")?;
                Ok(())
            }
        }
    };

    gen.parse().unwrap()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
    packages: &'static [&'static str],
}

const TEST_REPOS: &[Test] = &[
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "cf056ea5e8052c1feea6141e40ab0306715a2c33",
        lock: None,
        packages: &[],
    },
    Test {
        name: "ripgrep",
        repo: "https://github.com/BurntSushi/ripgrep",
        sha: "3de31f752729525d85a3d1575ac1978733b3f7e7",
        lock: None,
        packages: &[],
    },
    Test {
        name: "tokei",
        repo: "https://github.com/XAMPPRocky/tokei",
        sha: "fdf3f8cb279a7aeac0696c87e5d8b0cd946e4f9e",
        lock: None,
        packages: &[],
    },
    Test {
        name: "xsv",
        repo: "https://github.com/BurntSushi/xsv",
        sha: "3de6c04269a7d315f7e9864b9013451cd9580a08",
        lock: None,
        packages: &[],
    },
    Test {
        name: "servo",
        repo: "https://github.com/servo/servo",
        sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
        lock: None,
        // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
        // This takes much less time to build than all of Servo and supports stable Rust.
        packages: &["selectors"],
    },
];

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let cargo = &args[1];
    let out_dir = Path::new(&args[2]);
    let cargo = &Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        fs::write(&dir.join("Cargo.lock"), lockfile).unwrap();
    }
    if !run_cargo_test(cargo, &dir, test.packages) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap();
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                .arg("fetch")
                .arg(test.repo)
                .arg("master")
                .arg(&format!("--depth={}", depth))
                .current_dir(&out_dir)
                .status()
                .unwrap();
            assert!(status.success());
        }

        let status = Command::new("git")
            .arg("reset")
            .arg(test.sha)
            .arg("--hard")
            .current_dir(&out_dir)
            .status()
            .unwrap();

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status =
        Command::new("git").arg("clean").arg("-fdx").current_dir(&out_dir).status().unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bool {
    let mut command = Command::new(cargo_path);
    command.arg("test");
    for name in packages {
        command.arg("-p").arg(name);
    }
    let status = command
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        // Relax #![deny(warnings)] in some crates
        .env("RUSTFLAGS", "--cap-lints warn")
        .current_dir(crate_path)
        .status()
        .unwrap();

    status.success()
}
<commit_msg>Auto merge of #81507 - weiznich:add_diesel_to_cargo_test, r=Mark-Simulacrum<commit_after>use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
    packages: &'static [&'static str],
    features: Option<&'static [&'static str]>,
    manifest_path: Option<&'static str>,
}

const TEST_REPOS: &[Test] = &[
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "cf056ea5e8052c1feea6141e40ab0306715a2c33",
        lock: None,
        packages: &[],
        features: None,
        manifest_path: None,
    },
    Test {
        name: "ripgrep",
        repo: "https://github.com/BurntSushi/ripgrep",
        sha: "3de31f752729525d85a3d1575ac1978733b3f7e7",
        lock: None,
        packages: &[],
        features: None,
        manifest_path: None,
    },
    Test {
        name: "tokei",
        repo: "https://github.com/XAMPPRocky/tokei",
        sha: "fdf3f8cb279a7aeac0696c87e5d8b0cd946e4f9e",
        lock: None,
        packages: &[],
        features: None,
        manifest_path: None,
    },
    Test {
        name: "xsv",
        repo: "https://github.com/BurntSushi/xsv",
        sha: "3de6c04269a7d315f7e9864b9013451cd9580a08",
        lock: None,
        packages: &[],
        features: None,
        manifest_path: None,
    },
    Test {
        name: "servo",
        repo: "https://github.com/servo/servo",
        sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
        lock: None,
        // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
        // This takes much less time to build than all of Servo and supports stable Rust.
        packages: &["selectors"],
        features: None,
        manifest_path: None,
    },
    Test {
        name: "diesel",
        repo: "https://github.com/diesel-rs/diesel",
        sha: "91493fe47175076f330ce5fc518f0196c0476f56",
        lock: None,
        packages: &[],
        // Test the embeded sqlite variant of diesel
        // This does not require any dependency to be present,
        // sqlite will be compiled as part of the build process
        features: Some(&["sqlite", "libsqlite3-sys/bundled"]),
        // We are only interested in testing diesel itself
        // not any other crate present in the diesel workspace
        // (This is required to set the feature flags above)
        manifest_path: Some("diesel/Cargo.toml"),
    },
];

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let cargo = &args[1];
    let out_dir = Path::new(&args[2]);
    let cargo = &Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        fs::write(&dir.join("Cargo.lock"), lockfile).unwrap();
    }
    if !run_cargo_test(cargo, &dir, test.packages, test.features, test.manifest_path) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap();
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                .arg("fetch")
                .arg(test.repo)
                .arg("master")
                .arg(&format!("--depth={}", depth))
                .current_dir(&out_dir)
                .status()
                .unwrap();
            assert!(status.success());
        }

        let status = Command::new("git")
            .arg("reset")
            .arg(test.sha)
            .arg("--hard")
            .current_dir(&out_dir)
            .status()
            .unwrap();

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status =
        Command::new("git").arg("clean").arg("-fdx").current_dir(&out_dir).status().unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(
    cargo_path: &Path,
    crate_path: &Path,
    packages: &[&str],
    features: Option<&[&str]>,
    manifest_path: Option<&str>,
) -> bool {
    let mut command = Command::new(cargo_path);
    command.arg("test");

    if let Some(path) = manifest_path {
        command.arg(format!("--manifest-path={}", path));
    }

    if let Some(features) = features {
        command.arg("--no-default-features");
        for feature in features {
            command.arg(format!("--features={}", feature));
        }
    }

    for name in packages {
        command.arg("-p").arg(name);
    }

    let status = command
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        // Relax #![deny(warnings)] in some crates
        .env("RUSTFLAGS", "--cap-lints warn")
        .current_dir(crate_path)
        .status()
        .unwrap();

    status.success()
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    access_path::{AccessPath, Accesses},
    account_config,
    event::EventKey,
    identifier::{IdentStr, Identifier},
    language_storage::StructTag,
    validator_public_keys::ValidatorPublicKeys,
};
use canonical_serialization::{
    CanonicalDeserialize, CanonicalDeserializer, CanonicalSerialize, CanonicalSerializer,
    SimpleDeserializer,
};
use failure::prelude::*;
use lazy_static::lazy_static;
#[cfg(any(test, feature = "testing"))]
use proptest_derive::Arbitrary;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::fmt;

lazy_static! {
    static ref VALIDATOR_SET_MODULE_NAME: Identifier = Identifier::new("ValidatorSet").unwrap();
    static ref VALIDATOR_SET_STRUCT_NAME: Identifier = Identifier::new("T").unwrap();
}

pub fn validator_set_module_name() -> &'static IdentStr {
    &*VALIDATOR_SET_MODULE_NAME
}

pub fn validator_set_struct_name() -> &'static IdentStr {
    &*VALIDATOR_SET_STRUCT_NAME
}

pub fn validator_set_tag() -> StructTag {
    StructTag {
        name: validator_set_struct_name().to_owned(),
        address: account_config::core_code_address(),
        module: validator_set_module_name().to_owned(),
        type_params: vec![],
    }
}

pub(crate) fn validator_set_path() -> Vec<u8> {
    AccessPath::resource_access_vec(&validator_set_tag(), &Accesses::empty())
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
pub struct ValidatorSet(Vec<ValidatorPublicKeys>);

impl fmt::Display for ValidatorSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        write!(f, "[")?;
        for validator in &self.0 {
            write!(f, "{} ", validator)?;
        }
        write!(f, "]")
    }
}

impl ValidatorSet {
    /// Constructs a ValidatorSet resource.
    pub fn new(payload: Vec<ValidatorPublicKeys>) -> Self {
        ValidatorSet(payload)
    }

    pub fn payload(&self) -> &[ValidatorPublicKeys] {
        &self.0
    }

    pub fn change_event_key() -> EventKey {
        EventKey::new_from_address(&account_config::validator_set_address(), 0)
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        SimpleDeserializer::deserialize(bytes)
    }
}

impl CanonicalSerialize for ValidatorSet {
    fn serialize(&self, mut serializer: &mut impl CanonicalSerializer) -> Result<()> {
        // TODO: We do not use encode_vec and decode_vec because the VM serializes these
        // differently. This will be fixed once collections are supported in the language.
        serializer = serializer.encode_u32(self.0.len() as u32)?;
        for validator_public_keys in &self.0 {
            serializer = serializer.encode_struct(validator_public_keys)?;
        }
        Ok(())
    }
}

impl CanonicalDeserialize for ValidatorSet {
    fn deserialize(deserializer: &mut impl CanonicalDeserializer) -> Result<Self> {
        let size = deserializer.decode_u32()?;
        let mut payload = vec![];
        for _i in 0..size {
            payload.push(deserializer.decode_struct::<ValidatorPublicKeys>()?);
        }
        Ok(ValidatorSet::new(payload))
    }
}

impl FromProto for ValidatorSet {
    type ProtoType = crate::proto::validator_set::ValidatorSet;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        Ok(ValidatorSet::new(
            object
                .take_validator_public_keys()
                .into_iter()
                .map(ValidatorPublicKeys::from_proto)
                .collect::<Result<Vec<_>>>()?,
        ))
    }
}

impl IntoProto for ValidatorSet {
    type ProtoType = crate::proto::validator_set::ValidatorSet;

    fn into_proto(self) -> Self::ProtoType {
        let mut out = Self::ProtoType::new();
        out.set_validator_public_keys(protobuf::RepeatedField::from_vec(
            self.0
                .into_iter()
                .map(ValidatorPublicKeys::into_proto)
                .collect(),
        ));
        out
    }
}
<commit_msg>[types] impl conversions from/to prost proto and ValidatorSet<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    access_path::{AccessPath, Accesses},
    account_config,
    event::EventKey,
    identifier::{IdentStr, Identifier},
    language_storage::StructTag,
    validator_public_keys::ValidatorPublicKeys,
};
use canonical_serialization::{
    CanonicalDeserialize, CanonicalDeserializer, CanonicalSerialize, CanonicalSerializer,
    SimpleDeserializer,
};
use failure::prelude::*;
use lazy_static::lazy_static;
#[cfg(any(test, feature = "testing"))]
use proptest_derive::Arbitrary;
use proto_conv::{FromProto, IntoProto};
use serde::{Deserialize, Serialize};
use std::{
    convert::{TryFrom, TryInto},
    fmt,
};

lazy_static! {
    static ref VALIDATOR_SET_MODULE_NAME: Identifier = Identifier::new("ValidatorSet").unwrap();
    static ref VALIDATOR_SET_STRUCT_NAME: Identifier = Identifier::new("T").unwrap();
}

pub fn validator_set_module_name() -> &'static IdentStr {
    &*VALIDATOR_SET_MODULE_NAME
}

pub fn validator_set_struct_name() -> &'static IdentStr {
    &*VALIDATOR_SET_STRUCT_NAME
}

pub fn validator_set_tag() -> StructTag {
    StructTag {
        name: validator_set_struct_name().to_owned(),
        address: account_config::core_code_address(),
        module: validator_set_module_name().to_owned(),
        type_params: vec![],
    }
}

pub(crate) fn validator_set_path() -> Vec<u8> {
    AccessPath::resource_access_vec(&validator_set_tag(), &Accesses::empty())
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "testing"), derive(Arbitrary))]
pub struct ValidatorSet(Vec<ValidatorPublicKeys>);

impl fmt::Display for ValidatorSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        write!(f, "[")?;
        for validator in &self.0 {
            write!(f, "{} ", validator)?;
        }
        write!(f, "]")
    }
}

impl ValidatorSet {
    /// Constructs a ValidatorSet resource.
    pub fn new(payload: Vec<ValidatorPublicKeys>) -> Self {
        ValidatorSet(payload)
    }

    pub fn payload(&self) -> &[ValidatorPublicKeys] {
        &self.0
    }

    pub fn change_event_key() -> EventKey {
        EventKey::new_from_address(&account_config::validator_set_address(), 0)
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        SimpleDeserializer::deserialize(bytes)
    }
}

impl CanonicalSerialize for ValidatorSet {
    fn serialize(&self, mut serializer: &mut impl CanonicalSerializer) -> Result<()> {
        // TODO: We do not use encode_vec and decode_vec because the VM serializes these
        // differently. This will be fixed once collections are supported in the language.
        serializer = serializer.encode_u32(self.0.len() as u32)?;
        for validator_public_keys in &self.0 {
            serializer = serializer.encode_struct(validator_public_keys)?;
        }
        Ok(())
    }
}

impl CanonicalDeserialize for ValidatorSet {
    fn deserialize(deserializer: &mut impl CanonicalDeserializer) -> Result<Self> {
        let size = deserializer.decode_u32()?;
        let mut payload = vec![];
        for _i in 0..size {
            payload.push(deserializer.decode_struct::<ValidatorPublicKeys>()?);
        }
        Ok(ValidatorSet::new(payload))
    }
}

impl FromProto for ValidatorSet {
    type ProtoType = crate::proto::validator_set::ValidatorSet;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        Ok(ValidatorSet::new(
            object
                .take_validator_public_keys()
                .into_iter()
                .map(ValidatorPublicKeys::from_proto)
                .collect::<Result<Vec<_>>>()?,
        ))
    }
}

impl IntoProto for ValidatorSet {
    type ProtoType = crate::proto::validator_set::ValidatorSet;

    fn into_proto(self) -> Self::ProtoType {
        let mut out = Self::ProtoType::new();
        out.set_validator_public_keys(protobuf::RepeatedField::from_vec(
            self.0
                .into_iter()
                .map(ValidatorPublicKeys::into_proto)
                .collect(),
        ));
        out
    }
}

impl TryFrom<crate::proto::types::ValidatorSet> for ValidatorSet {
    type Error = Error;

    fn try_from(proto: crate::proto::types::ValidatorSet) -> Result<Self> {
        Ok(ValidatorSet::new(
            proto
                .validator_public_keys
                .into_iter()
                .map(TryInto::try_into)
                .collect::<Result<Vec<_>>>()?,
        ))
    }
}

impl From<ValidatorSet> for crate::proto::types::ValidatorSet {
    fn from(set: ValidatorSet) -> Self {
        Self {
            validator_public_keys: set.0.into_iter().map(Into::into).collect(),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(question_mark)]

extern crate cloudfm;
extern crate chill;
extern crate dotenv;
extern crate serde_json;

use cloudfm::{Index, Indexer, views, User, Error, Backend};
use chill::{ViewRow, DocumentId, AllDocumentsViewValue};
use std::env;
use dotenv::dotenv;

pub fn main() {
    dotenv().ok();

    let db_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let db = chill::Client::new(&db_url).expect("DATABASE_URL must be a valid URL");

    let (count, errors) = index_all(db);
    println!("index_all done. success: {}, failed: {}",
             count - errors.len(),
             errors.len());
    for error in errors {
        println!("error: {:#?}", error);
    }
}

pub fn index_all(db: chill::Client) -> (usize, Vec<Error>) {
    let mut errors: Vec<Error> = Vec::new();

    // skips design docs
    let start_key = &DocumentId::from("org.couchdb.user:");

    let action = match db.read_all_documents("/_users") {
        Ok(action) => action.with_start_key(start_key),
        Err(error) => return (1, vec![Error::from(error)]),
    };

    let res = match action.run() {
        Ok(res) => res,
        Err(error) => return (1, vec![Error::from(error)]),
    };

    let view = match res.as_unreduced() {
        Some(view) => view,
        None => unimplemented!(),
    };

    for row in view.rows() {
        if let Err(e) = index_user(&db, row) {
            errors.push(e);
        }
    }

    (view.rows().len(), errors)
}

pub fn index_user(db: &chill::Client,
                  row: &ViewRow<DocumentId, AllDocumentsViewValue>)
                  -> Result<(), Error> {
    let doc = db.read_document(("/_users", row.key()))?.run()?;
    let user: User = doc.get_content()?;

    views::apply(db, &user.db_name())?;

    if let Some(ref backends) = user.backends {
        for backend in backends {
            match backend {
                &Backend::File(ref backend) => Index::index(db, &user, backend)?,
                &Backend::Jamendo(ref backend) => Index::index(db, &user, backend)?,
                &Backend::Webdav(ref backend) => Index::index(db, &user, backend)?,
            }
        }
    }

    Ok(())
}
<commit_msg>feat(indexd): default db url<commit_after>#![feature(question_mark)]

extern crate cloudfm;
extern crate chill;
extern crate dotenv;
extern crate serde_json;

use cloudfm::{Index, Indexer, views, User, Error, Backend};
use chill::{ViewRow, DocumentId, AllDocumentsViewValue};
use std::env;
use dotenv::dotenv;

pub fn main() {
    dotenv().ok();

    let db_url = env::var("DATABASE_URL").unwrap_or("http://localhost:5984".into());
    let db = chill::Client::new(&db_url).expect("DATABASE_URL must be a valid URL");

    let (count, errors) = index_all(db);
    println!("index_all done. success: {}, failed: {}",
             count - errors.len(),
             errors.len());
    for error in errors {
        println!("error: {:#?}", error);
    }
}

pub fn index_all(db: chill::Client) -> (usize, Vec<Error>) {
    let mut errors: Vec<Error> = Vec::new();

    // skips design docs
    let start_key = &DocumentId::from("org.couchdb.user:");

    let action = match db.read_all_documents("/_users") {
        Ok(action) => action.with_start_key(start_key),
        Err(error) => return (1, vec![Error::from(error)]),
    };

    let res = match action.run() {
        Ok(res) => res,
        Err(error) => return (1, vec![Error::from(error)]),
    };

    let view = match res.as_unreduced() {
        Some(view) => view,
        None => unimplemented!(),
    };

    for row in view.rows() {
        if let Err(e) = index_user(&db, row) {
            errors.push(e);
        }
    }

    (view.rows().len(), errors)
}

pub fn index_user(db: &chill::Client,
                  row: &ViewRow<DocumentId, AllDocumentsViewValue>)
                  -> Result<(), Error> {
    let doc = db.read_document(("/_users", row.key()))?.run()?;
    let user: User = doc.get_content()?;

    views::apply(db, &user.db_name())?;

    if let Some(ref backends) = user.backends {
        for backend in backends {
            match backend {
                &Backend::File(ref backend) => Index::index(db, &user, backend)?,
                &Backend::Jamendo(ref backend) => Index::index(db, &user, backend)?,
                &Backend::Webdav(ref backend) => Index::index(db, &user, backend)?,
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![doc = include_str!("core_arch_docs.md")]
#![allow(improper_ctypes_definitions)]
#![allow(dead_code)]
#![allow(unused_features)]
#![deny(rust_2018_idioms)]
#![feature(
    custom_inner_attributes,
    link_llvm_intrinsics,
    platform_intrinsics,
    repr_simd,
    simd_ffi,
    proc_macro_hygiene,
    stmt_expr_attributes,
    core_intrinsics,
    no_core,
    rustc_attrs,
    stdsimd,
    staged_api,
    doc_cfg,
    tbm_target_feature,
    sse4a_target_feature,
    riscv_target_feature,
    arm_target_feature,
    cmpxchg16b_target_feature,
    avx512_target_feature,
    mips_target_feature,
    powerpc_target_feature,
    wasm_target_feature,
    abi_unadjusted,
    rtm_target_feature,
    f16c_target_feature,
    allow_internal_unstable,
    decl_macro,
    bench_black_box,
    asm_const
)]
#![cfg_attr(test, feature(test, abi_vectorcall))]
#![deny(clippy::missing_inline_in_public_items)]
#![allow(
    clippy::inline_always,
    clippy::too_many_arguments,
    clippy::cast_sign_loss,
    clippy::cast_lossless,
    clippy::cast_possible_wrap,
    clippy::cast_possible_truncation,
    clippy::cast_precision_loss,
    clippy::shadow_reuse,
    clippy::cognitive_complexity,
    clippy::similar_names,
    clippy::many_single_char_names
)]
#![cfg_attr(test, allow(unused_imports))]
#![no_std]
#![unstable(feature = "stdsimd", issue = "27731")]
#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate std_detect;
#[path = "mod.rs"]
mod core_arch;

pub mod arch {
    pub use crate::core_arch::arch::*;
    pub use core::arch::asm;
}

#[allow(unused_imports)]
use core::{convert, ffi, hint, intrinsics, marker, mem, ops, ptr, sync};
<commit_msg>crate: use target feature v1.1<commit_after>#![doc = include_str!("core_arch_docs.md")]
#![allow(improper_ctypes_definitions)]
#![allow(dead_code)]
#![allow(unused_features)]
#![deny(rust_2018_idioms)]
#![feature(
    custom_inner_attributes,
    link_llvm_intrinsics,
    platform_intrinsics,
    repr_simd,
    simd_ffi,
    proc_macro_hygiene,
    stmt_expr_attributes,
    core_intrinsics,
    no_core,
    rustc_attrs,
    stdsimd,
    staged_api,
    doc_cfg,
    tbm_target_feature,
    sse4a_target_feature,
    riscv_target_feature,
    arm_target_feature,
    cmpxchg16b_target_feature,
    avx512_target_feature,
    mips_target_feature,
    powerpc_target_feature,
    wasm_target_feature,
    abi_unadjusted,
    rtm_target_feature,
    f16c_target_feature,
    allow_internal_unstable,
    decl_macro,
    bench_black_box,
    asm_const,
    target_feature_11
)]
#![cfg_attr(test, feature(test, abi_vectorcall))]
#![deny(clippy::missing_inline_in_public_items)]
#![allow(
    clippy::inline_always,
    clippy::too_many_arguments,
    clippy::cast_sign_loss,
    clippy::cast_lossless,
    clippy::cast_possible_wrap,
    clippy::cast_possible_truncation,
    clippy::cast_precision_loss,
    clippy::shadow_reuse,
    clippy::cognitive_complexity,
    clippy::similar_names,
    clippy::many_single_char_names
)]
#![cfg_attr(test, allow(unused_imports))]
#![no_std]
#![unstable(feature = "stdsimd", issue = "27731")]
#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate std_detect;
#[path = "mod.rs"]
mod core_arch;

pub mod arch {
    pub use crate::core_arch::arch::*;
    pub use core::arch::asm;
}

#[allow(unused_imports)]
use core::{convert, ffi, hint, intrinsics, marker, mem, ops, ptr, sync};
<|endoftext|>


<commit_before>#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_mut
)]
#![feature(extern_types, libc)]

use cpu2::cpu::{reg128, reg64};

#[no_mangle]
pub static mut reg8: *mut u8 = unsafe { 4i32 as *mut u8 };
#[no_mangle]
pub static mut reg16: *mut u16 = unsafe { 4i32 as *mut u16 };
#[no_mangle]
pub static mut reg8s: *mut i8 = unsafe { 4i32 as *mut i8 };
#[no_mangle]
pub static mut reg16s: *mut i16 = unsafe { 4i32 as *mut i16 };
#[no_mangle]
pub static mut reg32s: *mut i32 = unsafe { 4i32 as *mut i32 };
#[no_mangle]
pub static mut last_op1: *mut i32 = unsafe { 512i32 as *mut i32 };
#[no_mangle]
pub static mut last_op2: *mut i32 = unsafe { 516i32 as *mut i32 };
#[no_mangle]
pub static mut last_op_size: *mut i32 = unsafe { 520i32 as *mut i32 };
#[no_mangle]
pub static mut last_add_result: *mut i32 = unsafe { 524i32 as *mut i32 };
#[no_mangle]
pub static mut last_result: *mut i32 = unsafe { 528i32 as *mut i32 };
#[no_mangle]
pub static mut flags_changed: *mut i32 = unsafe { 532i32 as *mut i32 };
#[no_mangle]
pub static mut flags: *mut i32 = unsafe { 536i32 as *mut i32 };
#[no_mangle]
pub static mut page_fault: *mut bool = unsafe { 540i32 as *mut bool };
#[no_mangle]
pub static mut a20_enabled: *mut bool = unsafe { 552i32 as *mut bool };
#[no_mangle]
pub static mut instruction_pointer: *mut i32 = unsafe { 556i32 as *mut i32 };
#[no_mangle]
pub static mut previous_ip: *mut i32 = unsafe { 560i32 as *mut i32 };
#[no_mangle]
pub static mut idtr_size: *mut i32 = unsafe { 564i32 as *mut i32 };
#[no_mangle]
pub static mut idtr_offset: *mut i32 = unsafe { 568i32 as *mut i32 };
#[no_mangle]
pub static mut gdtr_size: *mut i32 = unsafe { 572i32 as *mut i32 };
#[no_mangle]
pub static mut gdtr_offset: *mut i32 = unsafe { 576i32 as *mut i32 };
#[no_mangle]
pub static mut cr: *mut i32 = unsafe { 580i32 as *mut i32 };
#[no_mangle]
pub static mut cpl: *mut u8 = unsafe { 612i32 as *mut u8 };
#[no_mangle]
pub static mut in_hlt: *mut bool = unsafe { 616i32 as *mut bool };
#[no_mangle]
pub static mut last_virt_eip: *mut i32 = unsafe { 620i32 as *mut i32 };
#[no_mangle]
pub static mut eip_phys: *mut i32 = unsafe { 624i32 as *mut i32 };
#[no_mangle]
pub static mut last_virt_esp: *mut i32 = unsafe { 628i32 as *mut i32 };
#[no_mangle]
pub static mut esp_phys: *mut i32 = unsafe { 632i32 as *mut i32 };
#[no_mangle]
pub static mut sysenter_cs: *mut i32 = unsafe { 636i32 as *mut i32 };
#[no_mangle]
pub static mut sysenter_esp: *mut i32 = unsafe { 640i32 as *mut i32 };
#[no_mangle]
pub static mut sysenter_eip: *mut i32 = unsafe { 644i32 as *mut i32 };
#[no_mangle]
pub static mut prefixes: *mut u8 = unsafe { 648i32 as *mut u8 };
#[no_mangle]
pub static mut timestamp_counter: *mut u32 = unsafe { 664i32 as *mut u32 };
#[no_mangle]
pub static mut sreg: *mut u16 = unsafe { 668i32 as *mut u16 };
#[no_mangle]
pub static mut dreg: *mut i32 = unsafe { 684i32 as *mut i32 };
#[no_mangle]
pub static mut fw_value: *mut i32 = unsafe { 720i32 as *mut i32 };
#[no_mangle]
pub static mut segment_is_null: *mut bool = unsafe { 724i32 as *mut bool };
#[no_mangle]
pub static mut segment_offsets: *mut i32 = unsafe { 736i32 as *mut i32 };
#[no_mangle]
pub static mut segment_limits: *mut u32 = unsafe { 768i32 as *mut u32 };
#[no_mangle]
pub static mut protected_mode: *mut bool = unsafe { 800i32 as *mut bool };
#[no_mangle]
pub static mut is_32: *mut bool = unsafe { 804i32 as *mut bool };
#[no_mangle]
pub static mut stack_size_32: *mut bool = unsafe { 808i32 as *mut bool };
#[no_mangle]
pub static mut memory_size: *mut u32 = unsafe { 812i32 as *mut u32 };
#[no_mangle]
pub static mut fpu_stack_empty: *mut i32 = unsafe { 816i32 as *mut i32 };
#[no_mangle]
pub static mut mxcsr: *mut i32 = unsafe { 824i32 as *mut i32 };
#[no_mangle]
pub static mut reg_xmm: *mut reg128 = unsafe { 828i32 as *mut reg128 };
#[no_mangle]
pub static mut current_tsc: *mut u64 = unsafe { 956i32 as *mut u64 };
#[no_mangle]
pub static mut fpu_st: *mut f64 = unsafe { 968i32 as *mut f64 };
#[no_mangle]
pub static mut fpu_st8: *mut u8 = unsafe { 968i32 as *mut u8 };
#[no_mangle]
pub static mut fpu_st32: *mut i32 = unsafe { 968i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_stack_ptr: *mut u32 = unsafe { 1032i32 as *mut u32 };
#[no_mangle]
pub static mut fpu_control_word: *mut i32 = unsafe { 1036i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_status_word: *mut i32 = unsafe { 1040i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_opcode: *mut i32 = unsafe { 1044i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_ip: *mut i32 = unsafe { 1048i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_ip_selector: *mut i32 = unsafe { 1052i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_dp: *mut i32 = unsafe { 1056i32 as *mut i32 };
#[no_mangle]
pub static mut fpu_dp_selector: *mut i32 = unsafe { 1060i32 as *mut i32 };
#[no_mangle]
pub static mut reg_mmx: *mut reg64 = unsafe { 1064i32 as *mut reg64 };
#[no_mangle]
pub static mut opstats_buffer: *mut u32 = unsafe { 4096i32 as *mut u32 };
#[no_mangle]
pub static mut opstats_buffer_0f: *mut u32 = unsafe { 5120i32 as *mut u32 };
#[no_mangle]
pub static mut tlb_data: *mut i32 = unsafe { 4194304i32 as *mut i32 };
<commit_msg>c2rust cleanup: Make global pointers constants<commit_after>#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_mut
)]
#![feature(extern_types, libc)]

use cpu2::cpu::{reg128, reg64};

pub const reg8: *mut u8 = 4i32 as *mut u8;
pub const reg16: *mut u16 = 4i32 as *mut u16;
pub const reg8s: *mut i8 = 4i32 as *mut i8;
pub const reg16s: *mut i16 = 4i32 as *mut i16;
pub const reg32s: *mut i32 = 4i32 as *mut i32;
pub const last_op1: *mut i32 = 512i32 as *mut i32;
pub const last_op2: *mut i32 = 516i32 as *mut i32;
pub const last_op_size: *mut i32 = 520i32 as *mut i32;
pub const last_add_result: *mut i32 = 524i32 as *mut i32;
pub const last_result: *mut i32 = 528i32 as *mut i32;
pub const flags_changed: *mut i32 = 532i32 as *mut i32;
pub const flags: *mut i32 = 536i32 as *mut i32;
pub const page_fault: *mut bool = 540i32 as *mut bool;
pub const a20_enabled: *mut bool = 552i32 as *mut bool;
pub const instruction_pointer: *mut i32 = 556i32 as *mut i32;
pub const previous_ip: *mut i32 = 560i32 as *mut i32;
pub const idtr_size: *mut i32 = 564i32 as *mut i32;
pub const idtr_offset: *mut i32 = 568i32 as *mut i32;
pub const gdtr_size: *mut i32 = 572i32 as *mut i32;
pub const gdtr_offset: *mut i32 = 576i32 as *mut i32;
pub const cr: *mut i32 = 580i32 as *mut i32;
pub const cpl: *mut u8 = 612i32 as *mut u8;
pub const in_hlt: *mut bool = 616i32 as *mut bool;
pub const last_virt_eip: *mut i32 = 620i32 as *mut i32;
pub const eip_phys: *mut i32 = 624i32 as *mut i32;
pub const last_virt_esp: *mut i32 = 628i32 as *mut i32;
pub const esp_phys: *mut i32 = 632i32 as *mut i32;
pub const sysenter_cs: *mut i32 = 636i32 as *mut i32;
pub const sysenter_esp: *mut i32 = 640i32 as *mut i32;
pub const sysenter_eip: *mut i32 = 644i32 as *mut i32;
pub const prefixes: *mut u8 = 648i32 as *mut u8;
pub const timestamp_counter: *mut u32 = 664i32 as *mut u32;
pub const sreg: *mut u16 = 668i32 as *mut u16;
pub const dreg: *mut i32 = 684i32 as *mut i32;
pub const fw_value: *mut i32 = 720i32 as *mut i32;
pub const segment_is_null: *mut bool = 724i32 as *mut bool;
pub const segment_offsets: *mut i32 = 736i32 as *mut i32;
pub const segment_limits: *mut u32 = 768i32 as *mut u32;
pub const protected_mode: *mut bool = 800i32 as *mut bool;
pub const is_32: *mut bool = 804i32 as *mut bool;
pub const stack_size_32: *mut bool = 808i32 as *mut bool;
pub const memory_size: *mut u32 = 812i32 as *mut u32;
pub const fpu_stack_empty: *mut i32 = 816i32 as *mut i32;
pub const mxcsr: *mut i32 = 824i32 as *mut i32;
pub const reg_xmm: *mut reg128 = 828i32 as *mut reg128;
pub const current_tsc: *mut u64 = 956i32 as *mut u64;
pub const fpu_st: *mut f64 = 968i32 as *mut f64;
pub const fpu_st8: *mut u8 = 968i32 as *mut u8;
pub const fpu_st32: *mut i32 = 968i32 as *mut i32;
pub const fpu_stack_ptr: *mut u32 = 1032i32 as *mut u32;
pub const fpu_control_word: *mut i32 = 1036i32 as *mut i32;
pub const fpu_status_word: *mut i32 = 1040i32 as *mut i32;
pub const fpu_opcode: *mut i32 = 1044i32 as *mut i32;
pub const fpu_ip: *mut i32 = 1048i32 as *mut i32;
pub const fpu_ip_selector: *mut i32 = 1052i32 as *mut i32;
pub const fpu_dp: *mut i32 = 1056i32 as *mut i32;
pub const fpu_dp_selector: *mut i32 = 1060i32 as *mut i32;
pub const reg_mmx: *mut reg64 = 1064i32 as *mut reg64;
pub const opstats_buffer: *mut u32 = 4096i32 as *mut u32;
pub const opstats_buffer_0f: *mut u32 = 5120i32 as *mut u32;
pub const tlb_data: *mut i32 = 4194304i32 as *mut i32;
<|endoftext|>


<commit_before>

use errors::*;
use notifications::Notification;
use sha2::Sha256;
use std::env;
use std::path::Path;
use url::Url;

pub fn download_file(url: &Url,
                     path: &Path,
                     hasher: Option<&mut Sha256>,
                     notify_handler: &Fn(Notification))
                     -> Result<()> {
    if env::var_os("RUSTUP_USE_HYPER").is_some() {
        self::hyper::download_file(url, path, hasher, notify_handler)
    } else {
        self::curl::download_file(url, path, hasher, notify_handler)
    }
}

mod curl {
    use curl::easy::Easy;
    use errors::*;
    use notifications::Notification;
    use sha2::{Sha256, Digest};
    use std::cell::RefCell;
    use std::fs;
    use std::path::Path;
    use std::str;
    use std::time::Duration;
    use url::Url;

    pub fn download_file(url: &Url,
                         path: &Path,
                         mut hasher: Option<&mut Sha256>,
                         notify_handler: &Fn(Notification))
                         -> Result<()> {
        use notifications::Notification;
        use std::io::Write;

        let mut file = try!(fs::File::create(&path).chain_err(
            || "error creating file for download"));

        // Fetch either a cached libcurl handle (which will preserve open
        // connections) or create a new one if it isn't listed.
        //
        // Once we've acquired it, reset the lifetime from 'static to our local
        // scope.
        thread_local!(static EASY: RefCell<Easy> = RefCell::new(Easy::new()));
        EASY.with(|handle| {
            let mut handle = handle.borrow_mut();

            try!(handle.url(&url.to_string()).chain_err(|| "failed to set url"));
            try!(handle.follow_location(true).chain_err(|| "failed to set follow redirects"));

            // Take at most 30s to connect
            try!(handle.connect_timeout(Duration::new(30, 0)).chain_err(|| "failed to set connect timeout"));

            // Fail if less than 10 bytes are transferred every 30 seconds
            try!(handle.low_speed_limit(10).chain_err(|| "failed to set low speed limit"));
            try!(handle.low_speed_time(Duration::new(30, 0)).chain_err(|| "failed to set low speed time"));

            {
                let fserr = RefCell::new(None);
                let mut transfer = handle.transfer();

                // Data callback for libcurl which is called with data that's
                // downloaded. We just feed it into our hasher and also write it out
                // to disk.
                try!(transfer.write_function(|data| {
                    if let Some(ref mut h) = hasher {
                        h.input(data);
                    }
                    notify_handler(Notification::DownloadDataReceived(data.len()));
                    match file.write_all(data) {
                        Ok(()) => Ok(data.len()),
                        Err(e) => {
                            *fserr.borrow_mut() = Some(e);
                            Ok(0)
                        }
                    }
                }).chain_err(|| "failed to set write"));

                // Listen for headers and parse out a `Content-Length` if it comes
                // so we know how much we're downloading.
                try!(transfer.header_function(|header| {
                    if let Ok(data) = str::from_utf8(header) {
                        let prefix = "Content-Length: ";
                        if data.starts_with(prefix) {
                            if let Ok(s) = data[prefix.len()..].trim().parse() {
                                let msg = Notification::DownloadContentLengthReceived(s);
                                notify_handler(msg);
                            }
                        }
                    }
                    true
                }).chain_err(|| "failed to set header"));

                // If an error happens check to see if we had a filesystem error up
                // in `fserr`, but we always want to punt it up.
                try!(transfer.perform().or_else(|e| {
                    match fserr.borrow_mut().take() {
                        Some(fs) => Err(fs).chain_err(|| ErrorKind::HttpError(e)),
                        None => Err(ErrorKind::HttpError(e).into())
                    }
                }));
            }

            // If we didn't get a 200 or 0 ("OK" for files) then return an error
            let code = try!(handle.response_code().chain_err(|| "failed to get response code"));
            if code != 200 && code != 0 {
                return Err(ErrorKind::HttpStatus(code).into());
            }

            notify_handler(Notification::DownloadFinished);
            Ok(())
        })
    }
}

mod hyper {
    use hyper;
    use notifications::Notification;
    use sha2::{Digest, Sha256};
    use std::fs;
    use std::io;
    use std::path::Path;
    use std::time::Duration;
    use url::Url;
    use errors::*;

    fn proxy_from_env(url: &Url) -> Option<(String, u16)> {
        use std::env::var_os;

        let mut maybe_https_proxy = var_os("https_proxy").map(|ref v| v.to_str().unwrap_or("").to_string());
        if maybe_https_proxy.is_none() {
            maybe_https_proxy = var_os("HTTPS_PROXY").map(|ref v| v.to_str().unwrap_or("").to_string());
        }
        let maybe_http_proxy = var_os("http_proxy").map(|ref v| v.to_str().unwrap_or("").to_string());
        let mut maybe_all_proxy = var_os("all_proxy").map(|ref v| v.to_str().unwrap_or("").to_string());
        if maybe_all_proxy.is_none() {
            maybe_all_proxy = var_os("ALL_PROXY").map(|ref v| v.to_str().unwrap_or("").to_string());
        }
        if let Some(url_value) = match url.scheme() {
                                     "https" => maybe_https_proxy.or(maybe_http_proxy.or(maybe_all_proxy)),
                                     "http" => maybe_http_proxy.or(maybe_all_proxy),
                                     _ => maybe_all_proxy,
                                 } {
            if let Ok(proxy_url) = Url::parse(&url_value) {
                if let Some(host) = proxy_url.host_str() {
                    let port = proxy_url.port().unwrap_or(8080);
                    return Some((host.to_string(), port));
                }
            }
        }
        None
    }

    pub fn download_file(url: &Url,
                         path: &Path,
                         mut hasher: Option<&mut Sha256>,
                         notify_handler: &Fn(Notification))
                         -> Result<()> {

        // Short-circuit hyper for the "file:" URL scheme
        if try!(download_from_file_url(url, path, &mut hasher)) {
            return Ok(());
        }

        use hyper::client::{Client, ProxyConfig};
        use hyper::error::Result as HyperResult;
        use hyper::header::ContentLength;
        use hyper::net::{SslClient, NetworkStream, HttpsConnector};
        use native_tls;
        use std::io::Result as IoResult;
        use std::io::{Read, Write};
        use std::net::{SocketAddr, Shutdown};
        use std::sync::{Arc, Mutex};

        // The Hyper HTTP client
        let client;

        let maybe_proxy = proxy_from_env(url);
        if url.scheme() == "https" {

            // All the following is adapter code to use native_tls with hyper.

            struct NativeSslClient;

            impl<T: NetworkStream + Send + Clone> SslClient<T> for NativeSslClient {
                type Stream = NativeSslStream<T>;

                fn wrap_client(&self, stream: T, host: &str) -> HyperResult<Self::Stream> {
                    use native_tls::ClientBuilder as TlsClientBuilder;
                    use hyper::error::Error as HyperError;

                    let mut ssl_builder = try!(TlsClientBuilder::new()
                                               .map_err(|e| HyperError::Ssl(Box::new(e))));
                    let ssl_stream = try!(ssl_builder.handshake(host, stream)
                                          .map_err(|e| HyperError::Ssl(Box::new(e))));

                    Ok(NativeSslStream(Arc::new(Mutex::new(ssl_stream))))
                }
            }

            #[derive(Clone)]
            struct NativeSslStream<T>(Arc<Mutex<native_tls::TlsStream<T>>>);

            #[derive(Debug)]
            struct NativeSslPoisonError;

            impl ::std::error::Error for NativeSslPoisonError {
                fn description(&self) -> &str { "mutex poisoned during TLS operation" }
            }

            impl ::std::fmt::Display for NativeSslPoisonError {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
                    f.write_str(::std::error::Error::description(self))
                }
            }

            impl<T> NetworkStream for NativeSslStream<T>
                where T: NetworkStream
            {
                fn peer_addr(&mut self) -> IoResult<SocketAddr> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.get_mut().peer_addr())
                }
                fn set_read_timeout(&self, dur: Option<Duration>) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|t| t.get_ref().set_read_timeout(dur))
                }
                fn set_write_timeout(&self, dur: Option<Duration>) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|t| t.get_ref().set_write_timeout(dur))
                }
                fn close(&mut self, how: Shutdown) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.get_mut().close(how))
                }
            }

            impl<T> Read for NativeSslStream<T>
                where T: Read + Write
            {
                fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.read(buf))
                }
            }

            impl<T> Write for NativeSslStream<T>
                where T: Read + Write
            {
                fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.write(buf))
                }
                fn flush(&mut self) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.flush())
                }
            }

            maybe_init_certs();

            if maybe_proxy.is_none() {
                // Connect with hyper + native_tls
                client = Client::with_connector(HttpsConnector::new(NativeSslClient));
            } else {
                let proxy_host_port = maybe_proxy.unwrap();
                client = Client::with_proxy_config(ProxyConfig(proxy_host_port.0, proxy_host_port.1, NativeSslClient));
            }
        } else if url.scheme() == "http" {
            if maybe_proxy.is_none() {
                client = Client::new();
            } else {
                let proxy_host_port = maybe_proxy.unwrap();
                client = Client::with_http_proxy(proxy_host_port.0, proxy_host_port.1);
            }
        } else {
            return Err(format!("unsupported URL scheme: '{}'", url.scheme()).into());
        }

        let mut res = try!(client.get(url.clone()).send()
                           .chain_err(|| "failed to make network request"));
        if res.status != hyper::Ok {
            return Err(ErrorKind::HttpStatus(res.status.to_u16() as u32).into());
        }

        let buffer_size = 0x10000;
        let mut buffer = vec![0u8; buffer_size];

        let mut file = try!(fs::File::create(path).chain_err(
            || "error creating file for download"));

        if let Some(len) = res.headers.get::<ContentLength>().cloned() {
            notify_handler(Notification::DownloadContentLengthReceived(len.0));
        }

        loop {
            let bytes_read = try!(io::Read::read(&mut res, &mut buffer)
                                  .chain_err(|| "error reading from socket"));

            if bytes_read != 0 {
                if let Some(ref mut h) = hasher {
                    h.input(&buffer[0..bytes_read]);
                }
                try!(io::Write::write_all(&mut file, &mut buffer[0..bytes_read])
                     .chain_err(|| "unable to write download to disk"));
                notify_handler(Notification::DownloadDataReceived(bytes_read));
            } else {
                try!(file.sync_data().chain_err(|| "unable to sync download to disk"));
                notify_handler(Notification::DownloadFinished);
                return Ok(());
            }
        }
    }

    // Tell our statically-linked OpenSSL where to find root certs
    // cc https://github.com/alexcrichton/git2-rs/blob/master/libgit2-sys/lib.rs#L1267
    #[cfg(not(any(target_os = "windows", target_os = "macos")))]
    fn maybe_init_certs() {
        use std::sync::{Once, ONCE_INIT};
        static INIT: Once = ONCE_INIT;
        INIT.call_once(|| {
            ::openssl_sys::probe::init_ssl_cert_env_vars();
        });
    }

    #[cfg(any(target_os = "windows", target_os = "macos"))]
    fn maybe_init_certs() { }

    fn download_from_file_url(url: &Url,
                              path: &Path,
                              hasher: &mut Option<&mut Sha256>)
                              -> Result<bool> {
        use raw::is_file;

        // The file scheme is mostly for use by tests to mock the dist server
        if url.scheme() == "file" {
            let src = try!(url.to_file_path()
                           .map_err(|_| Error::from(format!("bogus file url: '{}'", url))));
            if !is_file(&src) {
                // Because some of multirust's logic depends on checking
                // the error when a downloaded file doesn't exist, make
                // the file case return the same error value as the
                // network case.
                return Err(ErrorKind::HttpStatus(hyper::status::StatusCode::NotFound.to_u16() as u32).into());
            }
            try!(fs::copy(&src, path).chain_err(|| "failure copying file"));

            if let Some(ref mut h) = *hasher {
                let ref mut f = try!(fs::File::open(path)
                                     .chain_err(|| "unable to open downloaded file"));

                let ref mut buffer = vec![0u8; 0x10000];
                loop {
                    let bytes_read = try!(io::Read::read(f, buffer)
                                          .chain_err(|| "unable to read downloaded file"));
                    if bytes_read == 0 { break }
                    h.input(&buffer[0..bytes_read]);
                }
            }

            Ok(true)
        } else {
            Ok(false)
        }
    }
}
<commit_msg>Add cursory docs to rust_utils::download<commit_after>//! Easy file downloading

use errors::*;
use notifications::Notification;
use sha2::Sha256;
use std::env;
use std::path::Path;
use url::Url;

pub fn download_file(url: &Url,
                     path: &Path,
                     hasher: Option<&mut Sha256>,
                     notify_handler: &Fn(Notification))
                     -> Result<()> {
    if env::var_os("RUSTUP_USE_HYPER").is_some() {
        self::hyper::download_file(url, path, hasher, notify_handler)
    } else {
        self::curl::download_file(url, path, hasher, notify_handler)
    }
}

/// Download via libcurl; encrypt with the native (or OpenSSl) TLS
/// stack via libcurl
mod curl {
    use curl::easy::Easy;
    use errors::*;
    use notifications::Notification;
    use sha2::{Sha256, Digest};
    use std::cell::RefCell;
    use std::fs;
    use std::path::Path;
    use std::str;
    use std::time::Duration;
    use url::Url;

    pub fn download_file(url: &Url,
                         path: &Path,
                         mut hasher: Option<&mut Sha256>,
                         notify_handler: &Fn(Notification))
                         -> Result<()> {
        use notifications::Notification;
        use std::io::Write;

        let mut file = try!(fs::File::create(&path).chain_err(
            || "error creating file for download"));

        // Fetch either a cached libcurl handle (which will preserve open
        // connections) or create a new one if it isn't listed.
        //
        // Once we've acquired it, reset the lifetime from 'static to our local
        // scope.
        thread_local!(static EASY: RefCell<Easy> = RefCell::new(Easy::new()));
        EASY.with(|handle| {
            let mut handle = handle.borrow_mut();

            try!(handle.url(&url.to_string()).chain_err(|| "failed to set url"));
            try!(handle.follow_location(true).chain_err(|| "failed to set follow redirects"));

            // Take at most 30s to connect
            try!(handle.connect_timeout(Duration::new(30, 0)).chain_err(|| "failed to set connect timeout"));

            // Fail if less than 10 bytes are transferred every 30 seconds
            try!(handle.low_speed_limit(10).chain_err(|| "failed to set low speed limit"));
            try!(handle.low_speed_time(Duration::new(30, 0)).chain_err(|| "failed to set low speed time"));

            {
                let fserr = RefCell::new(None);
                let mut transfer = handle.transfer();

                // Data callback for libcurl which is called with data that's
                // downloaded. We just feed it into our hasher and also write it out
                // to disk.
                try!(transfer.write_function(|data| {
                    if let Some(ref mut h) = hasher {
                        h.input(data);
                    }
                    notify_handler(Notification::DownloadDataReceived(data.len()));
                    match file.write_all(data) {
                        Ok(()) => Ok(data.len()),
                        Err(e) => {
                            *fserr.borrow_mut() = Some(e);
                            Ok(0)
                        }
                    }
                }).chain_err(|| "failed to set write"));

                // Listen for headers and parse out a `Content-Length` if it comes
                // so we know how much we're downloading.
                try!(transfer.header_function(|header| {
                    if let Ok(data) = str::from_utf8(header) {
                        let prefix = "Content-Length: ";
                        if data.starts_with(prefix) {
                            if let Ok(s) = data[prefix.len()..].trim().parse() {
                                let msg = Notification::DownloadContentLengthReceived(s);
                                notify_handler(msg);
                            }
                        }
                    }
                    true
                }).chain_err(|| "failed to set header"));

                // If an error happens check to see if we had a filesystem error up
                // in `fserr`, but we always want to punt it up.
                try!(transfer.perform().or_else(|e| {
                    match fserr.borrow_mut().take() {
                        Some(fs) => Err(fs).chain_err(|| ErrorKind::HttpError(e)),
                        None => Err(ErrorKind::HttpError(e).into())
                    }
                }));
            }

            // If we didn't get a 200 or 0 ("OK" for files) then return an error
            let code = try!(handle.response_code().chain_err(|| "failed to get response code"));
            if code != 200 && code != 0 {
                return Err(ErrorKind::HttpStatus(code).into());
            }

            notify_handler(Notification::DownloadFinished);
            Ok(())
        })
    }
}

/// Download via hyper; encrypt with the native (or OpenSSl) TLS
/// stack via native-tls
mod hyper {
    use hyper;
    use notifications::Notification;
    use sha2::{Digest, Sha256};
    use std::fs;
    use std::io;
    use std::path::Path;
    use std::time::Duration;
    use url::Url;
    use errors::*;

    fn proxy_from_env(url: &Url) -> Option<(String, u16)> {
        use std::env::var_os;

        let mut maybe_https_proxy = var_os("https_proxy").map(|ref v| v.to_str().unwrap_or("").to_string());
        if maybe_https_proxy.is_none() {
            maybe_https_proxy = var_os("HTTPS_PROXY").map(|ref v| v.to_str().unwrap_or("").to_string());
        }
        let maybe_http_proxy = var_os("http_proxy").map(|ref v| v.to_str().unwrap_or("").to_string());
        let mut maybe_all_proxy = var_os("all_proxy").map(|ref v| v.to_str().unwrap_or("").to_string());
        if maybe_all_proxy.is_none() {
            maybe_all_proxy = var_os("ALL_PROXY").map(|ref v| v.to_str().unwrap_or("").to_string());
        }
        if let Some(url_value) = match url.scheme() {
                                     "https" => maybe_https_proxy.or(maybe_http_proxy.or(maybe_all_proxy)),
                                     "http" => maybe_http_proxy.or(maybe_all_proxy),
                                     _ => maybe_all_proxy,
                                 } {
            if let Ok(proxy_url) = Url::parse(&url_value) {
                if let Some(host) = proxy_url.host_str() {
                    let port = proxy_url.port().unwrap_or(8080);
                    return Some((host.to_string(), port));
                }
            }
        }
        None
    }

    pub fn download_file(url: &Url,
                         path: &Path,
                         mut hasher: Option<&mut Sha256>,
                         notify_handler: &Fn(Notification))
                         -> Result<()> {

        // Short-circuit hyper for the "file:" URL scheme
        if try!(download_from_file_url(url, path, &mut hasher)) {
            return Ok(());
        }

        use hyper::client::{Client, ProxyConfig};
        use hyper::error::Result as HyperResult;
        use hyper::header::ContentLength;
        use hyper::net::{SslClient, NetworkStream, HttpsConnector};
        use native_tls;
        use std::io::Result as IoResult;
        use std::io::{Read, Write};
        use std::net::{SocketAddr, Shutdown};
        use std::sync::{Arc, Mutex};

        // The Hyper HTTP client
        let client;

        let maybe_proxy = proxy_from_env(url);
        if url.scheme() == "https" {

            // All the following is adapter code to use native_tls with hyper.

            struct NativeSslClient;

            impl<T: NetworkStream + Send + Clone> SslClient<T> for NativeSslClient {
                type Stream = NativeSslStream<T>;

                fn wrap_client(&self, stream: T, host: &str) -> HyperResult<Self::Stream> {
                    use native_tls::ClientBuilder as TlsClientBuilder;
                    use hyper::error::Error as HyperError;

                    let mut ssl_builder = try!(TlsClientBuilder::new()
                                               .map_err(|e| HyperError::Ssl(Box::new(e))));
                    let ssl_stream = try!(ssl_builder.handshake(host, stream)
                                          .map_err(|e| HyperError::Ssl(Box::new(e))));

                    Ok(NativeSslStream(Arc::new(Mutex::new(ssl_stream))))
                }
            }

            #[derive(Clone)]
            struct NativeSslStream<T>(Arc<Mutex<native_tls::TlsStream<T>>>);

            #[derive(Debug)]
            struct NativeSslPoisonError;

            impl ::std::error::Error for NativeSslPoisonError {
                fn description(&self) -> &str { "mutex poisoned during TLS operation" }
            }

            impl ::std::fmt::Display for NativeSslPoisonError {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
                    f.write_str(::std::error::Error::description(self))
                }
            }

            impl<T> NetworkStream for NativeSslStream<T>
                where T: NetworkStream
            {
                fn peer_addr(&mut self) -> IoResult<SocketAddr> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.get_mut().peer_addr())
                }
                fn set_read_timeout(&self, dur: Option<Duration>) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|t| t.get_ref().set_read_timeout(dur))
                }
                fn set_write_timeout(&self, dur: Option<Duration>) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|t| t.get_ref().set_write_timeout(dur))
                }
                fn close(&mut self, how: Shutdown) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.get_mut().close(how))
                }
            }

            impl<T> Read for NativeSslStream<T>
                where T: Read + Write
            {
                fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.read(buf))
                }
            }

            impl<T> Write for NativeSslStream<T>
                where T: Read + Write
            {
                fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.write(buf))
                }
                fn flush(&mut self) -> IoResult<()> {
                    self.0.lock()
                        .map_err(|_| io::Error::new(io::ErrorKind::Other, NativeSslPoisonError))
                        .and_then(|mut t| t.flush())
                }
            }

            maybe_init_certs();

            if maybe_proxy.is_none() {
                // Connect with hyper + native_tls
                client = Client::with_connector(HttpsConnector::new(NativeSslClient));
            } else {
                let proxy_host_port = maybe_proxy.unwrap();
                client = Client::with_proxy_config(ProxyConfig(proxy_host_port.0, proxy_host_port.1, NativeSslClient));
            }
        } else if url.scheme() == "http" {
            if maybe_proxy.is_none() {
                client = Client::new();
            } else {
                let proxy_host_port = maybe_proxy.unwrap();
                client = Client::with_http_proxy(proxy_host_port.0, proxy_host_port.1);
            }
        } else {
            return Err(format!("unsupported URL scheme: '{}'", url.scheme()).into());
        }

        let mut res = try!(client.get(url.clone()).send()
                           .chain_err(|| "failed to make network request"));
        if res.status != hyper::Ok {
            return Err(ErrorKind::HttpStatus(res.status.to_u16() as u32).into());
        }

        let buffer_size = 0x10000;
        let mut buffer = vec![0u8; buffer_size];

        let mut file = try!(fs::File::create(path).chain_err(
            || "error creating file for download"));

        if let Some(len) = res.headers.get::<ContentLength>().cloned() {
            notify_handler(Notification::DownloadContentLengthReceived(len.0));
        }

        loop {
            let bytes_read = try!(io::Read::read(&mut res, &mut buffer)
                                  .chain_err(|| "error reading from socket"));

            if bytes_read != 0 {
                if let Some(ref mut h) = hasher {
                    h.input(&buffer[0..bytes_read]);
                }
                try!(io::Write::write_all(&mut file, &mut buffer[0..bytes_read])
                     .chain_err(|| "unable to write download to disk"));
                notify_handler(Notification::DownloadDataReceived(bytes_read));
            } else {
                try!(file.sync_data().chain_err(|| "unable to sync download to disk"));
                notify_handler(Notification::DownloadFinished);
                return Ok(());
            }
        }
    }

    // Tell our statically-linked OpenSSL where to find root certs
    // cc https://github.com/alexcrichton/git2-rs/blob/master/libgit2-sys/lib.rs#L1267
    #[cfg(not(any(target_os = "windows", target_os = "macos")))]
    fn maybe_init_certs() {
        use std::sync::{Once, ONCE_INIT};
        static INIT: Once = ONCE_INIT;
        INIT.call_once(|| {
            ::openssl_sys::probe::init_ssl_cert_env_vars();
        });
    }

    #[cfg(any(target_os = "windows", target_os = "macos"))]
    fn maybe_init_certs() { }

    fn download_from_file_url(url: &Url,
                              path: &Path,
                              hasher: &mut Option<&mut Sha256>)
                              -> Result<bool> {
        use raw::is_file;

        // The file scheme is mostly for use by tests to mock the dist server
        if url.scheme() == "file" {
            let src = try!(url.to_file_path()
                           .map_err(|_| Error::from(format!("bogus file url: '{}'", url))));
            if !is_file(&src) {
                // Because some of multirust's logic depends on checking
                // the error when a downloaded file doesn't exist, make
                // the file case return the same error value as the
                // network case.
                return Err(ErrorKind::HttpStatus(hyper::status::StatusCode::NotFound.to_u16() as u32).into());
            }
            try!(fs::copy(&src, path).chain_err(|| "failure copying file"));

            if let Some(ref mut h) = *hasher {
                let ref mut f = try!(fs::File::open(path)
                                     .chain_err(|| "unable to open downloaded file"));

                let ref mut buffer = vec![0u8; 0x10000];
                loop {
                    let bytes_read = try!(io::Read::read(f, buffer)
                                          .chain_err(|| "unable to read downloaded file"));
                    if bytes_read == 0 { break }
                    h.input(&buffer[0..bytes_read]);
                }
            }

            Ok(true)
        } else {
            Ok(false)
        }
    }
}
<|endoftext|>


<commit_before>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::module_name;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    let (ptr, mut inner) = rustify_pointers(c_type);
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => &*inner,
                Unsupported => return Err(format!("Unsupported type {}", c_type)),
                VarArgs => panic!("Should not reach here"),
            }.into();
        }
        Type::Record(..)
            | Type::Alias(..)
            | Type::Callback(..) => return Err(format!("Not yet supported type {}", c_type)),
        // TODO: need to recurse into it
        Type::Array(..) => return Err(format!("Not yet supported type {}", c_type)),
        Type::List(..) | Type::SList(..) => (),
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    let msg = format!("c:type mismatch {} != {} of {}", inner, glib_name,
                      env.library.type_(tid).get_name());
                warn!("{}", msg);
                return Err(msg);
                }
            }
            else {
                warn!("Missing glib_name of {}, can't match != {}",
                      env.library.type_(tid).get_name(), inner);
                return Err(format!("Missing glib_name of {}, can't match != {}",
                                    env.library.type_(tid).get_name(), inner));
            }
            inner = try!(fix_external_name(env, tid, &inner));
        }
    }
    let res = if ptr.is_empty() { inner } else { [ptr, inner].connect(" ") };
    trace!("ffi_type({:?}, {}) -> {}", tid, c_type, res);
    Ok(res)
}

fn fix_external_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::MAIN_NAMESPACE || type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = format!("{}_ffi::{}",
            fix_namespace(env, type_id), name);
        if env.type_status(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix.into())
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    let mut name: &str = &module_name(&env.library.namespace(type_id.ns_id).name);
    name = match name {
        "gdk_pixbuf" => "gdk",
        "gio" => "glib",
        "gobject" => "glib",
        _ => name,
    };
    name.into()
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    (ptrs.connect(" "), inner)
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<commit_msg>ffi_type: tweak error handling<commit_after>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::module_name;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    let (ptr, mut inner) = rustify_pointers(c_type);
    let mut ok = true;
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            inner = match fund {
                None => "c_void".into(),
                Boolean => "gboolean".into(),
                Int8 => "i8".into(),
                UInt8 => "u8".into(),
                Int16 => "i16".into(),
                UInt16 => "u16".into(),
                Int32 => "i32".into(),
                UInt32 => "u32".into(),
                Int64 => "i64".into(),
                UInt64 => "u64".into(),
                Char => "c_char".into(),
                UChar => "c_char".into(),
                Int => "c_int".into(),
                UInt => "c_uint".into(),
                Long => "c_long".into(),
                ULong => "c_ulong".into(),
                Size => "size_t".into(),
                SSize => "ssize_t".into(),
                Float => "c_float".into(),
                Double => "c_double".into(),
                UniChar => "u32".into(),
                Utf8 => "c_char".into(),
                Filename => "c_char".into(),
                Type => "GType".into(),
                Pointer => inner,
                Unsupported => {
                    ok = false;
                    format!("[Unsupported type {}]", c_type)
                }
                VarArgs => panic!("Should not reach here"),
            };
        }
        Type::Record(..)
            | Type::Alias(..)
            | Type::Callback(..) => {
                inner = format!("[Not yet supported type {}]", c_type);
                ok = false;
            }
        // TODO: need to recurse into it
        Type::Array(..) => {
            inner = format!("[Not yet supported type {}]", c_type);
            ok = false;
        }
        Type::List(..) | Type::SList(..) => (),
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    inner = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", inner);
                    ok = false;
                }
            }
            else {
                inner = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", inner);
                ok = false;
            }

            if ok {
                let fixed = fix_external_name(env, tid, &inner);
                ok = fixed.is_ok();
                inner = fixed.unwrap_or_else(|s| s);
            }
        }
    }
    let res = if ptr.is_empty() { inner } else { [ptr, inner].connect(" ") };
    trace!("ffi_type({:?}, {}) -> {}", tid, c_type, res);
    if ok { Ok(res) } else { Err(res) }
}

fn fix_external_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::MAIN_NAMESPACE || type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = format!("{}_ffi::{}",
            fix_namespace(env, type_id), name);
        if env.type_status(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix.into())
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    let mut name: &str = &module_name(&env.library.namespace(type_id.ns_id).name);
    name = match name {
        "gdk_pixbuf" => "gdk",
        "gio" => "glib",
        "gobject" => "glib",
        _ => name,
    };
    name.into()
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<|endoftext|>