<commit_before>use crate::numeric::StateVector;
use crate::typenum::consts::{U0, U1, U2, U3, U5};
use crate::typenum::{Exp, Pow, Prod, Same, Unsigned};
use diffgeom::coordinates::{ConversionTo, CoordinateSystem, Point};
use diffgeom::inner;
use diffgeom::metric::MetricSystem;
use diffgeom::tensors::Vector;
use generic_array::{ArrayLength, GenericArray};
use numeric_algs::State;
use std::ops::Mul;

pub struct Entity<C: CoordinateSystem>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    x: Point<C>,
    dirs: [Vector<C>; 4],
}

impl<C: CoordinateSystem> Clone for Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    fn clone(&self) -> Self {
        Entity {
            x: self.x.clone(),
            dirs: self.dirs.clone(),
        }
    }
}

impl<C: CoordinateSystem> Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn new(
        x: Point<C>,
        v: Vector<C>,
        local_x: Vector<C>,
        local_y: Vector<C>,
        local_z: Vector<C>,
    ) -> Self {
        Entity {
            x: x,
            dirs: [v, local_x, local_y, local_z],
        }
    }

    pub fn orthonormalize(&mut self)
    where
        C: MetricSystem,
        C::Dimension: Pow<U2> + Pow<U3>,
        Exp<C::Dimension, U2>: ArrayLength<f64>,
        Exp<C::Dimension, U3>: ArrayLength<f64>,
    {
        let g = C::g(&self.x);
        for i in 0..4 {
            let dirs_i_cov = inner!(_, Vector<C>; U1, U2; g.clone(), self.dirs[i].clone());
            for j in 0..i {
                let dot_ij =
                    *inner!(_, Vector<C>; U0, U1; dirs_i_cov.clone(), self.dirs[j].clone());
                let abs_j_temp = inner!(_, Vector<C>; U1, U2; g.clone(), self.dirs[j].clone());
                let abs_j = *inner!(_, Vector<C>; U0, U1; abs_j_temp, self.dirs[j].clone());
                self.dirs[i] -= self.dirs[j].clone() * dot_ij / abs_j;
            }
            let dirs_i_abs = *inner!(_, Vector<C>; U0, U1; dirs_i_cov, self.dirs[i].clone());
            self.dirs[i] /= dirs_i_abs.abs().sqrt();
        }
    }

    pub fn get_pos(&self) -> &Point<C> {
        &self.x
    }

    pub fn get_vel(&self) -> &Vector<C> {
        &self.dirs[0]
    }
}

impl<C: CoordinateSystem> State for Entity<C>
where
    C::Dimension: Pow<U1> + Mul<U2> + Unsigned,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U2>: ArrayLength<f64>,
    <Prod<C::Dimension, U2> as ArrayLength<f64>>::ArrayType: Copy,
{
    type Derivative = StateVector<Prod<C::Dimension, U2>>;

    fn shift_in_place(&mut self, dir: &Self::Derivative, amount: f64) {
        let d = C::Dimension::to_usize();
        for i in 0..d {
            self.x[i] += dir.0[i] * amount;
            for j in 0..4 {
                self.dirs[j][i] += dir.0[i + (j + 1) * d] * amount;
                self.dirs[j].set_point(self.x.clone());
            }
        }
    }
}

impl<C: CoordinateSystem> Entity<C>
where
    C::Dimension: Pow<U1> + Mul<U5> + Unsigned + Pow<U2> + Pow<U3>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U5>: ArrayLength<f64>,
    <Prod<C::Dimension, U5> as ArrayLength<f64>>::ArrayType: Copy,
    C: MetricSystem,
    Exp<C::Dimension, U2>: ArrayLength<f64>,
    Exp<C::Dimension, U3>: ArrayLength<f64>,
{
    pub fn derivative(&self) -> StateVector<Prod<C::Dimension, U5>> {
        let christoffel = C::christoffel(&self.x);
        let chr_times_v = inner!(_, Vector<C>; U1, U3; christoffel, self.dirs[0].clone());
        let mut result = GenericArray::default();
        let d = C::Dimension::to_usize();

        // derivative of directions
        for j in 0..4 {
            let cov_der = inner!(_, Vector<C>; U1, U2; chr_times_v.clone(), self.dirs[j].clone());
            for i in 0..d {
                result[i + (j + 1) * d] = -cov_der[i];
            }
        }

        // position derivative
        for i in 0..d {
            result[i] = self.dirs[0][i];
        }
        StateVector(result)
    }
}

impl<C: CoordinateSystem> Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn convert<C2: CoordinateSystem + 'static>(&self) -> Entity<C2>
    where
        C: ConversionTo<C2>,
        C2::Dimension: Pow<U1> + Pow<U2>,
        Exp<C2::Dimension, U1>: ArrayLength<f64>,
        Exp<C2::Dimension, U2>: ArrayLength<f64>,
        C2::Dimension: Same<C::Dimension>,
    {
        let new_x: Point<C2> = C::convert_point(&self.x);
        let new_dirs: [Vector<C2>; 4] = [
            self.dirs[0].convert(),
            self.dirs[1].convert(),
            self.dirs[2].convert(),
            self.dirs[3].convert(),
        ];
        Entity {
            x: new_x,
            dirs: new_dirs,
        }
    }
}

pub trait PosAndVel<D: Unsigned + ArrayLength<f64> + Pow<U1>>
where
    Exp<D, U1>: ArrayLength<f64>,
{
    fn get_pos(&self) -> &GenericArray<f64, D>;
    fn get_vel(&self) -> &GenericArray<f64, Exp<D, U1>>;
}

impl<C: CoordinateSystem> PosAndVel<C::Dimension> for Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    fn get_pos(&self) -> &GenericArray<f64, C::Dimension> {
        self.x.coords_array()
    }

    fn get_vel(&self) -> &GenericArray<f64, Exp<C::Dimension, U1>> {
        self.dirs[0].coords_array()
    }
}
<commit_msg>Implement forces and angular velocity for Entities<commit_after>use crate::numeric::StateVector;
use crate::typenum::consts::{U0, U1, U2, U3, U5};
use crate::typenum::{Exp, Pow, Prod, Same, Unsigned};
use diffgeom::coordinates::{ConversionTo, CoordinateSystem, Point};
use diffgeom::inner;
use diffgeom::metric::MetricSystem;
use diffgeom::tensors::Vector;
use generic_array::{ArrayLength, GenericArray};
use numeric_algs::State;
use std::ops::Mul;

pub struct Entity<C: CoordinateSystem>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    // position
    x: Point<C>,
    // the local basis of spacetime; the vectors represent:
    // 0: 4-velocity
    // 1: the forward direction
    // 2: the right direction
    // 3: the up direction
    dirs: [Vector<C>; 4],
    // applied force in local coordinates
    force: [f64; 3],
    // angular velocity in local coordinates
    ang_vel: [f64; 3],
}

impl<C: CoordinateSystem> Clone for Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    fn clone(&self) -> Self {
        Entity {
            x: self.x.clone(),
            dirs: self.dirs.clone(),
            force: self.force,
            ang_vel: self.ang_vel,
        }
    }
}

impl<C: CoordinateSystem> Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn new(
        x: Point<C>,
        v: Vector<C>,
        local_x: Vector<C>,
        local_y: Vector<C>,
        local_z: Vector<C>,
    ) -> Self {
        Entity {
            x: x,
            dirs: [v, local_x, local_y, local_z],
            force: [0.0; 3],
            ang_vel: [0.0; 3],
        }
    }

    pub fn orthonormalize(&mut self)
    where
        C: MetricSystem,
        C::Dimension: Pow<U2> + Pow<U3>,
        Exp<C::Dimension, U2>: ArrayLength<f64>,
        Exp<C::Dimension, U3>: ArrayLength<f64>,
    {
        let g = C::g(&self.x);
        for i in 0..4 {
            let dirs_i_cov = inner!(_, Vector<C>; U1, U2; g.clone(), self.dirs[i].clone());
            for j in 0..i {
                let dot_ij =
                    *inner!(_, Vector<C>; U0, U1; dirs_i_cov.clone(), self.dirs[j].clone());
                let abs_j_temp = inner!(_, Vector<C>; U1, U2; g.clone(), self.dirs[j].clone());
                let abs_j = *inner!(_, Vector<C>; U0, U1; abs_j_temp, self.dirs[j].clone());
                self.dirs[i] -= self.dirs[j].clone() * dot_ij / abs_j;
            }
            let dirs_i_abs = *inner!(_, Vector<C>; U0, U1; dirs_i_cov, self.dirs[i].clone());
            self.dirs[i] /= dirs_i_abs.abs().sqrt();
        }
    }

    pub fn add_force(&mut self, x: f64, y: f64, z: f64) {
        self.force[0] += x;
        self.force[1] += y;
        self.force[2] += z;
    }

    pub fn add_ang_vel(&mut self, x: f64, y: f64, z: f64) {
        self.ang_vel[0] += x;
        self.ang_vel[1] += y;
        self.ang_vel[2] += z;
    }

    pub fn reset_force(&mut self) {
        self.force = [0.0; 3];
    }

    pub fn reset_ang_vel(&mut self) {
        self.ang_vel = [0.0; 3];
    }

    pub fn get_pos(&self) -> &Point<C> {
        &self.x
    }

    pub fn get_vel(&self) -> &Vector<C> {
        &self.dirs[0]
    }

    // calculates the covariant derivative of the selected component of the local basis in the
    // direction of 4-velocity
    fn calculate_derivative(&self, dir: usize) -> Vector<C> {
        let gen_matrix = [
            [0.0, self.force[0], self.force[1], self.force[2]],
            [self.force[0], 0.0, -self.ang_vel[2], self.ang_vel[1]],
            [self.force[1], self.ang_vel[2], 0.0, -self.ang_vel[0]],
            [self.force[2], -self.ang_vel[1], self.ang_vel[0], 0.0],
        ];

        let mut result = Vector::zero(self.x.clone());

        for i in 0..4 {
            result += gen_matrix[i][dir] * self.dirs[i].clone();
        }

        result
    }
}

impl<C: CoordinateSystem> State for Entity<C>
where
    C::Dimension: Pow<U1> + Mul<U2> + Unsigned,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U2>: ArrayLength<f64>,
    <Prod<C::Dimension, U2> as ArrayLength<f64>>::ArrayType: Copy,
{
    type Derivative = StateVector<Prod<C::Dimension, U2>>;

    fn shift_in_place(&mut self, dir: &Self::Derivative, amount: f64) {
        let d = C::Dimension::to_usize();
        for i in 0..d {
            self.x[i] += dir.0[i] * amount;
            for j in 0..4 {
                self.dirs[j][i] += dir.0[i + (j + 1) * d] * amount;
                self.dirs[j].set_point(self.x.clone());
            }
        }
    }
}

impl<C: CoordinateSystem> Entity<C>
where
    C::Dimension: Pow<U1> + Mul<U5> + Unsigned + Pow<U2> + Pow<U3>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
    Prod<C::Dimension, U5>: ArrayLength<f64>,
    <Prod<C::Dimension, U5> as ArrayLength<f64>>::ArrayType: Copy,
    C: MetricSystem,
    Exp<C::Dimension, U2>: ArrayLength<f64>,
    Exp<C::Dimension, U3>: ArrayLength<f64>,
{
    pub fn derivative(&self) -> StateVector<Prod<C::Dimension, U5>> {
        let christoffel = C::christoffel(&self.x);
        let chr_times_v = inner!(_, Vector<C>; U1, U3; christoffel, self.dirs[0].clone());
        let mut result = GenericArray::default();
        let d = C::Dimension::to_usize();

        // derivative of directions
        for j in 0..4 {
            let chr_part = inner!(_, Vector<C>; U1, U2; chr_times_v.clone(), self.dirs[j].clone());
            let cov_der = self.calculate_derivative(j);

            for i in 0..d {
                result[i + (j + 1) * d] = cov_der[i] - chr_part[i];
            }
        }

        // position derivative
        for i in 0..d {
            result[i] = self.dirs[0][i];
        }
        StateVector(result)
    }
}

impl<C: CoordinateSystem> Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    pub fn convert<C2: CoordinateSystem + 'static>(&self) -> Entity<C2>
    where
        C: ConversionTo<C2>,
        C2::Dimension: Pow<U1> + Pow<U2>,
        Exp<C2::Dimension, U1>: ArrayLength<f64>,
        Exp<C2::Dimension, U2>: ArrayLength<f64>,
        C2::Dimension: Same<C::Dimension>,
    {
        let new_x: Point<C2> = C::convert_point(&self.x);
        let new_dirs: [Vector<C2>; 4] = [
            self.dirs[0].convert(),
            self.dirs[1].convert(),
            self.dirs[2].convert(),
            self.dirs[3].convert(),
        ];
        Entity {
            x: new_x,
            dirs: new_dirs,
            force: self.force,
            ang_vel: self.ang_vel,
        }
    }
}

pub trait PosAndVel<D: Unsigned + ArrayLength<f64> + Pow<U1>>
where
    Exp<D, U1>: ArrayLength<f64>,
{
    fn get_pos(&self) -> &GenericArray<f64, D>;
    fn get_vel(&self) -> &GenericArray<f64, Exp<D, U1>>;
}

impl<C: CoordinateSystem> PosAndVel<C::Dimension> for Entity<C>
where
    C::Dimension: Pow<U1>,
    Exp<C::Dimension, U1>: ArrayLength<f64>,
{
    fn get_pos(&self) -> &GenericArray<f64, C::Dimension> {
        self.x.coords_array()
    }

    fn get_vel(&self) -> &GenericArray<f64, Exp<C::Dimension, U1>> {
        self.dirs[0].coords_array()
    }
}
<|endoftext|>


<commit_before>use bincode;
use std;
use std::path::PathBuf;

static ISSUE_TEMPLATE: &'static str = r#"
=> If this is a bug please file an issue at: https://git.io/v96U6"#;

error_chain! {
    errors {
        BookmarkNotFound(name: String) {
            description("Bookmark not found.")
            display("The bookmark \"{}\" was not found", name)
        }

        DBOpenError(path: PathBuf) {
            description("Failed to open database.")
            display("Failed to open db file: {:?}.{}", path, ISSUE_TEMPLATE)
        }

        DBCloseError(path: PathBuf) {
            description("Failed to close DB file")
            display("Could not close: \n\"{:?}\"\n\n{}", path, ISSUE_TEMPLATE)
        }

        ResolveError(path: PathBuf) {
            description("Failed to resolve path.")
            display("Failed to resolve {:?}.{}", path, ISSUE_TEMPLATE)
        }

        PathDoesNotExistError(path: PathBuf) {
            description("Path does not exist.")
            display("Path does not exist {:?}.{}", path, ISSUE_TEMPLATE)
        }

        CurrentDirectoryError(path: PathBuf) {
            description("Failed to derive current directory.")
            display("Failed to get current dir when resolving {:?}.{}", path, ISSUE_TEMPLATE)
        }

        ConfigError {
            description("Unable to derive config")
            display("{}", ISSUE_TEMPLATE)
        }

        BasenameError(path: PathBuf) {
            description("Failed to derive basename")
            display("Could not derive basename from {:?}.{}", path, ISSUE_TEMPLATE)
        }

        CreateDirError(path: PathBuf) {
            description("Failed to create dir")
            display("Failed to create {:?}.{}", path, ISSUE_TEMPLATE)
        }
    }

    foreign_links {
        IOError(std::io::Error) #[doc = "Error during IO"];
        BincodeError(std::boxed::Box<bincode::ErrorKind>);
    }
}

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

    #[test]
    fn bookmark_not_found() {
        let name = String::from("nope");
        let err = ErrorKind::BookmarkNotFound(name);
        assert_eq!(err.description(), "Bookmark not found.");
        assert_eq!(err.to_string(), "The bookmark \"nope\" was not found");
    }

    #[test]
    fn database_open_failure() {
        let path = PathBuf::from("nope");
        let err = ErrorKind::DBOpenError(path);
        assert_eq!(err.description(), "Failed to open database.");
        assert_eq!(err.to_string(), format!("Failed to open db file: {:?}.{}", PathBuf::from("nope"), ISSUE_TEMPLATE));
    }
}
<commit_msg>Adds error test for ErrorKind::DBCloseError<commit_after>use bincode;
use std;
use std::path::PathBuf;

static ISSUE_TEMPLATE: &'static str = r#"
=> If this is a bug please file an issue at: https://git.io/v96U6"#;

error_chain! {
    errors {
        BookmarkNotFound(name: String) {
            description("Bookmark not found.")
            display("The bookmark \"{}\" was not found", name)
        }

        DBOpenError(path: PathBuf) {
            description("Failed to open database.")
            display("Failed to open db file: {:?}.{}", path, ISSUE_TEMPLATE)
        }

        DBCloseError(path: PathBuf) {
            description("Failed to close database.")
            display("Failed to close db file: {:?}.{}", path, ISSUE_TEMPLATE)
        }

        ResolveError(path: PathBuf) {
            description("Failed to resolve path.")
            display("Failed to resolve {:?}.{}", path, ISSUE_TEMPLATE)
        }

        PathDoesNotExistError(path: PathBuf) {
            description("Path does not exist.")
            display("Path does not exist {:?}.{}", path, ISSUE_TEMPLATE)
        }

        CurrentDirectoryError(path: PathBuf) {
            description("Failed to derive current directory.")
            display("Failed to get current dir when resolving {:?}.{}", path, ISSUE_TEMPLATE)
        }

        ConfigError {
            description("Unable to derive config")
            display("{}", ISSUE_TEMPLATE)
        }

        BasenameError(path: PathBuf) {
            description("Failed to derive basename")
            display("Could not derive basename from {:?}.{}", path, ISSUE_TEMPLATE)
        }

        CreateDirError(path: PathBuf) {
            description("Failed to create dir")
            display("Failed to create {:?}.{}", path, ISSUE_TEMPLATE)
        }
    }

    foreign_links {
        IOError(std::io::Error) #[doc = "Error during IO"];
        BincodeError(std::boxed::Box<bincode::ErrorKind>);
    }
}

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

    #[test]
    fn bookmark_not_found() {
        let name = String::from("nope");
        let err = ErrorKind::BookmarkNotFound(name);
        assert_eq!(err.description(), "Bookmark not found.");
        assert_eq!(err.to_string(), "The bookmark \"nope\" was not found");
    }

    #[test]
    fn database_open_failure() {
        let path = PathBuf::from("nope");
        let err = ErrorKind::DBOpenError(path);
        assert_eq!(err.description(), "Failed to open database.");
        assert_eq!(err.to_string(), format!("Failed to open db file: {:?}.{}", PathBuf::from("nope"), ISSUE_TEMPLATE));
    }

    #[test]
    fn database_close_failure() {
        let path = PathBuf::from("nope");
        let err = ErrorKind::DBCloseError(path);
        assert_eq!(err.description(), "Failed to close database.");
        assert_eq!(err.to_string(), format!("Failed to close db file: {:?}.{}", PathBuf::from("nope"), ISSUE_TEMPLATE));
    }
}
<|endoftext|>


<commit_before>fn ispalindrome(n: u32) -> bool {
    let s = n.to_string();
    s == s.chars().rev().collect::<String>()
}

pub fn main() {
    let mut max = 0;
    for i in 100..1000 {
        for j in 100..1000 {
            let n = i * j;
            if n > max && ispalindrome(n) {
                max = n;
            }
        }
    }
    println!("{}", max);
}<commit_msg>use more iterators<commit_after>//fn ispalindrome(n: u32) -> bool {
//    let s = n.to_string();
//    s == s.chars().rev().collect::<String>()
//}

fn ispalindrome(n: u32) -> bool {
    let s = n.to_string();
    s.chars().zip(s.chars().rev()).all(|(x, y)| x == y)
}

pub fn main() {
    let mut max = 0;
    for i in 100..1000 {
        for j in 100..1000 {
            let n = i * j;
            if n > max && ispalindrome(n) {
                max = n;
            }
        }
    }
    println!("{}", max);
}<|endoftext|>


<commit_before>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Option<Pagination>,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                client: {:?}, pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
            pagination: None,
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", domain, 443, private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
        let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
                              self.scheme,
                              self.domain,
                              self.port,
                              API_VERSION,
                              query,
                              params_splitter,
                              self.private_token);

        self.pagination.as_ref().map(|pagination| {
            url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
        });

        url
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        let url = self.build_url(query);
        info!("url: {:?}", url);
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body:\n{:?}", body);

        // FIXME: Properly handle the error. Will require defining our own errors...
        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }
    //
    // pub fn projects(&self) -> Result<Projects, serde_json::Error> {
    //     self.get("projects")
    // }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<commit_msg>Print a warning in `GitLab::new_insecure()`<commit_after>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Option<Pagination>,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                client: {:?}, pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
            pagination: None,
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", domain, 443, private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
        let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
                              self.scheme,
                              self.domain,
                              self.port,
                              API_VERSION,
                              query,
                              params_splitter,
                              self.private_token);

        self.pagination.as_ref().map(|pagination| {
            url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
        });

        url
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        self.client.get(&url).header(hyper::header::Connection::close()).send()
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        let url = self.build_url(query);
        info!("url: {:?}", url);
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body:\n{:?}", body);

        // FIXME: Properly handle the error. Will require defining our own errors...
        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }
    //
    // pub fn projects(&self) -> Result<Projects, serde_json::Error> {
    //     self.get("projects")
    // }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        self.get(&query)
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

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


<commit_before>// Copyright(C) 2016 Chris Liebert
extern crate rusqlite;
extern crate time;

use self::rusqlite::Connection;

use std::path::Path;

use common::{ImageBlob, Material, Mesh, SceneNode, Scene, Shader, Vertex8f32};

pub struct DBLoader {
    filename: String,
}

fn create_vertex8f32(px: f64,
                     py: f64,
                     pz: f64,
                     nx: f64,
                     ny: f64,
                     nz: f64,
                     tu: f64,
                     tv: f64)
                     -> Vertex8f32 {
    let position: [f32; 3] = [px as f32, py as f32, pz as f32];
    let normal: [f32; 3] = [nx as f32, ny as f32, nz as f32];
    let texcoord: [f32; 2] = [tu as f32, tv as f32];
    Vertex8f32 {
        position: position,
        normal: normal,
        texcoord: texcoord,
    }
}

impl DBLoader {
    pub fn new(filename: &str) -> DBLoader {
        DBLoader { filename: String::from(filename) }
    }

    pub fn load_scene(&self) -> Scene {
        let conn = Connection::open(Path::new(&self.filename)).unwrap();

        // Load vertices
        let mut vertex_stmt = conn.prepare("SELECT px, py, pz, nx, ny, nz, tu, tv FROM vertex")
            .unwrap();
        let vertex_iter = vertex_stmt.query_map(&[], |row| {
                create_vertex8f32(row.get(0),
                                  row.get(1),
                                  row.get(2),
                                  row.get(3),
                                  row.get(4),
                                  row.get(5),
                                  row.get(6),
                                  row.get(7))
            })
            .unwrap();

        let mut vertices: Vec<Vertex8f32> = Vec::new();

        for vertex in vertex_iter {
            vertices.push(vertex.unwrap());
        }

        // Load materials
        let mut material_stmt =
            conn.prepare("SELECT name, diffuse_r, diffuse_g, diffuse_b, diffuse_texname FROM \
                          material")
                .unwrap();
        let material_iter = material_stmt.query_map(&[], |row| {
                let diffuse_r: f64 = row.get(1);
                let diffuse_g: f64 = row.get(2);
                let diffuse_b: f64 = row.get(3);
                Material {
                    name: row.get(0),
                    diffuse: [diffuse_r as f32, diffuse_g as f32, diffuse_b as f32],
                    diffuse_texname: row.get(4),
                }
            })
            .unwrap();

        let mut materials: Vec<Material> = Vec::new();

        for material in material_iter {
            materials.push(material.unwrap());
        }

        let mut meshes: Vec<Mesh> = Vec::new();

        // Load scene nodes
        let mut scene_node_stmt =
            conn.prepare("SELECT name, material_id, start_position, end_position FROM scene_node")
                .unwrap();
        let scene_node_iter = scene_node_stmt.query_map(&[], |row| {
                let material_id: i32 = row.get(1);
                let material_index: usize = material_id as usize - 1 as usize;
                SceneNode {
                    name: row.get(0),
                    material_index: material_index, // index starts at 1 in database, not 0
                    start_position: row.get(2),
                    end_position: row.get(3),
                }
            })
            .unwrap();

        for scene_node in scene_node_iter {
            let sn = scene_node.unwrap();
            let mut new_vertices: Vec<Vertex8f32> = Vec::new();

            for i in sn.start_position as usize..(sn.end_position) as usize {
                new_vertices.push(vertices[i]);

            }

            if sn.material_index >= materials.len() {
                panic!("Material index {} out of bounds", sn.material_index);
            }

            let mesh = Mesh {
                name: sn.name,
                material_index: sn.material_index,
                vertices: new_vertices,
            };
            meshes.push(mesh);
        }

        println!("Loaded {} vertices in {} meshes",
                 vertices.len(),
                 meshes.len());

        // Free up some memory
        vertices.clear();

        // Load textures
        let mut texture_stmt = conn.prepare("SELECT name, image FROM texture")
            .unwrap();
        let texture_iter = texture_stmt.query_map(&[], |row| {
                ImageBlob {
                    name: row.get(0),
                    image: row.get(1),
                }
            })
            .unwrap();

        let mut textures: Vec<ImageBlob> = Vec::new();

        for texture in texture_iter {
            textures.push(texture.unwrap());
        }

        // conn.close();
        return Scene {
            materials: materials,
            // scene_nodes: scene_nodes,
            // vertices: vertices,
            meshes: meshes,
            // shaders: shaders,
            images: textures,
        };
    }

    pub fn load_shader(&self, name: &str, glsl_version_string: &str) -> Shader {
        let conn = Connection::open(Path::new(&self.filename)).unwrap();
        let use_gles = false; // Use OpenGLES instead of OpenGL (for mobile devices)
        let glsl_version = 110;

        // Load the first shader in the database by default
        // TODO: load from config settings table?
        let shader_index = 0;

        let mut shader_id: i32 = conn.query_row("SELECT id FROM shader WHERE name = 'default'", //
                       &[],
                       |row| row.get(0))
            .unwrap();

        println!("Default shader id={}", shader_id);

        let mut vertex_source: String =
            conn.query_row("SELECT source FROM shader_version WHERE shader_id=1 AND version = \
                            110 AND type = 'vertex'", //
                           &[],
                           |row| row.get(0))
                .unwrap();

        let mut fragment_source: String =
            conn.query_row("SELECT source FROM shader_version WHERE shader_id=1 AND version = \
                            110 AND type = 'fragment'",
                           &[],
                           |row| row.get(0))
                .unwrap();

        Shader {
            name: String::from(name),
            vertex_source: vertex_source,
            fragment_source: fragment_source,
        }
    }
}
<commit_msg>changed a hardcoded sql query to concatenate the WHERE name= to name<commit_after>// Copyright(C) 2016 Chris Liebert
extern crate rusqlite;
extern crate time;

use self::rusqlite::Connection;

use std::path::Path;

use common::{ImageBlob, Material, Mesh, SceneNode, Scene, Shader, Vertex8f32};

pub struct DBLoader {
    filename: String,
}

fn create_vertex8f32(px: f64,
                     py: f64,
                     pz: f64,
                     nx: f64,
                     ny: f64,
                     nz: f64,
                     tu: f64,
                     tv: f64)
                     -> Vertex8f32 {
    let position: [f32; 3] = [px as f32, py as f32, pz as f32];
    let normal: [f32; 3] = [nx as f32, ny as f32, nz as f32];
    let texcoord: [f32; 2] = [tu as f32, tv as f32];
    Vertex8f32 {
        position: position,
        normal: normal,
        texcoord: texcoord,
    }
}

impl DBLoader {
    pub fn new(filename: &str) -> DBLoader {
        DBLoader { filename: String::from(filename) }
    }

    pub fn load_scene(&self) -> Scene {
        let conn = Connection::open(Path::new(&self.filename)).unwrap();

        // Load vertices
        let mut vertex_stmt = conn.prepare("SELECT px, py, pz, nx, ny, nz, tu, tv FROM vertex")
            .unwrap();
        let vertex_iter = vertex_stmt.query_map(&[], |row| {
                create_vertex8f32(row.get(0),
                                  row.get(1),
                                  row.get(2),
                                  row.get(3),
                                  row.get(4),
                                  row.get(5),
                                  row.get(6),
                                  row.get(7))
            })
            .unwrap();

        let mut vertices: Vec<Vertex8f32> = Vec::new();

        for vertex in vertex_iter {
            vertices.push(vertex.unwrap());
        }

        // Load materials
        let mut material_stmt =
            conn.prepare("SELECT name, diffuse_r, diffuse_g, diffuse_b, diffuse_texname FROM \
                          material")
                .unwrap();
        let material_iter = material_stmt.query_map(&[], |row| {
                let diffuse_r: f64 = row.get(1);
                let diffuse_g: f64 = row.get(2);
                let diffuse_b: f64 = row.get(3);
                Material {
                    name: row.get(0),
                    diffuse: [diffuse_r as f32, diffuse_g as f32, diffuse_b as f32],
                    diffuse_texname: row.get(4),
                }
            })
            .unwrap();

        let mut materials: Vec<Material> = Vec::new();

        for material in material_iter {
            materials.push(material.unwrap());
        }

        let mut meshes: Vec<Mesh> = Vec::new();

        // Load scene nodes
        let mut scene_node_stmt =
            conn.prepare("SELECT name, material_id, start_position, end_position FROM scene_node")
                .unwrap();
        let scene_node_iter = scene_node_stmt.query_map(&[], |row| {
                let material_id: i32 = row.get(1);
                let material_index: usize = material_id as usize - 1 as usize;
                SceneNode {
                    name: row.get(0),
                    material_index: material_index, // index starts at 1 in database, not 0
                    start_position: row.get(2),
                    end_position: row.get(3),
                }
            })
            .unwrap();

        for scene_node in scene_node_iter {
            let sn = scene_node.unwrap();
            let mut new_vertices: Vec<Vertex8f32> = Vec::new();

            for i in sn.start_position as usize..(sn.end_position) as usize {
                new_vertices.push(vertices[i]);

            }

            if sn.material_index >= materials.len() {
                panic!("Material index {} out of bounds", sn.material_index);
            }

            let mesh = Mesh {
                name: sn.name,
                material_index: sn.material_index,
                vertices: new_vertices,
            };
            meshes.push(mesh);
        }

        println!("Loaded {} vertices in {} meshes",
                 vertices.len(),
                 meshes.len());

        // Free up some memory
        vertices.clear();

        // Load textures
        let mut texture_stmt = conn.prepare("SELECT name, image FROM texture")
            .unwrap();
        let texture_iter = texture_stmt.query_map(&[], |row| {
                ImageBlob {
                    name: row.get(0),
                    image: row.get(1),
                }
            })
            .unwrap();

        let mut textures: Vec<ImageBlob> = Vec::new();

        for texture in texture_iter {
            textures.push(texture.unwrap());
        }

        // conn.close();
        return Scene {
            materials: materials,
            // scene_nodes: scene_nodes,
            // vertices: vertices,
            meshes: meshes,
            // shaders: shaders,
            images: textures,
        };
    }

    pub fn load_shader(&self, name: &str, glsl_version_string: &str) -> Shader {
        let conn = Connection::open(Path::new(&self.filename)).unwrap();
        let use_gles = false; // Use OpenGLES instead of OpenGL (for mobile devices)
        let glsl_version = 110;

        let mut id_sql: String = "SELECT id FROM shader WHERE name = '".to_owned();
        id_sql.push_str(name);
        id_sql.push('\'');

        let mut shader_id: i32 = conn.query_row(&id_sql /*  */, &[], |row| row.get(0))
            .unwrap();
        println!("Default shader id={}", shader_id);

        let mut vertex_source: String =
            conn.query_row("SELECT source FROM shader_version WHERE shader_id=1 AND version = \
                            110 AND type = 'vertex'", //
                           &[],
                           |row| row.get(0))
                .unwrap();

        let mut fragment_source: String =
            conn.query_row("SELECT source FROM shader_version WHERE shader_id=1 AND version = \
                            110 AND type = 'fragment'",
                           &[],
                           |row| row.get(0))
                .unwrap();

        Shader {
            name: String::from(name),
            vertex_source: vertex_source,
            fragment_source: fragment_source,
        }
    }
}
<|endoftext|>


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

// Format list-like macro invocations. These are invocations whose token trees
// can be interpreted as expressions and separated by commas.
// Note that these token trees do not actually have to be interpreted as
// expressions by the compiler. An example of an invocation we would reformat is
// foo!( x, y, z ). The token x may represent an identifier in the code, but we
// interpreted as an expression.
// Macro uses which are not-list like, such as bar!(key => val), will not be
// reformated.
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.

use syntax::ast;
use syntax::codemap::BytePos;
use syntax::parse::token::Token;
use syntax::parse::new_parser_from_tts;
use syntax::tokenstream::TokenStream;
use syntax::symbol;
use syntax::util::ThinVec;

use Shape;
use codemap::SpanUtils;
use rewrite::{Rewrite, RewriteContext};
use expr::{rewrite_call, rewrite_array, rewrite_pair};
use comment::{FindUncommented, contains_comment};
use utils::mk_sp;

const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"];

// FIXME: use the enum from libsyntax?
#[derive(Clone, Copy, PartialEq, Eq)]
enum MacroStyle {
    Parens,
    Brackets,
    Braces,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MacroPosition {
    Item,
    Statement,
    Expression,
}

impl MacroStyle {
    fn opener(&self) -> &'static str {
        match *self {
            MacroStyle::Parens => "(",
            MacroStyle::Brackets => "[",
            MacroStyle::Braces => "{",
        }
    }
}

pub fn rewrite_macro(
    mac: &ast::Mac,
    extra_ident: Option<ast::Ident>,
    context: &RewriteContext,
    shape: Shape,
    position: MacroPosition,
) -> Option<String> {
    let mut context = &mut context.clone();
    context.inside_macro = true;
    if context.config.use_try_shorthand() {
        if let Some(expr) = convert_try_mac(mac, context) {
            return expr.rewrite(context, shape);
        }
    }

    let original_style = macro_style(mac, context);

    let macro_name = match extra_ident {
        None => format!("{}!", mac.node.path),
        Some(ident) => {
            if ident == symbol::keywords::Invalid.ident() {
                format!("{}!", mac.node.path)
            } else {
                format!("{}! {}", mac.node.path, ident)
            }
        }
    };

    let style = if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
        MacroStyle::Brackets
    } else {
        original_style
    };

    let ts: TokenStream = mac.node.tts.clone().into();
    if ts.is_empty() && !contains_comment(&context.snippet(mac.span)) {
        return match style {
            MacroStyle::Parens if position == MacroPosition::Item => {
                Some(format!("{}();", macro_name))
            }
            MacroStyle::Parens => Some(format!("{}()", macro_name)),
            MacroStyle::Brackets => Some(format!("{}[]", macro_name)),
            MacroStyle::Braces => Some(format!("{}{{}}", macro_name)),
        };
    }

    let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
    let mut expr_vec = Vec::new();
    let mut vec_with_semi = false;

    if MacroStyle::Braces != style {
        loop {
            let expr = match parser.parse_expr() {
                Ok(expr) => {
                    // Recovered errors.
                    if context.parse_session.span_diagnostic.has_errors() {
                        return Some(context.snippet(mac.span));
                    }

                    expr
                }
                Err(mut e) => {
                    e.cancel();
                    return Some(context.snippet(mac.span));
                }
            };

            expr_vec.push(expr);

            match parser.token {
                Token::Eof => break,
                Token::Comma => (),
                Token::Semi => {
                    // Try to parse `vec![expr; expr]`
                    if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
                        parser.bump();
                        if parser.token != Token::Eof {
                            match parser.parse_expr() {
                                Ok(expr) => {
                                    if context.parse_session.span_diagnostic.has_errors() {
                                        return None;
                                    }
                                    expr_vec.push(expr);
                                    parser.bump();
                                    if parser.token == Token::Eof && expr_vec.len() == 2 {
                                        vec_with_semi = true;
                                        break;
                                    }
                                }
                                Err(mut e) => e.cancel(),
                            }
                        }
                    }
                    return None;
                }
                _ => return None,
            }

            parser.bump();

            if parser.token == Token::Eof {
                // vec! is a special case of bracket macro which should be formated as an array.
                if macro_name == "vec!" {
                    break;
                } else {
                    return None;
                }
            }
        }
    }

    match style {
        MacroStyle::Parens => {
            // Format macro invocation as function call, forcing no trailing
            // comma because not all macros support them.
            rewrite_call(context, &macro_name, &expr_vec, mac.span, shape).map(
                |rw| match position {
                    MacroPosition::Item => format!("{};", rw),
                    _ => rw,
                },
            )
        }
        MacroStyle::Brackets => {
            let mac_shape = try_opt!(shape.shrink_left(macro_name.len()));
            // Handle special case: `vec![expr; expr]`
            if vec_with_semi {
                let (lbr, rbr) = if context.config.spaces_within_square_brackets() {
                    ("[ ", " ]")
                } else {
                    ("[", "]")
                };
                rewrite_pair(
                    &*expr_vec[0],
                    &*expr_vec[1],
                    lbr,
                    "; ",
                    rbr,
                    context,
                    mac_shape,
                ).map(|s| format!("{}{}", macro_name, s))
            } else {
                // Format macro invocation as array literal.
                let rewrite = try_opt!(rewrite_array(
                    expr_vec.iter().map(|x| &**x),
                    mk_sp(
                        context.codemap.span_after(
                            mac.span,
                            original_style.opener(),
                        ),
                        mac.span.hi - BytePos(1),
                    ),
                    context,
                    mac_shape,
                ));

                Some(format!("{}{}", macro_name, rewrite))
            }
        }
        MacroStyle::Braces => {
            // Skip macro invocations with braces, for now.
            None
        }
    }
}

/// Tries to convert a macro use into a short hand try expression. Returns None
/// when the macro is not an instance of try! (or parsing the inner expression
/// failed).
pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option<ast::Expr> {
    if &format!("{}", mac.node.path)[..] == "try" {
        let ts: TokenStream = mac.node.tts.clone().into();
        let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());

        Some(ast::Expr {
            id: ast::NodeId::new(0), // dummy value
            node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())),
            span: mac.span, // incorrect span, but shouldn't matter too much
            attrs: ThinVec::new(),
        })
    } else {
        None
    }
}

fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
    let snippet = context.snippet(mac.span);
    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());

    if paren_pos < bracket_pos && paren_pos < brace_pos {
        MacroStyle::Parens
    } else if bracket_pos < brace_pos {
        MacroStyle::Brackets
    } else {
        MacroStyle::Braces
    }
}
<commit_msg>Direct format vec! instead of using rewrite_pair<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Format list-like macro invocations. These are invocations whose token trees
// can be interpreted as expressions and separated by commas.
// Note that these token trees do not actually have to be interpreted as
// expressions by the compiler. An example of an invocation we would reformat is
// foo!( x, y, z ). The token x may represent an identifier in the code, but we
// interpreted as an expression.
// Macro uses which are not-list like, such as bar!(key => val), will not be
// reformated.
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.

use syntax::ast;
use syntax::codemap::BytePos;
use syntax::parse::token::Token;
use syntax::parse::new_parser_from_tts;
use syntax::tokenstream::TokenStream;
use syntax::symbol;
use syntax::util::ThinVec;

use Shape;
use codemap::SpanUtils;
use rewrite::{Rewrite, RewriteContext};
use expr::{rewrite_call, rewrite_array};
use comment::{FindUncommented, contains_comment};
use utils::mk_sp;

const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"];

// FIXME: use the enum from libsyntax?
#[derive(Clone, Copy, PartialEq, Eq)]
enum MacroStyle {
    Parens,
    Brackets,
    Braces,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MacroPosition {
    Item,
    Statement,
    Expression,
}

impl MacroStyle {
    fn opener(&self) -> &'static str {
        match *self {
            MacroStyle::Parens => "(",
            MacroStyle::Brackets => "[",
            MacroStyle::Braces => "{",
        }
    }
}

pub fn rewrite_macro(
    mac: &ast::Mac,
    extra_ident: Option<ast::Ident>,
    context: &RewriteContext,
    shape: Shape,
    position: MacroPosition,
) -> Option<String> {
    let mut context = &mut context.clone();
    context.inside_macro = true;
    if context.config.use_try_shorthand() {
        if let Some(expr) = convert_try_mac(mac, context) {
            return expr.rewrite(context, shape);
        }
    }

    let original_style = macro_style(mac, context);

    let macro_name = match extra_ident {
        None => format!("{}!", mac.node.path),
        Some(ident) => {
            if ident == symbol::keywords::Invalid.ident() {
                format!("{}!", mac.node.path)
            } else {
                format!("{}! {}", mac.node.path, ident)
            }
        }
    };

    let style = if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
        MacroStyle::Brackets
    } else {
        original_style
    };

    let ts: TokenStream = mac.node.tts.clone().into();
    if ts.is_empty() && !contains_comment(&context.snippet(mac.span)) {
        return match style {
            MacroStyle::Parens if position == MacroPosition::Item => {
                Some(format!("{}();", macro_name))
            }
            MacroStyle::Parens => Some(format!("{}()", macro_name)),
            MacroStyle::Brackets => Some(format!("{}[]", macro_name)),
            MacroStyle::Braces => Some(format!("{}{{}}", macro_name)),
        };
    }

    let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
    let mut expr_vec = Vec::new();
    let mut vec_with_semi = false;

    if MacroStyle::Braces != style {
        loop {
            let expr = match parser.parse_expr() {
                Ok(expr) => {
                    // Recovered errors.
                    if context.parse_session.span_diagnostic.has_errors() {
                        return Some(context.snippet(mac.span));
                    }

                    expr
                }
                Err(mut e) => {
                    e.cancel();
                    return Some(context.snippet(mac.span));
                }
            };

            expr_vec.push(expr);

            match parser.token {
                Token::Eof => break,
                Token::Comma => (),
                Token::Semi => {
                    // Try to parse `vec![expr; expr]`
                    if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
                        parser.bump();
                        if parser.token != Token::Eof {
                            match parser.parse_expr() {
                                Ok(expr) => {
                                    if context.parse_session.span_diagnostic.has_errors() {
                                        return None;
                                    }
                                    expr_vec.push(expr);
                                    parser.bump();
                                    if parser.token == Token::Eof && expr_vec.len() == 2 {
                                        vec_with_semi = true;
                                        break;
                                    }
                                }
                                Err(mut e) => e.cancel(),
                            }
                        }
                    }
                    return None;
                }
                _ => return None,
            }

            parser.bump();

            if parser.token == Token::Eof {
                // vec! is a special case of bracket macro which should be formated as an array.
                if macro_name == "vec!" {
                    break;
                } else {
                    return None;
                }
            }
        }
    }

    match style {
        MacroStyle::Parens => {
            // Format macro invocation as function call, forcing no trailing
            // comma because not all macros support them.
            rewrite_call(context, &macro_name, &expr_vec, mac.span, shape).map(
                |rw| match position {
                    MacroPosition::Item => format!("{};", rw),
                    _ => rw,
                },
            )
        }
        MacroStyle::Brackets => {
            let mac_shape = try_opt!(shape.shrink_left(macro_name.len()));
            // Handle special case: `vec![expr; expr]`
            if vec_with_semi {
                let (lbr, rbr) = if context.config.spaces_within_square_brackets() {
                    ("[ ", " ]")
                } else {
                    ("[", "]")
                };
                // 6 = `vec!` + `; `
                let total_overhead = lbr.len() + rbr.len() + 6;
                let lhs = try_opt!(expr_vec[0].rewrite(context, mac_shape));
                let rhs = try_opt!(expr_vec[1].rewrite(context, mac_shape));
                if !lhs.contains('\n') && !rhs.contains('\n') &&
                    lhs.len() + rhs.len() + total_overhead <= shape.width
                {
                    Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr))
                } else {
                    let nested_indent = shape.indent.block_indent(context.config);
                    Some(format!(
                        "{}{}\n{}{};\n{}{}\n{}{}",
                        macro_name,
                        lbr,
                        nested_indent.to_string(context.config),
                        lhs,
                        nested_indent.to_string(context.config),
                        rhs,
                        shape.indent.to_string(context.config),
                        rbr
                    ))
                }
            } else {
                // Format macro invocation as array literal.
                let rewrite = try_opt!(rewrite_array(
                    expr_vec.iter().map(|x| &**x),
                    mk_sp(
                        context.codemap.span_after(
                            mac.span,
                            original_style.opener(),
                        ),
                        mac.span.hi - BytePos(1),
                    ),
                    context,
                    mac_shape,
                ));

                Some(format!("{}{}", macro_name, rewrite))
            }
        }
        MacroStyle::Braces => {
            // Skip macro invocations with braces, for now.
            None
        }
    }
}

/// Tries to convert a macro use into a short hand try expression. Returns None
/// when the macro is not an instance of try! (or parsing the inner expression
/// failed).
pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option<ast::Expr> {
    if &format!("{}", mac.node.path)[..] == "try" {
        let ts: TokenStream = mac.node.tts.clone().into();
        let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());

        Some(ast::Expr {
            id: ast::NodeId::new(0), // dummy value
            node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())),
            span: mac.span, // incorrect span, but shouldn't matter too much
            attrs: ThinVec::new(),
        })
    } else {
        None
    }
}

fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
    let snippet = context.snippet(mac.span);
    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());

    if paren_pos < bracket_pos && paren_pos < brace_pos {
        MacroStyle::Parens
    } else if bracket_pos < brace_pos {
        MacroStyle::Brackets
    } else {
        MacroStyle::Braces
    }
}
<|endoftext|>


<commit_before>macro_rules! cstr {
    ($s:expr) => ($s as *const _ as *const ::libc::c_char)
}

macro_rules! real {
    ($f:ident) => ({
        let func = POINTERS.read().unwrap().$f.get();
        func
    })
}

macro_rules! find {
    ($pointers:ident, $handle:ident, $f:ident, $symbol:tt) => ({
        $pointers.$f.set_from_raw($handle.sym($symbol)
                                         .chain_err(|| concat!("couldn't find ", stringify!($f), "()"))?);
    })
}

macro_rules! command {
    ($name:ident, $command:tt, $callback:expr) => (
        #[allow(non_camel_case_types)]
        struct $name;

        impl $name {
            extern "C" fn callback() {
                const F: &Fn(&::command::ArgsMaker) = &$callback;
                F(::command::MAKE_ARGS);
            }

            #[allow(dead_code)]
            extern "C" fn initialize() {
                #[link_section=".init_array"]
                static INITIALIZE: extern "C" fn() = $name::initialize;

                ::command::COMMANDS.write().unwrap().push(Box::new($name));
            }
        }

        impl ::command::Command for $name {
            fn name(&self) -> &'static [u8] {
                $command
            }

            fn callback(&self) -> extern "C" fn() {
                Self::callback
            }
        }
    )
}

macro_rules! gen_function_impls {
    (@make_impl ($($extern_type:tt)*) ($($arg_name:ident : $arg_type:ident),*)) => (
        impl<R $(, $arg_type)*> Default for Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            fn default() -> Self {
                Function {
                    ptr: Self::default_func as $($extern_type)* fn($($arg_type),*) -> R,
                }
            }
        }

        #[allow(dead_code)]
        impl<R $(, $arg_type)*> Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            pub fn is_default(&self) -> bool {
                self.ptr as *const usize == Self::default_func as *const usize
            }

            #[inline(always)]
            pub fn call(&self $(, $arg_name : $arg_type)*) -> R {
                (self.ptr)($($arg_name),*)
            }

            #[inline(always)]
            pub fn get(&self) -> $($extern_type)* fn($($arg_type),*) -> R {
                self.ptr
            }

            #[inline(always)]
            pub fn set(&mut self, f: $($extern_type)* fn($($arg_type),*) -> R) {
                self.ptr = f;
            }

            #[inline(always)]
            pub unsafe fn set_from_raw(&mut self, f: *const ::libc::c_void) {
                self.set(*(&f as *const _ as *const _));
            }

            // This should never be called.
            $($extern_type)* fn default_func($(_: $arg_type),*) -> R {
                unreachable!();
            }
        }
    );

    (@gen_impls $($arg_name:ident : $arg_type:ident),*) => (
        gen_function_impls!(@make_impl (                 ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (extern "C"       ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (extern "system"  ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (extern "fastcall") ($($arg_name : $arg_type),*));
    );

    () => (
        gen_function_impls!(@gen_impls);
    );

    ($first_arg_name:ident : $first_arg_type:ident $(, $arg_name:ident : $arg_type:ident)*) => (
        gen_function_impls!(@gen_impls $first_arg_name : $first_arg_type $(, $arg_name : $arg_type)*);
        gen_function_impls!($($arg_name : $arg_type),*);
    );
}
<commit_msg>Make real!() use ::hooks::hw::POINTERS<commit_after>macro_rules! cstr {
    ($s:expr) => ($s as *const _ as *const ::libc::c_char)
}

macro_rules! real {
    ($f:ident) => ({
        let func = ::hooks::hw::POINTERS.read().unwrap().$f.get();
        func
    })
}

macro_rules! find {
    ($pointers:ident, $handle:ident, $f:ident, $symbol:tt) => ({
        $pointers.$f.set_from_raw($handle.sym($symbol)
                                         .chain_err(|| concat!("couldn't find ", stringify!($f), "()"))?);
    })
}

macro_rules! command {
    ($name:ident, $command:tt, $callback:expr) => (
        #[allow(non_camel_case_types)]
        struct $name;

        impl $name {
            extern "C" fn callback() {
                const F: &Fn(&::command::ArgsMaker) = &$callback;
                F(::command::MAKE_ARGS);
            }

            #[allow(dead_code)]
            extern "C" fn initialize() {
                #[link_section=".init_array"]
                static INITIALIZE: extern "C" fn() = $name::initialize;

                ::command::COMMANDS.write().unwrap().push(Box::new($name));
            }
        }

        impl ::command::Command for $name {
            fn name(&self) -> &'static [u8] {
                $command
            }

            fn callback(&self) -> extern "C" fn() {
                Self::callback
            }
        }
    )
}

macro_rules! gen_function_impls {
    (@make_impl ($($extern_type:tt)*) ($($arg_name:ident : $arg_type:ident),*)) => (
        impl<R $(, $arg_type)*> Default for Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            fn default() -> Self {
                Function {
                    ptr: Self::default_func as $($extern_type)* fn($($arg_type),*) -> R,
                }
            }
        }

        #[allow(dead_code)]
        impl<R $(, $arg_type)*> Function<$($extern_type)* fn($($arg_type),*) -> R> {
            #[inline(always)]
            pub fn is_default(&self) -> bool {
                self.ptr as *const usize == Self::default_func as *const usize
            }

            #[inline(always)]
            pub fn call(&self $(, $arg_name : $arg_type)*) -> R {
                (self.ptr)($($arg_name),*)
            }

            #[inline(always)]
            pub fn get(&self) -> $($extern_type)* fn($($arg_type),*) -> R {
                self.ptr
            }

            #[inline(always)]
            pub fn set(&mut self, f: $($extern_type)* fn($($arg_type),*) -> R) {
                self.ptr = f;
            }

            #[inline(always)]
            pub unsafe fn set_from_raw(&mut self, f: *const ::libc::c_void) {
                self.set(*(&f as *const _ as *const _));
            }

            // This should never be called.
            $($extern_type)* fn default_func($(_: $arg_type),*) -> R {
                unreachable!();
            }
        }
    );

    (@gen_impls $($arg_name:ident : $arg_type:ident),*) => (
        gen_function_impls!(@make_impl (                 ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (extern "C"       ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (extern "system"  ) ($($arg_name : $arg_type),*));
        gen_function_impls!(@make_impl (extern "fastcall") ($($arg_name : $arg_type),*));
    );

    () => (
        gen_function_impls!(@gen_impls);
    );

    ($first_arg_name:ident : $first_arg_type:ident $(, $arg_name:ident : $arg_type:ident)*) => (
        gen_function_impls!(@gen_impls $first_arg_name : $first_arg_type $(, $arg_name : $arg_type)*);
        gen_function_impls!($($arg_name : $arg_type),*);
    );
}
<|endoftext|>


<commit_before>use rustc::lint::{Context, LintPass, LintArray};
use rustc_front::hir::*;
use syntax::ptr::P;
use std::cmp::PartialOrd;
use std::cmp::Ordering::*;

use consts::{Constant, constant_simple};
use utils::{match_path, span_lint};
use self::MinMax::{Min, Max};

declare_lint!(pub MIN_MAX, Deny,
    "`min(_, max(_, _))` (or vice versa) with bounds clamping the result \
    to a constant");

#[allow(missing_copy_implementations)]
pub struct MinMaxPass;

impl LintPass for MinMaxPass {
    fn get_lints(&self) -> LintArray {
       lint_array!(MIN_MAX)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let Some((outer_max, outer_c, oe)) = min_max(expr) {
            if let Some((inner_max, inner_c, _)) = min_max(oe) {
                if outer_max == inner_max { return; }
                match (outer_max, outer_c.partial_cmp(&inner_c)) {
                    (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (),
                    _ => {
                        span_lint(cx, MIN_MAX, expr.span,
                            "this min/max combination leads to constant result")
                    },
                }
            }
        }
    }
}

#[derive(PartialEq, Eq, Debug)]
enum MinMax {
    Min,
    Max,
}

fn min_max(expr: &Expr) -> Option<(MinMax, Constant, &Expr)> {
    if let ExprCall(ref path, ref args) = expr.node {
        if let ExprPath(None, ref path) = path.node {
            if match_path(path, &["std", "cmp", "min"]) {
                fetch_const(args, Min)
            } else {
                if match_path(path, &["std", "cmp", "max"]) {
                    fetch_const(args, Max)
                } else {
                    None
                }
            }
        } else { None }
    } else { None }
 }

fn fetch_const(args: &[P<Expr>], m: MinMax) ->
        Option<(MinMax, Constant, &Expr)> {
    if args.len() != 2 { return None }
    if let Some(c) = constant_simple(&args[0]) {
        if let None = constant_simple(&args[1]) { // otherwise ignore
            Some((m, c, &args[1]))
        } else { None }
    } else {
        if let Some(c) = constant_simple(&args[1]) {
            Some((m, c, &args[0]))
        } else { None }
    }
}
<commit_msg>Made min_max `Warn` by default<commit_after>use rustc::lint::{Context, LintPass, LintArray};
use rustc_front::hir::*;
use syntax::ptr::P;
use std::cmp::PartialOrd;
use std::cmp::Ordering::*;

use consts::{Constant, constant_simple};
use utils::{match_path, span_lint};
use self::MinMax::{Min, Max};

declare_lint!(pub MIN_MAX, Warn,
    "`min(_, max(_, _))` (or vice versa) with bounds clamping the result \
    to a constant");

#[allow(missing_copy_implementations)]
pub struct MinMaxPass;

impl LintPass for MinMaxPass {
    fn get_lints(&self) -> LintArray {
       lint_array!(MIN_MAX)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let Some((outer_max, outer_c, oe)) = min_max(expr) {
            if let Some((inner_max, inner_c, _)) = min_max(oe) {
                if outer_max == inner_max { return; }
                match (outer_max, outer_c.partial_cmp(&inner_c)) {
                    (_, None) | (Max, Some(Less)) | (Min, Some(Greater)) => (),
                    _ => {
                        span_lint(cx, MIN_MAX, expr.span,
                            "this min/max combination leads to constant result")
                    },
                }
            }
        }
    }
}

#[derive(PartialEq, Eq, Debug)]
enum MinMax {
    Min,
    Max,
}

fn min_max(expr: &Expr) -> Option<(MinMax, Constant, &Expr)> {
    if let ExprCall(ref path, ref args) = expr.node {
        if let ExprPath(None, ref path) = path.node {
            if match_path(path, &["std", "cmp", "min"]) {
                fetch_const(args, Min)
            } else {
                if match_path(path, &["std", "cmp", "max"]) {
                    fetch_const(args, Max)
                } else {
                    None
                }
            }
        } else { None }
    } else { None }
 }

fn fetch_const(args: &[P<Expr>], m: MinMax) ->
        Option<(MinMax, Constant, &Expr)> {
    if args.len() != 2 { return None }
    if let Some(c) = constant_simple(&args[0]) {
        if let None = constant_simple(&args[1]) { // otherwise ignore
            Some((m, c, &args[1]))
        } else { None }
    } else {
        if let Some(c) = constant_simple(&args[1]) {
            Some((m, c, &args[0]))
        } else { None }
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate puzrs;
extern crate rand;

use getopts::Matches;
use getopts::Options;
use std::env;

use puzrs::*;
use std::io;
use std::time::Instant;

use std::io::Write;
use std::sync::Mutex;
use std::thread;

macro_rules! run_timed {
    ($timer:ident, $flag:ident, $e:expr) => {
        if $flag {
            let start = Instant::now();
            let ret = $e;
            let end = start.elapsed();
            let cost_time = end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64;

            let mut timer_lock = $timer.lock().unwrap();
            *timer_lock += cost_time;

            ret
        } else {
            $e
        }
    };
}
fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    no_adjacent_clues: bool,
    symmetry: Symmetry,
    minimum_path_length: i32,
    empty_width: i32,
    max_clue: Option<i32>,
    corner: Option<(i32, i32)>,
    use_profiler: bool,
    prioritized_extension: bool,
}

fn run_generator(opts: GeneratorOption) {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = std::sync::Arc::new(Mutex::new(0i64));

    // profiling
    let use_profiler = opts.use_profiler;
    let cost_genenerator = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_pretest = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_exact_test = std::sync::Arc::new(Mutex::new(0.0f64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();
        let cost_genenerator = cost_genenerator.clone();
        let cost_pretest = cost_pretest.clone();
        let cost_exact_test = cost_exact_test.clone();

        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();

            let mut generator = numberlink::PlacementGenerator::new(height, width);

            let mut rng = rand::thread_rng();
            loop {
                let end = numberlink::generate_endpoint_constraint(
                    height,
                    width,
                    opts.empty_width,
                    opts.corner,
                    opts.symmetry,
                    &mut rng,
                );
                let opt = numberlink::GeneratorOption {
                    chain_threshold: opts.minimum_path_length,
                    endpoint_constraint: Some(&end),
                    forbid_adjacent_clue: opts.no_adjacent_clues,
                    symmetry: opts.symmetry,
                    clue_limit: opts.max_clue,
                    prioritized_extension: opts.prioritized_extension,
                };

                let placement = run_timed!(
                    cost_genenerator,
                    use_profiler,
                    generator.generate(&opt, &mut rng)
                );
                if let Some(placement) = placement {
                    // pretest
                    let pretest_res = run_timed!(
                        cost_pretest,
                        use_profiler,
                        numberlink::uniqueness_pretest(&placement)
                    );
                    if !pretest_res {
                        continue;
                    }

                    let problem = numberlink::extract_problem(&placement, &mut rng);

                    let ans = run_timed!(
                        cost_exact_test,
                        use_profiler,
                        numberlink::solve2(&problem, Some(2), false, true)
                    );

                    if ans.len() == 1 && !ans.found_not_fully_filled {
                        let stdin = io::stdout();
                        let handle = &mut stdin.lock();

                        let end = start.elapsed();
                        let cost_time =
                            (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                        let mut cnt = gen_probs.lock().unwrap();
                        *cnt += 1;
                        eprintln!(
                            "{} problem(s) in {:.3}[min] ({:.3} [prob/min])",
                            *cnt,
                            cost_time,
                            (*cnt) as f64 / cost_time
                        );
                        if use_profiler {
                            let cost_genenerator = *(cost_genenerator.lock().unwrap());
                            let cost_pretest = *(cost_pretest.lock().unwrap());
                            let cost_exact_test = *(cost_exact_test.lock().unwrap());
                            let cost_total = cost_genenerator + cost_pretest + cost_exact_test;

                            eprintln!("Generator: {:.3}[s] ({:.2}%) / Pretest: {:.3}[s] ({:.2}%) / Exact test: {:.3}[s] ({:.2}%)",
                                cost_genenerator, cost_genenerator / cost_total * 100.0f64,
                                cost_pretest, cost_pretest / cost_total * 100.0f64,
                                cost_exact_test, cost_exact_test / cost_total * 100.0f64);
                        }

                        writeln!(handle, "{} {}", height, width).unwrap();
                        for y in 0..height {
                            for x in 0..width {
                                let numberlink::Clue(c) = problem[(Y(y), X(x))];
                                if c >= 1 {
                                    write!(
                                        handle,
                                        "{}{}",
                                        c,
                                        if x == width - 1 { '\n' } else { ' ' }
                                    ).unwrap();
                                } else {
                                    write!(handle, ".{}", if x == width - 1 { '\n' } else { ' ' })
                                        .unwrap();
                                }
                            }
                        }
                        writeln!(handle).unwrap();
                    }
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
}

fn parse_options(matches: Matches) -> Result<GeneratorOption, &'static str> {
    let height = try!(
        matches
            .opt_str("h")
            .ok_or("'height' must be specified")
            .and_then(|arg| arg.parse::<i32>()
                .map_err(|_| "Could not parse value for 'height'"))
            .and_then(|arg| if arg > 0 {
                Ok(arg)
            } else {
                Err("'height' must be a positive integer")
            })
    );
    let width = try!(
        matches
            .opt_str("w")
            .ok_or("'width' must be specified")
            .and_then(|arg| arg.parse::<i32>()
                .map_err(|_| "Could not parse value for 'width'"))
            .and_then(|arg| if arg > 0 {
                Ok(arg)
            } else {
                Err("'width' must be a positive integer")
            })
    );
    let jobs = try!(
        matches
            .opt_str("j")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'jobs'")
                .and_then(|arg| if arg > 0 {
                    Ok(arg)
                } else {
                    Err("'jobs' must be a positive integer")
                }))
            .unwrap_or(Ok(1))
    );
    let no_adjacent_clues = matches.opt_present("no-adjacent-clues");
    let symmetry = Symmetry {
        dyad: matches.opt_present("symmetry"),
        tetrad: false,
        horizontal: false,
        vertical: false,
    };
    let minimum_path_length = try!(
        matches
            .opt_str("minimum-path-length")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'minimum-path-length'")
                .and_then(|arg| if arg > 0 {
                    Ok(arg)
                } else {
                    Err("'minimum-path-length' must be a positive integer")
                }))
            .unwrap_or(Ok(1))
    );
    let empty_width = try!(
        matches
            .opt_str("empty-width")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'empty-width'")
                .and_then(|arg| if arg > 0 {
                    Ok(arg)
                } else {
                    Err("'empty-width' must be a positive integer")
                }))
            .unwrap_or(Ok(1))
    );
    let max_clue = try!(
        matches
            .opt_str("max-clue")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'max-clue'")
                .and_then(|arg| if arg > 0 {
                    Ok(Some(arg))
                } else {
                    Err("'max-clue' must be a positive integer")
                }))
            .unwrap_or(Ok(None))
    );
    let use_profiler = matches.opt_present("use-profiler");
    let prioritized_extension = matches.opt_present("prioritized-extension");
    let corner = match matches.opt_str("corner") {
        Some(s) => {
            let split = s.split(",").collect::<Vec<&str>>();
            if split.len() != 2 {
                return Err("Could not parse value for 'corner'");
            }
            let lo = try!(
                split[0]
                    .parse::<i32>()
                    .map_err(|_| "Could not parse value for 'corner'")
            );
            let hi = try!(
                split[1]
                    .parse::<i32>()
                    .map_err(|_| "Could not parse value for 'corner'")
            );
            if !(1 <= lo && lo <= hi) {
                return Err("'corner' must be a valid range on positive integers");
            }
            Some((lo, hi))
        }
        None => None,
    };
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        no_adjacent_clues,
        symmetry,
        minimum_path_length,
        empty_width,
        max_clue,
        corner,
        use_profiler,
        prioritized_extension,
    })
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("a", "no-adjacent-clues", "Disallow adjacent clues");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optopt(
        "m",
        "minimum-path-length",
        "Minimum length of paths in the answer",
        "12",
    );
    options.optopt(
        "e",
        "empty-width",
        "Disallow clues on n cell(s) from the outer border",
        "1",
    );
    options.optopt(
        "c",
        "corner",
        "Put one clue within specified range from each corner",
        "1,3",
    );
    options.optopt("x", "max-clue", "Maximum value of clues", "10");
    options.optflag("p", "use-profiler", "Enable profiler");
    options.optflag(
        "r",
        "prioritized-extension",
        "Use prioritized extension in generator",
    );

    let matches = match options.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        }
    };

    if matches.opt_present("help") {
        print_usage(&program, options);
        return;
    }

    let opt = match parse_options(matches) {
        Ok(opt) => opt,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        }
    };
    run_generator(opt);
}
<commit_msg>Numberlink: support more symmetry types in nl_generator<commit_after>extern crate getopts;
extern crate puzrs;
extern crate rand;

use getopts::Matches;
use getopts::Options;
use std::env;

use puzrs::*;
use std::io;
use std::time::Instant;

use std::io::Write;
use std::sync::Mutex;
use std::thread;

macro_rules! run_timed {
    ($timer: ident, $flag: ident, $e: expr) => {
        if $flag {
            let start = Instant::now();
            let ret = $e;
            let end = start.elapsed();
            let cost_time = end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64;

            let mut timer_lock = $timer.lock().unwrap();
            *timer_lock += cost_time;

            ret
        } else {
            $e
        }
    };
}
fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    no_adjacent_clues: bool,
    symmetry: Symmetry,
    minimum_path_length: i32,
    empty_width: i32,
    max_clue: Option<i32>,
    corner: Option<(i32, i32)>,
    use_profiler: bool,
    prioritized_extension: bool,
}

fn run_generator(opts: GeneratorOption) {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = std::sync::Arc::new(Mutex::new(0i64));

    // profiling
    let use_profiler = opts.use_profiler;
    let cost_genenerator = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_pretest = std::sync::Arc::new(Mutex::new(0.0f64));
    let cost_exact_test = std::sync::Arc::new(Mutex::new(0.0f64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();
        let cost_genenerator = cost_genenerator.clone();
        let cost_pretest = cost_pretest.clone();
        let cost_exact_test = cost_exact_test.clone();

        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();

            let mut generator = numberlink::PlacementGenerator::new(height, width);

            let mut rng = rand::thread_rng();
            loop {
                let end = numberlink::generate_endpoint_constraint(
                    height,
                    width,
                    opts.empty_width,
                    opts.corner,
                    opts.symmetry,
                    &mut rng,
                );
                let opt = numberlink::GeneratorOption {
                    chain_threshold: opts.minimum_path_length,
                    endpoint_constraint: Some(&end),
                    forbid_adjacent_clue: opts.no_adjacent_clues,
                    symmetry: opts.symmetry,
                    clue_limit: opts.max_clue,
                    prioritized_extension: opts.prioritized_extension,
                };

                let placement = run_timed!(
                    cost_genenerator,
                    use_profiler,
                    generator.generate(&opt, &mut rng)
                );
                if let Some(placement) = placement {
                    // pretest
                    let pretest_res = run_timed!(
                        cost_pretest,
                        use_profiler,
                        numberlink::uniqueness_pretest(&placement)
                    );
                    if !pretest_res {
                        continue;
                    }

                    let problem = numberlink::extract_problem(&placement, &mut rng);

                    let ans = run_timed!(
                        cost_exact_test,
                        use_profiler,
                        numberlink::solve2(&problem, Some(2), false, true)
                    );

                    if ans.len() == 1 && !ans.found_not_fully_filled {
                        let stdin = io::stdout();
                        let handle = &mut stdin.lock();

                        let end = start.elapsed();
                        let cost_time =
                            (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                        let mut cnt = gen_probs.lock().unwrap();
                        *cnt += 1;
                        eprintln!(
                            "{} problem(s) in {:.3}[min] ({:.3} [prob/min])",
                            *cnt,
                            cost_time,
                            (*cnt) as f64 / cost_time
                        );
                        if use_profiler {
                            let cost_genenerator = *(cost_genenerator.lock().unwrap());
                            let cost_pretest = *(cost_pretest.lock().unwrap());
                            let cost_exact_test = *(cost_exact_test.lock().unwrap());
                            let cost_total = cost_genenerator + cost_pretest + cost_exact_test;

                            eprintln!("Generator: {:.3}[s] ({:.2}%) / Pretest: {:.3}[s] ({:.2}%) / Exact test: {:.3}[s] ({:.2}%)",
                                cost_genenerator, cost_genenerator / cost_total * 100.0f64,
                                cost_pretest, cost_pretest / cost_total * 100.0f64,
                                cost_exact_test, cost_exact_test / cost_total * 100.0f64);
                        }

                        writeln!(handle, "{} {}", height, width).unwrap();
                        for y in 0..height {
                            for x in 0..width {
                                let numberlink::Clue(c) = problem[(Y(y), X(x))];
                                if c >= 1 {
                                    write!(
                                        handle,
                                        "{}{}",
                                        c,
                                        if x == width - 1 { '\n' } else { ' ' }
                                    ).unwrap();
                                } else {
                                    write!(handle, ".{}", if x == width - 1 { '\n' } else { ' ' })
                                        .unwrap();
                                }
                            }
                        }
                        writeln!(handle).unwrap();
                    }
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
}
fn parse_symmetry(s: String) -> Result<Symmetry, &'static str> {
    let mut ret = Symmetry::none();
    let tokens = s.split(',');
    for token in tokens {
        if token == "d" || token == "dyad" || token == "180" {
            ret.dyad = true;
        } else if token == "t" || token == "tetrad" || token == "90" {
            ret.tetrad = true;
        } else if token == "h" || token == "horizontal" {
            ret.horizontal = true;
        } else if token == "v" || token == "vertical" {
            ret.vertical = true;
        } else {
            return Err("Unrecognized symmetry option");
        }
    }
    return Ok(ret);
}
fn parse_options(matches: Matches) -> Result<GeneratorOption, &'static str> {
    let height = try!(
        matches
            .opt_str("h")
            .ok_or("'height' must be specified")
            .and_then(|arg| arg.parse::<i32>()
                .map_err(|_| "Could not parse value for 'height'"))
            .and_then(|arg| if arg > 0 {
                Ok(arg)
            } else {
                Err("'height' must be a positive integer")
            })
    );
    let width = try!(
        matches
            .opt_str("w")
            .ok_or("'width' must be specified")
            .and_then(|arg| arg.parse::<i32>()
                .map_err(|_| "Could not parse value for 'width'"))
            .and_then(|arg| if arg > 0 {
                Ok(arg)
            } else {
                Err("'width' must be a positive integer")
            })
    );
    let jobs = try!(
        matches
            .opt_str("j")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'jobs'")
                .and_then(|arg| if arg > 0 {
                    Ok(arg)
                } else {
                    Err("'jobs' must be a positive integer")
                }))
            .unwrap_or(Ok(1))
    );
    let no_adjacent_clues = matches.opt_present("no-adjacent-clues");
    let symmetry = try!(
        matches
            .opt_str("s")
            .map(parse_symmetry)
            .unwrap_or(Ok(Symmetry::none()))
    );
    let minimum_path_length = try!(
        matches
            .opt_str("minimum-path-length")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'minimum-path-length'")
                .and_then(|arg| if arg > 0 {
                    Ok(arg)
                } else {
                    Err("'minimum-path-length' must be a positive integer")
                }))
            .unwrap_or(Ok(1))
    );
    let empty_width = try!(
        matches
            .opt_str("empty-width")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'empty-width'")
                .and_then(|arg| if arg > 0 {
                    Ok(arg)
                } else {
                    Err("'empty-width' must be a positive integer")
                }))
            .unwrap_or(Ok(1))
    );
    let max_clue = try!(
        matches
            .opt_str("max-clue")
            .map(|s| s.parse::<i32>()
                .map_err(|_| "Could not parse value for 'max-clue'")
                .and_then(|arg| if arg > 0 {
                    Ok(Some(arg))
                } else {
                    Err("'max-clue' must be a positive integer")
                }))
            .unwrap_or(Ok(None))
    );
    let use_profiler = matches.opt_present("use-profiler");
    let prioritized_extension = matches.opt_present("prioritized-extension");
    let corner = match matches.opt_str("corner") {
        Some(s) => {
            let split = s.split(",").collect::<Vec<&str>>();
            if split.len() != 2 {
                return Err("Could not parse value for 'corner'");
            }
            let lo = try!(
                split[0]
                    .parse::<i32>()
                    .map_err(|_| "Could not parse value for 'corner'")
            );
            let hi = try!(
                split[1]
                    .parse::<i32>()
                    .map_err(|_| "Could not parse value for 'corner'")
            );
            if !(1 <= lo && lo <= hi) {
                return Err("'corner' must be a valid range on positive integers");
            }
            Some((lo, hi))
        }
        None => None,
    };
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        no_adjacent_clues,
        symmetry,
        minimum_path_length,
        empty_width,
        max_clue,
        corner,
        use_profiler,
        prioritized_extension,
    })
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("a", "no-adjacent-clues", "Disallow adjacent clues");
    options.optopt("s", "symmetry", "Force symmetry", "180");
    options.optopt(
        "m",
        "minimum-path-length",
        "Minimum length of paths in the answer",
        "12",
    );
    options.optopt(
        "e",
        "empty-width",
        "Disallow clues on n cell(s) from the outer border",
        "1",
    );
    options.optopt(
        "c",
        "corner",
        "Put one clue within specified range from each corner",
        "1,3",
    );
    options.optopt("x", "max-clue", "Maximum value of clues", "10");
    options.optflag("p", "use-profiler", "Enable profiler");
    options.optflag(
        "r",
        "prioritized-extension",
        "Use prioritized extension in generator",
    );

    let matches = match options.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        }
    };

    if matches.opt_present("help") {
        print_usage(&program, options);
        return;
    }

    let opt = match parse_options(matches) {
        Ok(opt) => opt,
        Err(f) => {
            eprintln!("error: {}", f);
            return;
        }
    };
    run_generator(opt);
}
<|endoftext|>