<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate habitat_http_client as hab_http;
extern crate habitat_core as hab_core;
extern crate hyper;
extern crate hyper_openssl;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate url;

pub mod error;
pub use error::{Error, Result};

use std::io::Read;
use std::path::Path;

use hab_core::package::PackageIdent;
use hab_http::ApiClient;
use hab_http::util::decoded_response;
use hyper::client::{IntoUrl, Response, RequestBuilder};
use hyper::header::{Accept, Authorization, Bearer, ContentType};
use hyper::status::StatusCode;

const DEFAULT_API_PATH: &'static str = "/v1";

pub struct Client(ApiClient);

#[derive(Deserialize)]
pub struct ReverseDependencies {
    pub origin: String,
    pub name: String,
    pub rdeps: Vec<String>,
}

#[derive(Default, Deserialize)]
pub struct JobGroupPromoteResponse {
    pub group_id: String,
    pub not_promoted: Vec<PackageIdent>,
}

impl Client {
    pub fn new<U>(
        endpoint: U,
        product: &str,
        version: &str,
        fs_root_path: Option<&Path>,
    ) -> Result<Self>
    where
        U: IntoUrl,
    {
        let mut endpoint = endpoint.into_url().map_err(Error::URL)?;
        if !endpoint.cannot_be_a_base() && endpoint.path() == "/" {
            endpoint.set_path(DEFAULT_API_PATH);
        }
        Ok(Client(
            ApiClient::new(endpoint, product, version, fs_root_path)
                .map_err(Error::HabitatHttpClient)?,
        ))
    }

    /// Create a job.
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    ///
    /// # Panics
    ///
    /// * Authorization token was not set on client
    pub fn create_job(&self, ident: &PackageIdent, token: &str) -> Result<(String)> {
        debug!("Creating a job for {}", ident);

        let body = json!({
            "project_id": format!("{}", ident)
        });

        let sbody = serde_json::to_string(&body).unwrap();

        let result = self.add_authz(self.0.post("jobs"), token)
            .body(&sbody)
            .header(Accept::json())
            .header(ContentType::json())
            .send();
        match result {
            Ok(mut response) => {
                match response.status {
                    StatusCode::Created => {
                        let mut encoded = String::new();
                        response.read_to_string(&mut encoded).map_err(Error::IO)?;
                        debug!("Body: {:?}", encoded);
                        let v: serde_json::Value =
                            serde_json::from_str(&encoded).map_err(Error::Json)?;
                        let id = v["id"].as_str().unwrap();
                        Ok(id.to_string())
                    }
                    StatusCode::Unauthorized => {
                        Err(Error::APIError(
                            response.status,
                            "Your GitHub token requires both user:email and read:org \
                                             permissions."
                                .to_string(),
                        ))
                    }
                    _ => Err(err_from_response(response)),
                }
            }
            Err(e) => Err(Error::HyperError(e)),
        }
    }

    /// Fetch the reverse dependencies for a package
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    pub fn fetch_rdeps(&self, ident: &PackageIdent) -> Result<Vec<String>> {
        debug!("Fetching the reverse dependencies for {}", ident);

        let url = format!("rdeps/{}", ident);
        let mut res = self.0.get(&url).send().map_err(Error::HyperError)?;
        if res.status != StatusCode::Ok {
            return Err(err_from_response(res));
        }

        let mut encoded = String::new();
        res.read_to_string(&mut encoded).map_err(Error::IO)?;
        debug!("Body: {:?}", encoded);
        let rd: ReverseDependencies = serde_json::from_str(&encoded).map_err(Error::Json)?;
        Ok(rd.rdeps.to_vec())
    }

    /// Promote a job group to a channel
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    pub fn job_group_promote<T: AsRef<str> + serde::Serialize>(
        &self,
        group_id: u64,
        idents: &[T],
        channel: &str,
        token: &str,
    ) -> Result<Vec<PackageIdent>> {
        let json_idents = json!(idents);
        let body = json!({
            "idents": json_idents
        });
        let sbody = serde_json::to_string(&body).unwrap();
        let url = format!("jobs/group/{}/promote/{}", group_id, channel);
        let res = self.add_authz(self.0.post(&url), token)
            .body(&sbody)
            .header(Accept::json())
            .header(ContentType::json())
            .send()
            .map_err(Error::HyperError)?;

        if res.status != StatusCode::Ok {
            debug!("Failed to promote group, status: {:?}", res.status);
            return Err(err_from_response(res));
        }

        match decoded_response::<JobGroupPromoteResponse>(res).map_err(Error::HabitatHttpClient) {
            Ok(value) => Ok(value.not_promoted),
            Err(e) => {
                debug!("Failed to decode response, err: {:?}", e);
                return Err(e);
            }
        }
    }

    /// Cancel a job group
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    pub fn job_group_cancel(&self, group_id: u64, token: &str) -> Result<()> {
        let url = format!("jobs/group/{}/cancel", group_id);
        let res = self.add_authz(self.0.post(&url), token).send().map_err(
            Error::HyperError,
        )?;

        if res.status != StatusCode::NoContent {
            debug!("Failed to cancel group, status: {:?}", res.status);
            return Err(err_from_response(res));
        }

        Ok(())
    }

    fn add_authz<'a>(&'a self, rb: RequestBuilder<'a>, token: &str) -> RequestBuilder {
        rb.header(Authorization(Bearer { token: token.to_string() }))
    }
}

fn err_from_response(mut response: Response) -> Error {
    let mut s = String::new();
    response.read_to_string(&mut s).map_err(Error::IO).unwrap();
    Error::APIError(response.status, s)
}
<commit_msg>Fix hab job group promote result check<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate habitat_http_client as hab_http;
extern crate habitat_core as hab_core;
extern crate hyper;
extern crate hyper_openssl;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate url;

pub mod error;
pub use error::{Error, Result};

use std::io::Read;
use std::path::Path;

use hab_core::package::PackageIdent;
use hab_http::ApiClient;
use hyper::client::{IntoUrl, Response, RequestBuilder};
use hyper::header::{Accept, Authorization, Bearer, ContentType};
use hyper::status::StatusCode;

const DEFAULT_API_PATH: &'static str = "/v1";

pub struct Client(ApiClient);

#[derive(Deserialize)]
pub struct ReverseDependencies {
    pub origin: String,
    pub name: String,
    pub rdeps: Vec<String>,
}

#[derive(Default, Deserialize)]
pub struct JobGroupPromoteResponse {
    pub group_id: String,
    pub not_promoted: Vec<PackageIdent>,
}

impl Client {
    pub fn new<U>(
        endpoint: U,
        product: &str,
        version: &str,
        fs_root_path: Option<&Path>,
    ) -> Result<Self>
    where
        U: IntoUrl,
    {
        let mut endpoint = endpoint.into_url().map_err(Error::URL)?;
        if !endpoint.cannot_be_a_base() && endpoint.path() == "/" {
            endpoint.set_path(DEFAULT_API_PATH);
        }
        Ok(Client(
            ApiClient::new(endpoint, product, version, fs_root_path)
                .map_err(Error::HabitatHttpClient)?,
        ))
    }

    /// Create a job.
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    ///
    /// # Panics
    ///
    /// * Authorization token was not set on client
    pub fn create_job(&self, ident: &PackageIdent, token: &str) -> Result<(String)> {
        debug!("Creating a job for {}", ident);

        let body = json!({
            "project_id": format!("{}", ident)
        });

        let sbody = serde_json::to_string(&body).unwrap();

        let result = self.add_authz(self.0.post("jobs"), token)
            .body(&sbody)
            .header(Accept::json())
            .header(ContentType::json())
            .send();
        match result {
            Ok(mut response) => {
                match response.status {
                    StatusCode::Created => {
                        let mut encoded = String::new();
                        response.read_to_string(&mut encoded).map_err(Error::IO)?;
                        debug!("Body: {:?}", encoded);
                        let v: serde_json::Value =
                            serde_json::from_str(&encoded).map_err(Error::Json)?;
                        let id = v["id"].as_str().unwrap();
                        Ok(id.to_string())
                    }
                    StatusCode::Unauthorized => {
                        Err(Error::APIError(
                            response.status,
                            "Your GitHub token requires both user:email and read:org \
                                             permissions."
                                .to_string(),
                        ))
                    }
                    _ => Err(err_from_response(response)),
                }
            }
            Err(e) => Err(Error::HyperError(e)),
        }
    }

    /// Fetch the reverse dependencies for a package
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    pub fn fetch_rdeps(&self, ident: &PackageIdent) -> Result<Vec<String>> {
        debug!("Fetching the reverse dependencies for {}", ident);

        let url = format!("rdeps/{}", ident);
        let mut res = self.0.get(&url).send().map_err(Error::HyperError)?;
        if res.status != StatusCode::Ok {
            return Err(err_from_response(res));
        }

        let mut encoded = String::new();
        res.read_to_string(&mut encoded).map_err(Error::IO)?;
        debug!("Body: {:?}", encoded);
        let rd: ReverseDependencies = serde_json::from_str(&encoded).map_err(Error::Json)?;
        Ok(rd.rdeps.to_vec())
    }

    /// Promote a job group to a channel
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    pub fn job_group_promote<T: AsRef<str> + serde::Serialize>(
        &self,
        group_id: u64,
        idents: &[T],
        channel: &str,
        token: &str,
    ) -> Result<()> {
        let json_idents = json!(idents);
        let body = json!({
            "idents": json_idents
        });
        let sbody = serde_json::to_string(&body).unwrap();
        let url = format!("jobs/group/{}/promote/{}", group_id, channel);
        let res = self.add_authz(self.0.post(&url), token)
            .body(&sbody)
            .header(Accept::json())
            .header(ContentType::json())
            .send()
            .map_err(Error::HyperError)?;

        if res.status != StatusCode::NoContent {
            debug!("Failed to promote group, status: {:?}", res.status);
            return Err(err_from_response(res));
        }

        Ok(())
    }

    /// Cancel a job group
    ///
    /// # Failures
    ///
    /// * Remote API Server is not available
    pub fn job_group_cancel(&self, group_id: u64, token: &str) -> Result<()> {
        let url = format!("jobs/group/{}/cancel", group_id);
        let res = self.add_authz(self.0.post(&url), token).send().map_err(
            Error::HyperError,
        )?;

        if res.status != StatusCode::NoContent {
            debug!("Failed to cancel group, status: {:?}", res.status);
            return Err(err_from_response(res));
        }

        Ok(())
    }

    fn add_authz<'a>(&'a self, rb: RequestBuilder<'a>, token: &str) -> RequestBuilder {
        rb.header(Authorization(Bearer { token: token.to_string() }))
    }
}

fn err_from_response(mut response: Response) -> Error {
    let mut s = String::new();
    response.read_to_string(&mut s).map_err(Error::IO).unwrap();
    Error::APIError(response.status, s)
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
use rustc_serialize::base64::FromBase64;

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn main() {
	let data = match load_from_file() {
		Err(why) => panic!("Failed to read data/set1_challenge4.txt: {}", why),
		Ok(data) => data,
	};

	let mut smallest_keysize_distance = std::usize::MAX; // maxint?

	for key_size in 2..41 {
		let str1 = &data[0..key_size]; // slice?
		let str2 = &data[key_size..key_size*2];
		let str3 = &data[key_size*2..key_size*3];
		let str4 = &data[key_size*3..key_size*4];

		let mut distances = Vec::new();

		distances.push(edit_distance(str1, str2) / key_size);
		distances.push(edit_distance(str1, str3) / key_size);
		distances.push(edit_distance(str1, str4) / key_size);
		distances.push(edit_distance(str2, str3) / key_size);
		distances.push(edit_distance(str2, str4) / key_size);
		distances.push(edit_distance(str3, str4) / key_size);

		let average_distance = distances.iter().fold(0, |total, &value| total + value);

		if average_distance < smallest_keysize_distance {
			smallest_keysize_distance = average_distance;
		}
	}
}

fn load_from_file() -> std::io::Result<Vec<u8>> {
	let file = try!(File::open("data/set1_challenge6.txt"));
	let reader = BufReader::new(file);

	let mut data = String::new();

	for line in reader.lines() {
		data.push_str(&(line.unwrap()));
	}

	let decoded_data = data.from_base64().unwrap();
	return Ok(decoded_data);
}

/*
this is a test
wokka wokka!!!
-> 37
 */

fn edit_distance(str1: &[u8], str2: &[u8]) -> usize {
	return 0;
}

<commit_msg>set1 challenge6: added hamming distance function<commit_after>extern crate rustc_serialize;
use rustc_serialize::base64::FromBase64;

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn main() {
	let data = match load_from_file() {
		Err(why) => panic!("Failed to read data/set1_challenge4.txt: {}", why),
		Ok(data) => data,
	};

	let mut smallest_keysize_distance = std::usize::MAX;
	let mut smallest_keysize = 0;

	for key_size in 2..41 {
		let str1 = &data[0..key_size]; // slice?
		let str2 = &data[key_size..key_size*2];
		let str3 = &data[key_size*2..key_size*3];
		let str4 = &data[key_size*3..key_size*4];

		let mut distances = Vec::new();

		distances.push(hamming_distance(str1, str2) / key_size);
		distances.push(hamming_distance(str1, str3) / key_size);
		distances.push(hamming_distance(str1, str4) / key_size);
		distances.push(hamming_distance(str2, str3) / key_size);
		distances.push(hamming_distance(str2, str4) / key_size);
		distances.push(hamming_distance(str3, str4) / key_size);

		let average_distance = distances.iter().fold(0, |total, &value| total + value);

		if average_distance < smallest_keysize_distance {
			smallest_keysize_distance = average_distance;
			smallest_keysize = key_size;
		}
	}
	println!("smallest_keysize_distance: {}, key_size: {}", smallest_keysize_distance, smallest_keysize);
}

fn load_from_file() -> std::io::Result<Vec<u8>> {
	let file = try!(File::open("data/set1_challenge6.txt"));
	let reader = BufReader::new(file);

	let mut data = String::new();

	for line in reader.lines() {
		data.push_str(&(line.unwrap()));
	}

	let decoded_data = data.from_base64().unwrap();
	return Ok(decoded_data);
}

/*
binary hamming distance
this is a test
wokka wokka!!!
-> 37
 */
fn hamming_distance(str1: &[u8], str2: &[u8]) -> usize {
    let mut distance = 0;

    for i in 0..str1.len() {
		let diff = str1[i] ^ str2[i];
        if (diff & 0b00000001) > 0 { distance += 1; }
        if (diff & 0b00000010) > 0 { distance += 1; }
        if (diff & 0b00000100) > 0 { distance += 1; }
        if (diff & 0b00001000) > 0 { distance += 1; }
        if (diff & 0b00010000) > 0 { distance += 1; }
        if (diff & 0b00100000) > 0 { distance += 1; }
        if (diff & 0b01000000) > 0 { distance += 1; }
        if (diff & 0b10000000) > 0 { distance += 1; }
    }
    return distance;
}
<|endoftext|>


<commit_before>//! Shim which is passed to Cargo as "rustc" when running the bootstrap.
//!
//! This shim will take care of some various tasks that our build process
//! requires that Cargo can't quite do through normal configuration:
//!
//! 1. When compiling build scripts and build dependencies, we need a guaranteed
//!    full standard library available. The only compiler which actually has
//!    this is the snapshot, so we detect this situation and always compile with
//!    the snapshot compiler.
//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling
//!    (and this slightly differs based on a whether we're using a snapshot or
//!    not), so we do that all here.
//!
//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.

use std::env;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::time::Instant;

fn main() {
    let args = env::args_os().skip(1).collect::<Vec<_>>();

    // Detect whether or not we're a build script depending on whether --target
    // is passed (a bit janky...)
    let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
    let version = args.iter().find(|w| &**w == "-vV");

    let verbose = match env::var("RUSTC_VERBOSE") {
        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
        Err(_) => 0,
    };

    // Use a different compiler for build scripts, since there may not yet be a
    // libstd for the real compiler to use. However, if Cargo is attempting to
    // determine the version of the compiler, the real compiler needs to be
    // used. Currently, these two states are differentiated based on whether
    // --target and -vV is/isn't passed.
    let (rustc, libdir) = if target.is_none() && version.is_none() {
        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
    } else {
        ("RUSTC_REAL", "RUSTC_LIBDIR")
    };
    let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
    let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);

    let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
    let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
    let mut dylib_path = bootstrap::util::dylib_path();
    dylib_path.insert(0, PathBuf::from(&libdir));

    let mut cmd = Command::new(rustc);
    cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());

    // Get the name of the crate we're compiling, if any.
    let crate_name =
        args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str());

    if let Some(crate_name) = crate_name {
        if let Some(target) = env::var_os("RUSTC_TIME") {
            if target == "all"
                || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
            {
                cmd.arg("-Ztime");
            }
        }
    }

    // Print backtrace in case of ICE
    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
        cmd.env("RUST_BACKTRACE", "1");
    }

    if let Ok(lint_flags) = env::var("RUSTC_LINT_FLAGS") {
        cmd.args(lint_flags.split_whitespace());
    }

    if target.is_some() {
        // The stage0 compiler has a special sysroot distinct from what we
        // actually downloaded, so we just always pass the `--sysroot` option,
        // unless one is already set.
        if !args.iter().any(|arg| arg == "--sysroot") {
            cmd.arg("--sysroot").arg(&sysroot);
        }

        // If we're compiling specifically the `panic_abort` crate then we pass
        // the `-C panic=abort` option. Note that we do not do this for any
        // other crate intentionally as this is the only crate for now that we
        // ship with panic=abort.
        //
        // This... is a bit of a hack how we detect this. Ideally this
        // information should be encoded in the crate I guess? Would likely
        // require an RFC amendment to RFC 1513, however.
        //
        // `compiler_builtins` are unconditionally compiled with panic=abort to
        // workaround undefined references to `rust_eh_unwind_resume` generated
        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
        if crate_name == Some("panic_abort")
            || crate_name == Some("compiler_builtins") && stage != "0"
        {
            cmd.arg("-C").arg("panic=abort");
        }
    } else {
        // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars
        // here, but rather Cargo should know what flags to pass rustc itself.

        // Override linker if necessary.
        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
            cmd.arg(format!("-Clinker={}", host_linker));
        }

        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
            if s == "true" {
                cmd.arg("-C").arg("target-feature=+crt-static");
            }
            if s == "false" {
                cmd.arg("-C").arg("target-feature=-crt-static");
            }
        }
    }

    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
        cmd.arg("--remap-path-prefix").arg(&map);
    }

    // Force all crates compiled by this compiler to (a) be unstable and (b)
    // allow the `rustc_private` feature to link to other unstable crates
    // also in the sysroot. We also do this for host crates, since those
    // may be proc macros, in which case we might ship them.
    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
        cmd.arg("-Z").arg("force-unstable-if-unmarked");
    }

    if verbose > 1 {
        eprintln!(
            "rustc command: {:?}={:?} {:?}",
            bootstrap::util::dylib_path_var(),
            env::join_paths(&dylib_path).unwrap(),
            cmd,
        );
        eprintln!("sysroot: {:?}", sysroot);
        eprintln!("libdir: {:?}", libdir);
    }

    if let Some(mut on_fail) = on_fail {
        let e = match cmd.status() {
            Ok(s) if s.success() => std::process::exit(0),
            e => e,
        };
        println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd);
        status_code(&mut on_fail).expect("could not run the backup command");
        std::process::exit(1);
    }

    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
        if let Some(crate_name) = crate_name {
            let start = Instant::now();
            let status = cmd.status().unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
            let dur = start.elapsed();

            let is_test = args.iter().any(|a| a == "--test");
            eprintln!(
                "[RUSTC-TIMING] {} test:{} {}.{:03}",
                crate_name,
                is_test,
                dur.as_secs(),
                dur.subsec_millis()
            );

            match status.code() {
                Some(i) => std::process::exit(i),
                None => {
                    eprintln!("rustc exited with {}", status);
                    std::process::exit(0xfe);
                }
            }
        }
    }

    let code = status_code(&mut cmd).unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
    std::process::exit(code);
}

fn status_code(cmd: &mut Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap())
}
<commit_msg>rustbuild: use Display for exit status instead of Debug, see #74832 for justification<commit_after>//! Shim which is passed to Cargo as "rustc" when running the bootstrap.
//!
//! This shim will take care of some various tasks that our build process
//! requires that Cargo can't quite do through normal configuration:
//!
//! 1. When compiling build scripts and build dependencies, we need a guaranteed
//!    full standard library available. The only compiler which actually has
//!    this is the snapshot, so we detect this situation and always compile with
//!    the snapshot compiler.
//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling
//!    (and this slightly differs based on a whether we're using a snapshot or
//!    not), so we do that all here.
//!
//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.

use std::env;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::time::Instant;

fn main() {
    let args = env::args_os().skip(1).collect::<Vec<_>>();

    // Detect whether or not we're a build script depending on whether --target
    // is passed (a bit janky...)
    let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
    let version = args.iter().find(|w| &**w == "-vV");

    let verbose = match env::var("RUSTC_VERBOSE") {
        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
        Err(_) => 0,
    };

    // Use a different compiler for build scripts, since there may not yet be a
    // libstd for the real compiler to use. However, if Cargo is attempting to
    // determine the version of the compiler, the real compiler needs to be
    // used. Currently, these two states are differentiated based on whether
    // --target and -vV is/isn't passed.
    let (rustc, libdir) = if target.is_none() && version.is_none() {
        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
    } else {
        ("RUSTC_REAL", "RUSTC_LIBDIR")
    };
    let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
    let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);

    let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
    let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
    let mut dylib_path = bootstrap::util::dylib_path();
    dylib_path.insert(0, PathBuf::from(&libdir));

    let mut cmd = Command::new(rustc);
    cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());

    // Get the name of the crate we're compiling, if any.
    let crate_name =
        args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str());

    if let Some(crate_name) = crate_name {
        if let Some(target) = env::var_os("RUSTC_TIME") {
            if target == "all"
                || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
            {
                cmd.arg("-Ztime");
            }
        }
    }

    // Print backtrace in case of ICE
    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
        cmd.env("RUST_BACKTRACE", "1");
    }

    if let Ok(lint_flags) = env::var("RUSTC_LINT_FLAGS") {
        cmd.args(lint_flags.split_whitespace());
    }

    if target.is_some() {
        // The stage0 compiler has a special sysroot distinct from what we
        // actually downloaded, so we just always pass the `--sysroot` option,
        // unless one is already set.
        if !args.iter().any(|arg| arg == "--sysroot") {
            cmd.arg("--sysroot").arg(&sysroot);
        }

        // If we're compiling specifically the `panic_abort` crate then we pass
        // the `-C panic=abort` option. Note that we do not do this for any
        // other crate intentionally as this is the only crate for now that we
        // ship with panic=abort.
        //
        // This... is a bit of a hack how we detect this. Ideally this
        // information should be encoded in the crate I guess? Would likely
        // require an RFC amendment to RFC 1513, however.
        //
        // `compiler_builtins` are unconditionally compiled with panic=abort to
        // workaround undefined references to `rust_eh_unwind_resume` generated
        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
        if crate_name == Some("panic_abort")
            || crate_name == Some("compiler_builtins") && stage != "0"
        {
            cmd.arg("-C").arg("panic=abort");
        }
    } else {
        // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars
        // here, but rather Cargo should know what flags to pass rustc itself.

        // Override linker if necessary.
        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
            cmd.arg(format!("-Clinker={}", host_linker));
        }

        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
            if s == "true" {
                cmd.arg("-C").arg("target-feature=+crt-static");
            }
            if s == "false" {
                cmd.arg("-C").arg("target-feature=-crt-static");
            }
        }
    }

    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
        cmd.arg("--remap-path-prefix").arg(&map);
    }

    // Force all crates compiled by this compiler to (a) be unstable and (b)
    // allow the `rustc_private` feature to link to other unstable crates
    // also in the sysroot. We also do this for host crates, since those
    // may be proc macros, in which case we might ship them.
    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
        cmd.arg("-Z").arg("force-unstable-if-unmarked");
    }

    if verbose > 1 {
        eprintln!(
            "rustc command: {:?}={:?} {:?}",
            bootstrap::util::dylib_path_var(),
            env::join_paths(&dylib_path).unwrap(),
            cmd,
        );
        eprintln!("sysroot: {:?}", sysroot);
        eprintln!("libdir: {:?}", libdir);
    }

    if let Some(mut on_fail) = on_fail {
        let e = match cmd.status() {
            Ok(s) if s.success() => std::process::exit(0),
            e => e,
        };
        println!("\nDid not run successfully: {}\n{:?}\n-------------", e, cmd);
        status_code(&mut on_fail).expect("could not run the backup command");
        std::process::exit(1);
    }

    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
        if let Some(crate_name) = crate_name {
            let start = Instant::now();
            let status = cmd.status().unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
            let dur = start.elapsed();

            let is_test = args.iter().any(|a| a == "--test");
            eprintln!(
                "[RUSTC-TIMING] {} test:{} {}.{:03}",
                crate_name,
                is_test,
                dur.as_secs(),
                dur.subsec_millis()
            );

            match status.code() {
                Some(i) => std::process::exit(i),
                None => {
                    eprintln!("rustc exited with {}", status);
                    std::process::exit(0xfe);
                }
            }
        }
    }

    let code = status_code(&mut cmd).unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
    std::process::exit(code);
}

fn status_code(cmd: &mut Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap())
}
<|endoftext|>


<commit_before>use std::convert::From;

use binding::class;
use binding::global::ValueType;
use binding::util as binding_util;
use types::Value;
use util;

use AnyObject;
use Class;
use traits::VerifiedObject;

/// `Object`
///
/// Trait consists methods of Ruby `Object` class. Every struct like `Array`, `Hash` etc implements
/// this trait.
///
/// `class!` macro automatically implements this trait for custom classes.
pub trait Object: From<Value> {
    /// Usually this function just returns a `value` of current object.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::types::Value;
    /// use ruru::traits::Object;
    ///
    /// struct Array {
    ///     value: Value
    /// }
    ///
    /// impl From<Value> for Array {
    ///     fn from(value: Value) -> Self {
    ///         Array {
    ///             value: value
    ///         }
    ///     }
    /// }
    ///
    /// impl Object for Array {
    ///     fn value(&self) -> Value {
    ///         self.value
    ///     }
    /// }
    /// ```
    fn value(&self) -> Value;

    /// Returns a `Class` struct of current object
    ///
    /// # Examples
    /// ```
    /// use ruru::{Array, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert_eq!(Array::new().class(), Array::new().class());
    /// ```
    fn class(&self) -> Class {
        let class = class::object_class(self.value());

        Class::from(class)
    }

    /// Calls a given method on an object similarly to Ruby `Object#send` method
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, RString, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let array_to_str =
    ///     array
    ///         .send("to_s", vec![])
    ///         .try_convert_to::<RString>()
    ///         .unwrap()
    ///         .to_string();
    ///
    /// assert_eq!(array_to_str, "[1]".to_string());
    /// ```
    fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
        let (argc, argv) = util::create_arguments(arguments);

        let result = binding_util::call_method(self.value(), method, argc, argv.as_ptr());

        AnyObject::from(result)
    }

    /// Checks weather the object is `nil`
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, NilClass, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert!(NilClass::new().is_nil());
    /// assert!(!Hash::new().is_nil());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// nil.nil? == true
    /// {}.nil? == false
    /// ```
    fn is_nil(&self) -> bool {
        self.value().is_nil()
    }

    /// Converts struct to `AnyObject`
    ///
    /// See docs for `AnyObject` class for more details.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let args = vec![Fixnum::new(1).to_any_object()];
    /// let index =
    ///     array
    ///         .send("find_index", args)
    ///         .try_convert_to::<Fixnum>();
    ///
    /// assert_eq!(index, Ok(Fixnum::new(0)));
    /// ```
    fn to_any_object(&self) -> AnyObject {
        AnyObject::from(self.value())
    }

    /// Gets an instance variable of object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// #[macro_use]
    /// extern crate ruru;
    ///
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// class!(Counter);
    ///
    /// methods!(
    ///     Counter,
    ///     itself,
    ///
    ///     fn counter_initialize() -> AnyObject {
    ///         itself.instance_variable_set("@state", Fixnum::new(0))
    ///     }
    ///
    ///     fn counter_increment() -> AnyObject {
    ///         // Using unsafe conversion, because we are sure that `@state` is always a `Fixnum`
    ///         // and we don't provide an interface to set the value externally
    ///         let state = unsafe {
    ///             itself.instance_variable_get("@state").to::<Fixnum>().to_i64()
    ///         };
    ///
    ///         itself.instance_variable_set("@state", Fixnum::new(state + 1))
    ///     }
    ///
    ///     fn counter_state() -> Fixnum {
    ///         unsafe { itself.instance_variable_get("@state").to::<Fixnum>() }
    ///     }
    /// );
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).try_convert_to::<Fixnum>();
    ///
    ///     assert_eq!(new_state, Ok(Fixnum::new(1)));
    /// }
    /// ```
    fn instance_variable_get(&self, variable: &str) -> AnyObject {
        let result = class::instance_variable_get(self.value(), variable);

        AnyObject::from(result)
    }

    /// Sets an instance variable for object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// #[macro_use]
    /// extern crate ruru;
    ///
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// class!(Counter);
    ///
    /// methods!(
    ///     Counter,
    ///     itself,
    ///
    ///     fn counter_initialize() -> AnyObject {
    ///         itself.instance_variable_set("@state", Fixnum::new(0))
    ///     }
    ///
    ///     fn counter_increment() -> AnyObject {
    ///         // Using unsafe conversion, because we are sure that `@state` is always a `Fixnum`
    ///         // and we don't provide an interface to set the value externally
    ///         let state = unsafe {
    ///             itself.instance_variable_get("@state").to::<Fixnum>().to_i64()
    ///         };
    ///
    ///         itself.instance_variable_set("@state", Fixnum::new(state + 1))
    ///     }
    ///
    ///     fn counter_state() -> Fixnum {
    ///         unsafe { itself.instance_variable_get("@state").to::<Fixnum>() }
    ///     }
    /// );
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).try_convert_to::<Fixnum>();
    ///
    ///     assert_eq!(new_state, Ok(Fixnum::new(1)));
    /// }
    /// ```
    fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
        let result = class::instance_variable_set(self.value(), variable, value.value());

        AnyObject::from(result)
    }

    /// Casts current object to the specified Ruby type.
    ///
    /// This operation in unsafe, because it does not perform any validations on the object, but
    /// it is faster than `try_convert_to()`.
    ///
    /// Use it when:
    ///
    ///  - you own the Ruby code which passes the object to Rust;
    ///  - you are sure that the object has correct type;
    ///  - Ruby code has a good test coverage.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{AnyObject, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let fixnum_as_any_object = Fixnum::new(1).to_any_object();
    ///
    /// let fixnum = unsafe { fixnum_as_any_object.to::<Fixnum>() };
    ///
    /// assert_eq!(fixnum.to_i64(), 1);
    /// ```
    unsafe fn to<T: Object>(&self) -> T {
        T::from(self.value())
    }

    fn try_convert_to<T: VerifiedObject>(&self) -> Result<T, String> {
        if T::is_correct_type(self) {
            let converted_object = unsafe { self.to::<T>() };

            Ok(converted_object)
        } else {
            Err(T::error_message())
        }
    }

    /// Determines the value type of the object
    ///
    /// # Example
    ///
    /// ```
    /// use ruru::{AnyObject, Fixnum, VM};
    /// use ruru::traits::Object;
    /// use ruru::types::ValueType;
    /// # VM::init();
    ///
    /// let any_object = Fixnum::new(1).to_any_object();
    ///
    /// assert_eq!(any_object.ty(), ValueType::Fixnum);
    /// ```
    fn ty(&self) -> ValueType {
        self.value().ty()
    }
}
<commit_msg>Add documentation for Object::try_convert_to()<commit_after>use std::convert::From;

use binding::class;
use binding::global::ValueType;
use binding::util as binding_util;
use types::Value;
use util;

use AnyObject;
use Class;
use traits::VerifiedObject;

/// `Object`
///
/// Trait consists methods of Ruby `Object` class. Every struct like `Array`, `Hash` etc implements
/// this trait.
///
/// `class!` macro automatically implements this trait for custom classes.
pub trait Object: From<Value> {
    /// Usually this function just returns a `value` of current object.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::types::Value;
    /// use ruru::traits::Object;
    ///
    /// struct Array {
    ///     value: Value
    /// }
    ///
    /// impl From<Value> for Array {
    ///     fn from(value: Value) -> Self {
    ///         Array {
    ///             value: value
    ///         }
    ///     }
    /// }
    ///
    /// impl Object for Array {
    ///     fn value(&self) -> Value {
    ///         self.value
    ///     }
    /// }
    /// ```
    fn value(&self) -> Value;

    /// Returns a `Class` struct of current object
    ///
    /// # Examples
    /// ```
    /// use ruru::{Array, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert_eq!(Array::new().class(), Array::new().class());
    /// ```
    fn class(&self) -> Class {
        let class = class::object_class(self.value());

        Class::from(class)
    }

    /// Calls a given method on an object similarly to Ruby `Object#send` method
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, RString, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let array_to_str =
    ///     array
    ///         .send("to_s", vec![])
    ///         .try_convert_to::<RString>()
    ///         .unwrap()
    ///         .to_string();
    ///
    /// assert_eq!(array_to_str, "[1]".to_string());
    /// ```
    fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
        let (argc, argv) = util::create_arguments(arguments);

        let result = binding_util::call_method(self.value(), method, argc, argv.as_ptr());

        AnyObject::from(result)
    }

    /// Checks weather the object is `nil`
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Hash, NilClass, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert!(NilClass::new().is_nil());
    /// assert!(!Hash::new().is_nil());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// nil.nil? == true
    /// {}.nil? == false
    /// ```
    fn is_nil(&self) -> bool {
        self.value().is_nil()
    }

    /// Converts struct to `AnyObject`
    ///
    /// See docs for `AnyObject` class for more details.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let args = vec![Fixnum::new(1).to_any_object()];
    /// let index =
    ///     array
    ///         .send("find_index", args)
    ///         .try_convert_to::<Fixnum>();
    ///
    /// assert_eq!(index, Ok(Fixnum::new(0)));
    /// ```
    fn to_any_object(&self) -> AnyObject {
        AnyObject::from(self.value())
    }

    /// Gets an instance variable of object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// #[macro_use]
    /// extern crate ruru;
    ///
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// class!(Counter);
    ///
    /// methods!(
    ///     Counter,
    ///     itself,
    ///
    ///     fn counter_initialize() -> AnyObject {
    ///         itself.instance_variable_set("@state", Fixnum::new(0))
    ///     }
    ///
    ///     fn counter_increment() -> AnyObject {
    ///         // Using unsafe conversion, because we are sure that `@state` is always a `Fixnum`
    ///         // and we don't provide an interface to set the value externally
    ///         let state = unsafe {
    ///             itself.instance_variable_get("@state").to::<Fixnum>().to_i64()
    ///         };
    ///
    ///         itself.instance_variable_set("@state", Fixnum::new(state + 1))
    ///     }
    ///
    ///     fn counter_state() -> Fixnum {
    ///         unsafe { itself.instance_variable_get("@state").to::<Fixnum>() }
    ///     }
    /// );
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).try_convert_to::<Fixnum>();
    ///
    ///     assert_eq!(new_state, Ok(Fixnum::new(1)));
    /// }
    /// ```
    fn instance_variable_get(&self, variable: &str) -> AnyObject {
        let result = class::instance_variable_get(self.value(), variable);

        AnyObject::from(result)
    }

    /// Sets an instance variable for object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// #[macro_use]
    /// extern crate ruru;
    ///
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// class!(Counter);
    ///
    /// methods!(
    ///     Counter,
    ///     itself,
    ///
    ///     fn counter_initialize() -> AnyObject {
    ///         itself.instance_variable_set("@state", Fixnum::new(0))
    ///     }
    ///
    ///     fn counter_increment() -> AnyObject {
    ///         // Using unsafe conversion, because we are sure that `@state` is always a `Fixnum`
    ///         // and we don't provide an interface to set the value externally
    ///         let state = unsafe {
    ///             itself.instance_variable_get("@state").to::<Fixnum>().to_i64()
    ///         };
    ///
    ///         itself.instance_variable_set("@state", Fixnum::new(state + 1))
    ///     }
    ///
    ///     fn counter_state() -> Fixnum {
    ///         unsafe { itself.instance_variable_get("@state").to::<Fixnum>() }
    ///     }
    /// );
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).try_convert_to::<Fixnum>();
    ///
    ///     assert_eq!(new_state, Ok(Fixnum::new(1)));
    /// }
    /// ```
    fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
        let result = class::instance_variable_set(self.value(), variable, value.value());

        AnyObject::from(result)
    }

    /// Unsafely casts current object to the specified Ruby type
    ///
    /// This operation in unsafe, because it does not perform any validations on the object, but
    /// it is faster than `try_convert_to()`.
    ///
    /// Use it when:
    ///
    ///  - you own the Ruby code which passes the object to Rust;
    ///  - you are sure that the object has correct type;
    ///  - Ruby code has a good test coverage.
    ///
    /// This function is used by `unsafe_methods!` macro for argument casting.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{AnyObject, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let fixnum_as_any_object = Fixnum::new(1).to_any_object();
    ///
    /// let fixnum = unsafe { fixnum_as_any_object.to::<Fixnum>() };
    ///
    /// assert_eq!(fixnum.to_i64(), 1);
    /// ```
    unsafe fn to<T: Object>(&self) -> T {
        T::from(self.value())
    }

    /// Safely casts current object to the specified Ruby type
    ///
    /// This function is used by `methods!` macro for argument casting.
    ///
    /// # Examples
    ///
    /// ### Basic conversions
    ///
    /// ```
    /// use ruru::{Fixnum, RString, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let fixnum_as_any_object = Fixnum::new(1).to_any_object();
    /// let converted_fixnum = fixnum_as_any_object.try_convert_to::<Fixnum>();
    ///
    /// assert_eq!(converted_fixnum, Ok(Fixnum::new(1)));
    ///
    /// let string = RString::new("string");
    /// let string_as_fixnum = string.try_convert_to::<Fixnum>();
    ///
    /// assert_eq!(string_as_fixnum, Err("Error converting to Fixnum".to_string()));
    /// ```
    ///
    /// ### Method arguments
    ///
    /// To launch a server in Rust, you plan to write a simple `Server` class
    ///
    /// ```ruby
    /// class Server
    ///   def start(address)
    ///     # ...
    ///   end
    /// end
    /// ```
    ///
    /// The `address` must be `Hash` with the following structure:
    ///
    /// ```ruby
    /// {
    ///   host: 'localhost',
    ///   port: 8080,
    /// }
    /// ```
    ///
    /// You want to extract port from it. Default port is `8080` in case when:
    ///
    ///  - `address` is not a `Hash`
    ///  - `address[:port]` is not present
    ///  - `address[:port]` is not a `Fixnum`
    ///
    /// ```no_run
    /// #[macro_use]
    /// extern crate ruru;
    ///
    /// use ruru::{Class, Fixnum, Hash, NilClass, Symbol, VM};
    /// use ruru::traits::Object;
    ///
    /// class!(Server);
    ///
    /// methods!(
    ///     Server,
    ///     itself,
    ///
    ///     fn start(address: Hash) -> NilClass {
    ///         let default_port = 8080;
    ///
    ///         let port = address
    ///             .map(|hash| hash.at(Symbol::new("port")))
    ///             .and_then(|port| port.try_convert_to::<Fixnum>())
    ///             .map(|port| port.to_i64())
    ///             .unwrap_or(default_port);
    ///
    ///         // Start server...
    ///
    ///         NilClass::new()
    ///     }
    /// );
    ///
    /// fn main() {
    ///     # VM::init();
    ///     Class::new("Server").define(|itself| {
    ///         itself.def("start", start);
    ///     });
    /// }
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// class Server
    ///   def start(address)
    ///     default_port = 8080
    ///
    ///     port =
    ///       if address.is_a?(Hash) && address[:port].is_a?(Fixnum)
    ///         address[:port]
    ///       else
    ///         default_port
    ///       end
    ///
    ///     # Start server...
    ///   end
    /// end
    /// ```
    fn try_convert_to<T: VerifiedObject>(&self) -> Result<T, String> {
        if T::is_correct_type(self) {
            let converted_object = unsafe { self.to::<T>() };

            Ok(converted_object)
        } else {
            Err(T::error_message())
        }
    }

    /// Determines the value type of the object
    ///
    /// # Example
    ///
    /// ```
    /// use ruru::{AnyObject, Fixnum, VM};
    /// use ruru::traits::Object;
    /// use ruru::types::ValueType;
    /// # VM::init();
    ///
    /// let any_object = Fixnum::new(1).to_any_object();
    ///
    /// assert_eq!(any_object.ty(), ValueType::Fixnum);
    /// ```
    fn ty(&self) -> ValueType {
        self.value().ty()
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg(feature = "extra-traits")]

extern crate syn;
use syn::*;

macro_rules! assert_let {
    ($p:pat = $e:expr) => {
        assert_let!($p = $e; {})
    };

    ($p:pat = $e:expr; $body:block) => {
        if let $p = $e
            $body
        else {
            panic!("Expected to match {} but got {:?}", stringify!($p), $e)
        }
    };
}

#[test]
#[cfg(feature = "full")]
fn test_catch_expr() {
    // Taken from tests/rust/src/test/run-pass/catch-expr.rs
    let raw = r#"
        struct catch {}

        pub fn main() {
            let catch_result = do catch {
                let x = 5;
                x
            };
            assert_eq!(catch_result, 5);

            let mut catch = true;
            while catch { catch = false; }
            assert_eq!(catch, false);

            catch = if catch { false } else { true };
            assert_eq!(catch, true);

            match catch {
                _ => {}
            };

            let catch_err = do catch {
                Err(22)?;
                Ok(1)
            };
            assert_eq!(catch_err, Err(22));

            let catch_okay: Result<i32, i32> = do catch {
                if false { Err(25)?; }
                Ok::<(), i32>(())?;
                Ok(28)
            };
            assert_eq!(catch_okay, Ok(28));

            let catch_from_loop: Result<i32, i32> = do catch {
                for i in 0..10 {
                    if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
                }
                Ok(22)
            };
            assert_eq!(catch_from_loop, Err(5));

            let cfg_init;
            let _res: Result<(), ()> = do catch {
                cfg_init = 5;
                Ok(())
            };
            assert_eq!(cfg_init, 5);

            let cfg_init_2;
            let _res: Result<(), ()> = do catch {
                cfg_init_2 = 6;
                Err(())?;
                Ok(())
            };
            assert_eq!(cfg_init_2, 6);

            let my_string = "test".to_string();
            let res: Result<&str, ()> = do catch {
                Ok(&my_string)
            };
            assert_eq!(res, Ok("test"));
        }
    "#;

    let actual: File = syn::parse_str(raw).unwrap();

    assert_let!(Item::Struct(ItemStruct { ref ident, .. }) = actual.items[0]; {
        assert_eq!(ident, "catch");
    });

    assert_let!(Item::Fn(ItemFn { ref block, .. }) = actual.items[1]; {
        assert_let!(Stmt::Local(ref local) = block.stmts[0]; {
            assert_let!(Local { init: Some((_, ref init_expr)), .. } = *local; {
                assert_let!(Expr::Catch(..) = **init_expr);
            });
        });

        assert_let!(Stmt::Local(ref local) = block.stmts[2]; {
            assert_let!(Pat::Ident(PatIdent { by_ref: None, mutability: Some(_), ref ident, .. }) = local.pats.iter().next().unwrap(); {
                assert_eq!(ident, "catch");
            });
        });

        assert_let!(Stmt::Expr(ref expr) = block.stmts[3]; {
            assert_let!(Expr::While(ExprWhile { ref cond, .. }) = *expr; {
                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
                    assert_eq!(*path, "catch".into());
                });
            });
        });

        assert_let!(Stmt::Semi(ref expr, _) = block.stmts[5]; {
            assert_let!(Expr::Assign(ExprAssign { ref left, ref right, .. }) = *expr; {
                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **left; {
                    assert_eq!(*path, "catch".into());
                });

                assert_let!(Expr::If(ExprIf { ref cond, .. }) = **right; {
                    assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
                        assert_eq!(*path, "catch".into());
                    });
                });
            });
        });

        assert_let!(Stmt::Semi(ref expr, _) = block.stmts[7]; {
            assert_let!(Expr::Match(ExprMatch { ref expr, .. }) = *expr; {
                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **expr; {
                    assert_eq!(*path, "catch".into());
                });
            });
        });
    });
}
<commit_msg>Fix test_expr<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg(feature = "extra-traits")]

extern crate syn;
extern crate proc_macro2;
use syn::*;
use proc_macro2::*;

macro_rules! assert_let {
    ($p:pat = $e:expr) => {
        assert_let!($p = $e; {})
    };

    ($p:pat = $e:expr; $body:block) => {
        if let $p = $e
            $body
        else {
            panic!("Expected to match {} but got {:?}", stringify!($p), $e)
        }
    };
}

#[test]
#[cfg(feature = "full")]
fn test_catch_expr() {
    // Taken from tests/rust/src/test/run-pass/catch-expr.rs
    let raw = r#"
        struct catch {}

        pub fn main() {
            let catch_result = do catch {
                let x = 5;
                x
            };
            assert_eq!(catch_result, 5);

            let mut catch = true;
            while catch { catch = false; }
            assert_eq!(catch, false);

            catch = if catch { false } else { true };
            assert_eq!(catch, true);

            match catch {
                _ => {}
            };

            let catch_err = do catch {
                Err(22)?;
                Ok(1)
            };
            assert_eq!(catch_err, Err(22));

            let catch_okay: Result<i32, i32> = do catch {
                if false { Err(25)?; }
                Ok::<(), i32>(())?;
                Ok(28)
            };
            assert_eq!(catch_okay, Ok(28));

            let catch_from_loop: Result<i32, i32> = do catch {
                for i in 0..10 {
                    if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
                }
                Ok(22)
            };
            assert_eq!(catch_from_loop, Err(5));

            let cfg_init;
            let _res: Result<(), ()> = do catch {
                cfg_init = 5;
                Ok(())
            };
            assert_eq!(cfg_init, 5);

            let cfg_init_2;
            let _res: Result<(), ()> = do catch {
                cfg_init_2 = 6;
                Err(())?;
                Ok(())
            };
            assert_eq!(cfg_init_2, 6);

            let my_string = "test".to_string();
            let res: Result<&str, ()> = do catch {
                Ok(&my_string)
            };
            assert_eq!(res, Ok("test"));
        }
    "#;

    let actual: File = syn::parse_str(raw).unwrap();

    assert_let!(Item::Struct(ItemStruct { ref ident, .. }) = actual.items[0]; {
        assert_eq!(ident.to_string(), "catch");
    });

    assert_let!(Item::Fn(ItemFn { ref block, .. }) = actual.items[1]; {
        assert_let!(Stmt::Local(ref local) = block.stmts[0]; {
            assert_let!(Local { init: Some((_, ref init_expr)), .. } = *local; {
                assert_let!(Expr::Catch(..) = **init_expr);
            });
        });

        assert_let!(Stmt::Local(ref local) = block.stmts[2]; {
            assert_let!(Pat::Ident(PatIdent { by_ref: None, mutability: Some(_), ref ident, .. }) = local.pats.iter().next().unwrap(); {
                assert_eq!(ident.to_string(), "catch");
            });
        });

        assert_let!(Stmt::Expr(ref expr) = block.stmts[3]; {
            assert_let!(Expr::While(ExprWhile { ref cond, .. }) = *expr; {
                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
                    let name = Ident::new("catch", Span::call_site());
                    assert_eq!(*path, name.into());
                });
            });
        });

        assert_let!(Stmt::Semi(ref expr, _) = block.stmts[5]; {
            assert_let!(Expr::Assign(ExprAssign { ref left, ref right, .. }) = *expr; {
                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **left; {
                    let name = Ident::new("catch", Span::call_site());
                    assert_eq!(*path, name.into());
                });

                assert_let!(Expr::If(ExprIf { ref cond, .. }) = **right; {
                    assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
                        let name = Ident::new("catch", Span::call_site());
                        assert_eq!(*path, name.into());
                    });
                });
            });
        });

        assert_let!(Stmt::Semi(ref expr, _) = block.stmts[7]; {
            assert_let!(Expr::Match(ExprMatch { ref expr, .. }) = *expr; {
                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **expr; {
                    let name = Ident::new("catch", Span::call_site());
                    assert_eq!(*path, name.into());
                });
            });
        });
    });
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufRead, BufReader, Cursor, Read};
use std::path::{Path, PathBuf};

use {Error, Result};
use project::ImageData;

pub struct Image {
    path: PathBuf,
    header: Header,
    data: Vec<Vec<f64>>,
}

impl Image {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Image> {
        let mut buf = Vec::new();
        try!(File::open(&path).and_then(|mut f| f.read_to_end(&mut buf)));
        // We need to read everything in, then convert w/ utf8 lossy, because the degree sign
        // doesn't seem to be valid utf8.
        let mut reader = BufReader::new(Cursor::new(String::from_utf8_lossy(&buf[..])
            .into_owned()));
        let header = try!(Header::new(&mut reader));
        let data: Vec<Vec<f64>> = try!(reader.lines()
            .map(|r| {
                r.map_err(Error::from)
                    .and_then(|s| {
                        s.split(';').map(|s| s.parse::<f64>().map_err(Error::from)).collect()
                    })
            })
            .collect());
        Ok(Image {
            data: data,
            header: header,
            path: path.as_ref().to_path_buf(),
        })
    }

    pub fn version(&self) -> u8 {
        self.header.version
    }

    pub fn width(&self) -> usize {
        self.header.width
    }

    pub fn height(&self) -> usize {
        self.header.height
    }

    pub fn data(&self) -> &Vec<Vec<f64>> {
        &self.data
    }
}

impl ImageData for Image {
    fn path(&self) -> &Path {
        &self.path
    }

    fn get(&self, u: f64, v: f64) -> Option<f64> {
        unimplemented!()
    }
}

#[derive(Debug, Default)]
struct Header {
    version: u8,
    width: usize,
    height: usize,
}

impl Header {
    fn new<R: BufRead>(reader: &mut R) -> Result<Header> {
        let mut lines = reader.lines();
        let mut next_line = || {
            lines.next()
                .map(|r| r.map_err(Error::from))
                .unwrap_or(Err(Error::ReadInfratec("Unexpected EOF".to_string())))
        };
        let first_line = try!(next_line());
        if first_line != "[Settings]" {
            return Err(Error::ReadInfratec(format!("Invalid first line: {}", first_line)));
        }
        let mut header = Default::default();
        loop {
            let line = try!(next_line());
            if line == "[Data]" {
                return Ok(header);
            } else if line.is_empty() {
                continue;
            }
            let words = line.split('=').collect::<Vec<_>>();
            if words.len() != 2 {
                return Err(Error::ReadInfratec(format!("Invalid header line: {}", line)));
            }
            match words[0] {
                "ImageHeight" => header.height = try!(words[1].parse()),
                "ImageWidth" => header.width = try!(words[1].parse()),
                "Version" => header.version = try!(words[1].parse()),
                _ => {}
            };
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn image_from_path() {
        let image =
            Image::from_path("data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv")
                .unwrap();
        assert_eq!(3, image.version());
        assert_eq!(768, image.height());
        assert_eq!(1024, image.width());
        assert_eq!(768, image.data().len());
        assert!(image.data.iter().all(|v| v.len() == 1024));
        assert_eq!(-38.64, image.data()[0][0]);
        assert_eq!(23.84, *image.data().last().unwrap().last().unwrap());
    }
}
<commit_msg>Reading images and coloring points<commit_after>use std::fs::File;
use std::io::{BufRead, BufReader, Cursor, Read};
use std::path::{Path, PathBuf};

use {Error, Result};
use project::ImageData;

pub struct Image {
    path: PathBuf,
    header: Header,
    data: Vec<Vec<f64>>,
}

impl Image {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Image> {
        let mut buf = Vec::new();
        try!(File::open(&path).and_then(|mut f| f.read_to_end(&mut buf)));
        // We need to read everything in, then convert w/ utf8 lossy, because the degree sign
        // doesn't seem to be valid utf8.
        let mut reader = BufReader::new(Cursor::new(String::from_utf8_lossy(&buf[..])
            .into_owned()));
        let header = try!(Header::new(&mut reader));
        let data: Vec<Vec<f64>> = try!(reader.lines()
            .map(|r| {
                r.map_err(Error::from)
                    .and_then(|s| {
                        s.split(';').map(|s| s.parse::<f64>().map_err(Error::from)).collect()
                    })
            })
            .collect());
        Ok(Image {
            data: data,
            header: header,
            path: path.as_ref().to_path_buf(),
        })
    }

    pub fn width(&self) -> usize {
        self.header.width
    }

    pub fn height(&self) -> usize {
        self.header.height
    }
}

impl ImageData for Image {
    fn path(&self) -> &Path {
        &self.path
    }

    fn get(&self, u: f64, v: f64) -> Option<f64> {
        // Images are rotated 90 counterclockwise and flipped up-down, which leads to this
        // wonky checking and fetching.
        if u > 0. && v > 0. && u < self.width() as f64 && v < self.height() as f64 {
            Some(self.data[v as usize][u as usize])
        } else {
            None
        }
    }
}

#[derive(Debug, Default)]
struct Header {
    version: u8,
    width: usize,
    height: usize,
}

impl Header {
    fn new<R: BufRead>(reader: &mut R) -> Result<Header> {
        let mut lines = reader.lines();
        let mut next_line = || {
            lines.next()
                .map(|r| r.map_err(Error::from))
                .unwrap_or(Err(Error::ReadInfratec("Unexpected EOF".to_string())))
        };
        let first_line = try!(next_line());
        if first_line != "[Settings]" {
            return Err(Error::ReadInfratec(format!("Invalid first line: {}", first_line)));
        }
        let mut header = Default::default();
        loop {
            let line = try!(next_line());
            if line == "[Data]" {
                return Ok(header);
            } else if line.is_empty() {
                continue;
            }
            let words = line.split('=').collect::<Vec<_>>();
            if words.len() != 2 {
                return Err(Error::ReadInfratec(format!("Invalid header line: {}", line)));
            }
            match words[0] {
                "ImageHeight" => header.height = try!(words[1].parse()),
                "ImageWidth" => header.width = try!(words[1].parse()),
                "Version" => header.version = try!(words[1].parse()),
                _ => {}
            };
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn image_from_path() {
        let image =
            Image::from_path("data/project.RiSCAN/SCANS/SP01/SCANPOSIMAGES/SP01 - Image001.csv")
                .unwrap();
        assert_eq!(3, image.header.version);
        assert_eq!(768, image.height());
        assert_eq!(1024, image.width());
        assert_eq!(768, image.data.len());
        assert!(image.data.iter().all(|v| v.len() == 1024));
        assert_eq!(-38.64, image.data[0][0]);
        assert_eq!(23.84, *image.data.last().unwrap().last().unwrap());
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use crate::backend::Backend;
use crate::dsl::AsExprOf;
use crate::expression::subselect::ValidSubselect;
use crate::expression::*;
use crate::insertable::Insertable;
use crate::query_builder::distinct_clause::DistinctClause;
use crate::query_builder::group_by_clause::GroupByClause;
use crate::query_builder::insert_statement::InsertFromSelect;
use crate::query_builder::limit_clause::LimitClause;
use crate::query_builder::offset_clause::OffsetClause;
use crate::query_builder::order_clause::OrderClause;
use crate::query_builder::where_clause::*;
use crate::query_builder::*;
use crate::query_dsl::methods::*;
use crate::query_dsl::*;
use crate::query_source::joins::*;
use crate::query_source::{QuerySource, Table};
use crate::result::QueryResult;
use crate::sql_types::{BigInt, Bool, NotNull, Nullable};

#[allow(missing_debug_implementations)]
pub struct BoxedSelectStatement<'a, ST, QS, DB> {
    select: Box<dyn QueryFragment<DB> + Send + 'a>,
    from: QS,
    distinct: Box<dyn QueryFragment<DB> + Send + 'a>,
    where_clause: BoxedWhereClause<'a, DB>,
    order: Option<Box<dyn QueryFragment<DB> + Send + 'a>>,
    limit: Box<dyn QueryFragment<DB> + Send + 'a>,
    offset: Box<dyn QueryFragment<DB> + Send + 'a>,
    group_by: Box<dyn QueryFragment<DB> + Send + 'a>,
    _marker: PhantomData<ST>,
}

impl<'a, ST, QS, DB> BoxedSelectStatement<'a, ST, QS, DB> {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        select: Box<dyn QueryFragment<DB> + Send + 'a>,
        from: QS,
        distinct: Box<dyn QueryFragment<DB> + Send + 'a>,
        where_clause: BoxedWhereClause<'a, DB>,
<<<<<<< HEAD
        order: Option<Box<dyn QueryFragment<DB> + Send + 'a>>,
        limit: Box<dyn QueryFragment<DB> + Send + 'a>,
        offset: Box<dyn QueryFragment<DB> + Send + 'a>,
        group_by: Box<dyn QueryFragment<DB> + Send + 'a>,
=======
        order: Option<Box<QueryFragment<DB> + Send + 'a>>,
        limit: Box<QueryFragment<DB> + Send + 'a>,
        offset: Box<QueryFragment<DB> + Send + 'a>,
        group_by: Box<QueryFragment<DB> + Send + 'a>,
>>>>>>> Run rustfmt
    ) -> Self {
        BoxedSelectStatement {
            select: select,
            from: from,
            distinct: distinct,
            where_clause: where_clause,
            order: order,
            limit: limit,
            offset: offset,
            group_by: group_by,
            _marker: PhantomData,
        }
    }
}

impl<'a, ST, QS, DB> Query for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
{
    type SqlType = ST;
}

impl<'a, ST, QS, DB> SelectQuery for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
{
    type SqlType = ST;
}

impl<'a, ST, QS, QS2, DB> ValidSubselect<QS2> for BoxedSelectStatement<'a, ST, QS, DB> where
    Self: Query<SqlType = ST>
{
}

impl<'a, ST, QS, DB> QueryFragment<DB> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    QS: QuerySource,
    QS::FromClause: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("SELECT ");
        self.distinct.walk_ast(out.reborrow())?;
        self.select.walk_ast(out.reborrow())?;
        out.push_sql(" FROM ");
        self.from.from_clause().walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        self.group_by.walk_ast(out.reborrow())?;

        if let Some(ref order) = self.order {
            out.push_sql(" ORDER BY ");
            order.walk_ast(out.reborrow())?;
        }

        self.limit.walk_ast(out.reborrow())?;
        self.offset.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<'a, ST, DB> QueryFragment<DB> for BoxedSelectStatement<'a, ST, (), DB>
where
    DB: Backend,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("SELECT ");
        self.distinct.walk_ast(out.reborrow())?;
        self.select.walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        self.group_by.walk_ast(out.reborrow())?;
        self.order.walk_ast(out.reborrow())?;
        self.limit.walk_ast(out.reborrow())?;
        self.offset.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<'a, ST, QS, DB> QueryId for BoxedSelectStatement<'a, ST, QS, DB> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<'a, ST, QS, DB, Rhs, Kind, On> InternalJoinDsl<Rhs, Kind, On>
    for BoxedSelectStatement<'a, ST, QS, DB>
where
    BoxedSelectStatement<'a, ST, JoinOn<Join<QS, Rhs, Kind>, On>, DB>: AsQuery,
{
    type Output = BoxedSelectStatement<'a, ST, JoinOn<Join<QS, Rhs, Kind>, On>, DB>;

    fn join(self, rhs: Rhs, kind: Kind, on: On) -> Self::Output {
        BoxedSelectStatement::new(
            self.select,
            Join::new(self.from, rhs, kind).on(on),
            self.distinct,
            self.where_clause,
            self.order,
            self.limit,
            self.offset,
            self.group_by,
        )
    }
}

impl<'a, ST, QS, DB> DistinctDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    DistinctClause: QueryFragment<DB>,
{
    type Output = Self;

    fn distinct(mut self) -> Self::Output {
        self.distinct = Box::new(DistinctClause);
        self
    }
}

impl<'a, ST, QS, DB, Selection> SelectDsl<Selection> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    Selection: SelectableExpression<QS> + QueryFragment<DB> + Send + 'a,
{
    type Output = BoxedSelectStatement<'a, Selection::SqlType, QS, DB>;

    fn select(self, selection: Selection) -> Self::Output {
        BoxedSelectStatement::new(
            Box::new(selection),
            self.from,
            self.distinct,
            self.where_clause,
            self.order,
            self.limit,
            self.offset,
            self.group_by,
        )
    }
}

impl<'a, ST, QS, DB, Predicate> FilterDsl<Predicate> for BoxedSelectStatement<'a, ST, QS, DB>
where
    BoxedWhereClause<'a, DB>: WhereAnd<Predicate, Output = BoxedWhereClause<'a, DB>>,
    Predicate: AppearsOnTable<QS, SqlType = Bool> + NonAggregate,
{
    type Output = Self;

    fn filter(mut self, predicate: Predicate) -> Self::Output {
        self.where_clause = self.where_clause.and(predicate);
        self
    }
}

impl<'a, ST, QS, DB, Predicate> OrFilterDsl<Predicate> for BoxedSelectStatement<'a, ST, QS, DB>
where
    BoxedWhereClause<'a, DB>: WhereOr<Predicate, Output = BoxedWhereClause<'a, DB>>,
    Predicate: AppearsOnTable<QS, SqlType = Bool> + NonAggregate,
{
    type Output = Self;

    fn or_filter(mut self, predicate: Predicate) -> Self::Output {
        self.where_clause = self.where_clause.or(predicate);
        self
    }
}

impl<'a, ST, QS, DB> LimitDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    LimitClause<AsExprOf<i64, BigInt>>: QueryFragment<DB>,
{
    type Output = Self;

    fn limit(mut self, limit: i64) -> Self::Output {
        self.limit = Box::new(LimitClause(limit.into_sql::<BigInt>()));
        self
    }
}

impl<'a, ST, QS, DB> OffsetDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    OffsetClause<AsExprOf<i64, BigInt>>: QueryFragment<DB>,
{
    type Output = Self;

    fn offset(mut self, offset: i64) -> Self::Output {
        self.offset = Box::new(OffsetClause(offset.into_sql::<BigInt>()));
        self
    }
}

impl<'a, ST, QS, DB, Order> OrderDsl<Order> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    Order: QueryFragment<DB> + AppearsOnTable<QS> + Send + 'a,
{
    type Output = Self;

    fn order(mut self, order: Order) -> Self::Output {
        self.order = OrderClause(order).into();
        self
    }
}

impl<'a, ST, QS, DB, Order> ThenOrderDsl<Order> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend + 'a,
    Order: QueryFragment<DB> + AppearsOnTable<QS> + Send + 'a,
{
    type Output = Self;

    fn then_order_by(mut self, order: Order) -> Self::Output {
        self.order = match self.order {
            Some(old) => Some(Box::new((old, order))),
            None => Some(Box::new(order)),
        };
        self
    }
}

impl<'a, ST, QS, DB, Expr> GroupByDsl<Expr> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    Expr: QueryFragment<DB> + AppearsOnTable<QS> + Send + 'a,
    Self: Query,
{
    type Output = Self;

    fn group_by(mut self, group_by: Expr) -> Self::Output {
        self.group_by = Box::new(GroupByClause(group_by));
        self
    }
}

// FIXME: Should we disable joining when `.group_by` has been called? Are there
// any other query methods where a join no longer has the same semantics as
// joining on just the table?
impl<'a, ST, QS, DB, Rhs> JoinTo<Rhs> for BoxedSelectStatement<'a, ST, QS, DB>
where
    QS: JoinTo<Rhs>,
{
    type FromClause = QS::FromClause;
    type OnClause = QS::OnClause;

    fn join_target(rhs: Rhs) -> (Self::FromClause, Self::OnClause) {
        QS::join_target(rhs)
    }
}

impl<'a, ST, QS, DB> QueryDsl for BoxedSelectStatement<'a, ST, QS, DB> {}

impl<'a, ST, QS, DB, Conn> RunQueryDsl<Conn> for BoxedSelectStatement<'a, ST, QS, DB> {}

impl<'a, ST, QS, DB, T> Insertable<T> for BoxedSelectStatement<'a, ST, QS, DB>
where
    T: Table,
    Self: Query,
{
    type Values = InsertFromSelect<Self, T::AllColumns>;

    fn values(self) -> Self::Values {
        InsertFromSelect::new(self)
    }
}

impl<'a, 'b, ST, QS, DB, T> Insertable<T> for &'b BoxedSelectStatement<'a, ST, QS, DB>
where
    T: Table,
    Self: Query,
{
    type Values = InsertFromSelect<Self, T::AllColumns>;

    fn values(self) -> Self::Values {
        InsertFromSelect::new(self)
    }
}

impl<'a, ST, QS, DB> SelectNullableDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    ST: NotNull,
{
    type Output = BoxedSelectStatement<'a, Nullable<ST>, QS, DB>;

    fn nullable(self) -> Self::Output {
        BoxedSelectStatement {
            select: self.select,
            from: self.from,
            distinct: self.distinct,
            where_clause: self.where_clause,
            order: self.order,
            limit: self.limit,
            offset: self.offset,
            group_by: self.group_by,
            _marker: PhantomData,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::prelude::*;
    use crate::backend::Backend;

    table! {
        users {
            id -> Integer,
        }
    }

    fn assert_send<T>(_: T) where T: Send {}

    fn assert_boxed_query_send<B: Backend>() {
        assert_send(users::table.into_boxed::<B>());
        assert_send(users::table.filter(users::id.eq(10)).into_boxed::<B>());
    }

    #[test]
    fn boxed_is_send() {
        #[cfg(feature = "postgres")]
        assert_boxed_query_send::<crate::pg::Pg>();

        #[cfg(feature = "sqlite")]
        assert_boxed_query_send::<crate::sqlite::Sqlite>();

        #[cfg(feature = "mysql")]
        assert_boxed_query_send::<crate::mysql::Mysql>();
    }
}
<commit_msg>Run rustfmt<commit_after>use std::marker::PhantomData;

use crate::backend::Backend;
use crate::dsl::AsExprOf;
use crate::expression::subselect::ValidSubselect;
use crate::expression::*;
use crate::insertable::Insertable;
use crate::query_builder::distinct_clause::DistinctClause;
use crate::query_builder::group_by_clause::GroupByClause;
use crate::query_builder::insert_statement::InsertFromSelect;
use crate::query_builder::limit_clause::LimitClause;
use crate::query_builder::offset_clause::OffsetClause;
use crate::query_builder::order_clause::OrderClause;
use crate::query_builder::where_clause::*;
use crate::query_builder::*;
use crate::query_dsl::methods::*;
use crate::query_dsl::*;
use crate::query_source::joins::*;
use crate::query_source::{QuerySource, Table};
use crate::result::QueryResult;
use crate::sql_types::{BigInt, Bool, NotNull, Nullable};

#[allow(missing_debug_implementations)]
pub struct BoxedSelectStatement<'a, ST, QS, DB> {
    select: Box<dyn QueryFragment<DB> + Send + 'a>,
    from: QS,
    distinct: Box<dyn QueryFragment<DB> + Send + 'a>,
    where_clause: BoxedWhereClause<'a, DB>,
    order: Option<Box<dyn QueryFragment<DB> + Send + 'a>>,
    limit: Box<dyn QueryFragment<DB> + Send + 'a>,
    offset: Box<dyn QueryFragment<DB> + Send + 'a>,
    group_by: Box<dyn QueryFragment<DB> + Send + 'a>,
    _marker: PhantomData<ST>,
}

impl<'a, ST, QS, DB> BoxedSelectStatement<'a, ST, QS, DB> {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        select: Box<dyn QueryFragment<DB> + Send + 'a>,
        from: QS,
        distinct: Box<dyn QueryFragment<DB> + Send + 'a>,
        where_clause: BoxedWhereClause<'a, DB>,
        order: Option<Box<dyn QueryFragment<DB> + Send + 'a>>,
        limit: Box<dyn QueryFragment<DB> + Send + 'a>,
        offset: Box<dyn QueryFragment<DB> + Send + 'a>,
        group_by: Box<dyn QueryFragment<DB> + Send + 'a>,
    ) -> Self {
        BoxedSelectStatement {
            select: select,
            from: from,
            distinct: distinct,
            where_clause: where_clause,
            order: order,
            limit: limit,
            offset: offset,
            group_by: group_by,
            _marker: PhantomData,
        }
    }
}

impl<'a, ST, QS, DB> Query for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
{
    type SqlType = ST;
}

impl<'a, ST, QS, DB> SelectQuery for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
{
    type SqlType = ST;
}

impl<'a, ST, QS, QS2, DB> ValidSubselect<QS2> for BoxedSelectStatement<'a, ST, QS, DB> where
    Self: Query<SqlType = ST>
{
}

impl<'a, ST, QS, DB> QueryFragment<DB> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    QS: QuerySource,
    QS::FromClause: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("SELECT ");
        self.distinct.walk_ast(out.reborrow())?;
        self.select.walk_ast(out.reborrow())?;
        out.push_sql(" FROM ");
        self.from.from_clause().walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        self.group_by.walk_ast(out.reborrow())?;

        if let Some(ref order) = self.order {
            out.push_sql(" ORDER BY ");
            order.walk_ast(out.reborrow())?;
        }

        self.limit.walk_ast(out.reborrow())?;
        self.offset.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<'a, ST, DB> QueryFragment<DB> for BoxedSelectStatement<'a, ST, (), DB>
where
    DB: Backend,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("SELECT ");
        self.distinct.walk_ast(out.reborrow())?;
        self.select.walk_ast(out.reborrow())?;
        self.where_clause.walk_ast(out.reborrow())?;
        self.group_by.walk_ast(out.reborrow())?;
        self.order.walk_ast(out.reborrow())?;
        self.limit.walk_ast(out.reborrow())?;
        self.offset.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<'a, ST, QS, DB> QueryId for BoxedSelectStatement<'a, ST, QS, DB> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<'a, ST, QS, DB, Rhs, Kind, On> InternalJoinDsl<Rhs, Kind, On>
    for BoxedSelectStatement<'a, ST, QS, DB>
where
    BoxedSelectStatement<'a, ST, JoinOn<Join<QS, Rhs, Kind>, On>, DB>: AsQuery,
{
    type Output = BoxedSelectStatement<'a, ST, JoinOn<Join<QS, Rhs, Kind>, On>, DB>;

    fn join(self, rhs: Rhs, kind: Kind, on: On) -> Self::Output {
        BoxedSelectStatement::new(
            self.select,
            Join::new(self.from, rhs, kind).on(on),
            self.distinct,
            self.where_clause,
            self.order,
            self.limit,
            self.offset,
            self.group_by,
        )
    }
}

impl<'a, ST, QS, DB> DistinctDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    DistinctClause: QueryFragment<DB>,
{
    type Output = Self;

    fn distinct(mut self) -> Self::Output {
        self.distinct = Box::new(DistinctClause);
        self
    }
}

impl<'a, ST, QS, DB, Selection> SelectDsl<Selection> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    Selection: SelectableExpression<QS> + QueryFragment<DB> + Send + 'a,
{
    type Output = BoxedSelectStatement<'a, Selection::SqlType, QS, DB>;

    fn select(self, selection: Selection) -> Self::Output {
        BoxedSelectStatement::new(
            Box::new(selection),
            self.from,
            self.distinct,
            self.where_clause,
            self.order,
            self.limit,
            self.offset,
            self.group_by,
        )
    }
}

impl<'a, ST, QS, DB, Predicate> FilterDsl<Predicate> for BoxedSelectStatement<'a, ST, QS, DB>
where
    BoxedWhereClause<'a, DB>: WhereAnd<Predicate, Output = BoxedWhereClause<'a, DB>>,
    Predicate: AppearsOnTable<QS, SqlType = Bool> + NonAggregate,
{
    type Output = Self;

    fn filter(mut self, predicate: Predicate) -> Self::Output {
        self.where_clause = self.where_clause.and(predicate);
        self
    }
}

impl<'a, ST, QS, DB, Predicate> OrFilterDsl<Predicate> for BoxedSelectStatement<'a, ST, QS, DB>
where
    BoxedWhereClause<'a, DB>: WhereOr<Predicate, Output = BoxedWhereClause<'a, DB>>,
    Predicate: AppearsOnTable<QS, SqlType = Bool> + NonAggregate,
{
    type Output = Self;

    fn or_filter(mut self, predicate: Predicate) -> Self::Output {
        self.where_clause = self.where_clause.or(predicate);
        self
    }
}

impl<'a, ST, QS, DB> LimitDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    LimitClause<AsExprOf<i64, BigInt>>: QueryFragment<DB>,
{
    type Output = Self;

    fn limit(mut self, limit: i64) -> Self::Output {
        self.limit = Box::new(LimitClause(limit.into_sql::<BigInt>()));
        self
    }
}

impl<'a, ST, QS, DB> OffsetDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    OffsetClause<AsExprOf<i64, BigInt>>: QueryFragment<DB>,
{
    type Output = Self;

    fn offset(mut self, offset: i64) -> Self::Output {
        self.offset = Box::new(OffsetClause(offset.into_sql::<BigInt>()));
        self
    }
}

impl<'a, ST, QS, DB, Order> OrderDsl<Order> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    Order: QueryFragment<DB> + AppearsOnTable<QS> + Send + 'a,
{
    type Output = Self;

    fn order(mut self, order: Order) -> Self::Output {
        self.order = OrderClause(order).into();
        self
    }
}

impl<'a, ST, QS, DB, Order> ThenOrderDsl<Order> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend + 'a,
    Order: QueryFragment<DB> + AppearsOnTable<QS> + Send + 'a,
{
    type Output = Self;

    fn then_order_by(mut self, order: Order) -> Self::Output {
        self.order = match self.order {
            Some(old) => Some(Box::new((old, order))),
            None => Some(Box::new(order)),
        };
        self
    }
}

impl<'a, ST, QS, DB, Expr> GroupByDsl<Expr> for BoxedSelectStatement<'a, ST, QS, DB>
where
    DB: Backend,
    Expr: QueryFragment<DB> + AppearsOnTable<QS> + Send + 'a,
    Self: Query,
{
    type Output = Self;

    fn group_by(mut self, group_by: Expr) -> Self::Output {
        self.group_by = Box::new(GroupByClause(group_by));
        self
    }
}

// FIXME: Should we disable joining when `.group_by` has been called? Are there
// any other query methods where a join no longer has the same semantics as
// joining on just the table?
impl<'a, ST, QS, DB, Rhs> JoinTo<Rhs> for BoxedSelectStatement<'a, ST, QS, DB>
where
    QS: JoinTo<Rhs>,
{
    type FromClause = QS::FromClause;
    type OnClause = QS::OnClause;

    fn join_target(rhs: Rhs) -> (Self::FromClause, Self::OnClause) {
        QS::join_target(rhs)
    }
}

impl<'a, ST, QS, DB> QueryDsl for BoxedSelectStatement<'a, ST, QS, DB> {}

impl<'a, ST, QS, DB, Conn> RunQueryDsl<Conn> for BoxedSelectStatement<'a, ST, QS, DB> {}

impl<'a, ST, QS, DB, T> Insertable<T> for BoxedSelectStatement<'a, ST, QS, DB>
where
    T: Table,
    Self: Query,
{
    type Values = InsertFromSelect<Self, T::AllColumns>;

    fn values(self) -> Self::Values {
        InsertFromSelect::new(self)
    }
}

impl<'a, 'b, ST, QS, DB, T> Insertable<T> for &'b BoxedSelectStatement<'a, ST, QS, DB>
where
    T: Table,
    Self: Query,
{
    type Values = InsertFromSelect<Self, T::AllColumns>;

    fn values(self) -> Self::Values {
        InsertFromSelect::new(self)
    }
}

impl<'a, ST, QS, DB> SelectNullableDsl for BoxedSelectStatement<'a, ST, QS, DB>
where
    ST: NotNull,
{
    type Output = BoxedSelectStatement<'a, Nullable<ST>, QS, DB>;

    fn nullable(self) -> Self::Output {
        BoxedSelectStatement {
            select: self.select,
            from: self.from,
            distinct: self.distinct,
            where_clause: self.where_clause,
            order: self.order,
            limit: self.limit,
            offset: self.offset,
            group_by: self.group_by,
            _marker: PhantomData,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::backend::Backend;
    use crate::prelude::*;

    table! {
        users {
            id -> Integer,
        }
    }

    fn assert_send<T>(_: T)
    where
        T: Send,
    {
    }

    fn assert_boxed_query_send<B: Backend>() {
        assert_send(users::table.into_boxed::<B>());
        assert_send(users::table.filter(users::id.eq(10)).into_boxed::<B>());
    }

    #[test]
    fn boxed_is_send() {
        #[cfg(feature = "postgres")]
        assert_boxed_query_send::<crate::pg::Pg>();

        #[cfg(feature = "sqlite")]
        assert_boxed_query_send::<crate::sqlite::Sqlite>();

        #[cfg(feature = "mysql")]
        assert_boxed_query_send::<crate::mysql::Mysql>();
    }
}
<|endoftext|>