<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

use rustc_serialize::{Encodable, Decodable};
use toml::{self, Encoder, Value};

use core::{Resolve, resolver, Package, SourceId};
use util::{CargoResult, ChainError, human, paths};
use util::toml as cargo_toml;

pub fn load_pkg_lockfile(pkg: &Package) -> CargoResult<Option<Resolve>> {
    let lockfile = pkg.root().join("Cargo.lock");
    let source_id = pkg.package_id().source_id();
    load_lockfile(&lockfile, source_id).chain_error(|| {
        human(format!("failed to parse lock file at: {}", lockfile.display()))
    })
}

pub fn load_lockfile(path: &Path, sid: &SourceId) -> CargoResult<Option<Resolve>> {
    // If there is no lockfile, return none.
    let mut f = match File::open(path) {
        Ok(f) => f,
        Err(_) => return Ok(None)
    };

    let mut s = String::new();
    try!(f.read_to_string(&mut s));

    let table = toml::Value::Table(try!(cargo_toml::parse(&s, path)));
    let mut d = toml::Decoder::new(table);
    let v: resolver::EncodableResolve = try!(Decodable::decode(&mut d));
    Ok(Some(try!(v.to_resolve(sid))))
}

pub fn write_pkg_lockfile(pkg: &Package, resolve: &Resolve) -> CargoResult<()> {
    let loc = pkg.root().join("Cargo.lock");
    write_lockfile(&loc, resolve)
}

pub fn write_lockfile(dst: &Path, resolve: &Resolve) -> CargoResult<()> {
    let mut e = Encoder::new();
    resolve.encode(&mut e).unwrap();

    let mut out = String::new();

    // Note that we do not use e.toml.to_string() as we want to control the
    // exact format the toml is in to ensure pretty diffs between updates to the
    // lockfile.
    let root = e.toml.get(&"root".to_string()).unwrap();

    out.push_str("[root]\n");
    emit_package(root.as_table().unwrap(), &mut out);

    let deps = e.toml.get(&"package".to_string()).unwrap().as_slice().unwrap();
    for dep in deps.iter() {
        let dep = dep.as_table().unwrap();

        out.push_str("[[package]]\n");
        emit_package(dep, &mut out);
    }

    match e.toml.get(&"metadata".to_string()) {
        Some(metadata) => {
            out.push_str("[metadata]\n");
            out.push_str(&metadata.to_string());
        }
        None => {}
    }

    try!(paths::write(dst, out.as_bytes()));
    Ok(())
}

fn emit_package(dep: &toml::Table, out: &mut String) {
    out.push_str(&format!("name = {}\n", lookup(dep, "name")));
    out.push_str(&format!("version = {}\n", lookup(dep, "version")));

    if dep.contains_key("source") {
        out.push_str(&format!("source = {}\n", lookup(dep, "source")));
    }

    if let Some(ref s) = dep.get("dependencies") {
        let slice = Value::as_slice(*s).unwrap();

        if !slice.is_empty() {
            out.push_str("dependencies = [\n");

            for child in slice.iter() {
                out.push_str(&format!(" {},\n", child));
            }

            out.push_str("]\n");
        }
        out.push_str("\n");
    }
}

fn lookup<'a>(table: &'a toml::Table, key: &str) -> &'a toml::Value {
    table.get(key).expect(&format!("didn't find {}", key))
}
<commit_msg>Avoid overwriting the lockfile if there are no changes<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

use rustc_serialize::{Encodable, Decodable};
use toml::{self, Encoder, Value};

use core::{Resolve, resolver, Package, SourceId};
use util::{CargoResult, ChainError, human, paths};
use util::toml as cargo_toml;

pub fn load_pkg_lockfile(pkg: &Package) -> CargoResult<Option<Resolve>> {
    let lockfile = pkg.root().join("Cargo.lock");
    let source_id = pkg.package_id().source_id();
    load_lockfile(&lockfile, source_id).chain_error(|| {
        human(format!("failed to parse lock file at: {}", lockfile.display()))
    })
}

pub fn load_lockfile(path: &Path, sid: &SourceId) -> CargoResult<Option<Resolve>> {
    // If there is no lockfile, return none.
    let mut f = match File::open(path) {
        Ok(f) => f,
        Err(_) => return Ok(None)
    };

    let mut s = String::new();
    try!(f.read_to_string(&mut s));

    let table = toml::Value::Table(try!(cargo_toml::parse(&s, path)));
    let mut d = toml::Decoder::new(table);
    let v: resolver::EncodableResolve = try!(Decodable::decode(&mut d));
    Ok(Some(try!(v.to_resolve(sid))))
}

pub fn write_pkg_lockfile(pkg: &Package, resolve: &Resolve) -> CargoResult<()> {
    let loc = pkg.root().join("Cargo.lock");
    write_lockfile(&loc, resolve)
}

pub fn write_lockfile(dst: &Path, resolve: &Resolve) -> CargoResult<()> {
    let mut e = Encoder::new();
    resolve.encode(&mut e).unwrap();

    let mut out = String::new();

    // Note that we do not use e.toml.to_string() as we want to control the
    // exact format the toml is in to ensure pretty diffs between updates to the
    // lockfile.
    let root = e.toml.get(&"root".to_string()).unwrap();

    out.push_str("[root]\n");
    emit_package(root.as_table().unwrap(), &mut out);

    let deps = e.toml.get(&"package".to_string()).unwrap().as_slice().unwrap();
    for dep in deps.iter() {
        let dep = dep.as_table().unwrap();

        out.push_str("[[package]]\n");
        emit_package(dep, &mut out);
    }

    match e.toml.get(&"metadata".to_string()) {
        Some(metadata) => {
            out.push_str("[metadata]\n");
            out.push_str(&metadata.to_string());
        }
        None => {}
    }

    // Load the original lockfile if it exists.
    if let Ok(orig) = paths::read(dst) {
        if out == orig {
            // The lockfile contents haven't changed so don't rewrite it.
            // This is helpful on read-only filesystems.
            return Ok(())
        }
    }

    try!(paths::write(dst, out.as_bytes()));
    Ok(())
}

fn emit_package(dep: &toml::Table, out: &mut String) {
    out.push_str(&format!("name = {}\n", lookup(dep, "name")));
    out.push_str(&format!("version = {}\n", lookup(dep, "version")));

    if dep.contains_key("source") {
        out.push_str(&format!("source = {}\n", lookup(dep, "source")));
    }

    if let Some(ref s) = dep.get("dependencies") {
        let slice = Value::as_slice(*s).unwrap();

        if !slice.is_empty() {
            out.push_str("dependencies = [\n");

            for child in slice.iter() {
                out.push_str(&format!(" {},\n", child));
            }

            out.push_str("]\n");
        }
        out.push_str("\n");
    }
}

fn lookup<'a>(table: &'a toml::Table, key: &str) -> &'a toml::Value {
    table.get(key).expect(&format!("didn't find {}", key))
}
<|endoftext|>


<commit_before>#![allow(clippy::unreadable_literal)]

use chrono::Utc;
use imagesize::size;
use orgize::{
    export::{html::Escape, DefaultHtmlHandler, HtmlHandler},
    Element,
};
use std::{io::Write, path::PathBuf, process::Command};
use syntect::{
    easy::HighlightLines,
    highlighting::ThemeSet,
    html::{styled_line_to_highlighted_html, IncludeBackground},
    parsing::SyntaxSet,
};
use url::Url;

use crate::error::{Error, Result};

pub struct SolomonBaseHandler(DefaultHtmlHandler);

impl SolomonBaseHandler {
    fn highlight(&self, language: Option<&str>, content: &str) -> String {
        lazy_static::lazy_static! {
            static ref SYNTAX_SET: SyntaxSet = {
                let set = SyntaxSet::load_defaults_newlines();
                let mut builder = set.into_builder();
                // add extra language syntax files
                builder.add_from_folder("gen/syntax", true).unwrap();
                builder.build()
            };
            static ref THEME_SET: ThemeSet = ThemeSet::load_defaults();
        }

        let language = match language {
            Some("elisp") | Some("emacs-lisp") => Some("lisp"),
            _ => language,
        };
        let mut highlighter = HighlightLines::new(
            language
                .and_then(|lang| SYNTAX_SET.find_syntax_by_token(lang))
                .unwrap_or_else(|| SYNTAX_SET.find_syntax_plain_text()),
            &THEME_SET.themes["InspiredGitHub"],
        );
        let regions = highlighter.highlight(content, &SYNTAX_SET);
        styled_line_to_highlighted_html(&regions[..], IncludeBackground::No)
    }
}

impl HtmlHandler<Error> for SolomonBaseHandler {
    fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<()> {
        match element {
            Element::InlineSrc(inline_src) => write!(
                w,
                "{}",
                self.highlight(Some(&inline_src.lang), &inline_src.body)
            )?,
            Element::SourceBlock(block) => {
                if block.language.is_empty() {
                    write!(w, "
{}
", block.contents)?;
                } else {
                    write!(
                        w,
                        "
{}
",
                        self.highlight(Some(&block.language), &block.contents)
                    )?
                }
            }
            Element::FixedWidth { value } => {
                write!(w, "
{}
", self.highlight(None, value))?
            }
            Element::ExampleBlock(block) => write!(
                w,
                "
{}
",
                self.highlight(None, &block.contents)
            )?,
            Element::Macros(macros) => match &macros.name as &str {
                "age-days" => {
                    write!(w, " {:.} ", (Utc::now().timestamp() - 1382071200) / 86400)?;
                }
                "angular-core-version" => {
                    write_nodejs_package_version(w, "@angular/core")?;
                }
                "angular-material-version" => {
                    write_nodejs_package_version(w, "@angular/material")?;
                }
                "angular-cli-version" => {
                    write_nodejs_package_version(w, "@angular/cli")?;
                }
                _ => (),
            },
            Element::Link(link) => {
                if let Some(desc) = &link.desc {
                    write!(
                        w,
                        r#"{}"#,
                        Escape(&link.path),
                        Escape(desc)
                    )?;
                } else {
                    write!(w, r#"{0}"#, Escape(&link.path))?;
                }
            }
            _ => self.0.start(w, element)?,
        }
        Ok(())
    }
}

pub struct SolomonHtmlHandler(SolomonBaseHandler);

impl Default for SolomonHtmlHandler {
    fn default() -> Self {
        SolomonHtmlHandler(SolomonBaseHandler(DefaultHtmlHandler))
    }
}

impl HtmlHandler<Error> for SolomonHtmlHandler {
    fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<()> {
        if let Element::Link(link) = element {
            let url = Url::parse(&link.path)?;
            if url.scheme() == "file" {
                let size = size(PathBuf::from(r"content/post").join(&url.path()[1..]))?;

                write!(
                    w,
                    "
\

\

",
                    url.path(),
                    (size.height as f32 / size.width as f32) * 100.
                )?;
            } else {
                self.0.start(w, element)?;
            }

            Ok(())
        } else {
            self.0.start(w, element)
        }
    }
}

pub struct SolomonRssHandler(SolomonBaseHandler);

impl Default for SolomonRssHandler {
    fn default() -> Self {
        SolomonRssHandler(SolomonBaseHandler(DefaultHtmlHandler))
    }
}

impl HtmlHandler<Error> for SolomonRssHandler {
    fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<()> {
        if let Element::Link(link) = element {
            let url = Url::parse(&link.path)?;
            if url.scheme() == "file" {
                let size = size(PathBuf::from(r"content/post").join(&url.path()[1..]))?;

                write!(
                    w,
                    r#""#,
                    url.path(),
                    size.width,
                    size.height
                )?;
            } else {
                self.0.start(w, element)?;
            }
        } else {
            self.0.start(w, element)?;
        }

        Ok(())
    }
}

fn write_nodejs_package_version<W: Write>(mut w: W, package: &str) -> Result<()> {
    write!(w, "")?;

    let command = Command::new("yarn")
        .args(&["--cwd", "web", "--silent", "list", "--pattern", package])
        .output()?;

    let output = String::from_utf8(output.stdout)?;

    if let Some(version) = output.trim().split_whitespace().last() {
        write!(w, "{}", version)?;
    }

    write!(w, "")?;

    Ok(())
}

// fn should_insert_space(c1: char, c2: char) -> bool {
//     const CHINESE_PUNCTUATION: [char; 14] = [
//         '。', '？', '，', '、', '；', '：', '“', '”', '「', '」', '（', '）', '《', '》',
//     ];

//     (c1.is_ascii_graphic() && c2.is_ascii_graphic())
//         || (c1.is_ascii_graphic()
//             && 0x4E00 < (c2 as u32)
//             && (c2 as u32) < 0x9FFF
//             && !CHINESE_PUNCTUATION.contains(&c2))
//         || (c2.is_ascii_graphic()
//             && 0x4E00 < (c1 as u32)
//             && (c1 as u32) < 0x9FFF
//             && !CHINESE_PUNCTUATION.contains(&c1))
// }
<commit_msg>fix(gen): fix varibale name<commit_after>#![allow(clippy::unreadable_literal)]

use chrono::Utc;
use imagesize::size;
use orgize::{
    export::{html::Escape, DefaultHtmlHandler, HtmlHandler},
    Element,
};
use std::{io::Write, path::PathBuf, process::Command};
use syntect::{
    easy::HighlightLines,
    highlighting::ThemeSet,
    html::{styled_line_to_highlighted_html, IncludeBackground},
    parsing::SyntaxSet,
};
use url::Url;

use crate::error::{Error, Result};

pub struct SolomonBaseHandler(DefaultHtmlHandler);

impl SolomonBaseHandler {
    fn highlight(&self, language: Option<&str>, content: &str) -> String {
        lazy_static::lazy_static! {
            static ref SYNTAX_SET: SyntaxSet = {
                let set = SyntaxSet::load_defaults_newlines();
                let mut builder = set.into_builder();
                // add extra language syntax files
                builder.add_from_folder("gen/syntax", true).unwrap();
                builder.build()
            };
            static ref THEME_SET: ThemeSet = ThemeSet::load_defaults();
        }

        let language = match language {
            Some("elisp") | Some("emacs-lisp") => Some("lisp"),
            _ => language,
        };
        let mut highlighter = HighlightLines::new(
            language
                .and_then(|lang| SYNTAX_SET.find_syntax_by_token(lang))
                .unwrap_or_else(|| SYNTAX_SET.find_syntax_plain_text()),
            &THEME_SET.themes["InspiredGitHub"],
        );
        let regions = highlighter.highlight(content, &SYNTAX_SET);
        styled_line_to_highlighted_html(&regions[..], IncludeBackground::No)
    }
}

impl HtmlHandler<Error> for SolomonBaseHandler {
    fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<()> {
        match element {
            Element::InlineSrc(inline_src) => write!(
                w,
                "{}",
                self.highlight(Some(&inline_src.lang), &inline_src.body)
            )?,
            Element::SourceBlock(block) => {
                if block.language.is_empty() {
                    write!(w, "
{}
", block.contents)?;
                } else {
                    write!(
                        w,
                        "
{}
",
                        self.highlight(Some(&block.language), &block.contents)
                    )?
                }
            }
            Element::FixedWidth { value } => {
                write!(w, "
{}
", self.highlight(None, value))?
            }
            Element::ExampleBlock(block) => write!(
                w,
                "
{}
",
                self.highlight(None, &block.contents)
            )?,
            Element::Macros(macros) => match &macros.name as &str {
                "age-days" => {
                    write!(w, " {:.} ", (Utc::now().timestamp() - 1382071200) / 86400)?;
                }
                "angular-core-version" => {
                    write_nodejs_package_version(w, "@angular/core")?;
                }
                "angular-material-version" => {
                    write_nodejs_package_version(w, "@angular/material")?;
                }
                "angular-cli-version" => {
                    write_nodejs_package_version(w, "@angular/cli")?;
                }
                _ => (),
            },
            Element::Link(link) => {
                if let Some(desc) = &link.desc {
                    write!(
                        w,
                        r#"{}"#,
                        Escape(&link.path),
                        Escape(desc)
                    )?;
                } else {
                    write!(w, r#"{0}"#, Escape(&link.path))?;
                }
            }
            _ => self.0.start(w, element)?,
        }
        Ok(())
    }
}

pub struct SolomonHtmlHandler(SolomonBaseHandler);

impl Default for SolomonHtmlHandler {
    fn default() -> Self {
        SolomonHtmlHandler(SolomonBaseHandler(DefaultHtmlHandler))
    }
}

impl HtmlHandler<Error> for SolomonHtmlHandler {
    fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<()> {
        if let Element::Link(link) = element {
            let url = Url::parse(&link.path)?;
            if url.scheme() == "file" {
                let size = size(PathBuf::from(r"content/post").join(&url.path()[1..]))?;

                write!(
                    w,
                    "
\

\

",
                    url.path(),
                    (size.height as f32 / size.width as f32) * 100.
                )?;
            } else {
                self.0.start(w, element)?;
            }

            Ok(())
        } else {
            self.0.start(w, element)
        }
    }
}

pub struct SolomonRssHandler(SolomonBaseHandler);

impl Default for SolomonRssHandler {
    fn default() -> Self {
        SolomonRssHandler(SolomonBaseHandler(DefaultHtmlHandler))
    }
}

impl HtmlHandler<Error> for SolomonRssHandler {
    fn start<W: Write>(&mut self, mut w: W, element: &Element<'_>) -> Result<()> {
        if let Element::Link(link) = element {
            let url = Url::parse(&link.path)?;
            if url.scheme() == "file" {
                let size = size(PathBuf::from(r"content/post").join(&url.path()[1..]))?;

                write!(
                    w,
                    r#""#,
                    url.path(),
                    size.width,
                    size.height
                )?;
            } else {
                self.0.start(w, element)?;
            }
        } else {
            self.0.start(w, element)?;
        }

        Ok(())
    }
}

fn write_nodejs_package_version<W: Write>(mut w: W, package: &str) -> Result<()> {
    write!(w, "")?;

    let output = Command::new("yarn")
        .args(&["--cwd", "web", "--silent", "list", "--pattern", package])
        .output()?;

    let output = String::from_utf8(output.stdout)?;

    if let Some(version) = output.trim().split_whitespace().last() {
        write!(w, "{}", version)?;
    }

    write!(w, "")?;

    Ok(())
}

// fn should_insert_space(c1: char, c2: char) -> bool {
//     const CHINESE_PUNCTUATION: [char; 14] = [
//         '。', '？', '，', '、', '；', '：', '“', '”', '「', '」', '（', '）', '《', '》',
//     ];

//     (c1.is_ascii_graphic() && c2.is_ascii_graphic())
//         || (c1.is_ascii_graphic()
//             && 0x4E00 < (c2 as u32)
//             && (c2 as u32) < 0x9FFF
//             && !CHINESE_PUNCTUATION.contains(&c2))
//         || (c2.is_ascii_graphic()
//             && 0x4E00 < (c1 as u32)
//             && (c1 as u32) < 0x9FFF
//             && !CHINESE_PUNCTUATION.contains(&c1))
// }
<|endoftext|>


<commit_before>#[macro_use]
extern crate perl_xs;
#[macro_use]
extern crate perl_sys;

use perl_xs::{ SV, AV, IV, NV };

xs! {
    package XSBench::RS;

    sub rs_sum_loop(ctx) {
        let param: SV = ctx.st_fetch(0);
        let array: AV = param.deref_av().expect("not an array ref");
        let mut sum = 0.0;
        for i in 0..array.top_index() + 1 {
            if let Some(val) = array.fetch(i) {
                sum += val;
            }
        }
        xs_return!(ctx, sum);
    }

    sub rs_sum_iter(ctx) {
        let param: SV = ctx.st_fetch(0);
        let array: AV = param.deref_av().expect("not an array ref");
        let sum: NV = array.iter().map(|v| v.unwrap_or(0.0)).sum();
        xs_return!(ctx, sum);
    }

    sub rs_gcd(ctx) {
        let mut a = ctx.st_fetch::<IV>(0);
        let mut b = ctx.st_fetch::<IV>(1);
        while b > 0 {
            let t = a;
            a = b;
            b = t % b;
        }

        let res = if a < 0 {
            -a
        } else {
            a
        };

        xs_return!(ctx, res);
    }
}

xs! {
    bootstrap boot_XSBench__RS;
    use self;
}
<commit_msg>Update benchmarks to use signatures.<commit_after>#[macro_use]
extern crate perl_xs;
#[macro_use]
extern crate perl_sys;

use perl_xs::{ SV, AV, IV, NV };

xs! {
    package XSBench::RS;

    sub rs_sum_loop(ctx, param: SV) {
        let array: AV = param.deref_av().expect("not an array ref");
        let mut sum = 0.0;
        for i in 0..array.top_index() + 1 {
            if let Some(val) = array.fetch(i) {
                sum += val;
            }
        }
        xs_return!(ctx, sum);
    }

    sub rs_sum_iter(ctx, param: SV) {
        let array: AV = param.deref_av().expect("not an array ref");
        let sum: NV = array.iter().map(|v| v.unwrap_or(0.0)).sum();
        xs_return!(ctx, sum);
    }

    sub rs_gcd(ctx, a: IV, b: IV) {
        let mut a = a;
        let mut b = b;
        while b > 0 {
            let t = a;
            a = b;
            b = t % b;
        }

        let res = if a < 0 {
            -a
        } else {
            a
        };

        xs_return!(ctx, res);
    }
}

xs! {
    bootstrap boot_XSBench__RS;
    use self;
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate identicon;
extern crate openssl;
extern crate test;

use openssl::crypto::hash::{hash, Type};
use test::Bencher;

use identicon::Identicon;

#[bench]
fn generate(x: &mut Bencher) {
    let source = "42".to_string();
    let input = source.as_bytes();

    x.iter(|| {
        let bytes = hash(Type::MD5, input);
        Identicon::new(&bytes[..]).image();
    });
}
<commit_msg>Update digest usage in benchmark<commit_after>#![feature(test)]

extern crate identicon;
extern crate openssl;
extern crate test;

use openssl::hash::{hash2, MessageDigest};
use test::Bencher;

use identicon::Identicon;

#[bench]
fn generate(x: &mut Bencher) {
    let input = "42".as_bytes();
    let md5 = MessageDigest::md5();

    x.iter(|| match hash2(md5, input) {
        Ok(bytes) => Identicon::new(&bytes).image(),
        Err(e) => panic!(e),
    });
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate identicon;
extern crate openssl;
extern crate test;

use openssl::hash::{hash2, MessageDigest};
use test::Bencher;

use identicon::Identicon;

#[bench]
fn generate(x: &mut Bencher) {
    let input = "42".as_bytes();
    let md5 = MessageDigest::md5();

    x.iter(|| match hash2(md5, input) {
        Ok(bytes) => Identicon::new(&bytes).image(),
        Err(e) => panic!(e),
    });
}
<commit_msg>Benchmark image generation in isolation<commit_after>#![feature(test)]

extern crate identicon;
extern crate openssl;
extern crate test;

use openssl::hash::{hash2, MessageDigest};
use test::Bencher;

use identicon::Identicon;

#[bench]
fn generate(x: &mut Bencher) {
    let input = "42".as_bytes();
    let md5 = MessageDigest::md5();
    let bytes = hash2(md5, input).unwrap();
    let identicon = Identicon::new(&bytes);
    x.iter(|| identicon.image());
}
<|endoftext|>


<commit_before>extern crate bindgen;

fn sdk_path(target: &str) -> Result<String, std::io::Error> {
    // Use environment variable if set
    println!("cargo:rerun-if-env-changed=COREAUDIO_SDK_PATH");
    if let Ok(path) = std::env::var("COREAUDIO_SDK_PATH") {
        return Ok(path);
    }

    use std::process::Command;

    let sdk = if target.contains("apple-darwin") {
        "macosx"
    } else if target.contains("apple-ios") {
        "iphoneos"
    } else {
        unreachable!();
    };
    let output = Command::new("xcrun")
        .args(&["--sdk", sdk, "--show-sdk-path"])
        .output()?
        .stdout;
    let prefix_str = std::str::from_utf8(&output).expect("invalid output from `xcrun`");
    Ok(prefix_str.trim_end().to_string())
}

fn build(sdk_path: &str, target: &str) {
    // Generate one large set of bindings for all frameworks.
    //
    // We do this rather than generating a module per framework as some frameworks depend on other
    // frameworks and in turn share types. To ensure all types are compatible across each
    // framework, we feed all headers to bindgen at once.
    //
    // Only link to each framework and include their headers if their features are enabled and they
    // are available on the target os.

    use std::env;
    use std::path::PathBuf;

    let mut headers = vec![];

    #[cfg(feature = "audio_toolbox")]
    {
        println!("cargo:rustc-link-lib=framework=AudioToolbox");
        headers.push("AudioToolbox/AudioToolbox.h");
    }

    #[cfg(feature = "audio_unit")]
    {
        println!("cargo:rustc-link-lib=framework=AudioUnit");
        headers.push("AudioUnit/AudioUnit.h");
    }

    #[cfg(feature = "core_audio")]
    {
        println!("cargo:rustc-link-lib=framework=CoreAudio");
        headers.push("CoreAudio/CoreAudio.h");
    }

    #[cfg(feature = "open_al")]
    {
        println!("cargo:rustc-link-lib=framework=OpenAL");
        headers.push("OpenAL/al.h");
        headers.push("OpenAL/alc.h");
    }

    #[cfg(all(feature = "core_midi"))]
    {
        if target.contains("apple-darwin") {
            println!("cargo:rustc-link-lib=framework=CoreMIDI");
            headers.push("CoreMIDI/CoreMIDI.h");
        }
    }

    println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS");
    // Get the cargo out directory.
    let out_dir = PathBuf::from(env::var("OUT_DIR").expect("env variable OUT_DIR not found"));

    // Begin building the bindgen params.
    let mut builder = bindgen::Builder::default();

    builder = builder.clang_args(&[&format!("--target={}", target), "-isysroot", sdk_path]);

    let meta_header: Vec<_> = headers
        .iter()
        .map(|h| format!("#include <{}>\n", h))
        .collect();

    builder = builder.header_contents("coreaudio.h", &meta_header.concat());

    // Generate the bindings.
    builder = builder
        .trust_clang_mangling(false)
        .derive_default(true);

    let bindings = builder.generate().expect("unable to generate bindings");

    // Write them to the crate root.
    bindings
        .write_to_file(out_dir.join("coreaudio.rs"))
        .expect("could not write bindings");
}

fn main() {
    let target = std::env::var("TARGET").unwrap();
    if !(target.contains("apple-darwin") || target.contains("apple-ios")) {
        panic!("coreaudio-sys requires macos or ios target");
    }

    if let Ok(directory) = sdk_path(&target) {
        build(&directory, &target);
    } else {
        panic!("coreaudio-sys could not find an appropriate SDK");
    }
}
<commit_msg>Allow the SDK not to be found by the build script<commit_after>extern crate bindgen;

fn sdk_path(target: &str) -> Result<String, std::io::Error> {
    // Use environment variable if set
    println!("cargo:rerun-if-env-changed=COREAUDIO_SDK_PATH");
    if let Ok(path) = std::env::var("COREAUDIO_SDK_PATH") {
        return Ok(path);
    }

    use std::process::Command;

    let sdk = if target.contains("apple-darwin") {
        "macosx"
    } else if target.contains("apple-ios") {
        "iphoneos"
    } else {
        unreachable!();
    };
    let output = Command::new("xcrun")
        .args(&["--sdk", sdk, "--show-sdk-path"])
        .output()?
        .stdout;
    let prefix_str = std::str::from_utf8(&output).expect("invalid output from `xcrun`");
    Ok(prefix_str.trim_end().to_string())
}

fn build(sdk_path: Option<&str>, target: &str) {
    // Generate one large set of bindings for all frameworks.
    //
    // We do this rather than generating a module per framework as some frameworks depend on other
    // frameworks and in turn share types. To ensure all types are compatible across each
    // framework, we feed all headers to bindgen at once.
    //
    // Only link to each framework and include their headers if their features are enabled and they
    // are available on the target os.

    use std::env;
    use std::path::PathBuf;

    let mut headers = vec![];

    #[cfg(feature = "audio_toolbox")]
    {
        println!("cargo:rustc-link-lib=framework=AudioToolbox");
        headers.push("AudioToolbox/AudioToolbox.h");
    }

    #[cfg(feature = "audio_unit")]
    {
        println!("cargo:rustc-link-lib=framework=AudioUnit");
        headers.push("AudioUnit/AudioUnit.h");
    }

    #[cfg(feature = "core_audio")]
    {
        println!("cargo:rustc-link-lib=framework=CoreAudio");
        headers.push("CoreAudio/CoreAudio.h");
    }

    #[cfg(feature = "open_al")]
    {
        println!("cargo:rustc-link-lib=framework=OpenAL");
        headers.push("OpenAL/al.h");
        headers.push("OpenAL/alc.h");
    }

    #[cfg(all(feature = "core_midi"))]
    {
        if target.contains("apple-darwin") {
            println!("cargo:rustc-link-lib=framework=CoreMIDI");
            headers.push("CoreMIDI/CoreMIDI.h");
        }
    }

    println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS");
    // Get the cargo out directory.
    let out_dir = PathBuf::from(env::var("OUT_DIR").expect("env variable OUT_DIR not found"));

    // Begin building the bindgen params.
    let mut builder = bindgen::Builder::default();

    builder = builder.clang_args(&[&format!("--target={}", target)]);

    if let Some(sdk_path) = sdk_path {
        builder = builder.clang_args(&["-isysroot", sdk_path]);
    }

    let meta_header: Vec<_> = headers
        .iter()
        .map(|h| format!("#include <{}>\n", h))
        .collect();

    builder = builder.header_contents("coreaudio.h", &meta_header.concat());

    // Generate the bindings.
    builder = builder
        .trust_clang_mangling(false)
        .derive_default(true);

    let bindings = builder.generate().expect("unable to generate bindings");

    // Write them to the crate root.
    bindings
        .write_to_file(out_dir.join("coreaudio.rs"))
        .expect("could not write bindings");
}

fn main() {
    let target = std::env::var("TARGET").unwrap();
    if !(target.contains("apple-darwin") || target.contains("apple-ios")) {
        panic!("coreaudio-sys requires macos or ios target");
    }

    let directory = sdk_path(&target).ok();
    build(directory.as_ref().map(String::as_ref), &target);
}
<|endoftext|>


<commit_before>fn main() {
  // libpq-dev libpq5
  println! ("cargo:rustc-link-lib=pq");
}
<commit_msg>Giving cargo the library path (Debian).<commit_after>fn main() {  // cf. http://doc.crates.io/build-script.html
  // libpq-dev libpq5
  // println! ("cargo:rustc-link-lib=pq");
  println! ("cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu");}
<|endoftext|>


<commit_before>extern crate gcc;

fn main() {
    let litend = if cfg!(target_endian = "little") {
        "1"
    } else {
        "0"
    };
    gcc::Config::new()
        .include("decNumber")
        .file("decNumber/decContext.c")
        .file("decNumber/decDouble.c")
        .file("decNumber/decNumber.c")
        .file("decNumber/decPacked.c")
        .file("decNumber/decQuad.c")
        .file("decNumber/decSingle.c")
        .file("decNumber/decimal128.c")
        .file("decNumber/decimal32.c")
        .file("decNumber/decimal64.c")
        .define("DECNUMDIGITS", Some("34"))
        .define("DECLITEND", Some(litend))
        .compile("libdecNumber.a");
}
<commit_msg>Remove bad defined and useless file from c library.<commit_after>extern crate gcc;

fn main() {
    let litend = if cfg!(target_endian = "little") {
        "1"
    } else {
        "0"
    };
    gcc::Config::new()
        .include("decNumber")
        .file("decNumber/decContext.c")
        .file("decNumber/decDouble.c")
        .file("decNumber/decNumber.c")
        .file("decNumber/decPacked.c")
        .file("decNumber/decQuad.c")
        .file("decNumber/decSingle.c")
        .file("decNumber/decimal128.c")
        .file("decNumber/decimal64.c") // for conversion tables
        .define("DECLITEND", Some(litend))
        .compile("libdecNumber.a");
}
<|endoftext|>


<commit_before>use std::env::var;
use std::io::{self, Write};
use std::fs::{DirEntry, File, read_dir};
use std::path::{Path, PathBuf};
use std::process::exit;

fn main() {
  let out_dir = var("OUT_DIR").unwrap();
  let path = Path::new(&out_dir).join("resources.rs");

  if path.exists() {
    exit(0);
  }

  let mut manifest = File::create(path).unwrap();
  let mut resources: Vec<PathBuf> = Vec::new();

  visit_dirs("spectra/data", &mut |entry| {
    resources.push(Path::new("../..").join(entry.path()));
  }).unwrap();

  write!(&mut manifest, "use std::path::PathBuf;\n").unwrap();
  write!(&mut manifest, "pub fn get_resources() -> Vec<(PathBuf, &'static [u8])> {{\n").unwrap();
  write!(&mut manifest, "  let mut resources = Vec::new();\n").unwrap();

  for entry in &resources {
    println!("cargo:warning=packing up resource {:?}", entry);
    write!(&mut manifest, "  resources.push((PathBuf::from(&{0:?}[13..]), include_bytes!({0:?}).as_ref()));\n", entry).unwrap();
  }

  write!(&mut manifest, "  resources\n").unwrap();
  write!(&mut manifest, "}}").unwrap(); // get_resources
}

fn visit_dirs<P, F>(dir: P, visitor: &mut F) -> io::Result<()> where P: AsRef<Path>, F: FnMut(&DirEntry) {
  let dir = dir.as_ref();

  if dir.is_dir() {
    for entry in read_dir(dir)? {
      let entry = entry?;
      let path = entry.path();

      if path.is_dir() {
        visit_dirs(path, visitor).unwrap();
      } else {
        visitor(&entry);
      }
    }
  }

  Ok(())
}
<commit_msg>Fixed spectra bin.<commit_after>use std::env::var;
use std::io::{self, Write};
use std::fs::{DirEntry, File, read_dir};
use std::path::{Path, PathBuf};
use std::process::exit;

fn main() {
  let out_dir = var("OUT_DIR").unwrap();
  let path = Path::new(&out_dir).join("resources.rs");

  if path.exists() {
    exit(0);
  }

  let mut manifest = File::create(path).unwrap();
  let mut resources: Vec<PathBuf> = Vec::new();

  visit_dirs("spectra/data", &mut |entry| {
    resources.push(Path::new("../..").join(entry.path()));
  }).unwrap();

  write!(&mut manifest, "use std::path::PathBuf;\n").unwrap();
  write!(&mut manifest, "pub fn get_resources() -> Vec<(PathBuf, &'static [u8])> {{\n").unwrap();
  write!(&mut manifest, "  let mut resources = Vec::new();\n").unwrap();

  for entry in &resources {
    println!("cargo:warning=packing up resource {:?}", entry);
    write!(&mut manifest, "  resources.push((PathBuf::from(&{0:?}[14..]), include_bytes!({0:?}).as_ref()));\n", entry).unwrap();
  }

  write!(&mut manifest, "  resources\n").unwrap();
  write!(&mut manifest, "}}").unwrap(); // get_resources
}

fn visit_dirs<P, F>(dir: P, visitor: &mut F) -> io::Result<()> where P: AsRef<Path>, F: FnMut(&DirEntry) {
  let dir = dir.as_ref();

  if dir.is_dir() {
    for entry in read_dir(dir)? {
      let entry = entry?;
      let path = entry.path();

      if path.is_dir() {
        visit_dirs(path, visitor).unwrap();
      } else {
        visitor(&entry);
      }
    }
  }

  Ok(())
}
<|endoftext|>


<commit_before>/*!

# Supported types

| Rust Type               | JSON Serialization     | Notes                                     |
|-------------------------|------------------------|-------------------------------------------|
| `DateTime<FixedOffset>` | RFC3339 string         |                                           |
| `DateTime<Utc>`         | RFC3339 string         |                                           |
| `NaiveDate`             | RFC3339 string         |                                           |
| `NaiveDateTime`         | float (unix timestamp) | JSON numbers (i.e. IEEE doubles) are not  |
|                         |                        | precise enough for nanoseconds.           |
|                         |                        | Values will be truncated to microsecond   |
|                         |                        | resolution.                               |

*/
use chrono::prelude::*;

use ::Value;

#[doc(hidden)]
pub static RFC3339_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%z";

graphql_scalar!(DateTime<FixedOffset> {
    description: "DateTime"

    resolve(&self) -> Value {
        Value::string(self.to_rfc3339())
    }

    from_input_value(v: &InputValue) -> Option<DateTime<FixedOffset>> {
        v.as_string_value()
         .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
    }
});

graphql_scalar!(DateTime<Utc> {
    description: "DateTime"

    resolve(&self) -> Value {
        Value::string(self.to_rfc3339())
    }

    from_input_value(v: &InputValue) -> Option<DateTime<Utc>> {
        v.as_string_value()
         .and_then(|s| (s.parse::<DateTime<Utc>>().ok()))
    }
});

// Don't use `Date` as the docs say:
// "[Date] should be considered ambiguous at best, due to the "
// inherent lack of precision required for the time zone resolution.
// For serialization and deserialization uses, it is best to use
// `NaiveDate` instead."
graphql_scalar!(NaiveDate {
    description: "NaiveDate"

    resolve(&self) -> Value {
        Value::string(self.format(RFC3339_FORMAT).to_string())
    }

    from_input_value(v: &InputValue) -> Option<NaiveDate> {
        v.as_string_value()
         .and_then(|s| NaiveDate::parse_from_str(s, RFC3339_FORMAT).ok())
    }
});

/// JSON numbers (i.e. IEEE doubles) are not precise enough for nanosecond
/// datetimes. Values will be truncated to microsecond resolution.
graphql_scalar!(NaiveDateTime {
    description: "NaiveDateTime"

    resolve(&self) -> Value {
        Value::float(self.timestamp() as f64)
    }

    from_input_value(v: &InputValue) -> Option<NaiveDateTime> {
        v.as_float_value()
         .and_then(|f| NaiveDateTime::from_timestamp_opt(f as i64, 0))
    }
});

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

    #[test]
    fn datetime_fixedoffset_from_input_value() {
        let raw = "2014-11-28T21:00:09+09:00";
        let input = ::InputValue::String(raw.to_string());

        let parsed: DateTime<FixedOffset> = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = DateTime::parse_from_rfc3339(raw).unwrap();

        assert_eq!(parsed, expected);
    }

    #[test]
    fn datetime_utc_from_input_value() {
        let raw = "2014-11-28T21:00:09+09:00";
        let input = ::InputValue::String(raw.to_string());

        let parsed: DateTime<Utc> = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = DateTime::parse_from_rfc3339(raw).unwrap().with_timezone(&Utc);

        assert_eq!(parsed, expected);
    }

    #[test]
    fn naivedate_from_input_value() {
        let raw = "1996-12-19T16:39:57-08:00";
        let input = ::InputValue::String(raw.to_string());

        let parsed: NaiveDate = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = NaiveDate::parse_from_str(raw, &RFC3339_FORMAT).unwrap();
        let expected_via_datetime = DateTime::parse_from_rfc3339(raw).unwrap().date().naive_utc();
        let expected_via_ymd = NaiveDate::from_ymd(1996, 12, 19);

        assert_eq!(parsed, expected);
        assert_eq!(parsed, expected_via_datetime);
        assert_eq!(parsed, expected_via_ymd);

        assert_eq!(parsed.year(), 1996);
        assert_eq!(parsed.month(), 12);
        assert_eq!(parsed.day(), 19);
    }

    #[test]
    fn naivedatetime_from_input_value() {
        let raw = 1_000_000_000_f64;
        let input = ::InputValue::Float(raw);

        let parsed: NaiveDateTime = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = NaiveDateTime::from_timestamp_opt(raw as i64, 0).unwrap();

        assert_eq!(parsed, expected);
        assert_eq!(raw, expected.timestamp() as f64);

    }
}
<commit_msg>Give DateTime scalars valid names to pass validation<commit_after>/*!

# Supported types

| Rust Type               | JSON Serialization     | Notes                                     |
|-------------------------|------------------------|-------------------------------------------|
| `DateTime<FixedOffset>` | RFC3339 string         |                                           |
| `DateTime<Utc>`         | RFC3339 string         |                                           |
| `NaiveDate`             | RFC3339 string         |                                           |
| `NaiveDateTime`         | float (unix timestamp) | JSON numbers (i.e. IEEE doubles) are not  |
|                         |                        | precise enough for nanoseconds.           |
|                         |                        | Values will be truncated to microsecond   |
|                         |                        | resolution.                               |

*/
use chrono::prelude::*;

use ::Value;

#[doc(hidden)]
pub static RFC3339_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%z";

graphql_scalar!(DateTime<FixedOffset> as "DateTimeFixedOffset" {
    description: "DateTime"

    resolve(&self) -> Value {
        Value::string(self.to_rfc3339())
    }

    from_input_value(v: &InputValue) -> Option<DateTime<FixedOffset>> {
        v.as_string_value()
         .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
    }
});

graphql_scalar!(DateTime<Utc> as "DateTimeUtc" {
    description: "DateTime"

    resolve(&self) -> Value {
        Value::string(self.to_rfc3339())
    }

    from_input_value(v: &InputValue) -> Option<DateTime<Utc>> {
        v.as_string_value()
         .and_then(|s| (s.parse::<DateTime<Utc>>().ok()))
    }
});

// Don't use `Date` as the docs say:
// "[Date] should be considered ambiguous at best, due to the "
// inherent lack of precision required for the time zone resolution.
// For serialization and deserialization uses, it is best to use
// `NaiveDate` instead."
graphql_scalar!(NaiveDate {
    description: "NaiveDate"

    resolve(&self) -> Value {
        Value::string(self.format(RFC3339_FORMAT).to_string())
    }

    from_input_value(v: &InputValue) -> Option<NaiveDate> {
        v.as_string_value()
         .and_then(|s| NaiveDate::parse_from_str(s, RFC3339_FORMAT).ok())
    }
});

/// JSON numbers (i.e. IEEE doubles) are not precise enough for nanosecond
/// datetimes. Values will be truncated to microsecond resolution.
graphql_scalar!(NaiveDateTime {
    description: "NaiveDateTime"

    resolve(&self) -> Value {
        Value::float(self.timestamp() as f64)
    }

    from_input_value(v: &InputValue) -> Option<NaiveDateTime> {
        v.as_float_value()
         .and_then(|f| NaiveDateTime::from_timestamp_opt(f as i64, 0))
    }
});

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

    #[test]
    fn datetime_fixedoffset_from_input_value() {
        let raw = "2014-11-28T21:00:09+09:00";
        let input = ::InputValue::String(raw.to_string());

        let parsed: DateTime<FixedOffset> = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = DateTime::parse_from_rfc3339(raw).unwrap();

        assert_eq!(parsed, expected);
    }

    #[test]
    fn datetime_utc_from_input_value() {
        let raw = "2014-11-28T21:00:09+09:00";
        let input = ::InputValue::String(raw.to_string());

        let parsed: DateTime<Utc> = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = DateTime::parse_from_rfc3339(raw).unwrap().with_timezone(&Utc);

        assert_eq!(parsed, expected);
    }

    #[test]
    fn naivedate_from_input_value() {
        let raw = "1996-12-19T16:39:57-08:00";
        let input = ::InputValue::String(raw.to_string());

        let parsed: NaiveDate = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = NaiveDate::parse_from_str(raw, &RFC3339_FORMAT).unwrap();
        let expected_via_datetime = DateTime::parse_from_rfc3339(raw).unwrap().date().naive_utc();
        let expected_via_ymd = NaiveDate::from_ymd(1996, 12, 19);

        assert_eq!(parsed, expected);
        assert_eq!(parsed, expected_via_datetime);
        assert_eq!(parsed, expected_via_ymd);

        assert_eq!(parsed.year(), 1996);
        assert_eq!(parsed.month(), 12);
        assert_eq!(parsed.day(), 19);
    }

    #[test]
    fn naivedatetime_from_input_value() {
        let raw = 1_000_000_000_f64;
        let input = ::InputValue::Float(raw);

        let parsed: NaiveDateTime = ::FromInputValue::from_input_value(&input).unwrap();
        let expected = NaiveDateTime::from_timestamp_opt(raw as i64, 0).unwrap();

        assert_eq!(parsed, expected);
        assert_eq!(raw, expected.timestamp() as f64);

    }
}
<|endoftext|>


<commit_before>use std::cmp::PartialEq;
use std::cmp::PartialOrd;
use std::fmt::Display;
use std::clone::Clone;

#[cfg(feature = "inclusive_range")]
use std::ops::RangeInclusive;

/// Enforce that a `String` is minimum `min` characters long.
pub fn min(min: usize) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if s.len() >= min {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must not contain less characters than %1.".to_string(),
                args: vec![min.to_string()],
            })
        }
    })
}

/// Enforce that a `String` is maximum `max` characters long.
pub fn max(max: usize) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if s.len() <= max {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must not contain more characters than %1.".to_string(),
                args: vec![max.to_string()],
            })
        }
    })
}

#[cfg(not(feature = "inclusive_range"))]
/// Enforce that a string is minimum `mi` and maximum `ma` characters long.
pub fn length(mi: usize, ma: usize) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        match (min(mi)(s), max(ma)(s)) {
            (Err(_), Err(_)) => {
                Err(::Invalid {
                    msg: "Must not be less characters than %1 and not more than %2.".to_string(),
                    args: vec![mi.to_string(), ma.to_string()],
                })
            }
            (Err(e), _) => Err(e),
            (_, Err(e)) => Err(e),
            (_, _) => Ok(()),
        }
    })
}

#[cfg(feature = "inclusive_range")]
/// Enforce that a string is minimum `mi` and maximum `ma` characters long.
pub fn length(range: RangeInclusive<usize>) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        match range {
            RangeInclusive::NonEmpty { ref start, ref end } => {
                match (min(*start)(s), max(*end)(s)) {
                    (Err(_), Err(_)) => {
                        Err(::Invalid {
                            msg: "Must not be less characters than %1 and not more than %2."
                                .to_string(),
                            args: vec![start.to_string(), end.to_string()],
                        })
                    }
                    (Err(e), _) => Err(e),
                    (_, Err(e)) => Err(e),
                    (_, _) => Ok(()),
                }
            }
            _ => panic!("range must be a RangeInclusive::NonEmpty"),
        }
    })
}

#[cfg(not(feature = "inclusive_range"))]
pub fn range<T: 'static + PartialOrd + Display + Clone>(a: T,
                                                        b: T)
                                                        -> Box<Fn(&T) -> ::ValidatorResult> {
    Box::new(move |s: &T| {
        if *s >= a && *s <= b {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must be in the range %1..%2.".to_string(),
                args: vec![a.to_string(), b.to_string()],
            })
        }
    })
}

#[cfg(feature = "inclusive_range")]
pub fn range<T: 'static + PartialOrd + Display + Clone>(range: RangeInclusive<T>)
                                                        -> Box<Fn(&T) -> ::ValidatorResult> {
    Box::new(move |s: &T| {
        match range {
            RangeInclusive::NonEmpty { ref start, ref end } => {
                if *s >= *start && *s <= *end {
                    Ok(())
                } else {
                    Err(::Invalid {
                        msg: "Must be in the range %1..%2.".to_string(),
                        args: vec![start.to_string(), end.to_string()],
                    })
                }
            }
            _ => panic!("range must be a RangeInclusive::NonEmpty"),
        }
    })
}

/// Enforce that a string must contain `needle`.
pub fn contains(needle: &'static str) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if s.contains(needle) {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must contain %1.".to_string(),
                args: vec![needle.to_string()],
            })
        }
    })
}

/// Enforce that a string must not contain `needle`.
pub fn not_contain(needle: &'static str) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if !s.contains(needle) {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must not contain %1.".to_string(),
                args: vec![needle.to_string()],
            })
        }
    })
}

/// Enforce that a string must not contain any of `needles`.
pub fn not_contain_any(needles: &'static [&'static str]) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        for needle in needles {
			if s.contains(needle) {
				return Err(::Invalid {
					msg: "Must not contain %1.".to_string(),
					args: vec![needle.to_string()],
				});
			}
		}
		Ok(())
    })
}

/// Enforce that `T` must equal `value`.
pub fn eq<T: 'static>(value: T) -> Box<Fn(&T) -> ::ValidatorResult>
    where T: PartialEq + Display
{
    Box::new(move |s: &T| {
        if *s == value {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Does not equal %1.".to_string(),
                args: vec![value.to_string()],
            })
        }
    })
}

/// Enforce that `T` equals any of the values in `values`.
pub fn either<T: 'static>(values: Vec<T>) -> Box<Fn(&T) -> ::ValidatorResult>
    where T: PartialEq + Display + Clone
{
    Box::new(move |s: &T| {
        let x = values.iter().find(|x| *x == s);
        let r = x.is_some();
        if r == true {
            Ok(())
        } else {
            let list = values.iter()
                .cloned()
                .fold(String::new(), |acc, v| format!("{}, {}", acc, v));
            Err(::Invalid {
                msg: "Must be one of %1.".to_string(),
                args: vec![list.to_string()],
            })
        }
    })
}

#[cfg(test)]
mod tests {
    use validators::{length, range};

    #[test]
    #[cfg(feature = "inclusive_range")]
    fn test_length() {
        assert!(length(3...5)(&"12".to_string()).is_err());
        assert!(length(3...5)(&"123".to_string()).is_ok());
        assert!(length(3...5)(&"1234".to_string()).is_ok());
        assert!(length(3...5)(&"12345".to_string()).is_ok());
        assert!(length(3...5)(&"123456".to_string()).is_err());
    }

    #[test]
    #[cfg(not(feature = "inclusive_range"))]
    fn test_length() {
        assert!(length(3, 5)(&"12".to_string()).is_err());
        assert!(length(3, 5)(&"123".to_string()).is_ok());
        assert!(length(3, 5)(&"1234".to_string()).is_ok());
        assert!(length(3, 5)(&"12345".to_string()).is_ok());
        assert!(length(3, 5)(&"123456".to_string()).is_err());
    }

    #[test]
    #[cfg(feature = "inclusive_range")]
    fn test_range() {
        assert!(range(12...127)(&11).is_err());
        assert!(range(12...127)(&12).is_ok());
        assert!(range(12...127)(&50).is_ok());
        assert!(range(12...127)(&127).is_ok());
        assert!(range(12...127)(&128).is_err());
    }

    #[test]
    #[cfg(not(feature = "inclusive_range"))]
    fn test_range() {
        assert!(range(12, 127)(&11).is_err());
        assert!(range(12, 127)(&12).is_ok());
        assert!(range(12, 127)(&50).is_ok());
        assert!(range(12, 127)(&127).is_ok());
        assert!(range(12, 127)(&128).is_err());
    }
}
<commit_msg>Added contains_only validator<commit_after>use std::cmp::PartialEq;
use std::cmp::PartialOrd;
use std::fmt::Display;
use std::clone::Clone;

#[cfg(feature = "inclusive_range")]
use std::ops::RangeInclusive;

/// Enforce that a `String` is minimum `min` characters long.
pub fn min(min: usize) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if s.len() >= min {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must not contain less characters than %1.".to_string(),
                args: vec![min.to_string()],
            })
        }
    })
}

/// Enforce that a `String` is maximum `max` characters long.
pub fn max(max: usize) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if s.len() <= max {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must not contain more characters than %1.".to_string(),
                args: vec![max.to_string()],
            })
        }
    })
}

#[cfg(not(feature = "inclusive_range"))]
/// Enforce that a string is minimum `mi` and maximum `ma` characters long.
pub fn length(mi: usize, ma: usize) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        match (min(mi)(s), max(ma)(s)) {
            (Err(_), Err(_)) => {
                Err(::Invalid {
                    msg: "Must not be less characters than %1 and not more than %2.".to_string(),
                    args: vec![mi.to_string(), ma.to_string()],
                })
            }
            (Err(e), _) => Err(e),
            (_, Err(e)) => Err(e),
            (_, _) => Ok(()),
        }
    })
}

#[cfg(feature = "inclusive_range")]
/// Enforce that a string is minimum `mi` and maximum `ma` characters long.
pub fn length(range: RangeInclusive<usize>) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        match range {
            RangeInclusive::NonEmpty { ref start, ref end } => {
                match (min(*start)(s), max(*end)(s)) {
                    (Err(_), Err(_)) => {
                        Err(::Invalid {
                            msg: "Must not be less characters than %1 and not more than %2."
                                .to_string(),
                            args: vec![start.to_string(), end.to_string()],
                        })
                    }
                    (Err(e), _) => Err(e),
                    (_, Err(e)) => Err(e),
                    (_, _) => Ok(()),
                }
            }
            _ => panic!("range must be a RangeInclusive::NonEmpty"),
        }
    })
}

#[cfg(not(feature = "inclusive_range"))]
pub fn range<T: 'static + PartialOrd + Display + Clone>(a: T,
                                                        b: T)
                                                        -> Box<Fn(&T) -> ::ValidatorResult> {
    Box::new(move |s: &T| {
        if *s >= a && *s <= b {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must be in the range %1..%2.".to_string(),
                args: vec![a.to_string(), b.to_string()],
            })
        }
    })
}

#[cfg(feature = "inclusive_range")]
pub fn range<T: 'static + PartialOrd + Display + Clone>(range: RangeInclusive<T>)
                                                        -> Box<Fn(&T) -> ::ValidatorResult> {
    Box::new(move |s: &T| {
        match range {
            RangeInclusive::NonEmpty { ref start, ref end } => {
                if *s >= *start && *s <= *end {
                    Ok(())
                } else {
                    Err(::Invalid {
                        msg: "Must be in the range %1..%2.".to_string(),
                        args: vec![start.to_string(), end.to_string()],
                    })
                }
            }
            _ => panic!("range must be a RangeInclusive::NonEmpty"),
        }
    })
}

/// Enforce that a string must contain `needle`.
pub fn contains(needle: &'static str) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if s.contains(needle) {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must contain %1.".to_string(),
                args: vec![needle.to_string()],
            })
        }
    })
}

/// Enforce that a string contains only characters in `accepted`
pub fn contain_only(accepted: &'static [char]) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        for c in s.chars() {
			if !accepted.contains(&c) {
				return Err(::Invalid {
					msg: "Must not contain %1.".to_string(),
					args: vec![c.to_string()],
				});
			}
		}
		Ok(())
    })
}

/// Enforce that a string must not contain `needle`.
pub fn not_contain(needle: &'static str) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        if !s.contains(needle) {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Must not contain %1.".to_string(),
                args: vec![needle.to_string()],
            })
        }
    })
}

/// Enforce that a string must not contain any of `needles`.
pub fn not_contain_any(needles: &'static [&'static str]) -> Box<Fn(&String) -> ::ValidatorResult> {
    Box::new(move |s: &String| {
        for needle in needles {
			if s.contains(needle) {
				return Err(::Invalid {
					msg: "Must not contain %1.".to_string(),
					args: vec![needle.to_string()],
				});
			}
		}
		Ok(())
    })
}

/// Enforce that `T` must equal `value`.
pub fn eq<T: 'static>(value: T) -> Box<Fn(&T) -> ::ValidatorResult>
    where T: PartialEq + Display
{
    Box::new(move |s: &T| {
        if *s == value {
            Ok(())
        } else {
            Err(::Invalid {
                msg: "Does not equal %1.".to_string(),
                args: vec![value.to_string()],
            })
        }
    })
}

/// Enforce that `T` equals any of the values in `values`.
pub fn either<T: 'static>(values: Vec<T>) -> Box<Fn(&T) -> ::ValidatorResult>
    where T: PartialEq + Display + Clone
{
    Box::new(move |s: &T| {
        let x = values.iter().find(|x| *x == s);
        let r = x.is_some();
        if r == true {
            Ok(())
        } else {
            let list = values.iter()
                .cloned()
                .fold(String::new(), |acc, v| format!("{}, {}", acc, v));
            Err(::Invalid {
                msg: "Must be one of %1.".to_string(),
                args: vec![list.to_string()],
            })
        }
    })
}

#[cfg(test)]
mod tests {
    use validators::{length, range};

    #[test]
    #[cfg(feature = "inclusive_range")]
    fn test_length() {
        assert!(length(3...5)(&"12".to_string()).is_err());
        assert!(length(3...5)(&"123".to_string()).is_ok());
        assert!(length(3...5)(&"1234".to_string()).is_ok());
        assert!(length(3...5)(&"12345".to_string()).is_ok());
        assert!(length(3...5)(&"123456".to_string()).is_err());
    }

    #[test]
    #[cfg(not(feature = "inclusive_range"))]
    fn test_length() {
        assert!(length(3, 5)(&"12".to_string()).is_err());
        assert!(length(3, 5)(&"123".to_string()).is_ok());
        assert!(length(3, 5)(&"1234".to_string()).is_ok());
        assert!(length(3, 5)(&"12345".to_string()).is_ok());
        assert!(length(3, 5)(&"123456".to_string()).is_err());
    }

    #[test]
    #[cfg(feature = "inclusive_range")]
    fn test_range() {
        assert!(range(12...127)(&11).is_err());
        assert!(range(12...127)(&12).is_ok());
        assert!(range(12...127)(&50).is_ok());
        assert!(range(12...127)(&127).is_ok());
        assert!(range(12...127)(&128).is_err());
    }

    #[test]
    #[cfg(not(feature = "inclusive_range"))]
    fn test_range() {
        assert!(range(12, 127)(&11).is_err());
        assert!(range(12, 127)(&12).is_ok());
        assert!(range(12, 127)(&50).is_ok());
        assert!(range(12, 127)(&127).is_ok());
        assert!(range(12, 127)(&128).is_err());
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use cgmath::{Vector2, Vector3, deg};
use glutin::{Window, WindowBuilder, VirtualKeyCode, Event};
use glutin::ElementState::{Pressed, Released};
use glutin::MouseButton::{LeftMouseButton};
use core_types::{Size2, ZInt, MapPos};
use visualizer_types::{
    ZFloat,
    Color3,
    Color4,
    ColorId,
    MatId,
    WorldPos,
    ScreenPos,
    VertexCoord,
};
use zgl::{Zgl};
use mesh::{Mesh};
use camera::Camera;
use shader::{Shader};
use geom;
use core_map::{MapPosIter};
use dir::{DirIter};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &Window) -> Size2<ZInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as ZInt, h: h as ZInt}
}

fn get_max_camera_pos(map_size: &Size2<ZInt>) -> WorldPos {
    let pos = geom::map_pos_to_world_pos(
        MapPos{v: Vector2{x: map_size.w, y: map_size.h - 1}});
    WorldPos{v: Vector3{x: -pos.v.x, y: -pos.v.y, z: 0.0}}
}

fn generate_mesh(map_size: &Size2<ZInt>, zgl: &Zgl) -> Mesh {
    let mut vertex_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom::map_pos_to_world_pos(tile_pos);
        for dir in DirIter::new() {
            let num = dir.to_int();
            let vertex = geom::index_to_hex_vertex(num);
            let next_vertex = geom::index_to_hex_vertex(num + 1);
            vertex_data.push(VertexCoord{v: pos.v + vertex.v});
            vertex_data.push(VertexCoord{v: pos.v + next_vertex.v});
            vertex_data.push(VertexCoord{v: pos.v});
        }
    }
    Mesh::new(zgl, vertex_data.as_slice())
}

pub struct Visualizer {
    zgl: Zgl,
    window: Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    shader: Shader,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
    mouse_pos: ScreenPos,
    is_lmb_pressed: bool,
    win_size: Size2<ZInt>,
    mesh: Mesh,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut zgl = Zgl::new(|s| window.get_proc_address(s));
        zgl.print_gl_info();
        let shader = Shader::new(&zgl, VS_SRC, FS_SRC);
        let color_uniform_location = shader.get_uniform_color(&zgl, "col");
        let mvp_uniform_location = shader.get_uniform_mat(&zgl, "mvp_mat");
        zgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        let mut camera = Camera::new(&win_size);
        let map_size = Size2{w: 5, h: 8};
        camera.set_max_pos(get_max_camera_pos(&map_size));
        let mesh = generate_mesh(&map_size, &zgl);
        Visualizer {
            zgl: zgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            shader: shader,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: camera,
            mouse_pos: ScreenPos{v: Vector2::from_value(0)},
            is_lmb_pressed: false,
            win_size: win_size,
            mesh: mesh,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_event_mouse_move(&mut self, pos: &ScreenPos) {
        if self.is_lmb_pressed {
            let diff = pos.v - self.mouse_pos.v;
            let win_w = self.win_size.w as ZFloat;
            let win_h = self.win_size.h as ZFloat;
            self.camera.add_horizontal_angle(
                deg(diff.x as ZFloat * (360.0 / win_w)));
            self.camera.add_vertical_angle(
                deg(diff.y as ZFloat * (360.0 / win_h)));
        }
        self.mouse_pos = pos.clone();
    }

    fn handle_event_key_press(&mut self, key: VirtualKeyCode) {
        match key {
            VirtualKeyCode::Q | VirtualKeyCode::Escape => {
                self.should_close = true;
            },
            VirtualKeyCode::W => self.camera.move_camera(deg(270.0), 0.1),
            VirtualKeyCode::S => self.camera.move_camera(deg(90.0), 0.1),
            VirtualKeyCode::D => self.camera.move_camera(deg(0.0), 0.1),
            VirtualKeyCode::A => self.camera.move_camera(deg(180.0), 0.1),
            VirtualKeyCode::Minus => self.camera.change_zoom(1.3),
            VirtualKeyCode::Equals => self.camera.change_zoom(0.7),
            _ => {},
        }
    }

    fn handle_event(&mut self, event: &Event) {
        match *event {
            Event::Closed => {
                self.should_close = true;
            },
            Event::Resized(w, h) => {
                self.win_size = Size2{w: w as ZInt, h: h as ZInt};
                self.zgl.set_viewport(&self.win_size);
            },
            Event::MouseMoved((x, y)) => {
                let pos = ScreenPos{v: Vector2{x: x as ZInt, y: y as ZInt}};
                self.handle_event_mouse_move(&pos);
            },
            Event::MouseInput(Pressed, LeftMouseButton) => {
                self.is_lmb_pressed = true;
            },
            Event::MouseInput(Released, LeftMouseButton) => {
                self.is_lmb_pressed = false;
                let (r, g, b, a) = self.zgl.read_pixel_bytes(
                    &self.win_size, &self.mouse_pos);
                println!("r: {}, g: {}, b: {}, a: {}", r, g, b, a);
            },
            Event::KeyboardInput(Released, _, Some(key)) => {
                self.handle_event_key_press(key);
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        // println!("{}", events);
        for event in events.iter() {
            self.handle_event(event);
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color.clone(),
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.zgl.clear_screen();
        self.shader.activate(&self.zgl);
        self.shader.set_uniform_color(
            &self.zgl, &self.color_uniform_location, &self.test_color);
        self.shader.set_uniform_mat4f(
            &self.zgl, &self.mvp_uniform_location, &self.camera.mat(&self.zgl));
        self.mesh.draw(&self.zgl, &self.shader);
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Visualizer: Added arrow keys handling<commit_after>// See LICENSE file for copyright and license details.

use cgmath::{Vector2, Vector3, deg};
use glutin::{Window, WindowBuilder, VirtualKeyCode, Event};
use glutin::ElementState::{Pressed, Released};
use glutin::MouseButton::{LeftMouseButton};
use core_types::{Size2, ZInt, MapPos};
use visualizer_types::{
    ZFloat,
    Color3,
    Color4,
    ColorId,
    MatId,
    WorldPos,
    ScreenPos,
    VertexCoord,
};
use zgl::{Zgl};
use mesh::{Mesh};
use camera::Camera;
use shader::{Shader};
use geom;
use core_map::{MapPosIter};
use dir::{DirIter};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &Window) -> Size2<ZInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as ZInt, h: h as ZInt}
}

fn get_max_camera_pos(map_size: &Size2<ZInt>) -> WorldPos {
    let pos = geom::map_pos_to_world_pos(
        MapPos{v: Vector2{x: map_size.w, y: map_size.h - 1}});
    WorldPos{v: Vector3{x: -pos.v.x, y: -pos.v.y, z: 0.0}}
}

fn generate_mesh(map_size: &Size2<ZInt>, zgl: &Zgl) -> Mesh {
    let mut vertex_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom::map_pos_to_world_pos(tile_pos);
        for dir in DirIter::new() {
            let num = dir.to_int();
            let vertex = geom::index_to_hex_vertex(num);
            let next_vertex = geom::index_to_hex_vertex(num + 1);
            vertex_data.push(VertexCoord{v: pos.v + vertex.v});
            vertex_data.push(VertexCoord{v: pos.v + next_vertex.v});
            vertex_data.push(VertexCoord{v: pos.v});
        }
    }
    Mesh::new(zgl, vertex_data.as_slice())
}

pub struct Visualizer {
    zgl: Zgl,
    window: Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    shader: Shader,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
    mouse_pos: ScreenPos,
    is_lmb_pressed: bool,
    win_size: Size2<ZInt>,
    mesh: Mesh,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut zgl = Zgl::new(|s| window.get_proc_address(s));
        zgl.print_gl_info();
        let shader = Shader::new(&zgl, VS_SRC, FS_SRC);
        let color_uniform_location = shader.get_uniform_color(&zgl, "col");
        let mvp_uniform_location = shader.get_uniform_mat(&zgl, "mvp_mat");
        zgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        let mut camera = Camera::new(&win_size);
        let map_size = Size2{w: 5, h: 8};
        camera.set_max_pos(get_max_camera_pos(&map_size));
        let mesh = generate_mesh(&map_size, &zgl);
        Visualizer {
            zgl: zgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            shader: shader,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: camera,
            mouse_pos: ScreenPos{v: Vector2::from_value(0)},
            is_lmb_pressed: false,
            win_size: win_size,
            mesh: mesh,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_event_mouse_move(&mut self, pos: &ScreenPos) {
        if self.is_lmb_pressed {
            let diff = pos.v - self.mouse_pos.v;
            let win_w = self.win_size.w as ZFloat;
            let win_h = self.win_size.h as ZFloat;
            self.camera.add_horizontal_angle(
                deg(diff.x as ZFloat * (360.0 / win_w)));
            self.camera.add_vertical_angle(
                deg(diff.y as ZFloat * (360.0 / win_h)));
        }
        self.mouse_pos = pos.clone();
    }

    fn handle_event_key_press(&mut self, key: VirtualKeyCode) {
        match key {
            VirtualKeyCode::Q | VirtualKeyCode::Escape => {
                self.should_close = true;
            },
            VirtualKeyCode::W | VirtualKeyCode::Up => {
                self.camera.move_camera(deg(270.0), 0.1);
            },
            VirtualKeyCode::S | VirtualKeyCode::Down => {
                self.camera.move_camera(deg(90.0), 0.1);
            },
            VirtualKeyCode::D | VirtualKeyCode::Right => {
                self.camera.move_camera(deg(0.0), 0.1);
            },
            VirtualKeyCode::A | VirtualKeyCode::Left => {
                self.camera.move_camera(deg(180.0), 0.1);
            },
            VirtualKeyCode::Minus => {
                self.camera.change_zoom(1.3);
            },
            VirtualKeyCode::Equals => {
                self.camera.change_zoom(0.7);
            },
            _ => {},
        }
    }

    fn handle_event(&mut self, event: &Event) {
        match *event {
            Event::Closed => {
                self.should_close = true;
            },
            Event::Resized(w, h) => {
                self.win_size = Size2{w: w as ZInt, h: h as ZInt};
                self.zgl.set_viewport(&self.win_size);
            },
            Event::MouseMoved((x, y)) => {
                let pos = ScreenPos{v: Vector2{x: x as ZInt, y: y as ZInt}};
                self.handle_event_mouse_move(&pos);
            },
            Event::MouseInput(Pressed, LeftMouseButton) => {
                self.is_lmb_pressed = true;
            },
            Event::MouseInput(Released, LeftMouseButton) => {
                self.is_lmb_pressed = false;
                let (r, g, b, a) = self.zgl.read_pixel_bytes(
                    &self.win_size, &self.mouse_pos);
                println!("r: {}, g: {}, b: {}, a: {}", r, g, b, a);
            },
            Event::KeyboardInput(Released, _, Some(key)) => {
                self.handle_event_key_press(key);
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        // println!("{}", events);
        for event in events.iter() {
            self.handle_event(event);
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color.clone(),
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.zgl.clear_screen();
        self.shader.activate(&self.zgl);
        self.shader.set_uniform_color(
            &self.zgl, &self.color_uniform_location, &self.test_color);
        self.shader.set_uniform_mat4f(
            &self.zgl, &self.mvp_uniform_location, &self.camera.mat(&self.zgl));
        self.mesh.draw(&self.zgl, &self.shader);
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;

struct Platform {
    id: cl_platform_id
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}

pub fn create_context(device: Device) -> Context {
    // TODO: Support for multiple devices
    let mut errcode = 0;

    // TODO: Proper error messages
    let ctx = clCreateContext(ptr::null(), 1, ptr::addr_of(&device.id),
                              ptr::null(), ptr::null(), ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create opencl context!";
    }

    Context { ctx: ctx };
}

struct CommandQueue {
    cqueue: cl_command_queue,

    drop {
        clReleaseCommandQueue(self.cqueue);
    }
}

pub fn create_commandqueue(ctx: Context, device: Device) -> CommandQueue {
    let mut errcode = 0;

    let cqueue = clCreateCommandQueue(ctx.ctx, device.id, 0, ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create command queue!";
    }

    CommandQueue { cqueue: cqueue };
}
<commit_msg>Fixed return void issue.<commit_after>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;

struct Platform {
    id: cl_platform_id
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}

pub fn create_context(device: Device) -> Context {
    // TODO: Support for multiple devices
    let mut errcode = 0;

    // TODO: Proper error messages
    let ctx = clCreateContext(ptr::null(), 1, ptr::addr_of(&device.id),
                              ptr::null(), ptr::null(), ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create opencl context!"
    }

    Context { ctx: ctx }
}

struct CommandQueue {
    cqueue: cl_command_queue,

    drop {
        clReleaseCommandQueue(self.cqueue);
    }
}

pub fn create_commandqueue(ctx: Context, device: Device) -> CommandQueue {
    let mut errcode = 0;

    let cqueue = clCreateCommandQueue(ctx.ctx, device.id, 0, ptr::addr_of(&errcode));

    if errcode != CL_SUCCESS {
        fail ~"Failed to create command queue!"
    }

    CommandQueue { cqueue: cqueue }
}
<|endoftext|>


<commit_before>use crate::convert::TryFrom;
use crate::ptr;
use crate::sync::atomic::{
    AtomicI8, AtomicUsize,
    Ordering::{Acquire, Relaxed, Release},
};
use crate::sys::{c, dur2timeout};
use crate::time::Duration;

pub struct Parker {
    state: AtomicI8,
}

const PARKED: i8 = -1;
const EMPTY: i8 = 0;
const NOTIFIED: i8 = 1;

// Notes about memory ordering:
//
// Memory ordering is only relevant for the relative ordering of operations
// between different variables. Even Ordering::Relaxed guarantees a
// monotonic/consistent order when looking at just a single atomic variable.
//
// So, since this parker is just a single atomic variable, we only need to look
// at the ordering guarantees we need to provide to the 'outside world'.
//
// The only memory ordering guarantee that parking and unparking provide, is
// that things which happened before unpark() are visible on the thread
// returning from park() afterwards. Otherwise, it was effectively unparked
// before unpark() was called while still consuming the 'token'.
//
// In other words, unpark() needs to synchronize with the part of park() that
// consumes the token and returns.
//
// This is done with a release-acquire synchronization, by using
// Ordering::Release when writing NOTIFIED (the 'token') in unpark(), and using
// Ordering::Acquire when checking for this state in park().
impl Parker {
    pub fn new() -> Self {
        Self { state: AtomicI8::new(EMPTY) }
    }

    // Assumes this is only called by the thread that owns the Parker,
    // which means that `self.state != PARKED`.
    pub unsafe fn park(&self) {
        // Change NOTIFIED=>EMPTY or EMPTY=>PARKED, and directly return in the
        // first case.
        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
            return;
        }

        if c::WaitOnAddress::is_available() {
            loop {
                // Wait for something to happen, assuming it's still set to PARKED.
                c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, c::INFINITE);
                // Change NOTIFIED=>EMPTY but leave PARKED alone.
                if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED {
                    // Actually woken up by unpark().
                    return;
                } else {
                    // Spurious wake up. We loop to try again.
                }
            }
        } else {
            // Wait for unpark() to produce this event.
            c::NtWaitForKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
            // Note that we don't just write EMPTY, but use swap() to also
            // include a acquire-ordered read to synchronize with unpark()'s
            // release-ordered write.
            self.state.swap(EMPTY, Acquire);
        }
    }

    // Assumes this is only called by the thread that owns the Parker,
    // which means that `self.state != PARKED`.
    pub unsafe fn park_timeout(&self, timeout: Duration) {
        // Change NOTIFIED=>EMPTY or EMPTY=>PARKED, and directly return in the
        // first case.
        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
            return;
        }

        if c::WaitOnAddress::is_available() {
            // Wait for something to happen, assuming it's still set to PARKED.
            c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, dur2timeout(timeout));
            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
            // Note that we don't just write EMPTY, but use swap() to also
            // include a acquire-ordered read to synchronize with unpark()'s
            // release-ordered write.
            if self.state.swap(EMPTY, Acquire) == NOTIFIED {
                // Actually woken up by unpark().
            } else {
                // Timeout or spurious wake up.
                // We return either way, because we can't easily tell if it was the
                // timeout or not.
            }
        } else {
            // Need to wait for unpark() using NtWaitForKeyedEvent.
            let handle = keyed_event_handle();

            // NtWaitForKeyedEvent uses a unit of 100ns, and uses negative values
            // to indicate the monotonic clock.
            let mut timeout = match i64::try_from((timeout.as_nanos() + 99) / 100) {
                Ok(t) => -t,
                Err(_) => i64::MIN,
            };

            // Wait for unpark() to produce this event.
            let unparked = c::NtWaitForKeyedEvent(handle, self.ptr(), 0, &mut timeout) == c::STATUS_SUCCESS;

            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
            let prev_state = self.state.swap(EMPTY, Acquire);

            if !unparked && prev_state == NOTIFIED {
                // We were awoken by a timeout, not by unpark(), but the state
                // was set to NOTIFIED, which means we *just* missed an
                // unpark(), which is now blocked on us to wait for it.
                // Wait for it to consume the event and unblock that thread.
                c::NtWaitForKeyedEvent(handle, self.ptr(), 0, ptr::null_mut());
            }
        }
    }

    pub fn unpark(&self) {
        // Change PARKED=>NOTIFIED, EMPTY=>NOTIFIED, or NOTIFIED=>NOTIFIED, and
        // wake the thread in the first case.
        //
        // Note that even NOTIFIED=>NOTIFIED results in a write. This is on
        // purpose, to make sure every unpark() has a release-acquire ordering
        // with park().
        if self.state.swap(NOTIFIED, Release) == PARKED {
            if c::WakeByAddressSingle::is_available() {
                unsafe {
                    c::WakeByAddressSingle(self.ptr());
                }
            } else {
                // If we run NtReleaseKeyedEvent before the waiting thread runs
                // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
                // If the waiting thread wakes up before we run NtReleaseKeyedEvent
                // (e.g. due to a timeout), this blocks until we do wake up a thread.
                // To prevent this thread from blocking indefinitely in that case,
                // park_impl() will, after seeing the state set to NOTIFIED after
                // waking up, call NtWaitForKeyedEvent again to unblock us.
                unsafe {
                    c::NtReleaseKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
                }
            }
        }
    }

    fn ptr(&self) -> c::LPVOID {
        &self.state as *const _ as c::LPVOID
    }
}

fn keyed_event_handle() -> c::HANDLE {
    const INVALID: usize = !0;
    static HANDLE: AtomicUsize = AtomicUsize::new(INVALID);
    match HANDLE.load(Relaxed) {
        INVALID => {
            let mut handle = c::INVALID_HANDLE_VALUE;
            unsafe {
                match c::NtCreateKeyedEvent(
                    &mut handle,
                    c::GENERIC_READ | c::GENERIC_WRITE,
                    ptr::null_mut(),
                    0,
                ) {
                    c::STATUS_SUCCESS => {}
                    r => panic!("Unable to create keyed event handle: error {}", r),
                }
            }
            match HANDLE.compare_exchange(INVALID, handle as usize, Relaxed, Relaxed) {
                Ok(_) => handle,
                Err(h) => {
                    // Lost the race to another thread initializing HANDLE before we did.
                    // Closing our handle and using theirs instead.
                    unsafe {
                        c::CloseHandle(handle);
                    }
                    h as c::HANDLE
                }
            }
        }
        handle => handle as c::HANDLE,
    }
}
<commit_msg>Fix typos in comments.<commit_after>use crate::convert::TryFrom;
use crate::ptr;
use crate::sync::atomic::{
    AtomicI8, AtomicUsize,
    Ordering::{Acquire, Relaxed, Release},
};
use crate::sys::{c, dur2timeout};
use crate::time::Duration;

pub struct Parker {
    state: AtomicI8,
}

const PARKED: i8 = -1;
const EMPTY: i8 = 0;
const NOTIFIED: i8 = 1;

// Notes about memory ordering:
//
// Memory ordering is only relevant for the relative ordering of operations
// between different variables. Even Ordering::Relaxed guarantees a
// monotonic/consistent order when looking at just a single atomic variable.
//
// So, since this parker is just a single atomic variable, we only need to look
// at the ordering guarantees we need to provide to the 'outside world'.
//
// The only memory ordering guarantee that parking and unparking provide, is
// that things which happened before unpark() are visible on the thread
// returning from park() afterwards. Otherwise, it was effectively unparked
// before unpark() was called while still consuming the 'token'.
//
// In other words, unpark() needs to synchronize with the part of park() that
// consumes the token and returns.
//
// This is done with a release-acquire synchronization, by using
// Ordering::Release when writing NOTIFIED (the 'token') in unpark(), and using
// Ordering::Acquire when checking for this state in park().
impl Parker {
    pub fn new() -> Self {
        Self { state: AtomicI8::new(EMPTY) }
    }

    // Assumes this is only called by the thread that owns the Parker,
    // which means that `self.state != PARKED`.
    pub unsafe fn park(&self) {
        // Change NOTIFIED=>EMPTY or EMPTY=>PARKED, and directly return in the
        // first case.
        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
            return;
        }

        if c::WaitOnAddress::is_available() {
            loop {
                // Wait for something to happen, assuming it's still set to PARKED.
                c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, c::INFINITE);
                // Change NOTIFIED=>EMPTY but leave PARKED alone.
                if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED {
                    // Actually woken up by unpark().
                    return;
                } else {
                    // Spurious wake up. We loop to try again.
                }
            }
        } else {
            // Wait for unpark() to produce this event.
            c::NtWaitForKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
            // Note that we don't just write EMPTY, but use swap() to also
            // include an acquire-ordered read to synchronize with unpark()'s
            // release-ordered write.
            self.state.swap(EMPTY, Acquire);
        }
    }

    // Assumes this is only called by the thread that owns the Parker,
    // which means that `self.state != PARKED`.
    pub unsafe fn park_timeout(&self, timeout: Duration) {
        // Change NOTIFIED=>EMPTY or EMPTY=>PARKED, and directly return in the
        // first case.
        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
            return;
        }

        if c::WaitOnAddress::is_available() {
            // Wait for something to happen, assuming it's still set to PARKED.
            c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, dur2timeout(timeout));
            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
            // Note that we don't just write EMPTY, but use swap() to also
            // include an acquire-ordered read to synchronize with unpark()'s
            // release-ordered write.
            if self.state.swap(EMPTY, Acquire) == NOTIFIED {
                // Actually woken up by unpark().
            } else {
                // Timeout or spurious wake up.
                // We return either way, because we can't easily tell if it was the
                // timeout or not.
            }
        } else {
            // Need to wait for unpark() using NtWaitForKeyedEvent.
            let handle = keyed_event_handle();

            // NtWaitForKeyedEvent uses a unit of 100ns, and uses negative values
            // to indicate the monotonic clock.
            let mut timeout = match i64::try_from((timeout.as_nanos() + 99) / 100) {
                Ok(t) => -t,
                Err(_) => i64::MIN,
            };

            // Wait for unpark() to produce this event.
            let unparked = c::NtWaitForKeyedEvent(handle, self.ptr(), 0, &mut timeout) == c::STATUS_SUCCESS;

            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
            let prev_state = self.state.swap(EMPTY, Acquire);

            if !unparked && prev_state == NOTIFIED {
                // We were awoken by a timeout, not by unpark(), but the state
                // was set to NOTIFIED, which means we *just* missed an
                // unpark(), which is now blocked on us to wait for it.
                // Wait for it to consume the event and unblock that thread.
                c::NtWaitForKeyedEvent(handle, self.ptr(), 0, ptr::null_mut());
            }
        }
    }

    pub fn unpark(&self) {
        // Change PARKED=>NOTIFIED, EMPTY=>NOTIFIED, or NOTIFIED=>NOTIFIED, and
        // wake the thread in the first case.
        //
        // Note that even NOTIFIED=>NOTIFIED results in a write. This is on
        // purpose, to make sure every unpark() has a release-acquire ordering
        // with park().
        if self.state.swap(NOTIFIED, Release) == PARKED {
            if c::WakeByAddressSingle::is_available() {
                unsafe {
                    c::WakeByAddressSingle(self.ptr());
                }
            } else {
                // If we run NtReleaseKeyedEvent before the waiting thread runs
                // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
                // If the waiting thread wakes up before we run NtReleaseKeyedEvent
                // (e.g. due to a timeout), this blocks until we do wake up a thread.
                // To prevent this thread from blocking indefinitely in that case,
                // park_impl() will, after seeing the state set to NOTIFIED after
                // waking up, call NtWaitForKeyedEvent again to unblock us.
                unsafe {
                    c::NtReleaseKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
                }
            }
        }
    }

    fn ptr(&self) -> c::LPVOID {
        &self.state as *const _ as c::LPVOID
    }
}

fn keyed_event_handle() -> c::HANDLE {
    const INVALID: usize = !0;
    static HANDLE: AtomicUsize = AtomicUsize::new(INVALID);
    match HANDLE.load(Relaxed) {
        INVALID => {
            let mut handle = c::INVALID_HANDLE_VALUE;
            unsafe {
                match c::NtCreateKeyedEvent(
                    &mut handle,
                    c::GENERIC_READ | c::GENERIC_WRITE,
                    ptr::null_mut(),
                    0,
                ) {
                    c::STATUS_SUCCESS => {}
                    r => panic!("Unable to create keyed event handle: error {}", r),
                }
            }
            match HANDLE.compare_exchange(INVALID, handle as usize, Relaxed, Relaxed) {
                Ok(_) => handle,
                Err(h) => {
                    // Lost the race to another thread initializing HANDLE before we did.
                    // Closing our handle and using theirs instead.
                    unsafe {
                        c::CloseHandle(handle);
                    }
                    h as c::HANDLE
                }
            }
        }
        handle => handle as c::HANDLE,
    }
}
<|endoftext|>