<commit_before>//! Source code browser

use std::collections::BTreeMap;
use std::cmp::Ordering;
use super::MetaData;
use super::page::Page;
use super::pool::Pool;
use super::file::File as DbFile;
use iron::prelude::*;
use router::Router;
use rustc_serialize::json::{Json, ToJson};
use postgres::Connection;

#[derive(PartialEq, PartialOrd)]
enum FileType {
    Dir,
    Text,
    Binary,
    RustSource,
}

#[derive(PartialEq, PartialOrd)]
struct File {
    name: String,
    file_type: FileType,
}

struct FileList {
    metadata: MetaData,
    files: Vec<File>,
}

impl ToJson for FileList {
    fn to_json(&self) -> Json {
        let mut m: BTreeMap<String, Json> = BTreeMap::new();

        m.insert("metadata".to_string(), self.metadata.to_json());

        let mut file_vec: Vec<Json> = Vec::new();

        for file in &self.files {
            let mut file_m: BTreeMap<String, Json> = BTreeMap::new();
            file_m.insert("name".to_string(), file.name.to_json());

            file_m.insert(match file.file_type {
                              FileType::Dir => "file_type_dir".to_string(),
                              FileType::Text => "file_type_text".to_string(),
                              FileType::Binary => "file_type_binary".to_string(),
                              FileType::RustSource => "file_type_rust_source".to_string(),
                          },
                          true.to_json());

            file_vec.push(file_m.to_json());
        }

        m.insert("files".to_string(), file_vec.to_json());
        m.to_json()
    }
}

impl FileList {
    /// Gets FileList from a request path
    ///
    /// All paths stored in database have this format:
    ///
    /// ```text
    /// [
    ///   ["text/plain",".gitignore"],
    ///   ["text/x-c","src/reseeding.rs"],
    ///   ["text/x-c","src/lib.rs"],
    ///   ["text/x-c","README.md"],
    ///   ...
    /// ]
    /// ```
    ///
    /// This function is only returning FileList for requested directory. If is empty,
    /// it will return list of files (and dirs) for root directory. req_path must be a
    /// directory or empty for root directory.
    pub fn from_path(conn: &Connection,
                     name: &str,
                     version: &str,
                     req_path: &str)
                     -> Option<FileList> {

        let rows = conn.query("SELECT crates.name,
                                      releases.version,
                                      releases.description,
                                      releases.target_name,
                                      releases.rustdoc_status,
                                      releases.files
                               FROM releases
                               LEFT OUTER JOIN crates ON crates.id = releases.crate_id
                               WHERE crates.name = $1 AND releases.version = $2",
                   &[&name, &version])
            .unwrap();

        if rows.len() == 0 {
            return None;
        }

        let files: Json = rows.get(0).get(5);

        let mut file_list: Vec<File> = Vec::new();

        files.as_array().map(|files| {
            for file in files {
                file.as_array().map(|file| {
                    let mime = file[0].as_string().unwrap();
                    let path = file[1].as_string().unwrap();

                    // skip .cargo-ok generated by cargo
                    if path == ".cargo-ok" {
                        return;
                    }

                    // look only files for req_path
                    if path.starts_with(&req_path) {
                        // remove req_path from path to reach files in this directory
                        let path = path.replace(&req_path, "");
                        let path_splited: Vec<&str> = path.split("/").collect();

                        // if path have '/' it is a directory
                        let ftype = if path_splited.len() > 1 {
                            FileType::Dir
                        } else if mime.starts_with("text") &&
                                              path_splited[0].ends_with(".rs") {
                            FileType::RustSource
                        } else if mime.starts_with("text") {
                            FileType::Text
                        } else {
                            FileType::Binary
                        };

                        let file = File {
                            name: path_splited[0].to_owned(),
                            file_type: ftype,
                        };

                        // avoid adding duplicates, a directory may occur more than once
                        if !file_list.contains(&file) {
                            file_list.push(file);
                        }
                    }
                });
            }
        });

        if file_list.is_empty() {
            return None;
        }

        file_list.sort_by(|a, b| {
            // directories must be listed first
            if a.file_type == FileType::Dir && b.file_type != FileType::Dir {
                Ordering::Less
            } else if a.file_type != FileType::Dir && b.file_type == FileType::Dir {
                Ordering::Greater
            } else {
                a.name.to_lowercase().cmp(&b.name.to_lowercase())
            }
        });

        Some(FileList {
            metadata: MetaData {
                name: rows.get(0).get(0),
                version: rows.get(0).get(1),
                description: rows.get(0).get(2),
                target_name: rows.get(0).get(3),
                rustdoc_status: rows.get(0).get(4),
            },
            files: file_list,
        })
    }
}

pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
    let router = extension!(req, Router);
    let name = cexpect!(router.find("name"));
    let version = cexpect!(router.find("version"));

    // get path (req_path) for FileList::from_path and actual path for super::file::File::from_path
    let (req_path, file_path) = {
        let mut req_path = req.url.path();
        // remove first elements from path which is /crate/:name/:version/source
        for _ in 0..4 {
            req_path.remove(0);
        }
        let file_path = format!("sources/{}/{}/{}", name, version, req_path.join("/"));

        // FileList::from_path is only working for directories
        // remove file name if it's not a directory
        req_path.last_mut().map(|last| {
            if !last.is_empty() {
                *last = "";
            }
        });

        // remove crate name and version from req_path
        let path = req_path.join("/").replace(&format!("{}/{}/", name, version), "");

        (path, file_path)
    };

    let conn = extension!(req, Pool);

    // try to get actual file first
    // skip if request is a directory
    let file = if !file_path.ends_with("/") {
        DbFile::from_path(&conn, &file_path)
    } else {
        None
    };

    let (content, is_rust_source) = if let Some(file) = file {
        // serve the file with DatabaseFileHandler if file isn't text and not empty
        if !file.0.mime.starts_with("text") && !file.is_empty() {
            return Ok(file.serve());
        } else if file.0.mime.starts_with("text") && !file.is_empty() {
            (String::from_utf8(file.0.content).ok(), file.0.path.ends_with(".rs"))
        } else {
            (None, false)
        }
    } else {
        (None, false)
    };

    let list = FileList::from_path(&conn, &name, &version, &req_path);

    let page = Page::new(list)
        .set_bool("show_parent_link", !req_path.is_empty())
        .set_true("javascript_highlightjs")
        .set_true("show_package_navigation")
        .set_true("package_source_tab");

    if let Some(content) = content {
        page.set("file_content", &content)
            .set_bool("file_content_rust_source", is_rust_source)
            .to_resp("source")
    } else {
        page.to_resp("source")
    }
}
<commit_msg>revert all the changes except for fixing the panic<commit_after>//! Source code browser

use std::collections::BTreeMap;
use std::cmp::Ordering;
use super::MetaData;
use super::page::Page;
use super::pool::Pool;
use super::file::File as DbFile;
use iron::prelude::*;
use router::Router;
use rustc_serialize::json::{Json, ToJson};
use postgres::Connection;

#[derive(PartialEq, PartialOrd)]
enum FileType {
    Dir,
    Text,
    Binary,
    RustSource,
}

#[derive(PartialEq, PartialOrd)]
struct File {
    name: String,
    file_type: FileType,
}

struct FileList {
    metadata: MetaData,
    files: Vec<File>,
}

impl ToJson for FileList {
    fn to_json(&self) -> Json {
        let mut m: BTreeMap<String, Json> = BTreeMap::new();

        m.insert("metadata".to_string(), self.metadata.to_json());

        let mut file_vec: Vec<Json> = Vec::new();

        for file in &self.files {
            let mut file_m: BTreeMap<String, Json> = BTreeMap::new();
            file_m.insert("name".to_string(), file.name.to_json());

            file_m.insert(match file.file_type {
                              FileType::Dir => "file_type_dir".to_string(),
                              FileType::Text => "file_type_text".to_string(),
                              FileType::Binary => "file_type_binary".to_string(),
                              FileType::RustSource => "file_type_rust_source".to_string(),
                          },
                          true.to_json());

            file_vec.push(file_m.to_json());
        }

        m.insert("files".to_string(), file_vec.to_json());
        m.to_json()
    }
}

impl FileList {
    /// Gets FileList from a request path
    ///
    /// All paths stored in database have this format:
    ///
    /// ```text
    /// [
    ///   ["text/plain",".gitignore"],
    ///   ["text/x-c","src/reseeding.rs"],
    ///   ["text/x-c","src/lib.rs"],
    ///   ["text/x-c","README.md"],
    ///   ...
    /// ]
    /// ```
    ///
    /// This function is only returning FileList for requested directory. If is empty,
    /// it will return list of files (and dirs) for root directory. req_path must be a
    /// directory or empty for root directory.
    pub fn from_path(conn: &Connection,
                     name: &str,
                     version: &str,
                     req_path: &str)
                     -> Option<FileList> {

        let rows = conn.query("SELECT crates.name,
                                      releases.version,
                                      releases.description,
                                      releases.target_name,
                                      releases.rustdoc_status,
                                      releases.files
                               FROM releases
                               LEFT OUTER JOIN crates ON crates.id = releases.crate_id
                               WHERE crates.name = $1 AND releases.version = $2",
                   &[&name, &version])
            .unwrap();

        if rows.len() == 0 {
            return None;
        }

        let files: Json = rows.get(0).get_opt(5).unwrap().ok()?;

        let mut file_list: Vec<File> = Vec::new();

        files.as_array().map(|files| {
            for file in files {
                file.as_array().map(|file| {
                    let mime = file[0].as_string().unwrap();
                    let path = file[1].as_string().unwrap();

                    // skip .cargo-ok generated by cargo
                    if path == ".cargo-ok" {
                        return;
                    }

                    // look only files for req_path
                    if path.starts_with(&req_path) {
                        // remove req_path from path to reach files in this directory
                        let path = path.replace(&req_path, "");
                        let path_splited: Vec<&str> = path.split("/").collect();

                        // if path have '/' it is a directory
                        let ftype = if path_splited.len() > 1 {
                            FileType::Dir
                        } else if mime.starts_with("text") &&
                                              path_splited[0].ends_with(".rs") {
                            FileType::RustSource
                        } else if mime.starts_with("text") {
                            FileType::Text
                        } else {
                            FileType::Binary
                        };

                        let file = File {
                            name: path_splited[0].to_owned(),
                            file_type: ftype,
                        };

                        // avoid adding duplicates, a directory may occur more than once
                        if !file_list.contains(&file) {
                            file_list.push(file);
                        }
                    }
                });
            }
        });

        if file_list.is_empty() {
            return None;
        }

        file_list.sort_by(|a, b| {
            // directories must be listed first
            if a.file_type == FileType::Dir && b.file_type != FileType::Dir {
                Ordering::Less
            } else if a.file_type != FileType::Dir && b.file_type == FileType::Dir {
                Ordering::Greater
            } else {
                a.name.to_lowercase().cmp(&b.name.to_lowercase())
            }
        });

        Some(FileList {
            metadata: MetaData {
                name: rows.get(0).get(0),
                version: rows.get(0).get(1),
                description: rows.get(0).get(2),
                target_name: rows.get(0).get(3),
                rustdoc_status: rows.get(0).get(4),
            },
            files: file_list,
        })
    }
}

pub fn source_browser_handler(req: &mut Request) -> IronResult<Response> {
    let router = extension!(req, Router);
    let name = cexpect!(router.find("name"));
    let version = cexpect!(router.find("version"));

    // get path (req_path) for FileList::from_path and actual path for super::file::File::from_path
    let (req_path, file_path) = {
        let mut req_path = req.url.path();
        // remove first elements from path which is /crate/:name/:version/source
        for _ in 0..4 {
            req_path.remove(0);
        }
        let file_path = format!("sources/{}/{}/{}", name, version, req_path.join("/"));

        // FileList::from_path is only working for directories
        // remove file name if it's not a directory
        req_path.last_mut().map(|last| {
            if !last.is_empty() {
                *last = "";
            }
        });

        // remove crate name and version from req_path
        let path = req_path.join("/").replace(&format!("{}/{}/", name, version), "");

        (path, file_path)
    };

    let conn = extension!(req, Pool);

    // try to get actual file first
    // skip if request is a directory
    let file = if !file_path.ends_with("/") {
        DbFile::from_path(&conn, &file_path)
    } else {
        None
    };

    let (content, is_rust_source) = if let Some(file) = file {
        // serve the file with DatabaseFileHandler if file isn't text and not empty
        if !file.0.mime.starts_with("text") && !file.is_empty() {
            return Ok(file.serve());
        } else if file.0.mime.starts_with("text") && !file.is_empty() {
            (String::from_utf8(file.0.content).ok(), file.0.path.ends_with(".rs"))
        } else {
            (None, false)
        }
    } else {
        (None, false)
    };

    let list = FileList::from_path(&conn, &name, &version, &req_path);

    let page = Page::new(list)
        .set_bool("show_parent_link", !req_path.is_empty())
        .set_true("javascript_highlightjs")
        .set_true("show_package_navigation")
        .set_true("package_source_tab");

    if let Some(content) = content {
        page.set("file_content", &content)
            .set_bool("file_content_rust_source", is_rust_source)
            .to_resp("source")
    } else {
        page.to_resp("source")
    }
}
<|endoftext|>


<commit_before>extern crate tempdir;
extern crate toml;

use std::{fs, process};
use std::io::prelude::*;
use std::ffi::OsStr;

fn clone_out_test(source: &str) -> (tempdir::TempDir, String) {
    let tmpdir = tempdir::TempDir::new("cargo-add-test")
        .ok().expect("failed to construct temporary directory");
    fs::copy(source, tmpdir.path().join("Cargo.toml"))
        .unwrap_or_else(|err| panic!("could not copy test manifest: {}", err));
    let path = tmpdir.path().join("Cargo.toml").to_str().unwrap().to_string().clone();

    (tmpdir, path)
}

fn execute_command<S>(command: &[S], manifest: &str) where S: AsRef<OsStr> {
    let call = process::Command::new("target/debug/cargo-add")
        .args(command)
        .arg(format!("--manifest-path={}", manifest))
        .output().unwrap();

    if !call.status.success() {
        println!("Status code: {:?}", call.status);
        println!("STDOUT: {:?}", String::from_utf8_lossy(&call.stdout));
        println!("STDERR: {:?}", String::from_utf8_lossy(&call.stderr));
        panic!("cargo-add failed to execute")
    }
}

fn get_toml(manifest_path: &str) -> toml::Value {
    let mut f = fs::File::open(manifest_path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    toml::Value::Table(toml::Parser::new(&s).parse().unwrap())
}

#[test]
fn adds_dependencies() {
    let (tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package").is_none());

    execute_command(&["add", "my-package"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "*")
}
<commit_msg>Add more tests<commit_after>extern crate tempdir;
extern crate toml;

use std::{fs, process};
use std::io::prelude::*;
use std::ffi::OsStr;

fn clone_out_test(source: &str) -> (tempdir::TempDir, String) {
    let tmpdir = tempdir::TempDir::new("cargo-add-test")
        .ok().expect("failed to construct temporary directory");
    fs::copy(source, tmpdir.path().join("Cargo.toml"))
        .unwrap_or_else(|err| panic!("could not copy test manifest: {}", err));
    let path = tmpdir.path().join("Cargo.toml").to_str().unwrap().to_string().clone();

    (tmpdir, path)
}

fn execute_command<S>(command: &[S], manifest: &str) where S: AsRef<OsStr> {
    let call = process::Command::new("target/debug/cargo-add")
        .args(command)
        .arg(format!("--manifest-path={}", manifest))
        .output().unwrap();

    if !call.status.success() {
        println!("Status code: {:?}", call.status);
        println!("STDOUT: {}", String::from_utf8_lossy(&call.stdout));
        println!("STDERR: {}", String::from_utf8_lossy(&call.stderr));
        panic!("cargo-add failed to execute")
    }
}

fn get_toml(manifest_path: &str) -> toml::Value {
    let mut f = fs::File::open(manifest_path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    toml::Value::Table(toml::Parser::new(&s).parse().unwrap())
}

#[test]
fn adds_dependencies() {
    let (tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package").is_none());

    execute_command(&["add", "my-package"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "*");
}

#[test]
fn adds_dev_build_dependencies() {
    let (tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.my-dev-package").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package").is_none());

    execute_command(&["add", "my-dev-package", "--dev"], &manifest);
    execute_command(&["add", "my-build-package", "--build"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.my-dev-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "*");
    let val = toml.lookup("build-dependencies.my-build-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "*");

    // cannot run with both --dev and --build at the same time
    let call = process::Command::new("target/debug/cargo-add")
        .args(&["add", "failure", "--dev", "--build"])
        .arg(format!("--manifest-path={}", &manifest))
        .output().unwrap();
    assert!(!call.status.success());

    // 'failure' dep not present
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.failure").is_none());
    assert!(toml.lookup("dev-dependencies.failure").is_none());
    assert!(toml.lookup("build-dependencies.failure").is_none());
}

#[test]
fn adds_fixed_version() {
    let (tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package", "--ver", ">=0.1.1"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");

    // cannot run with both --dev and --build at the same time
    let call = process::Command::new("target/debug/cargo-add")
        .args(&["add", "failure", "--ver", "invalid version string"])
        .arg(format!("--manifest-path={}", &manifest))
        .output().unwrap();
    assert!(!call.status.success());

    // 'failure' dep not present
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.failure").is_none());
    assert!(toml.lookup("dev-dependencies.failure").is_none());
    assert!(toml.lookup("build-dependencies.failure").is_none());
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use crate::Error;
use mimir;
use std::process::exit;
use std::sync::Arc;
use structopt::StructOpt;

pub fn format_label(admins: &[Arc<mimir::Admin>], name: &str) -> String {
    match admins.iter().position(|adm| adm.is_city()) {
        Some(idx) => format!("{} ({})", name, admins[idx].name),
        None => name.to_string(),
    }
}

pub fn format_international_labels(
    admins: &[Arc<mimir::Admin>],
    poi_names: &mimir::I18nProperties,
    default_poi_name: &str,
    default_poi_label: &str,
    langs: &[String],
) -> mimir::I18nProperties {
    let labels = langs
        .iter()
        .filter_map(|ref lang| {
            let local_poi_name = poi_names.get(lang).unwrap_or(default_poi_name);
            let i18n_poi_label =
                admins
                    .iter()
                    .find(|adm| adm.is_city())
                    .map_or(local_poi_name.to_string(), |adm| {
                        let default_admin_name = &adm.name;
                        let local_admin_name = &adm.names.get(lang).unwrap_or(&default_admin_name);
                        format!("{} ({})", local_poi_name, local_admin_name)
                    });

            if i18n_poi_label == default_poi_label {
                None
            } else {
                Some(mimir::Property {
                    key: lang.to_string(),
                    value: i18n_poi_label,
                })
            }
        })
        .collect();
    mimir::I18nProperties(labels)
}

pub fn get_zip_codes_from_admins(admins: &[Arc<mimir::Admin>]) -> Vec<String> {
    let level = admins.iter().fold(0, |level, adm| {
        if adm.level > level && !adm.zip_codes.is_empty() {
            adm.level
        } else {
            level
        }
    });
    if level == 0 {
        return vec![];
    }
    admins
        .into_iter()
        .filter(|adm| adm.level == level)
        .flat_map(|adm| adm.zip_codes.iter().cloned())
        .collect()
}

/// normalize the admin weight for it to be in [0, 1]
pub fn normalize_admin_weight(admins: &mut [mimir::Admin]) {
    let max = admins.iter().fold(1f64, |m, a| f64::max(m, a.weight));
    for ref mut a in admins {
        a.weight = normalize_weight(a.weight, max);
    }
}

/// normalize the weight for it to be in [0, 1]
pub fn normalize_weight(weight: f64, max_weight: f64) -> f64 {
    return weight / max_weight;
}

pub fn wrapped_launch_run<O, F>(run: F) -> Result<(), Error>
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    let _guard = mimir::logger_init();
    if let Err(err) = run(O::from_args()) {
        for cause in err.iter_chain() {
            error!("{}", cause);
        }
        Err(err)
    } else {
        Ok(())
    }
}

pub fn launch_run<O, F>(run: F)
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    if wrapped_launch_run(run).is_err() {
        // we wrap the real stuff in another method to std::exit after
        // the destruction of the logger (so we won't loose any messages)
        exit(1);
    }
}
<commit_msg>format_international_poi_label<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use crate::Error;
use mimir;
use std::process::exit;
use std::sync::Arc;
use structopt::StructOpt;

pub fn format_label(admins: &[Arc<mimir::Admin>], name: &str) -> String {
    match admins.iter().position(|adm| adm.is_city()) {
        Some(idx) => format!("{} ({})", name, admins[idx].name),
        None => name.to_string(),
    }
}

pub fn format_international_poi_label(
    admins: &[Arc<mimir::Admin>],
    poi_names: &mimir::I18nProperties,
    default_poi_name: &str,
    default_poi_label: &str,
    langs: &[String],
) -> mimir::I18nProperties {
    let labels = langs
        .iter()
        .filter_map(|ref lang| {
            let local_poi_name = poi_names.get(lang).unwrap_or(default_poi_name);
            let i18n_poi_label =
                admins
                    .iter()
                    .find(|adm| adm.is_city())
                    .map_or(local_poi_name.to_string(), |adm| {
                        let default_admin_name = &adm.name;
                        let local_admin_name = &adm.names.get(lang).unwrap_or(&default_admin_name);
                        format!("{} ({})", local_poi_name, local_admin_name)
                    });

            if i18n_poi_label == default_poi_label {
                None
            } else {
                Some(mimir::Property {
                    key: lang.to_string(),
                    value: i18n_poi_label,
                })
            }
        })
        .collect();
    mimir::I18nProperties(labels)
}

pub fn get_zip_codes_from_admins(admins: &[Arc<mimir::Admin>]) -> Vec<String> {
    let level = admins.iter().fold(0, |level, adm| {
        if adm.level > level && !adm.zip_codes.is_empty() {
            adm.level
        } else {
            level
        }
    });
    if level == 0 {
        return vec![];
    }
    admins
        .into_iter()
        .filter(|adm| adm.level == level)
        .flat_map(|adm| adm.zip_codes.iter().cloned())
        .collect()
}

/// normalize the admin weight for it to be in [0, 1]
pub fn normalize_admin_weight(admins: &mut [mimir::Admin]) {
    let max = admins.iter().fold(1f64, |m, a| f64::max(m, a.weight));
    for ref mut a in admins {
        a.weight = normalize_weight(a.weight, max);
    }
}

/// normalize the weight for it to be in [0, 1]
pub fn normalize_weight(weight: f64, max_weight: f64) -> f64 {
    return weight / max_weight;
}

pub fn wrapped_launch_run<O, F>(run: F) -> Result<(), Error>
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    let _guard = mimir::logger_init();
    if let Err(err) = run(O::from_args()) {
        for cause in err.iter_chain() {
            error!("{}", cause);
        }
        Err(err)
    } else {
        Ok(())
    }
}

pub fn launch_run<O, F>(run: F)
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    if wrapped_launch_run(run).is_err() {
        // we wrap the real stuff in another method to std::exit after
        // the destruction of the logger (so we won't loose any messages)
        exit(1);
    }
}
<|endoftext|>


<commit_before>//! Internal only utilities
use std::io::{Error, ErrorKind, Write};
use std::str;

use unicode_width::UnicodeWidthStr;

use super::format::Alignment;

#[cfg(any(not(windows), not(feature="win_crlf")))]
pub static NEWLINE: &'static [u8] = b"\n";
#[cfg(all(windows, feature="win_crlf"))]
pub static NEWLINE: &'static [u8] = b"\r\n";

/// Internal utility for writing data into a string
pub struct StringWriter {
    string: String,
}

impl StringWriter {
    /// Create a new `StringWriter`
    pub fn new() -> StringWriter {
        StringWriter { string: String::new() }
    }

    /// Return a reference to the internally written `String`
    pub fn as_string(&self) -> &str {
        &self.string
    }
}

impl Write for StringWriter {
    fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
        let string = match str::from_utf8(data) {
            Ok(s) => s,
            Err(e) => {
                return Err(Error::new(ErrorKind::Other,
                                      format!("Cannot decode utf8 string : {}", e)))
            }
        };
        self.string.push_str(string);
        Ok(data.len())
    }

    fn flush(&mut self) -> Result<(), Error> {
        // Nothing to do here
        Ok(())
    }
}

/// Align/fill a string and print it to `out`
/// If `skip_right_fill` is set to `true`, then no space will be added after the string
/// to complete alignment
pub fn print_align<T: Write + ?Sized>(out: &mut T,
                                      align: Alignment,
                                      text: &str,
                                      fill: char,
                                      size: usize,
                                      skip_right_fill: bool)
                                      -> Result<(), Error> {
    let text_len = UnicodeWidthStr::width(text);
    let mut nfill = if text_len < size { size - text_len } else { 0 };
    let n = match align {
        Alignment::LEFT => 0,
        Alignment::RIGHT => nfill,
        Alignment::CENTER => nfill / 2,
    };
    if n > 0 {
        try!(out.write_all(&vec![fill as u8; n]));
        nfill -= n;
    }
    try!(out.write_all(text.as_bytes()));
    if nfill > 0 && !skip_right_fill {
        try!(out.write_all(&vec![fill as u8; nfill]));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use format::Alignment;
    use std::io::Write;

    #[test]
    fn string_writer() {
        let mut out = StringWriter::new();
        out.write("foo".as_bytes()).unwrap();
        out.write(" ".as_bytes()).unwrap();
        out.write("".as_bytes()).unwrap();
        out.write("bar".as_bytes()).unwrap();
        assert_eq!(out.as_string(), "foo bar");
    }

    #[test]
    fn fill_align() {
        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::RIGHT, "foo", '*', 10, false).unwrap();
        assert_eq!(out.as_string(), "*******foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::LEFT, "foo", '*', 10, false).unwrap();
        assert_eq!(out.as_string(), "foo*******");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 10, false).unwrap();
        assert_eq!(out.as_string(), "***foo****");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 1, false).unwrap();
        assert_eq!(out.as_string(), "foo");
    }

    #[test]
    fn skip_right_fill() {
        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::RIGHT, "foo", '*', 10, true).unwrap();
        assert_eq!(out.as_string(), "*******foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::LEFT, "foo", '*', 10, true).unwrap();
        assert_eq!(out.as_string(), "foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 10, true).unwrap();
        assert_eq!(out.as_string(), "***foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 1, false).unwrap();
        assert_eq!(out.as_string(), "foo");
    }
}
<commit_msg>Improving coverage, just for testing<commit_after>//! Internal only utilities
use std::io::{Error, ErrorKind, Write};
use std::str;

use unicode_width::UnicodeWidthStr;

use super::format::Alignment;

#[cfg(any(not(windows), not(feature="win_crlf")))]
pub static NEWLINE: &'static [u8] = b"\n";
#[cfg(all(windows, feature="win_crlf"))]
pub static NEWLINE: &'static [u8] = b"\r\n";

/// Internal utility for writing data into a string
pub struct StringWriter {
    string: String,
}

impl StringWriter {
    /// Create a new `StringWriter`
    pub fn new() -> StringWriter {
        StringWriter { string: String::new() }
    }

    /// Return a reference to the internally written `String`
    pub fn as_string(&self) -> &str {
        &self.string
    }
}

impl Write for StringWriter {
    fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
        let string = match str::from_utf8(data) {
            Ok(s) => s,
            Err(e) => {
                return Err(Error::new(ErrorKind::Other,
                                      format!("Cannot decode utf8 string : {}", e)))
            }
        };
        self.string.push_str(string);
        Ok(data.len())
    }

    fn flush(&mut self) -> Result<(), Error> {
        // Nothing to do here
        Ok(())
    }
}

/// Align/fill a string and print it to `out`
/// If `skip_right_fill` is set to `true`, then no space will be added after the string
/// to complete alignment
pub fn print_align<T: Write + ?Sized>(out: &mut T,
                                      align: Alignment,
                                      text: &str,
                                      fill: char,
                                      size: usize,
                                      skip_right_fill: bool)
                                      -> Result<(), Error> {
    let text_len = UnicodeWidthStr::width(text);
    let mut nfill = if text_len < size { size - text_len } else { 0 };
    let n = match align {
        Alignment::LEFT => 0,
        Alignment::RIGHT => nfill,
        Alignment::CENTER => nfill / 2,
    };
    if n > 0 {
        try!(out.write_all(&vec![fill as u8; n]));
        nfill -= n;
    }
    try!(out.write_all(text.as_bytes()));
    if nfill > 0 && !skip_right_fill {
        try!(out.write_all(&vec![fill as u8; nfill]));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use format::Alignment;
    use std::io::Write;

    #[test]
    fn string_writer() {
        let mut out = StringWriter::new();
        out.write("foo".as_bytes()).unwrap();
        out.write(" ".as_bytes()).unwrap();
        out.write("".as_bytes()).unwrap();
        out.write("bar".as_bytes()).unwrap();
        assert_eq!(out.as_string(), "foo bar");
    }

    #[test]
    fn fill_align() {
        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::RIGHT, "foo", '*', 10, false).unwrap();
        assert_eq!(out.as_string(), "*******foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::LEFT, "foo", '*', 10, false).unwrap();
        assert_eq!(out.as_string(), "foo*******");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 10, false).unwrap();
        assert_eq!(out.as_string(), "***foo****");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 1, false).unwrap();
        assert_eq!(out.as_string(), "foo");
    }

    #[test]
    fn skip_right_fill() {
        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::RIGHT, "foo", '*', 10, true).unwrap();
        assert_eq!(out.as_string(), "*******foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::LEFT, "foo", '*', 10, true).unwrap();
        assert_eq!(out.as_string(), "foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 10, true).unwrap();
        assert_eq!(out.as_string(), "***foo");

        let mut out = StringWriter::new();
        print_align(&mut out, Alignment::CENTER, "foo", '*', 1, false).unwrap();
        assert_eq!(out.as_string(), "foo");
    }

    #[test]
    fn utf8_error() {
        let mut out = StringWriter::new();
        let res = out.write_all(&vec![0, 255]);
        assert!(res.is_err());
    }
}
<|endoftext|>


<commit_before>use helpers::Size;
use helpers::compute_index;
use helpers::Position;

use robot::Orientation;
use robot::Robot;

// World definition
#[derive(Clone, Copy)]
pub enum Tile {
    Empty,
    Wall,
    Beepers(Size),
    Robot(Orientation)
}

pub struct World {
    karel: Robot,
    heigth: Size,
    width: Size,
    tiles: Vec<Tile>
}

impl World {
    pub fn new(width: Size, heigth: Size, karel: Robot, tiles: Vec<Tile>) -> World {
        World {
            heigth: width,
            width: heigth,
            karel: karel,
            tiles: tiles
        }
    }

    pub fn render(&self) -> String {
        let tiles_projection = self.project_robot();
        let mut rendered_world = String::new();

        for (index, tile) in tiles_projection.iter().enumerate() {
            if index as u32  % self.width == 0 {
                rendered_world.push_str("\n");
            }

            rendered_world.push_str(" ");
            rendered_world.push_str(&self.render_tile(tile));
        }

        rendered_world
    }

    fn render_tile(&self, tile: &Tile) -> String {
        match *tile {
            Tile::Empty => ".".to_string(),
            Tile::Wall => "W".to_string(),
            Tile::Beepers(_) => "*".to_string(),
            Tile::Robot(ref orientation) => self.render_orientation(orientation),
        }
    }

    fn render_orientation(&self, orientation: &Orientation) -> String {
        match *orientation {
            Orientation::North => "^".to_string(),
            Orientation::East => ">".to_string(),
            Orientation::South => "v".to_string(),
            Orientation::West => "<".to_string(),
        }
    }

    fn project_robot(&self) -> Vec<Tile> {
        let (position, orientation, _) = self.karel.info();
        let index = compute_index(&position, self.width) as usize;
        let mut tiles_projection = self.tiles.clone();

        tiles_projection[index] = Tile::Robot(orientation);
        tiles_projection
    }

    #[allow(dead_code)]
    pub fn dimensions(&self) -> (Size, Size) {
        (self.width, self.heigth)
    }

    pub fn get_robot(&mut self) -> &mut Robot {
        &mut self.karel
    }

    pub fn pick_beeper(&mut self) -> bool {
        let (position, _, _) = self.karel.info();
        let index = compute_index(&position, self.width) as usize;

        match self.tiles[index] {
            Tile::Beepers(beepers) => Some(beepers),
            _ => None,
        }.map(|beepers| {
            if beepers > 1 {
                self.tiles[index] = Tile::Beepers(beepers - 1);
                self.get_robot().add_beeper();
                return true;
            }

            if beepers == 1 {
                self.tiles[index] = Tile::Empty;
                return true;
            }

            false
        }).unwrap_or(false)
    }

    pub fn put_beeper(&mut self) -> bool {
        let (position, _, _) = self.karel.info();
        let index = compute_index(&position, self.width) as usize;

        match self.tiles[index] {
            Tile::Beepers(beepers) => Some(Tile::Beepers(beepers + 1)),
            Tile::Empty => Some(Tile::Beepers(1)),
            _ => None
        }.map(|tile| {
            let action_result = self.get_robot().remove_beeper();

            if action_result {
                self.tiles[index] = tile;
                return true
            }

            false
        }).unwrap_or(false)
    }

    pub fn move_robot(&mut self) -> bool {
        let (karel_position, orientation, _) = self.karel.info();
        let (karel_x, karel_y) = karel_position.extract();

        let (new_option_x, new_option_y) = match orientation {
            Orientation::North => (Some(karel_x), karel_y.checked_sub(1)),
            Orientation::South => (Some(karel_x), karel_y.checked_add(1)),
            Orientation::East => (karel_x.checked_add(1), Some(karel_y)),
            Orientation::West => (karel_x.checked_sub(1), Some(karel_y)),
        };

        // check  if not moving out of world bounds
        let new_x = match new_option_x {
            Some(x) => x,
            None => self.width + 1 // put out of bound
        };

        let new_y = match new_option_y {
            Some(y) => y,
            None => self.width + 1 // put out of bound
        };

        if new_x >= self.width || new_y >= self.heigth {
            return false;
        }

        let new_position = Position::new(new_x, new_y);
        let new_position_index = compute_index(&new_position, self.width);

        // check for not running into wall
        match self.tiles[new_position_index as usize] {
            Tile::Wall => return false,
            _ => ()
        }

        // move karel
        self.karel.set_position(new_position);

        return true;
    }
}
<commit_msg>fixed pick beeper bug<commit_after>use helpers::Size;
use helpers::compute_index;
use helpers::Position;

use robot::Orientation;
use robot::Robot;

// World definition
#[derive(Clone, Copy)]
pub enum Tile {
    Empty,
    Wall,
    Beepers(Size),
    Robot(Orientation)
}

pub struct World {
    karel: Robot,
    heigth: Size,
    width: Size,
    tiles: Vec<Tile>
}

impl World {
    pub fn new(width: Size, heigth: Size, karel: Robot, tiles: Vec<Tile>) -> World {
        World {
            heigth: width,
            width: heigth,
            karel: karel,
            tiles: tiles
        }
    }

    pub fn render(&self) -> String {
        let tiles_projection = self.project_robot();
        let mut rendered_world = String::new();

        for (index, tile) in tiles_projection.iter().enumerate() {
            if index as u32  % self.width == 0 {
                rendered_world.push_str("\n");
            }

            rendered_world.push_str(" ");
            rendered_world.push_str(&self.render_tile(tile));
        }

        rendered_world
    }

    fn render_tile(&self, tile: &Tile) -> String {
        match *tile {
            Tile::Empty => ".".to_string(),
            Tile::Wall => "W".to_string(),
            Tile::Beepers(_) => "*".to_string(),
            Tile::Robot(ref orientation) => self.render_orientation(orientation),
        }
    }

    fn render_orientation(&self, orientation: &Orientation) -> String {
        match *orientation {
            Orientation::North => "^".to_string(),
            Orientation::East => ">".to_string(),
            Orientation::South => "v".to_string(),
            Orientation::West => "<".to_string(),
        }
    }

    fn project_robot(&self) -> Vec<Tile> {
        let (position, orientation, _) = self.karel.info();
        let index = compute_index(&position, self.width) as usize;
        let mut tiles_projection = self.tiles.clone();

        tiles_projection[index] = Tile::Robot(orientation);
        tiles_projection
    }

    #[allow(dead_code)]
    pub fn dimensions(&self) -> (Size, Size) {
        (self.width, self.heigth)
    }

    pub fn get_robot(&mut self) -> &mut Robot {
        &mut self.karel
    }

    pub fn pick_beeper(&mut self) -> bool {
        let (position, _, _) = self.karel.info();
        let index = compute_index(&position, self.width) as usize;

        match self.tiles[index] {
            Tile::Beepers(beepers) => Some(beepers),
            _ => None,
        }.map(|beepers| {
            if beepers > 1 {
                self.tiles[index] = Tile::Beepers(beepers - 1);
                self.get_robot().add_beeper();
                return true;
            }

            if beepers == 1 {
                self.tiles[index] = Tile::Empty;
                self.get_robot().add_beeper();
                return true;
            }

            false
        }).unwrap_or(false)
    }

    pub fn put_beeper(&mut self) -> bool {
        let (position, _, _) = self.karel.info();
        let index = compute_index(&position, self.width) as usize;

        match self.tiles[index] {
            Tile::Beepers(beepers) => Some(Tile::Beepers(beepers + 1)),
            Tile::Empty => Some(Tile::Beepers(1)),
            _ => None
        }.map(|tile| {
            let action_result = self.get_robot().remove_beeper();

            if action_result {
                self.tiles[index] = tile;
                return true
            }

            false
        }).unwrap_or(false)
    }

    pub fn move_robot(&mut self) -> bool {
        let (karel_position, orientation, _) = self.karel.info();
        let (karel_x, karel_y) = karel_position.extract();

        let (new_option_x, new_option_y) = match orientation {
            Orientation::North => (Some(karel_x), karel_y.checked_sub(1)),
            Orientation::South => (Some(karel_x), karel_y.checked_add(1)),
            Orientation::East => (karel_x.checked_add(1), Some(karel_y)),
            Orientation::West => (karel_x.checked_sub(1), Some(karel_y)),
        };

        // check  if not moving out of world bounds
        let new_x = match new_option_x {
            Some(x) => x,
            None => self.width + 1 // put out of bound
        };

        let new_y = match new_option_y {
            Some(y) => y,
            None => self.width + 1 // put out of bound
        };

        if new_x >= self.width || new_y >= self.heigth {
            return false;
        }

        let new_position = Position::new(new_x, new_y);
        let new_position_index = compute_index(&new_position, self.width);

        // check for not running into wall
        match self.tiles[new_position_index as usize] {
            Tile::Wall => return false,
            _ => ()
        }

        // move karel
        self.karel.set_position(new_position);

        return true;
    }
}
<|endoftext|>


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

#![allow(missing_docs)]

use std::ptr;
use winapi::{FLOAT, INT, UINT, UINT8, DXGI_FORMAT,
             DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R32_UINT,
             D3D11_CLEAR_FLAG, D3D11_PRIMITIVE_TOPOLOGY, D3D11_VIEWPORT, D3D11_RECT,
             ID3D11RasterizerState, ID3D11DepthStencilState, ID3D11BlendState};
use gfx_core::{draw, pso, shade, state, target, tex};
use gfx_core::{IndexType, VertexCount};
use gfx_core::{MAX_VERTEX_ATTRIBUTES, MAX_COLOR_TARGETS};
use {native, Resources, InputLayout, Pipeline, Program};

///Serialized device command.
#[derive(Clone, Copy, Debug)]
pub enum Command {
    // states
    BindProgram(Program),
    BindInputLayout(InputLayout),
    BindIndex(native::Buffer, DXGI_FORMAT),
    BindVertexBuffers([native::Buffer; MAX_VERTEX_ATTRIBUTES], [UINT; MAX_VERTEX_ATTRIBUTES], [UINT; MAX_VERTEX_ATTRIBUTES]),
    BindPixelTargets([native::Rtv; MAX_COLOR_TARGETS], native::Dsv),
    SetPrimitive(D3D11_PRIMITIVE_TOPOLOGY),
    SetViewport(D3D11_VIEWPORT),
    SetScissor(D3D11_RECT),
    SetRasterizer(*const ID3D11RasterizerState),
    SetDepthStencil(*const ID3D11DepthStencilState, UINT),
    SetBlend(*const ID3D11BlendState, [FLOAT; 4], UINT),
    // resource updates
    // drawing
    ClearColor(native::Rtv, [f32; 4]),
    ClearDepthStencil(native::Dsv, D3D11_CLEAR_FLAG, FLOAT, UINT8),
    Draw(UINT, UINT),
    DrawInstanced(UINT, UINT, UINT, UINT),
    DrawIndexed(UINT, UINT, INT),
    DrawIndexedInstanced(UINT, UINT, UINT, INT, UINT),
}

unsafe impl Send for Command {}

struct Cache {
    attributes: [Option<pso::AttributeDesc>; MAX_VERTEX_ATTRIBUTES],
    rasterizer: *const ID3D11RasterizerState,
    depth_stencil: *const ID3D11DepthStencilState,
    stencil_ref: UINT,
    blend: *const ID3D11BlendState,
    blend_ref: [FLOAT; 4],
}

pub struct CommandBuffer {
    pub buf: Vec<Command>,
    cache: Cache,
}

impl CommandBuffer {
    pub fn new() -> CommandBuffer {
        CommandBuffer {
            buf: Vec::new(),
            cache: Cache {
                attributes: [None; MAX_VERTEX_ATTRIBUTES],
                rasterizer: ptr::null(),
                depth_stencil: ptr::null(),
                stencil_ref: 0,
                blend: ptr::null(),
                blend_ref: [0.0; 4],
            },
        }
    }

    fn flush(&mut self) {
        let sample_mask = !0; //TODO
        self.buf.push(Command::SetDepthStencil(self.cache.depth_stencil, self.cache.stencil_ref));
        self.buf.push(Command::SetBlend(self.cache.blend, self.cache.blend_ref, sample_mask));
    }
}

impl draw::CommandBuffer<Resources> for CommandBuffer {
    fn clone_empty(&self) -> CommandBuffer { CommandBuffer::new() }
    fn reset(&mut self) {}
    fn bind_pipeline_state(&mut self, pso: Pipeline) {
        use std::mem; //temporary
        self.buf.push(Command::SetPrimitive(unsafe{mem::transmute(pso.topology)}));
        if self.cache.rasterizer != pso.rasterizer {
            self.cache.rasterizer = pso.rasterizer;
            self.buf.push(Command::SetRasterizer(pso.rasterizer));
        }
        self.cache.depth_stencil = pso.depth_stencil;
        self.cache.blend = pso.blend;
        self.buf.push(Command::BindInputLayout(pso.layout));
        self.buf.push(Command::BindProgram(pso.program));
    }

    fn bind_vertex_buffers(&mut self, vbs: pso::VertexBufferSet<Resources>) {
        let mut buffers = [native::Buffer(ptr::null_mut()); MAX_VERTEX_ATTRIBUTES];
        let mut strides = [0; MAX_VERTEX_ATTRIBUTES];
        let mut offsets = [0; MAX_VERTEX_ATTRIBUTES];
        for i in 0 .. MAX_VERTEX_ATTRIBUTES {
            match (vbs.0[i], self.cache.attributes[i]) {
                (None, Some(fm)) => {
                    error!("No vertex input provided for slot {} of format {:?}", i, fm)
                },
                (Some((buffer, offset)), Some(ref format)) => {
                    buffers[i] = buffer;
                    strides[i] = format.0.stride as UINT;
                    offsets[i] = format.0.offset as UINT + (offset as UINT);
                },
                (_, None) => (),
            }
        }
        self.buf.push(Command::BindVertexBuffers(buffers, strides, offsets));
    }

    fn bind_constant_buffers(&mut self, _: pso::ConstantBufferSet<Resources>) {}
    fn bind_global_constant(&mut self, _: shade::Location, _: shade::UniformValue) {}
    fn bind_resource_views(&mut self, _: pso::ResourceViewSet<Resources>) {}
    fn bind_unordered_views(&mut self, _: pso::UnorderedViewSet<Resources>) {}
    fn bind_samplers(&mut self, _: pso::SamplerSet<Resources>) {}

    fn bind_pixel_targets(&mut self, pts: pso::PixelTargetSet<Resources>) {
        if let (Some(ref d), Some(ref s)) = (pts.depth, pts.stencil) {
            if d != s {
                error!("Depth and stencil views have to be the same");
            }
        }
        let viewport = D3D11_VIEWPORT {
            TopLeftX: 0.0, TopLeftY: 0.0,
            Width: pts.size.0 as f32, Height: pts.size.1 as f32,
            MinDepth: 0.0, MaxDepth: 1.0,
        };
        let mut colors = [native::Rtv(ptr::null_mut()); MAX_COLOR_TARGETS];
        for i in 0 .. MAX_COLOR_TARGETS {
            if let Some(c) = pts.colors[i] {
                colors[i] = c;
            }
        }
        let ds = pts.depth.unwrap_or(native::Dsv(ptr::null_mut()));
        self.buf.push(Command::BindPixelTargets(colors, ds));
        self.buf.push(Command::SetViewport(viewport));
    }

    fn bind_index(&mut self, buf: native::Buffer, itype: IndexType) {
        let format = match itype {
            IndexType::U8  => DXGI_FORMAT_R8_UINT,
            IndexType::U16 => DXGI_FORMAT_R16_UINT,
            IndexType::U32 => DXGI_FORMAT_R32_UINT,
        };
        self.buf.push(Command::BindIndex(buf, format));
    }

    fn set_scissor(&mut self, rect: target::Rect) {
        self.buf.push(Command::SetScissor(D3D11_RECT {
            left: rect.x as INT,
            top: rect.y as INT,
            right: (rect.x + rect.w) as INT,
            bottom: (rect.y + rect.h) as INT,
        }));
    }

    fn set_ref_values(&mut self, rv: state::RefValues) {
        if rv.stencil.0 != rv.stencil.1 {
            error!("Unable to set different stencil ref values for front ({}) and back ({})",
                rv.stencil.0, rv.stencil.1);
        }
        self.cache.stencil_ref = rv.stencil.0 as UINT;
        self.cache.blend_ref = rv.blend;
    }

    fn update_buffer(&mut self, _: native::Buffer, _: draw::DataPointer, _: usize) {}
    fn update_texture(&mut self, _: native::Texture, _: tex::Kind, _: Option<tex::CubeFace>,
                      _: draw::DataPointer, _: tex::RawImageInfo) {}

    fn clear_color(&mut self, target: native::Rtv, value: draw::ClearColor) {
        match value {
            draw::ClearColor::Float(data) => {
                self.buf.push(Command::ClearColor(target, data));
            },
            _ => {
                error!("Unable to clear int/uint target");
            },
        }
    }

    fn clear_depth_stencil(&mut self, target: native::Dsv, depth: Option<target::Depth>,
                           stencil: Option<target::Stencil>) {
        let flags = //warning: magic constants ahead
            D3D11_CLEAR_FLAG(if depth.is_some() {1} else {0}) |
            D3D11_CLEAR_FLAG(if stencil.is_some() {2} else {0});
        self.buf.push(Command::ClearDepthStencil(target, flags,
                      depth.unwrap_or_default() as FLOAT,
                      stencil.unwrap_or_default() as UINT8
        ));
    }

    fn call_draw(&mut self, start: VertexCount, count: VertexCount, instances: draw::InstanceOption) {
        self.flush();
        self.buf.push(match instances {
            Some((ninst, offset)) => Command::DrawInstanced(
                count as UINT, ninst as UINT, start as UINT, offset as UINT),
            None => Command::Draw(count as UINT, start as UINT),
        });
    }

    fn call_draw_indexed(&mut self, start: VertexCount, count: VertexCount,
                         base: VertexCount, instances: draw::InstanceOption) {
        self.flush();
        self.buf.push(match instances {
            Some((ninst, offset)) => Command::DrawIndexedInstanced(
                count as UINT, ninst as UINT, start as UINT, base as INT, offset as UINT),
            None => Command::DrawIndexed(count as UINT, start as UINT, base as INT),
        });
    }
}
<commit_msg>DX - filling the gaps in CommandBuffer implementation with unimplemented macro<commit_after>// Copyright 2016 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(missing_docs)]

use std::ptr;
use winapi::{FLOAT, INT, UINT, UINT8, DXGI_FORMAT,
             DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R32_UINT,
             D3D11_CLEAR_FLAG, D3D11_PRIMITIVE_TOPOLOGY, D3D11_VIEWPORT, D3D11_RECT,
             ID3D11RasterizerState, ID3D11DepthStencilState, ID3D11BlendState};
use gfx_core::{draw, pso, shade, state, target, tex};
use gfx_core::{IndexType, VertexCount};
use gfx_core::{MAX_VERTEX_ATTRIBUTES, MAX_COLOR_TARGETS};
use {native, Resources, InputLayout, Pipeline, Program};

///Serialized device command.
#[derive(Clone, Copy, Debug)]
pub enum Command {
    // states
    BindProgram(Program),
    BindInputLayout(InputLayout),
    BindIndex(native::Buffer, DXGI_FORMAT),
    BindVertexBuffers([native::Buffer; MAX_VERTEX_ATTRIBUTES], [UINT; MAX_VERTEX_ATTRIBUTES], [UINT; MAX_VERTEX_ATTRIBUTES]),
    BindPixelTargets([native::Rtv; MAX_COLOR_TARGETS], native::Dsv),
    SetPrimitive(D3D11_PRIMITIVE_TOPOLOGY),
    SetViewport(D3D11_VIEWPORT),
    SetScissor(D3D11_RECT),
    SetRasterizer(*const ID3D11RasterizerState),
    SetDepthStencil(*const ID3D11DepthStencilState, UINT),
    SetBlend(*const ID3D11BlendState, [FLOAT; 4], UINT),
    // resource updates
    // drawing
    ClearColor(native::Rtv, [f32; 4]),
    ClearDepthStencil(native::Dsv, D3D11_CLEAR_FLAG, FLOAT, UINT8),
    Draw(UINT, UINT),
    DrawInstanced(UINT, UINT, UINT, UINT),
    DrawIndexed(UINT, UINT, INT),
    DrawIndexedInstanced(UINT, UINT, UINT, INT, UINT),
}

unsafe impl Send for Command {}

struct Cache {
    attributes: [Option<pso::AttributeDesc>; MAX_VERTEX_ATTRIBUTES],
    rasterizer: *const ID3D11RasterizerState,
    depth_stencil: *const ID3D11DepthStencilState,
    stencil_ref: UINT,
    blend: *const ID3D11BlendState,
    blend_ref: [FLOAT; 4],
}

impl Cache {
    fn new() -> Cache {
        Cache {
            attributes: [None; MAX_VERTEX_ATTRIBUTES],
            rasterizer: ptr::null(),
            depth_stencil: ptr::null(),
            stencil_ref: 0,
            blend: ptr::null(),
            blend_ref: [0.0; 4],
        }
    }
}

pub struct CommandBuffer {
    pub buf: Vec<Command>,
    cache: Cache,
}

impl CommandBuffer {
    pub fn new() -> CommandBuffer {
        CommandBuffer {
            buf: Vec::new(),
            cache: Cache::new(),
        }
    }

    fn flush(&mut self) {
        let sample_mask = !0; //TODO
        self.buf.push(Command::SetDepthStencil(self.cache.depth_stencil, self.cache.stencil_ref));
        self.buf.push(Command::SetBlend(self.cache.blend, self.cache.blend_ref, sample_mask));
    }
}

impl draw::CommandBuffer<Resources> for CommandBuffer {
    fn clone_empty(&self) -> CommandBuffer {
        CommandBuffer::new()
    }

    fn reset(&mut self) {
        self.buf.clear();
        self.cache = Cache::new();
    }

    fn bind_pipeline_state(&mut self, pso: Pipeline) {
        use std::mem; //temporary
        self.buf.push(Command::SetPrimitive(unsafe{mem::transmute(pso.topology)}));
        if self.cache.rasterizer != pso.rasterizer {
            self.cache.rasterizer = pso.rasterizer;
            self.buf.push(Command::SetRasterizer(pso.rasterizer));
        }
        self.cache.depth_stencil = pso.depth_stencil;
        self.cache.blend = pso.blend;
        self.buf.push(Command::BindInputLayout(pso.layout));
        self.buf.push(Command::BindProgram(pso.program));
    }

    fn bind_vertex_buffers(&mut self, vbs: pso::VertexBufferSet<Resources>) {
        let mut buffers = [native::Buffer(ptr::null_mut()); MAX_VERTEX_ATTRIBUTES];
        let mut strides = [0; MAX_VERTEX_ATTRIBUTES];
        let mut offsets = [0; MAX_VERTEX_ATTRIBUTES];
        for i in 0 .. MAX_VERTEX_ATTRIBUTES {
            match (vbs.0[i], self.cache.attributes[i]) {
                (None, Some(fm)) => {
                    error!("No vertex input provided for slot {} of format {:?}", i, fm)
                },
                (Some((buffer, offset)), Some(ref format)) => {
                    buffers[i] = buffer;
                    strides[i] = format.0.stride as UINT;
                    offsets[i] = format.0.offset as UINT + (offset as UINT);
                },
                (_, None) => (),
            }
        }
        self.buf.push(Command::BindVertexBuffers(buffers, strides, offsets));
    }

    fn bind_constant_buffers(&mut self, _: pso::ConstantBufferSet<Resources>) {
        unimplemented!()
    }

    fn bind_global_constant(&mut self, _: shade::Location, _: shade::UniformValue) {
        unimplemented!()
    }

    fn bind_resource_views(&mut self, _: pso::ResourceViewSet<Resources>) {
        unimplemented!()
    }

    fn bind_unordered_views(&mut self, _: pso::UnorderedViewSet<Resources>) {
        unimplemented!()
    }

    fn bind_samplers(&mut self, _: pso::SamplerSet<Resources>) {
        unimplemented!()
    }

    fn bind_pixel_targets(&mut self, pts: pso::PixelTargetSet<Resources>) {
        if let (Some(ref d), Some(ref s)) = (pts.depth, pts.stencil) {
            if d != s {
                error!("Depth and stencil views have to be the same");
            }
        }
        let viewport = D3D11_VIEWPORT {
            TopLeftX: 0.0, TopLeftY: 0.0,
            Width: pts.size.0 as f32, Height: pts.size.1 as f32,
            MinDepth: 0.0, MaxDepth: 1.0,
        };
        let mut colors = [native::Rtv(ptr::null_mut()); MAX_COLOR_TARGETS];
        for i in 0 .. MAX_COLOR_TARGETS {
            if let Some(c) = pts.colors[i] {
                colors[i] = c;
            }
        }
        let ds = pts.depth.unwrap_or(native::Dsv(ptr::null_mut()));
        self.buf.push(Command::BindPixelTargets(colors, ds));
        self.buf.push(Command::SetViewport(viewport));
    }

    fn bind_index(&mut self, buf: native::Buffer, itype: IndexType) {
        let format = match itype {
            IndexType::U8  => DXGI_FORMAT_R8_UINT,
            IndexType::U16 => DXGI_FORMAT_R16_UINT,
            IndexType::U32 => DXGI_FORMAT_R32_UINT,
        };
        self.buf.push(Command::BindIndex(buf, format));
    }

    fn set_scissor(&mut self, rect: target::Rect) {
        self.buf.push(Command::SetScissor(D3D11_RECT {
            left: rect.x as INT,
            top: rect.y as INT,
            right: (rect.x + rect.w) as INT,
            bottom: (rect.y + rect.h) as INT,
        }));
    }

    fn set_ref_values(&mut self, rv: state::RefValues) {
        if rv.stencil.0 != rv.stencil.1 {
            error!("Unable to set different stencil ref values for front ({}) and back ({})",
                rv.stencil.0, rv.stencil.1);
        }
        self.cache.stencil_ref = rv.stencil.0 as UINT;
        self.cache.blend_ref = rv.blend;
    }

    fn update_buffer(&mut self, _: native::Buffer, _: draw::DataPointer, _: usize) {
        unimplemented!()
    }

    fn update_texture(&mut self, _: native::Texture, _: tex::Kind, _: Option<tex::CubeFace>,
                      _: draw::DataPointer, _: tex::RawImageInfo) {
        unimplemented!()
    }

    fn clear_color(&mut self, target: native::Rtv, value: draw::ClearColor) {
        match value {
            draw::ClearColor::Float(data) => {
                self.buf.push(Command::ClearColor(target, data));
            },
            _ => {
                error!("Unable to clear int/uint target");
            },
        }
    }

    fn clear_depth_stencil(&mut self, target: native::Dsv, depth: Option<target::Depth>,
                           stencil: Option<target::Stencil>) {
        let flags = //warning: magic constants ahead
            D3D11_CLEAR_FLAG(if depth.is_some() {1} else {0}) |
            D3D11_CLEAR_FLAG(if stencil.is_some() {2} else {0});
        self.buf.push(Command::ClearDepthStencil(target, flags,
                      depth.unwrap_or_default() as FLOAT,
                      stencil.unwrap_or_default() as UINT8
        ));
    }

    fn call_draw(&mut self, start: VertexCount, count: VertexCount, instances: draw::InstanceOption) {
        self.flush();
        self.buf.push(match instances {
            Some((ninst, offset)) => Command::DrawInstanced(
                count as UINT, ninst as UINT, start as UINT, offset as UINT),
            None => Command::Draw(count as UINT, start as UINT),
        });
    }

    fn call_draw_indexed(&mut self, start: VertexCount, count: VertexCount,
                         base: VertexCount, instances: draw::InstanceOption) {
        self.flush();
        self.buf.push(match instances {
            Some((ninst, offset)) => Command::DrawIndexedInstanced(
                count as UINT, ninst as UINT, start as UINT, base as INT, offset as UINT),
            None => Command::DrawIndexed(count as UINT, start as UINT, base as INT),
        });
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

use heck::SnakeCase;
use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::{format_ident, quote, ToTokens};
use std::cell::RefCell;
use syn::{Generics, Item};

// CAUTION: This is all wildly unstable and relies on the compiler maintaining
// a certain order between proc macro expansions. So this could break any
// minute. Better have a robust CI.
thread_local! {
    static NODES: RefCell<Vec<Node>> = Default::default();
}

struct Node {
    name: String,
    generics: String,
}

pub(crate) fn add_node(name: &Ident, generics: &Generics) {
    // Map everything to a string here. Compiler panics horribly if we hand out
    // the actual idents and generics.
    let node = Node {
        name: name.to_string(),
        generics: generics.to_token_stream().to_string(),
    };
    NODES.with(|c| c.borrow_mut().push(node));
}

pub(crate) fn all_node(_input: TokenStream) -> TokenStream {
    // Flush the accumulated nodes.
    let nodes = NODES.with(|c| std::mem::take(&mut *c.borrow_mut()));

    // Catch the trivial case of an empty node list.
    if nodes.is_empty() {
        panic!("no nodes marked for AllNode generation");
    }

    // Determine a lifetime for the enum.
    let lt: syn::Lifetime = syn::parse_str("'a").unwrap();

    // Generate the enum variants.
    let mut variants = vec![];
    let mut from_impls = vec![];
    let mut get_funcs = vec![];
    let mut is_funcs = vec![];
    let mut unwrap_funcs = vec![];
    let mut variant_names = vec![];
    for node in nodes {
        // Convert the name back to identifiers and re-parse the generics.
        let name = format_ident!("{}", node.name);
        let generics: syn::Generics = syn::parse_str(&node.generics).unwrap();

        let mut impl_generics = generics.clone();
        let var_lt = crate::first_lifetime(&mut impl_generics);

        // Render the corresponding variant.
        variants.push(quote! {
            #name(&#lt #name #generics),
        });
        variant_names.push(name.clone());

        // Render the corresponding `From` implementation.
        from_impls.push(quote! {
            impl #impl_generics From<&#var_lt #name #generics> for AllNode<#var_lt> {
                fn from(node: &#var_lt #name #generics) -> Self {
                    Self::#name(node)
                }
            }
        });

        // Render the corresponding `get_*` function.
        let get_fn = format_ident!("get_{}", node.name.to_snake_case());
        let get_doc = format!(
            r#"Get the underlying `{0}`, or `None` if the node is not a `{0}`.
            "#,
            name
        );
        get_funcs.push(quote! {
            #[doc = #get_doc]
            pub fn #get_fn(self) -> Option<&#lt #name #generics> {
                match self {
                    Self::#name(node) => Some(node),
                    _ => None,
                }
            }
        });

        // Render the corresponding `is_*` function.
        let is_fn = format_ident!("is_{}", node.name.to_snake_case());
        let is_doc = format!(
            r#"Check whether this is a `{}` node.
            "#,
            name
        );
        is_funcs.push(quote! {
            #[doc = #is_doc]
            pub fn #is_fn(self) -> bool {
                match self {
                    Self::#name(..) => true,
                    _ => false,
                }
            }
        });

        // Render the corresponding `unwrap_*` function.
        let unwrap_fn = format_ident!("unwrap_{}", node.name.to_snake_case());
        let unwrap_doc = format!(
            r#"Get the underlying `{0}`, or panic if the node is not a `{0}`.
            "#,
            name
        );
        unwrap_funcs.push(quote! {
            #[doc = #unwrap_doc]
            pub fn #unwrap_fn(self) -> &#lt #name #generics {
                match self.#get_fn() {
                    Some(node) => node,
                    None => panic!("node is not a {}", stringify!(#name)),
                }
            }
        });
    }

    let output = quote! {
        /// An exhaustive list of all nodes.
        #[derive(Copy, Clone, Debug)]
        pub enum AllNode<#lt> {
            #(#variants)*
        }

        impl<#lt> AllNode<#lt> {
            #(#get_funcs)*
            #(#is_funcs)*
            #(#unwrap_funcs)*

            /// Convert to an `AnyNode` trait object.
            pub fn as_any(self) -> &'a dyn AnyNode<'a> {
                match self {
                    #(Self::#variant_names(node) => node,)*
                }
            }
        }

        #(#from_impls)*
    };
    output.into()
}

pub(crate) fn mark_all_node(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(input as Item);
    let (name, generics) = match &input {
        Item::Enum(item) => (&item.ident, &item.generics),
        Item::Struct(item) => (&item.ident, &item.generics),
        Item::Type(item) => (&item.ident, &item.generics),
        _ => panic!("unsupported item to add to AllNode"),
    };
    add_node(&name, &generics);
    let output = quote! {
        #input
    };
    output.into()
}
<commit_msg>derive: Fix rust 1.38 compat<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

use heck::SnakeCase;
use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::{format_ident, quote, ToTokens};
use std::cell::RefCell;
use syn::{Generics, Item};

// CAUTION: This is all wildly unstable and relies on the compiler maintaining
// a certain order between proc macro expansions. So this could break any
// minute. Better have a robust CI.
thread_local! {
    static NODES: RefCell<Vec<Node>> = Default::default();
}

struct Node {
    name: String,
    generics: String,
}

pub(crate) fn add_node(name: &Ident, generics: &Generics) {
    // Map everything to a string here. Compiler panics horribly if we hand out
    // the actual idents and generics.
    let node = Node {
        name: name.to_string(),
        generics: generics.to_token_stream().to_string(),
    };
    NODES.with(|c| c.borrow_mut().push(node));
}

pub(crate) fn all_node(_input: TokenStream) -> TokenStream {
    // Flush the accumulated nodes.
    let nodes = NODES.with(|c| std::mem::replace(&mut *c.borrow_mut(), Default::default()));

    // Catch the trivial case of an empty node list.
    if nodes.is_empty() {
        panic!("no nodes marked for AllNode generation");
    }

    // Determine a lifetime for the enum.
    let lt: syn::Lifetime = syn::parse_str("'a").unwrap();

    // Generate the enum variants.
    let mut variants = vec![];
    let mut from_impls = vec![];
    let mut get_funcs = vec![];
    let mut is_funcs = vec![];
    let mut unwrap_funcs = vec![];
    let mut variant_names = vec![];
    for node in nodes {
        // Convert the name back to identifiers and re-parse the generics.
        let name = format_ident!("{}", node.name);
        let generics: syn::Generics = syn::parse_str(&node.generics).unwrap();

        let mut impl_generics = generics.clone();
        let var_lt = crate::first_lifetime(&mut impl_generics);

        // Render the corresponding variant.
        variants.push(quote! {
            #name(&#lt #name #generics),
        });
        variant_names.push(name.clone());

        // Render the corresponding `From` implementation.
        from_impls.push(quote! {
            impl #impl_generics From<&#var_lt #name #generics> for AllNode<#var_lt> {
                fn from(node: &#var_lt #name #generics) -> Self {
                    Self::#name(node)
                }
            }
        });

        // Render the corresponding `get_*` function.
        let get_fn = format_ident!("get_{}", node.name.to_snake_case());
        let get_doc = format!(
            r#"Get the underlying `{0}`, or `None` if the node is not a `{0}`.
            "#,
            name
        );
        get_funcs.push(quote! {
            #[doc = #get_doc]
            pub fn #get_fn(self) -> Option<&#lt #name #generics> {
                match self {
                    Self::#name(node) => Some(node),
                    _ => None,
                }
            }
        });

        // Render the corresponding `is_*` function.
        let is_fn = format_ident!("is_{}", node.name.to_snake_case());
        let is_doc = format!(
            r#"Check whether this is a `{}` node.
            "#,
            name
        );
        is_funcs.push(quote! {
            #[doc = #is_doc]
            pub fn #is_fn(self) -> bool {
                match self {
                    Self::#name(..) => true,
                    _ => false,
                }
            }
        });

        // Render the corresponding `unwrap_*` function.
        let unwrap_fn = format_ident!("unwrap_{}", node.name.to_snake_case());
        let unwrap_doc = format!(
            r#"Get the underlying `{0}`, or panic if the node is not a `{0}`.
            "#,
            name
        );
        unwrap_funcs.push(quote! {
            #[doc = #unwrap_doc]
            pub fn #unwrap_fn(self) -> &#lt #name #generics {
                match self.#get_fn() {
                    Some(node) => node,
                    None => panic!("node is not a {}", stringify!(#name)),
                }
            }
        });
    }

    let output = quote! {
        /// An exhaustive list of all nodes.
        #[derive(Copy, Clone, Debug)]
        pub enum AllNode<#lt> {
            #(#variants)*
        }

        impl<#lt> AllNode<#lt> {
            #(#get_funcs)*
            #(#is_funcs)*
            #(#unwrap_funcs)*

            /// Convert to an `AnyNode` trait object.
            pub fn as_any(self) -> &'a dyn AnyNode<'a> {
                match self {
                    #(Self::#variant_names(node) => node,)*
                }
            }
        }

        #(#from_impls)*
    };
    output.into()
}

pub(crate) fn mark_all_node(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(input as Item);
    let (name, generics) = match &input {
        Item::Enum(item) => (&item.ident, &item.generics),
        Item::Struct(item) => (&item.ident, &item.generics),
        Item::Type(item) => (&item.ident, &item.generics),
        _ => panic!("unsupported item to add to AllNode"),
    };
    add_node(&name, &generics);
    let output = quote! {
        #input
    };
    output.into()
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Discordian_date
extern crate chrono;
use chrono::*;

const SEASONS: [&'static str; 5] = ["Chaos",
                                    "Discord",
                                    "Confusion",
                                    "Bureaucracy",
                                    "The Aftermath"];
const WEEKDAYS: [&'static str; 5] = ["Sweetmorn",
                                     "Boomtime",
                                     "Pungenday",
                                     "Prickle-Prickle",
                                     "Setting Orange"];
const YEAR_OFFSET: i32 = 1166;

fn discordian_day(day: usize, leap: bool) -> String {
    if day == 59 && leap {
        return String::from("St. Tib's Day");
    }
    let offset = if day > 59 && leap {
        1
    } else {
        0
    };
    let day_off = day - offset;
    let day_num = day_off % 73 + 1;
    let season = SEASONS[day_off / 73];
    let weekday = WEEKDAYS[day_off % 5];
    String::from(format!("{}, {} {}", weekday, season, day_num))
}

fn discordian_date<T: Datelike>(date: T) -> String {
    let dday = discordian_day(date.ordinal0() as usize, is_leap_year(date.year()));
    let year = date.year() + YEAR_OFFSET;
    String::from(format!("{}, YOLD {}", dday, year))
}

// implementation from https://en.wikipedia.org/wiki/Leap_year#Algorithm
#[cfg_attr(feature="clippy", allow(if_same_then_else))]
fn is_leap_year(year: i32) -> bool {
    if year % 4 != 0 {
        false
    } else if year % 100 != 0 {
        true
    } else if year % 400 != 0 {
        false
    } else {
        true
    }
}

fn main() {
    // sample date
    let utc: DateTime<UTC> = UTC::now();
    println!("{} in the Discordian Calendar is:", utc);
    println!("{}", discordian_date(utc));
    let local: DateTime<Local> = Local::now();
    println!("{} in the Discordian Calendar is:", local);
    println!("{}", discordian_date(local));
}

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

    #[test]
    fn curse_of_greyface_test() {
        let dt = UTC.ymd(-1166, 1, 1);
        assert_eq!("Sweetmorn, Chaos 1, YOLD 0", discordian_date(dt));
    }

    #[test]
    fn before_leap_day_test() {
        let dt = UTC.ymd(2016, 2, 28);
        assert_eq!("Prickle-Prickle, Chaos 59, YOLD 3182", discordian_date(dt));
    }

    #[test]
    fn leap_day_test() {
        let dt = UTC.ymd(2016, 2, 29);
        assert_eq!("St. Tib's Day, YOLD 3182", discordian_date(dt));
    }

    #[test]
    fn after_leap_day_test() {
        let dt = UTC.ymd(2016, 3, 1);
        assert_eq!("Setting Orange, Chaos 60, YOLD 3182", discordian_date(dt));
    }

    #[test]
    fn before_not_leap_day_test() {
        let dt = UTC.ymd(2015, 2, 28);
        assert_eq!("Prickle-Prickle, Chaos 59, YOLD 3181", discordian_date(dt));
    }

    #[test]
    fn not_leap_day_test() {
        let dt = UTC.ymd(2015, 3, 1);
        assert_eq!("Setting Orange, Chaos 60, YOLD 3181", discordian_date(dt));
    }

    #[test]
    fn birthday_test() {
        let dt = UTC.ymd(1994, 5, 14);
        assert_eq!("Prickle-Prickle, Discord 61, YOLD 3160",
                   discordian_date(dt));
    }

    #[test]
    fn magna_carta_test() {
        let dt = UTC.ymd(1215, 6, 15);
        assert_eq!("Sweetmorn, Confusion 20, YOLD 2381", discordian_date(dt));
    }
}
<commit_msg>fix needless boolean return warnings<commit_after>// http://rosettacode.org/wiki/Discordian_date
extern crate chrono;
use chrono::*;

const SEASONS: [&'static str; 5] = ["Chaos",
                                    "Discord",
                                    "Confusion",
                                    "Bureaucracy",
                                    "The Aftermath"];
const WEEKDAYS: [&'static str; 5] = ["Sweetmorn",
                                     "Boomtime",
                                     "Pungenday",
                                     "Prickle-Prickle",
                                     "Setting Orange"];
const YEAR_OFFSET: i32 = 1166;

fn discordian_day(day: usize, leap: bool) -> String {
    if day == 59 && leap {
        return String::from("St. Tib's Day");
    }
    let offset = if day > 59 && leap {
        1
    } else {
        0
    };
    let day_off = day - offset;
    let day_num = day_off % 73 + 1;
    let season = SEASONS[day_off / 73];
    let weekday = WEEKDAYS[day_off % 5];
    String::from(format!("{}, {} {}", weekday, season, day_num))
}

fn discordian_date<T: Datelike>(date: T) -> String {
    let dday = discordian_day(date.ordinal0() as usize, is_leap_year(date.year()));
    let year = date.year() + YEAR_OFFSET;
    String::from(format!("{}, YOLD {}", dday, year))
}

// implementation from https://en.wikipedia.org/wiki/Leap_year#Algorithm
#[cfg_attr(feature="clippy", allow(if_same_then_else, needless_bool))]
fn is_leap_year(year: i32) -> bool {
    if year % 4 != 0 {
        false
    } else if year % 100 != 0 {
        true
    } else if year % 400 != 0 {
        false
    } else {
        true
    }
}

fn main() {
    // sample date
    let utc: DateTime<UTC> = UTC::now();
    println!("{} in the Discordian Calendar is:", utc);
    println!("{}", discordian_date(utc));
    let local: DateTime<Local> = Local::now();
    println!("{} in the Discordian Calendar is:", local);
    println!("{}", discordian_date(local));
}

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

    #[test]
    fn curse_of_greyface_test() {
        let dt = UTC.ymd(-1166, 1, 1);
        assert_eq!("Sweetmorn, Chaos 1, YOLD 0", discordian_date(dt));
    }

    #[test]
    fn before_leap_day_test() {
        let dt = UTC.ymd(2016, 2, 28);
        assert_eq!("Prickle-Prickle, Chaos 59, YOLD 3182", discordian_date(dt));
    }

    #[test]
    fn leap_day_test() {
        let dt = UTC.ymd(2016, 2, 29);
        assert_eq!("St. Tib's Day, YOLD 3182", discordian_date(dt));
    }

    #[test]
    fn after_leap_day_test() {
        let dt = UTC.ymd(2016, 3, 1);
        assert_eq!("Setting Orange, Chaos 60, YOLD 3182", discordian_date(dt));
    }

    #[test]
    fn before_not_leap_day_test() {
        let dt = UTC.ymd(2015, 2, 28);
        assert_eq!("Prickle-Prickle, Chaos 59, YOLD 3181", discordian_date(dt));
    }

    #[test]
    fn not_leap_day_test() {
        let dt = UTC.ymd(2015, 3, 1);
        assert_eq!("Setting Orange, Chaos 60, YOLD 3181", discordian_date(dt));
    }

    #[test]
    fn birthday_test() {
        let dt = UTC.ymd(1994, 5, 14);
        assert_eq!("Prickle-Prickle, Discord 61, YOLD 3160",
                   discordian_date(dt));
    }

    #[test]
    fn magna_carta_test() {
        let dt = UTC.ymd(1215, 6, 15);
        assert_eq!("Sweetmorn, Confusion 20, YOLD 2381", discordian_date(dt));
    }
}
<|endoftext|>


<commit_before>// automatically generated by rust-bindgen

pub type Enum_Unnamed1 = ::libc::c_uint;
pub const FALSE: ::libc::c_uint = 0;
pub const TRUE: ::libc::c_uint = 1;
pub type Rboolean = Enum_Unnamed1;
<commit_msg>Use obsolute type name for Rboolean<commit_after>// automatically generated by rust-bindgen

pub type Rboolean = ::libc::c_uint;
pub const FALSE: ::libc::c_uint = 0;
pub const TRUE: ::libc::c_uint = 1;
<|endoftext|>


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

#[phase(plugin)]
extern crate gl_generator;
extern crate glfw;

extern crate time;

use glfw::{Glfw, Context, OpenGlProfileHint, WindowHint, WindowMode};

use std::rand::{task_rng, Rng};

use std::num::FloatMath;

use self::gl::Gl;

#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
pub mod gl {
    use self::types::*;
    generate_gl_bindings! {
        api: "gl",
        profile: "core",
        version: "3.0",
        generator: "struct",
        extensions: [
            "GL_EXT_texture_filter_anisotropic",
        ]
    }
}

struct Color {
    red: f32,
    green: f32,
    blue: f32,
    alpha: f32
}

struct Particle {
    life: f32,
    fade: f32,
    x: f32,
    y: f32,
    xi: f32,
    yi: f32,
    color: Color
}

static WINDOW_WIDTH: u32 = 800;
static WINDOW_HEIGHT: u32 = 600;

static MAX_PARTICLES: uint = 10000;
static MAX_LIFE: f32 = 2.5;
static PARTICLE_SIZE: f32 = 1.5;

fn init_gl(gl: &Gl, glfw: &Glfw) {

    // Choose a GL profile that is compatible with OS X 10.7+
    glfw.window_hint(WindowHint::ContextVersion(3, 2));
    glfw.window_hint(WindowHint::OpenglForwardCompat(true));
    glfw.window_hint(WindowHint::OpenglProfile(OpenGlProfileHint::Core));

    glfw.set_swap_interval(1);

    unsafe {
        gl.Viewport(0, 0, WINDOW_WIDTH.to_i32().unwrap(), WINDOW_HEIGHT.to_i32().unwrap());
        gl.MatrixMode(gl::PROJECTION);
        gl.LoadIdentity();
        gl.Ortho(0.0, 800.0, 600.0, 0.0, 0.0, 1.0);

        gl.Enable(gl::TEXTURE_2D);
        gl.Enable(gl::BLEND);
        gl.ShadeModel(gl::SMOOTH);
        gl.BlendFunc(gl::SRC_ALPHA, gl::ONE);
    }
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    let (window, _) = glfw.create_window(WINDOW_WIDTH, WINDOW_HEIGHT, "OpenGL", WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();

    // Load the OpenGL function pointers
    let gl = Gl::load_with(|s| window.get_proc_address(s));

    init_gl(&gl, &glfw);

    let mut particles: Vec<Particle> = Vec::with_capacity(MAX_PARTICLES);

    while !window.should_close() {
        // Poll events
        glfw.poll_events();

        // Clear the screen to black
        unsafe {
            gl.ClearColor(0.0, 0.0, 0.0, 1.0);
            gl.Clear(gl::COLOR_BUFFER_BIT);

            gl.PointSize(PARTICLE_SIZE);
            gl.Begin(gl::POINTS);

            // Draw particles
            for p in particles.iter() {
                gl.Color4f(p.color.red, p.color.green, p.color.blue, p.color.alpha);
                gl.Vertex2f(p.x, p.y);
            }

            gl.End();
        }

        move_particles(&mut particles);

        // Swap buffers
        window.swap_buffers();

    }
}

fn create_new_particle() -> Particle {
    let angle: f32 = task_rng().gen_range(0.0, 360.0);
    let v: f32 = task_rng().gen_range(0.1, 1.0);

    let timespec = time::get_time();
    let millis = timespec.nsec as f32 / 1000.0 / 1000.0;
    let sec = timespec.sec.rem(100) as f32;

    let radius = (WINDOW_WIDTH as f32).min(WINDOW_HEIGHT as f32) / 4.0;

    let x = millis.sin() * radius;
    let y = millis.cos() * radius;

    Particle {
        life: task_rng().gen_range(MAX_LIFE * 0.8, MAX_LIFE),
        fade: task_rng().gen_range(0.01, 0.05),
        x: x + WINDOW_WIDTH as f32 / 2.0,
        y: y + WINDOW_HEIGHT as f32 / 2.0,
        xi: angle.cos() * v,
        yi: angle.sin() * v,
        color: Color {
            red: sec.sin(),
            green: sec.cos(),
            blue: task_rng().gen_range(0.4, 0.6),
            alpha: 1.0
        }
    }
}

fn move_particles(particles: &mut Vec<Particle>) {
    // Move & decay existing particles
    for mut particle in particles.iter_mut() {
        particle.life -= particle.fade;
        particle.x += particle.xi;
        particle.y += particle.yi;
        particle.xi *= 0.999;
        particle.yi *= 0.999;

        particle.color.alpha = 1.0 * particle.life / MAX_LIFE;
        particle.color.red += particle.fade / 3.0;
        particle.color.green += particle.fade / 3.0;
        particle.color.blue += particle.fade / 3.0;
    }

    // Replace dead particles
    for i in range(0u, particles.len()) {
        if particles[i].life < 0.05 {
            particles.remove(i);
            particles.insert(i, create_new_particle());
        }
    }

    // Add new particles if missing
    let mut i = 0i;
    loop {
        if particles.len() < MAX_PARTICLES {
            particles.push(create_new_particle());
            i += 1 ;
        } else {
            break;
        }

        if i > 20 {
            break;
        }
    }
}
<commit_msg>Tweak variables<commit_after>#![feature(macro_rules)]
#![feature(globs)]
#![feature(phase)]
#![allow(missing_copy_implementations)]

#[phase(plugin)]
extern crate gl_generator;
extern crate glfw;

extern crate time;

use glfw::{Glfw, Context, OpenGlProfileHint, WindowHint, WindowMode};

use std::rand::{task_rng, Rng};

use std::num::FloatMath;

use self::gl::Gl;

#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
pub mod gl {
    use self::types::*;
    generate_gl_bindings! {
        api: "gl",
        profile: "core",
        version: "3.0",
        generator: "struct",
        extensions: [
            "GL_EXT_texture_filter_anisotropic",
        ]
    }
}

struct Color {
    red: f32,
    green: f32,
    blue: f32,
    alpha: f32
}

struct Particle {
    life: f32,
    fade: f32,
    x: f32,
    y: f32,
    xi: f32,
    yi: f32,
    color: Color
}

static WINDOW_WIDTH: u32 = 800;
static WINDOW_HEIGHT: u32 = 600;

static MAX_PARTICLES: uint = 20000;
static MAX_LIFE: f32 = 2.5;
static PARTICLE_SIZE: f32 = 1.5;

fn init_gl(gl: &Gl, glfw: &Glfw) {

    // Choose a GL profile that is compatible with OS X 10.7+
    glfw.window_hint(WindowHint::ContextVersion(3, 2));
    glfw.window_hint(WindowHint::OpenglForwardCompat(true));
    glfw.window_hint(WindowHint::OpenglProfile(OpenGlProfileHint::Core));

    glfw.set_swap_interval(1);

    unsafe {
        gl.Viewport(0, 0, WINDOW_WIDTH.to_i32().unwrap(), WINDOW_HEIGHT.to_i32().unwrap());
        gl.MatrixMode(gl::PROJECTION);
        gl.LoadIdentity();
        gl.Ortho(0.0, 800.0, 600.0, 0.0, 0.0, 1.0);

        gl.Enable(gl::TEXTURE_2D);
        gl.Enable(gl::BLEND);
        gl.ShadeModel(gl::SMOOTH);
        gl.BlendFunc(gl::SRC_ALPHA, gl::ONE);
    }
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    let (window, _) = glfw.create_window(WINDOW_WIDTH, WINDOW_HEIGHT, "OpenGL", WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();

    // Load the OpenGL function pointers
    let gl = Gl::load_with(|s| window.get_proc_address(s));

    init_gl(&gl, &glfw);

    let mut particles: Vec<Particle> = Vec::with_capacity(MAX_PARTICLES);

    while !window.should_close() {
        // Poll events
        glfw.poll_events();

        // Clear the screen to black
        unsafe {
            gl.ClearColor(0.0, 0.0, 0.0, 1.0);
            gl.Clear(gl::COLOR_BUFFER_BIT);

            gl.PointSize(PARTICLE_SIZE);
            gl.Begin(gl::POINTS);

            // Draw particles
            for p in particles.iter() {
                gl.Color4f(p.color.red, p.color.green, p.color.blue, p.color.alpha);
                gl.Vertex2f(p.x, p.y);
            }

            gl.End();
        }

        move_particles(&mut particles);

        // Swap buffers
        window.swap_buffers();

    }
}

fn create_new_particle() -> Particle {
    let angle: f32 = task_rng().gen_range(0.0, 360.0);
    let v: f32 = task_rng().gen_range(0.1, 1.1);

    let timespec = time::get_time();
    let millis = timespec.nsec as f32 / 1000.0 / 1000.0;
    let sec = timespec.sec.rem(100) as f32;

    let radius = (WINDOW_WIDTH as f32).min(WINDOW_HEIGHT as f32) / 4.0;

    let x = millis.sin() * radius;
    let y = millis.cos() * radius;

    Particle {
        life: task_rng().gen_range(MAX_LIFE * 0.8, MAX_LIFE),
        fade: task_rng().gen_range(0.01, 0.05),
        x: x + WINDOW_WIDTH as f32 / 2.0,
        y: y + WINDOW_HEIGHT as f32 / 2.0,
        xi: angle.cos() * v,
        yi: angle.sin() * v,
        color: Color {
            red: sec.sin(),
            green: sec.cos(),
            blue: task_rng().gen_range(0.4, 0.6),
            alpha: 1.0
        }
    }
}

fn move_particles(particles: &mut Vec<Particle>) {
    // Move & decay existing particles
    for mut particle in particles.iter_mut() {
        particle.life -= particle.fade;
        particle.x += particle.xi;
        particle.y += particle.yi;
        particle.xi *= 0.999;
        particle.yi *= 0.999;

        particle.color.alpha = 1.0 * particle.life / MAX_LIFE;
        particle.color.red += particle.fade / 3.0;
        particle.color.green += particle.fade / 3.0;
        particle.color.blue += particle.fade / 3.0;
    }

    // Replace dead particles
    for i in range(0u, particles.len()) {
        if particles[i].life < 0.05 {
            particles.remove(i);
            particles.insert(i, create_new_particle());
        }
    }

    // Add new particles if missing
    let mut i = 0i;
    loop {
        if particles.len() < MAX_PARTICLES {
            particles.push(create_new_particle());
            i += 1 ;
        } else {
            break;
        }

        if i > 20 {
            break;
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Write};

const EXCEEDS_BMP: char = '\u{FFFF}';

pub enum KlcKey {
    Character(char),
    DeadKey(char),
    Ligature,
    None,
    Skip,
}

impl Display for KlcKey {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            KlcKey::Character(character) => display_klc_character(*character, f),
            KlcKey::DeadKey(character) => {
                f.write_char('@')?;
                display_klc_character(*character, f)
            }
            KlcKey::Ligature => f.write_str("%%"),
            KlcKey::None => f.write_str("-1"),
            KlcKey::Skip => Ok(()),
        }
    }
}

// ASCII characters can be represented as is
// Unicode characters must be converted to their UTF-16 representation
pub fn display_klc_character(character: char, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    if character.is_ascii_graphic() {
        f.write_char(character)
    } else {
        f.write_fmt(format_args!("{:04x}", character as u32))
    }
}

pub fn validate_for_klc(key: &str) {
    key.chars().for_each(|character| {
        if character >= EXCEEDS_BMP {
            panic!("Unrepresentable key detected! {}", key);
        }
    });
}
<commit_msg>0xFFFF is technically within BMP<commit_after>use std::fmt::{Display, Write};

const EXCEEDS_BMP: char = '\u{FFFF}';

pub enum KlcKey {
    Character(char),
    DeadKey(char),
    Ligature,
    None,
    Skip,
}

impl Display for KlcKey {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            KlcKey::Character(character) => display_klc_character(*character, f),
            KlcKey::DeadKey(character) => {
                f.write_char('@')?;
                display_klc_character(*character, f)
            }
            KlcKey::Ligature => f.write_str("%%"),
            KlcKey::None => f.write_str("-1"),
            KlcKey::Skip => Ok(()),
        }
    }
}

// ASCII characters can be represented as is
// Unicode characters must be converted to their UTF-16 representation
pub fn display_klc_character(character: char, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    if character.is_ascii_graphic() {
        f.write_char(character)
    } else {
        f.write_fmt(format_args!("{:04x}", character as u32))
    }
}

pub fn validate_for_klc(key: &str) {
    key.chars().for_each(|character| {
        if character > EXCEEDS_BMP {
            panic!("Unrepresentable key detected! {}", key);
        }
    });
}
<|endoftext|>