<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::future::{self, Future};
use httparse;
use hyper::{Error, Method, StatusCode, Headers};
use hyper::header::{Origin, IfNoneMatch, ETag, EntityTag};
use hyper::server::{Request, Response};

use super::header::ProxyHeader;
use super::tunnel::ProxyTunnel;
use header::janitor::HeaderJanitor;
use header::request_shard::HeaderRequestBloomRequestShard;
use header::status::{HeaderBloomStatus, HeaderBloomStatusValue};
use cache::read::CacheRead;
use cache::write::CacheWrite;
use cache::route::CacheRoute;
use LINE_FEED;

pub struct ProxyServe;

const CACHED_PARSE_MAX_HEADERS: usize = 100;

pub type ProxyServeFuture = Box<Future<Item = Response, Error = Error>>;

impl ProxyServe {
    pub fn handle(req: Request) -> ProxyServeFuture {
        info!("handled request: {} on {}", req.method(), req.path());

        if req.headers().has::<HeaderRequestBloomRequestShard>() == true {
            match *req.method() {
                Method::Options | Method::Head | Method::Get | Method::Post | Method::Patch |
                Method::Put | Method::Delete => Self::accept(req),
                _ => Self::reject(req, StatusCode::MethodNotAllowed),
            }
        } else {
            Self::reject(req, StatusCode::NotExtended)
        }
    }

    fn accept(req: Request) -> ProxyServeFuture {
        Self::tunnel(req)
    }

    fn reject(req: Request, status: StatusCode) -> ProxyServeFuture {
        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Reject));

        Self::respond(&req.method(), status, headers, format!("{}", status))
    }

    fn tunnel(req: Request) -> ProxyServeFuture {
        let (method, uri, version, headers, body) = req.deconstruct();
        let (headers, auth, shard) = ProxyHeader::parse_from_request(headers);

        let auth_hash = CacheRoute::hash(&auth);

        let (ns, ns_mask) = CacheRoute::gen_key_cache(
            shard,
            &auth_hash,
            version,
            &method,
            uri.path(),
            uri.query(),
            headers.get::<Origin>(),
        );

        info!("tunneling for ns = {}", ns);

        Box::new(
            CacheRead::acquire(&ns, &method)
                .or_else(|_| Err(Error::Incomplete))
                .and_then(move |result| {
                    match result {
                        Ok(value) => Self::dispatch_cached(&method, &headers, &value.0, value.1),
                        Err(_) => {
                            // Clone method value for closures. Sadly, it looks like Rust borrow \
                            //   checker doesnt discriminate properly on this check.
                            let method_success = method.to_owned();
                            let method_failure = method.to_owned();

                            Box::new(
                                ProxyTunnel::run(&method, &uri, &headers, body, shard)
                                    .and_then(move |tunnel_res| {
                                        CacheWrite::save(
                                            ns,
                                            ns_mask,
                                            auth_hash,
                                            shard,
                                            method,
                                            version,
                                            tunnel_res.status(),
                                            tunnel_res.headers().to_owned(),
                                            tunnel_res.body(),
                                        )
                                    })
                                    .and_then(move |mut result| match result.body {
                                        Ok(body_string) => {
                                            Self::dispatch_fetched(
                                                &method_success,
                                                &result.status,
                                                result.headers,
                                                HeaderBloomStatusValue::Miss,
                                                body_string,
                                                result.fingerprint,
                                            )
                                        }
                                        Err(body_string_values) => {
                                            match body_string_values {
                                                Some(body_string) => {
                                                    // Enforce clean headers, has usually they get \
                                                    //   cleaned from cache writer
                                                    HeaderJanitor::clean(&mut result.headers);

                                                    Self::dispatch_fetched(
                                                        &method_success,
                                                        &result.status,
                                                        result.headers,
                                                        HeaderBloomStatusValue::Direct,
                                                        body_string,
                                                        result.fingerprint,
                                                    )
                                                }
                                                _ => Self::dispatch_failure(&method_success),
                                            }
                                        }
                                    })
                                    .or_else(move |_| Self::dispatch_failure(&method_failure)),
                            )
                        }
                    }
                }),
        )
    }

    fn dispatch_cached(
        method: &Method,
        headers: &Headers,
        res_string: &str,
        res_fingerprint: String,
    ) -> ProxyServeFuture {
        // Check if not modified?
        let isnt_modified = match headers.get::<IfNoneMatch>() {
            Some(req_if_none_match) => {
                match *req_if_none_match {
                    IfNoneMatch::Any => true,
                    IfNoneMatch::Items(ref req_etags) => {
                        if let Some(req_etag) = req_etags.first() {
                            req_etag.weak_eq(&EntityTag::new(false, res_fingerprint.to_owned()))
                        } else {
                            false
                        }
                    }
                }
            }
            _ => false,
        };

        // Response not modified for client?
        if isnt_modified == true {
            // Process non-modified + cached headers
            let mut headers = Headers::new();

            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
            headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

            // Serve non-modified response
            return Self::respond(method, StatusCode::NotModified, headers, String::from(""));
        }

        // Response modified
        let mut headers = [httparse::EMPTY_HEADER; CACHED_PARSE_MAX_HEADERS];
        let mut res = httparse::Response::new(&mut headers);

        // Split headers from body
        let mut res_body_string = String::new();
        let mut is_last_line_empty = false;

        for res_line in res_string.lines() {
            if res_body_string.is_empty() == false || is_last_line_empty == true {
                // Write to body
                res_body_string.push_str(res_line.as_ref());
                res_body_string.push_str(LINE_FEED);
            }

            is_last_line_empty = res_line.is_empty();
        }

        match res.parse(res_string.as_bytes()) {
            Ok(_) => {
                // Process cached status
                let code = res.code.unwrap_or(500u16);
                let status = StatusCode::try_from(code).unwrap_or(StatusCode::Unregistered(code));

                // Process cached headers
                let mut headers = Headers::new();

                for header in res.headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (
                            String::from_utf8(Vec::from(header.name)),
                            String::from_utf8(Vec::from(header.value)),
                        )
                    {
                        headers.set_raw(header_name, header_value);
                    }
                }

                ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
                headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

                // Serve cached response
                Self::respond(method, status, headers, res_body_string)
            }
            Err(err) => {
                error!("failed parsing cached response: {}", err);

                Self::dispatch_failure(method)
            }
        }
    }

    fn dispatch_fetched(
        method: &Method,
        status: &StatusCode,
        mut headers: Headers,
        bloom_status: HeaderBloomStatusValue,
        body_string: String,
        fingerprint: Option<String>,
    ) -> ProxyServeFuture {
        // Process ETag for content?
        if let Some(fingerprint_value) = fingerprint {
            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(fingerprint_value));
        }

        headers.set(HeaderBloomStatus(bloom_status));

        Self::respond(method, *status, headers, body_string)
    }

    fn dispatch_failure(method: &Method) -> ProxyServeFuture {
        let status = StatusCode::BadGateway;

        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Offline));

        Self::respond(method, status, headers, format!("{}", status))
    }

    fn fingerprint_etag(fingerprint: String) -> ETag {
        ETag(EntityTag::new(false, fingerprint))
    }

    fn respond(
        method: &Method,
        status: StatusCode,
        headers: Headers,
        body_string: String,
    ) -> ProxyServeFuture {
        Box::new(future::ok(match method {
            &Method::Get | &Method::Post | &Method::Patch | &Method::Put | &Method::Delete => {
                Response::new()
                    .with_status(status)
                    .with_headers(headers)
                    .with_body(body_string)
            }
            _ => Response::new().with_status(status).with_headers(headers),
        }))
    }
}
<commit_msg>Fix<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use futures::future::{self, Future};
use httparse;
use hyper::{Error, Method, StatusCode, Headers};
use hyper::header::{Origin, IfNoneMatch, ETag, EntityTag};
use hyper::server::{Request, Response};

use super::header::ProxyHeader;
use super::tunnel::ProxyTunnel;
use header::janitor::HeaderJanitor;
use header::request_shard::HeaderRequestBloomRequestShard;
use header::status::{HeaderBloomStatus, HeaderBloomStatusValue};
use cache::read::CacheRead;
use cache::write::CacheWrite;
use cache::route::CacheRoute;
use LINE_FEED;

pub struct ProxyServe;

const CACHED_PARSE_MAX_HEADERS: usize = 100;

pub type ProxyServeFuture = Box<Future<Item = Response, Error = Error>>;

impl ProxyServe {
    pub fn handle(req: Request) -> ProxyServeFuture {
        info!("handled request: {} on {}", req.method(), req.path());

        if req.headers().has::<HeaderRequestBloomRequestShard>() == true {
            match *req.method() {
                Method::Options | Method::Head | Method::Get | Method::Post | Method::Patch |
                Method::Put | Method::Delete => Self::accept(req),
                _ => Self::reject(req, StatusCode::MethodNotAllowed),
            }
        } else {
            Self::reject(req, StatusCode::NotExtended)
        }
    }

    fn accept(req: Request) -> ProxyServeFuture {
        Self::tunnel(req)
    }

    fn reject(req: Request, status: StatusCode) -> ProxyServeFuture {
        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Reject));

        Self::respond(&req.method(), status, headers, format!("{}", status))
    }

    fn tunnel(req: Request) -> ProxyServeFuture {
        let (method, uri, version, headers, body) = req.deconstruct();
        let (headers, auth, shard) = ProxyHeader::parse_from_request(headers);

        let auth_hash = CacheRoute::hash(&auth);

        let (ns, ns_mask) = CacheRoute::gen_key_cache(
            shard,
            &auth_hash,
            version,
            &method,
            uri.path(),
            uri.query(),
            headers.get::<Origin>(),
        );

        info!("tunneling for ns = {}", ns);

        Box::new(
            CacheRead::acquire(&ns, &method)
                .or_else(|_| Err(Error::Incomplete))
                .and_then(move |result| {
                    match result {
                        Ok(value) => Self::dispatch_cached(&method, &headers, &value.0, value.1),
                        Err(_) => {
                            // Clone method value for closures. Sadly, it looks like Rust borrow \
                            //   checker doesnt discriminate properly on this check.
                            let method_success = method.to_owned();
                            let method_failure = method.to_owned();

                            Box::new(
                                ProxyTunnel::run(&method, &uri, &headers, body, shard)
                                    .and_then(move |tunnel_res| {
                                        CacheWrite::save(
                                            ns,
                                            ns_mask,
                                            auth_hash,
                                            shard,
                                            method,
                                            version,
                                            tunnel_res.status(),
                                            tunnel_res.headers().to_owned(),
                                            tunnel_res.body(),
                                        )
                                    })
                                    .and_then(move |mut result| match result.body {
                                        Ok(body_string) => {
                                            Self::dispatch_fetched(
                                                &method_success,
                                                &result.status,
                                                result.headers,
                                                HeaderBloomStatusValue::Miss,
                                                body_string,
                                                result.fingerprint,
                                            )
                                        }
                                        Err(body_string_values) => {
                                            match body_string_values {
                                                Some(body_string) => {
                                                    // Enforce clean headers, has usually they get \
                                                    //   cleaned from cache writer
                                                    HeaderJanitor::clean(&mut result.headers);

                                                    Self::dispatch_fetched(
                                                        &method_success,
                                                        &result.status,
                                                        result.headers,
                                                        HeaderBloomStatusValue::Direct,
                                                        body_string,
                                                        result.fingerprint,
                                                    )
                                                }
                                                _ => Self::dispatch_failure(&method_success),
                                            }
                                        }
                                    })
                                    .or_else(move |_| Self::dispatch_failure(&method_failure)),
                            )
                        }
                    }
                }),
        )
    }

    fn dispatch_cached(
        method: &Method,
        headers: &Headers,
        res_body: &str,
        res_fingerprint: String,
    ) -> ProxyServeFuture {
        // Check if not modified?
        let isnt_modified = match headers.get::<IfNoneMatch>() {
            Some(req_if_none_match) => {
                match *req_if_none_match {
                    IfNoneMatch::Any => true,
                    IfNoneMatch::Items(ref req_etags) => {
                        if let Some(req_etag) = req_etags.first() {
                            req_etag.weak_eq(&EntityTag::new(false, res_fingerprint.to_owned()))
                        } else {
                            false
                        }
                    }
                }
            }
            _ => false,
        };

        // Response not modified for client?
        if isnt_modified == true {
            // Process non-modified + cached headers
            let mut headers = Headers::new();

            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
            headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

            // Serve non-modified response
            return Self::respond(method, StatusCode::NotModified, headers, String::from(""));
        }

        // Response modified
        let mut headers = [httparse::EMPTY_HEADER; CACHED_PARSE_MAX_HEADERS];
        let mut res = httparse::Response::new(&mut headers);

        // Split headers from body
        let mut res_body_string = String::new();
        let mut is_last_line_empty = false;

        for res_line in res_body.lines() {
            if res_body_string.is_empty() == false || is_last_line_empty == true {
                // Write to body
                res_body_string.push_str(res_line.as_ref());
                res_body_string.push_str(LINE_FEED);
            }

            is_last_line_empty = res_line.is_empty();
        }

        match res.parse(res_body.as_bytes()) {
            Ok(_) => {
                // Process cached status
                let code = res.code.unwrap_or(500u16);
                let status = StatusCode::try_from(code).unwrap_or(StatusCode::Unregistered(code));

                // Process cached headers
                let mut headers = Headers::new();

                for header in res.headers {
                    if let (Ok(header_name), Ok(header_value)) =
                        (
                            String::from_utf8(Vec::from(header.name)),
                            String::from_utf8(Vec::from(header.value)),
                        )
                    {
                        headers.set_raw(header_name, header_value);
                    }
                }

                ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(res_fingerprint));
                headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Hit));

                // Serve cached response
                Self::respond(method, status, headers, res_body_string)
            }
            Err(err) => {
                error!("failed parsing cached response: {}", err);

                Self::dispatch_failure(method)
            }
        }
    }

    fn dispatch_fetched(
        method: &Method,
        status: &StatusCode,
        mut headers: Headers,
        bloom_status: HeaderBloomStatusValue,
        body_string: String,
        fingerprint: Option<String>,
    ) -> ProxyServeFuture {
        // Process ETag for content?
        if let Some(fingerprint_value) = fingerprint {
            ProxyHeader::set_etag(&mut headers, Self::fingerprint_etag(fingerprint_value));
        }

        headers.set(HeaderBloomStatus(bloom_status));

        Self::respond(method, *status, headers, body_string)
    }

    fn dispatch_failure(method: &Method) -> ProxyServeFuture {
        let status = StatusCode::BadGateway;

        let mut headers = Headers::new();

        headers.set::<HeaderBloomStatus>(HeaderBloomStatus(HeaderBloomStatusValue::Offline));

        Self::respond(method, status, headers, format!("{}", status))
    }

    fn fingerprint_etag(fingerprint: String) -> ETag {
        ETag(EntityTag::new(false, fingerprint))
    }

    fn respond(
        method: &Method,
        status: StatusCode,
        headers: Headers,
        body_string: String,
    ) -> ProxyServeFuture {
        Box::new(future::ok(match method {
            &Method::Get | &Method::Post | &Method::Patch | &Method::Put | &Method::Delete => {
                Response::new()
                    .with_status(status)
                    .with_headers(headers)
                    .with_body(body_string)
            }
            _ => Response::new().with_status(status).with_headers(headers),
        }))
    }
}
<|endoftext|>


<commit_before>import std::io;
import std::io::writer_util;

export write_markdown;

type ctxt = {
    w: io::writer
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer
    };

    write_header(ctxt, doc.topmod.name);
    write_top_module(ctxt, doc.topmod);
}

fn write_header(ctxt: ctxt, name: str) {
    ctxt.w.write_line("# Crate " + name);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        write_fn(ctxt, fndoc);
    }

    for moddoc in *moddoc.mods {
        write_mod(ctxt, moddoc);
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    ctxt.w.write_line("## Function `" + doc.name + "`");
    alt doc.brief {
      some(brief) {
        ctxt.w.write_line(brief);
      }
      none. { }
    }
    alt doc.desc {
        some(_d) {
            ctxt.w.write_line("");
            ctxt.w.write_line(_d);
            ctxt.w.write_line("");
        }
        none. { }
    }
    for (arg, desc) in doc.args {
        ctxt.w.write_str("### Argument `" + arg + "`: ");
        ctxt.w.write_str(desc)
    }
    alt doc.return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line("### Returns `" + ty + "`");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let source = "";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "belch");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch\n");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let source = "fn func() { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "## Function `func`");
    }
}<commit_msg>rustdoc: Refactor header writing a bit<commit_after>import std::io;
import std::io::writer_util;

export write_markdown;

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    ctxt.depth = 1u;
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        write_fn(ctxt, fndoc);
    }

    for moddoc in *moddoc.mods {
        write_mod(ctxt, moddoc);
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    ctxt.depth = 2u;
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    alt doc.brief {
      some(brief) {
        ctxt.w.write_line(brief);
      }
      none. { }
    }
    alt doc.desc {
        some(_d) {
            ctxt.w.write_line("");
            ctxt.w.write_line(_d);
            ctxt.w.write_line("");
        }
        none. { }
    }
    for (arg, desc) in doc.args {
        ctxt.w.write_str("### Argument `" + arg + "`: ");
        ctxt.w.write_str(desc)
    }
    alt doc.return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line("### Returns `" + ty + "`");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let source = "";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "belch");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch\n");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let source = "fn func() { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "## Function `func`");
    }
}<|endoftext|>


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

use azure::{AzScaledFontRef, AzFloat};
use azure::{struct__AzNativeFont};

use azure_hl::{BackendType,SkiaBackend};
use azure::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};

use libc::c_void;
use std::mem;
use std::ptr;

#[cfg(target_os="macos")]
use scaled_font::macos::*;

#[cfg(target_os="linux")]
use scaled_font::linux::*;

#[cfg(target_os="android")]
use scaled_font::android::*;

#[cfg(target_os="macos")]
pub mod macos {
    pub use core_text::font::CTFontRef;
    pub use core_graphics::font::{CGFont, CGFontRef};
}

#[cfg(target_os="linux")]
pub mod linux {
    pub use freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

#[cfg(target_os="android")]
pub mod android {
    pub use freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

pub type SkTypeface = *mut c_void;

#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub enum FontInfo<'a> {
    NativeFont(FT_Face),
    FontData(&'a Vec<u8>),
}

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,
}

impl Drop for ScaledFont {
    fn drop(&mut self) {
        unsafe {
            AzReleaseScaledFont(self.azure_scaled_font);
        }
    }
}

impl ScaledFont {
    pub fn get_ref(&self) -> AzScaledFontRef {
        self.azure_scaled_font
    }

    #[cfg(target_os="linux")]
    #[cfg(target_os="android")]
    pub fn new(backend: BackendType, font_info: FontInfo, size: AzFloat)
        -> ScaledFont {
        use azure::AZ_NATIVE_FONT_SKIA_FONT_FACE;
        use azure::{AzCreateFontOptionsForData, AzCreateFontOptionsForName, AzDestroyFontOptions};

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::null_mut()
        };

        match backend {
            SkiaBackend => {
                unsafe {
                    let options = match font_info {
                        NativeFont(native_font) => {
                            // NOTE: azure style flags and freetype style flags are the same in the lowest 2 bits
                            let style = ((*native_font).style_flags & 3) as u32;
                            AzCreateFontOptionsForName(&*(*native_font).family_name, style)
                        },
                        FontData(bytes) => {
                            AzCreateFontOptionsForData(bytes.as_ptr(), bytes.len() as u32)
                        },
                    };
                    azure_native_font.mType = AZ_NATIVE_FONT_SKIA_FONT_FACE;
                    azure_native_font.mFont = mem::transmute(options);
                    let azure_native_font_ptr = &mut azure_native_font;
                    let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
                    AzDestroyFontOptions(options);
                    ScaledFont { azure_scaled_font: azure_scaled_font }
                }
            }
            _ => { panic!("don't know how to make a scaled font for this backend"); }
        }
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    pub fn new(backend: BackendType, native_font: &CGFont, size: AzFloat) -> ScaledFont {
        use azure::AZ_NATIVE_FONT_MAC_FONT_FACE;
        use azure_hl::{CoreGraphicsBackend,CoreGraphicsAcceleratedBackend};
        use core_foundation::base::TCFType;

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::null_mut()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;
                unsafe {
                    azure_native_font.mFont = mem::transmute(native_font.as_concrete_TypeRef());
                }
            }
            _ => {
                panic!("don't know how to make a scaled font for this backend");
            }
        }

        unsafe {
            let azure_scaled_font = AzCreateScaledFontForNativeFont(&mut azure_native_font, size);
            ScaledFont {
                azure_scaled_font: azure_scaled_font
            }
        }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[cfg(target_os="macos")]
#[link(name = "skia")]
extern {
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *mut SkTypeface;
}

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

use azure::{AzScaledFontRef, AzFloat};
use azure::{struct__AzNativeFont};

use azure_hl::{BackendType,SkiaBackend};
use azure::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};

use libc::c_void;
use std::mem;
use std::ptr;

#[cfg(target_os="macos")]
use scaled_font::macos::*;

#[cfg(target_os="linux")]
use scaled_font::linux::*;

#[cfg(target_os="android")]
use scaled_font::android::*;

#[cfg(target_os="macos")]
pub mod macos {
    pub use core_text::font::CTFontRef;
    pub use core_graphics::font::{CGFont, CGFontRef};
}

#[cfg(target_os="linux")]
pub mod linux {
    pub use freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

#[cfg(target_os="android")]
pub mod android {
    pub use freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

pub type SkTypeface = *mut c_void;

#[cfg(any(target_os="linux", target_os = "android"))]
pub enum FontInfo<'a> {
    NativeFont(FT_Face),
    FontData(&'a Vec<u8>),
}

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,
}

impl Drop for ScaledFont {
    fn drop(&mut self) {
        unsafe {
            AzReleaseScaledFont(self.azure_scaled_font);
        }
    }
}

impl ScaledFont {
    pub fn get_ref(&self) -> AzScaledFontRef {
        self.azure_scaled_font
    }

    #[cfg(any(target_os="linux", target_os = "android"))]
    pub fn new(backend: BackendType, font_info: FontInfo, size: AzFloat)
        -> ScaledFont {
        use azure::AZ_NATIVE_FONT_SKIA_FONT_FACE;
        use azure::{AzCreateFontOptionsForData, AzCreateFontOptionsForName, AzDestroyFontOptions};

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::null_mut()
        };

        match backend {
            SkiaBackend => {
                unsafe {
                    let options = match font_info {
                        NativeFont(native_font) => {
                            // NOTE: azure style flags and freetype style flags are the same in the lowest 2 bits
                            let style = ((*native_font).style_flags & 3) as u32;
                            AzCreateFontOptionsForName(&*(*native_font).family_name, style)
                        },
                        FontData(bytes) => {
                            AzCreateFontOptionsForData(bytes.as_ptr(), bytes.len() as u32)
                        },
                    };
                    azure_native_font.mType = AZ_NATIVE_FONT_SKIA_FONT_FACE;
                    azure_native_font.mFont = mem::transmute(options);
                    let azure_native_font_ptr = &mut azure_native_font;
                    let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
                    AzDestroyFontOptions(options);
                    ScaledFont { azure_scaled_font: azure_scaled_font }
                }
            }
            _ => { panic!("don't know how to make a scaled font for this backend"); }
        }
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    pub fn new(backend: BackendType, native_font: &CGFont, size: AzFloat) -> ScaledFont {
        use azure::AZ_NATIVE_FONT_MAC_FONT_FACE;
        use azure_hl::{CoreGraphicsBackend,CoreGraphicsAcceleratedBackend};
        use core_foundation::base::TCFType;

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::null_mut()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;
                unsafe {
                    azure_native_font.mFont = mem::transmute(native_font.as_concrete_TypeRef());
                }
            }
            _ => {
                panic!("don't know how to make a scaled font for this backend");
            }
        }

        unsafe {
            let azure_scaled_font = AzCreateScaledFontForNativeFont(&mut azure_native_font, size);
            ScaledFont {
                azure_scaled_font: azure_scaled_font
            }
        }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[cfg(target_os="macos")]
#[link(name = "skia")]
extern {
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *mut SkTypeface;
}

<|endoftext|>


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

use rustc::util::nodemap::DefIdSet;
use std::mem;

use clean::{self, AttributesExt, NestedAttributesExt};
use clean::Item;
use core::DocContext;
use fold;
use fold::DocFolder;
use fold::StripItem;
use passes::{ImplStripper, Pass};

pub const STRIP_HIDDEN: Pass =
    Pass::early("strip-hidden", strip_hidden,
                "strips all doc(hidden) items from the output");

/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
    let mut retained = DefIdSet();

    // strip all #[doc(hidden)] items
    let krate = {
        let mut stripper = Stripper{ retained: &mut retained, update_retained: true };
        stripper.fold_crate(krate)
    };

    // strip all impls referencing stripped items
    let mut stripper = ImplStripper { retained: &retained };
    stripper.fold_crate(krate)
}

struct Stripper<'a> {
    retained: &'a mut DefIdSet,
    update_retained: bool,
}

impl<'a> fold::DocFolder for Stripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        if i.attrs.lists("doc").has_word("hidden") {
            debug!("found one in strip_hidden; removing");
            // use a dedicated hidden item for given item type if any
            match i.inner {
                clean::StructFieldItem(..) | clean::ModuleItem(..) => {
                    // We need to recurse into stripped modules to
                    // strip things like impl methods but when doing so
                    // we must not add any items to the `retained` set.
                    let old = mem::replace(&mut self.update_retained, false);
                    let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
                    self.update_retained = old;
                    return ret;
                }
                _ => return None,
            }
        } else {
            if self.update_retained {
                self.retained.insert(i.def_id);
            }
        }
        self.fold_item_recur(i)
    }
}
<commit_msg>swap external_traits into the crate before running strip_hidden<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::util::nodemap::DefIdSet;
use std::mem;

use clean::{self, AttributesExt, NestedAttributesExt};
use clean::Item;
use core::DocContext;
use fold;
use fold::DocFolder;
use fold::StripItem;
use passes::{ImplStripper, Pass};

pub const STRIP_HIDDEN: Pass =
    Pass::early("strip-hidden", strip_hidden,
                "strips all doc(hidden) items from the output");

/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
    let mut retained = DefIdSet();

    // as an early pass, the external traits haven't been swapped in, so we need to do that ahead
    // of time
    mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());

    // strip all #[doc(hidden)] items
    let krate = {
        let mut stripper = Stripper{ retained: &mut retained, update_retained: true };
        stripper.fold_crate(krate)
    };

    // strip all impls referencing stripped items
    let mut stripper = ImplStripper { retained: &retained };
    let mut krate = stripper.fold_crate(krate);
    mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());

    krate
}

struct Stripper<'a> {
    retained: &'a mut DefIdSet,
    update_retained: bool,
}

impl<'a> fold::DocFolder for Stripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        if i.attrs.lists("doc").has_word("hidden") {
            debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name);
            // use a dedicated hidden item for given item type if any
            match i.inner {
                clean::StructFieldItem(..) | clean::ModuleItem(..) => {
                    // We need to recurse into stripped modules to
                    // strip things like impl methods but when doing so
                    // we must not add any items to the `retained` set.
                    let old = mem::replace(&mut self.update_retained, false);
                    let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
                    self.update_retained = old;
                    return ret;
                }
                _ => return None,
            }
        } else {
            if self.update_retained {
                self.retained.insert(i.def_id);
            }
        }
        self.fold_item_recur(i)
    }
}
<|endoftext|>


<commit_before><commit_msg>Add missing file<commit_after><|endoftext|>


<commit_before>extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use quote::Ident;

#[proc_macro_derive(Submodular)]
pub fn submodular(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let expanded = expand_bounds(&ast,
                                 Ident::new("Submodular"),
                                 Ident::new("None"),
                                 Ident::new("Some(1.0)"));

    expanded.parse().unwrap()
}

#[proc_macro_derive(Supermodular)]
pub fn supermodular(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let expanded = expand_bounds(&ast,
                                 Ident::new("Supermodular"),
                                 Ident::new("Some(1.0)"),
                                 Ident::new("None"));

    expanded.parse().unwrap()
}

#[proc_macro_derive(Modular)]
pub fn modular(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let expanded = expand_bounds(&ast,
                                 Ident::new("Modular"),
                                 Ident::new("Some(1.0)"),
                                 Ident::new("Some(1.0)"));

    expanded.parse().unwrap()
}

fn expand_bounds(ast: &syn::DeriveInput, ty: Ident, low: Ident, high: Ident) -> quote::Tokens {
    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    quote! {
        impl #impl_generics ::objective::curvature::#ty for #name #ty_generics #where_clause {}
        impl #impl_generics ::objective::curvature::Bounded for #name #ty_generics #where_clause {
            fn bounds() -> (Option<f64>, Option<f64>) {
                (#low, #high)
            }
        }
    }
}
<commit_msg>Fixed using derives in external crates.<commit_after>extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use quote::Ident;

#[proc_macro_derive(Submodular)]
pub fn submodular(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let expanded = expand_bounds(&ast,
                                 Ident::new("Submodular"),
                                 Ident::new("None"),
                                 Ident::new("Some(1.0)"));

    expanded.parse().unwrap()
}

#[proc_macro_derive(Supermodular)]
pub fn supermodular(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let expanded = expand_bounds(&ast,
                                 Ident::new("Supermodular"),
                                 Ident::new("Some(1.0)"),
                                 Ident::new("None"));

    expanded.parse().unwrap()
}

#[proc_macro_derive(Modular)]
pub fn modular(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let expanded = expand_bounds(&ast,
                                 Ident::new("Modular"),
                                 Ident::new("Some(1.0)"),
                                 Ident::new("Some(1.0)"));

    expanded.parse().unwrap()
}

fn expand_bounds(ast: &syn::DeriveInput, ty: Ident, low: Ident, high: Ident) -> quote::Tokens {
    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    quote! {
        impl #impl_generics ::avarice::objective::curvature::#ty for #name #ty_generics #where_clause {}
        impl #impl_generics ::avarice::objective::curvature::Bounded for #name #ty_generics #where_clause {
            fn bounds() -> (Option<f64>, Option<f64>) {
                (#low, #high)
            }
        }
    }
}
<|endoftext|>


<commit_before>///!  Utility functions for Rustup
pub(crate) mod notifications;
pub mod raw;
pub(crate) mod toml_utils;
pub(crate) mod tty;
pub(crate) mod units;
#[allow(clippy::module_inception)]
pub mod utils;

pub(crate) use crate::utils::notifications::Notification;
pub(crate) mod notify;
<commit_msg>fix just one doc typo<commit_after>//!  Utility functions for Rustup
pub(crate) mod notifications;
pub mod raw;
pub(crate) mod toml_utils;
pub(crate) mod tty;
pub(crate) mod units;
#[allow(clippy::module_inception)]
pub mod utils;

pub(crate) use crate::utils::notifications::Notification;
pub(crate) mod notify;
<|endoftext|>


<commit_before>//! Module for holding Validated logic
//!
//! `Validated` is a way of running a bunch of operations that can go wrong (for example,
//! functions returning `Result<T, E>`) and, in the case of one or more things going wrong,
//! having all the errors returned to you all at once. In the case that everything went well, you get
//! an `HList` of all your results.
//!
//! ```
//! # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
//!
//! #[derive(PartialEq, Eq, Debug)]
//! struct Person {
//!     age: i32,
//!     name: String,
//! }
//!
//! fn get_name() -> Result<String, String> {
//!     Result::Ok("James".to_owned())
//! }
//!
//! fn get_age() -> Result<i32, String> {
//!     Result::Ok(32)
//! }
//!
//! let v = get_name().into_validated() + get_age();
//! let person = v.into_result()
//!                .map(|hlist| {
//!                     let (name, age) = hlist.into_tuple2();
//!                     Person {
//!                         name: name,
//!                         age: age,
//!                     }
//!                 });
//!
//!  assert_eq!(person.unwrap(),
//!             Person {
//!                 name: "James".to_owned(),
//!                 age: 32,
//!             });
//! # }
//! ```

use super::hlist::*;
use std::ops::Add;

/// A Validated is either an Ok holding an HList or an Err, holding a vector
/// of collected errors.
#[derive(PartialEq, Debug, Eq, Clone, PartialOrd, Ord)]
pub enum Validated<T, E>
    where T: HList
{
    Ok(T),
    Err(Vec<E>),
}

impl<T, E> Validated<T, E>
    where T: HList
{
    /// Returns true if this validation is Ok, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, String> = Result::Ok(String::from("hello"));
    /// let v = r1.into_validated();
    /// assert!(v.is_ok());
    /// ```
    pub fn is_ok(&self) -> bool {
        match *self {
            Validated::Ok(_) => true,
            _ => false,
        }
    }

    /// Returns true if this validation is Err, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }

    /// Turns this Validated into a Result.
    ///
    /// If this Validated is Ok, it will become a Result::Ok, holding an HList of all the accumulated
    /// results. Otherwise, it will become a Result::Err with a list of all accumulated errors.
    ///
    /// ```
    /// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
    ///
    /// #[derive(PartialEq, Eq, Debug)]
    /// struct Person {
    ///     age: i32,
    ///     name: String,
    /// }
    ///
    /// fn get_name() -> Result<String, String> {
    ///     Result::Ok("James".to_owned())
    /// }
    ///
    /// fn get_age() -> Result<i32, String> {
    ///     Result::Ok(32)
    /// }
    ///
    /// let v = get_name().into_validated() + get_age();
    /// let person = v.into_result()
    ///                .map(|hlist| {
    ///                     let (name, age) = hlist.into_tuple2();
    ///                     Person {
    ///                         name: name,
    ///                         age: age,
    ///                     }
    ///                 });
    ///
    ///  assert_eq!(person.unwrap(),
    ///             Person {
    ///                 name: "James".to_owned(),
    ///                 age: 32,
    ///             });
    /// # }
    pub fn into_result(self) -> Result<T, Vec<E>> {
        match self {
            Validated::Ok(h) => Result::Ok(h),
            Validated::Err(errors) => Result::Err(errors),
        }
    }
}

/// Trait for "lifting" a given type into a Validated
pub trait IntoValidated<T, E> {
    /// Consumes the current Result into a Validated so that we can begin chaining
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    fn into_validated(self) -> Validated<HCons<T, HNil>, E>;
}

impl<T, E> IntoValidated<T, E> for Result<T, E> {
    fn into_validated(self) -> Validated<HCons<T, HNil>, E> {
        match self {
            Result::Err(e) => Validated::Err(vec![e]),
            Result::Ok(v) => {
                Validated::Ok(HCons {
                    head: v,
                    tail: HNil,
                })
            }
        }
    }
}

/// Implements Add for the current Validated with a Result, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
///
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v = r1.into_validated() + r2;
/// assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
///
impl<T, E, T2> Add<Result<T2, E>> for Validated<T, E>
    where T: HList + Add<HCons<T2, HNil>>,
          <T as Add<HCons<T2, HNil>>>::Output: HList
{
    type Output = Validated<<T as Add<HCons<T2, HNil>>>::Output, E>;

    fn add(self, other: Result<T2, E>) -> Self::Output {
        let other_as_validated = other.into_validated();
        self + other_as_validated
    }
}

/// Implements Add for the current Validated with another Validated, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v1 = r1.into_validated();
/// let v2 = r2.into_validated();
/// let v3 = v1 + v2;
/// assert_eq!(v3, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
impl<T, E, T2> Add<Validated<T2, E>> for Validated<T, E>
    where T: HList + Add<T2>,
          T2: HList,
          <T as Add<T2>>::Output: HList
{
    type Output = Validated<<T as Add<T2>>::Output, E>;

    fn add(self, other: Validated<T2, E>) -> Self::Output {
        match (self, other) {
            (Validated::Err(mut errs), Validated::Err(errs2)) => {
                errs.extend(errs2);
                Validated::Err(errs)
            }
            (Validated::Err(errs), _) => Validated::Err(errs),
            (_, Validated::Err(errs)) => Validated::Err(errs),
            (Validated::Ok(h1), Validated::Ok(h2)) => Validated::Ok(h1 + h2),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::super::hlist::*;
    use super::*;

    #[test]
    fn test_adding_ok_results() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let v = r1.into_validated() + r2;
        assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
    }

    #[test]
    fn test_adding_validated_oks() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let r3: Result<i32, String> = Result::Ok(3);
        let v1 = r1.into_validated();
        let v2 = r2.into_validated();
        let v3 = r3.into_validated();
        let comb = v1 + v2 + v3;
        assert_eq!(comb, Validated::Ok(hlist!(String::from("hello"), 1, 3)))
    }

    #[test]
    fn test_adding_err_results() {
        let r1: Result<i16, String> = Result::Ok(1);
        let r2: Result<i16, String> = Result::Err(String::from("NO!"));
        let v1 = r1.into_validated() + r2;
        assert!(v1.is_err());
        assert_eq!(v1, Validated::Err(vec!["NO!".to_owned()]))
    }

    #[derive(PartialEq, Eq, Debug)]
    struct Person {
        age: i32,
        name: String,
        email: String,
    }

    #[derive(PartialEq, Eq, Debug)]
    pub enum YahNah {
        Yah,
        Nah,
    }

    /// Our Errors
    #[derive(PartialEq, Eq, Debug)]
    pub enum Nope {
        NameNope,
        AgeNope,
        EmailNope,
    }

    fn get_name(yah_nah: YahNah) -> Result<String, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok("James".to_owned()),
            _ => Result::Err(Nope::NameNope),
        }
    }

    fn get_age(yah_nah: YahNah) -> Result<i32, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok(32),
            _ => Result::Err(Nope::AgeNope),
        }
    }

    fn get_email(yah_nah: YahNah) -> Result<String, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok("hello@world.com".to_owned()),
            _ => Result::Err(Nope::EmailNope),
        }
    }

    #[test]
    fn test_to_result_ok() {
        let v = get_name(YahNah::Yah).into_validated() + get_age(YahNah::Yah) +
                get_email(YahNah::Yah);
        let person = v.into_result()
                      .map(|hlist| {
                          let (name, (age, email)) = hlist.into_tuple2();
                          Person {
                              name: name,
                              age: age,
                              email: email,
                          }
                      });

        assert_eq!(person.unwrap(),
                   Person {
                       name: "James".to_owned(),
                       age: 32,
                       email: "hello@world.com".to_owned(),
                   });
    }

    #[test]
    fn test_to_result_faulty() {
        let v = get_name(YahNah::Nah).into_validated() + get_age(YahNah::Nah) +
                get_email(YahNah::Nah);
        let person = v.into_result()
                      .map(|_| unimplemented!());

        assert_eq!(person.unwrap_err(),
                   vec![Nope::NameNope, Nope::AgeNope, Nope::EmailNope]);
    }

}
<commit_msg>Add a test for a middle Result failing<commit_after>//! Module for holding Validated logic
//!
//! `Validated` is a way of running a bunch of operations that can go wrong (for example,
//! functions returning `Result<T, E>`) and, in the case of one or more things going wrong,
//! having all the errors returned to you all at once. In the case that everything went well, you get
//! an `HList` of all your results.
//!
//! ```
//! # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
//!
//! #[derive(PartialEq, Eq, Debug)]
//! struct Person {
//!     age: i32,
//!     name: String,
//! }
//!
//! fn get_name() -> Result<String, String> {
//!     Result::Ok("James".to_owned())
//! }
//!
//! fn get_age() -> Result<i32, String> {
//!     Result::Ok(32)
//! }
//!
//! let v = get_name().into_validated() + get_age();
//! let person = v.into_result()
//!                .map(|hlist| {
//!                     let (name, age) = hlist.into_tuple2();
//!                     Person {
//!                         name: name,
//!                         age: age,
//!                     }
//!                 });
//!
//!  assert_eq!(person.unwrap(),
//!             Person {
//!                 name: "James".to_owned(),
//!                 age: 32,
//!             });
//! # }
//! ```

use super::hlist::*;
use std::ops::Add;

/// A Validated is either an Ok holding an HList or an Err, holding a vector
/// of collected errors.
#[derive(PartialEq, Debug, Eq, Clone, PartialOrd, Ord)]
pub enum Validated<T, E>
    where T: HList
{
    Ok(T),
    Err(Vec<E>),
}

impl<T, E> Validated<T, E>
    where T: HList
{
    /// Returns true if this validation is Ok, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, String> = Result::Ok(String::from("hello"));
    /// let v = r1.into_validated();
    /// assert!(v.is_ok());
    /// ```
    pub fn is_ok(&self) -> bool {
        match *self {
            Validated::Ok(_) => true,
            _ => false,
        }
    }

    /// Returns true if this validation is Err, false otherwise
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    pub fn is_err(&self) -> bool {
        !self.is_ok()
    }

    /// Turns this Validated into a Result.
    ///
    /// If this Validated is Ok, it will become a Result::Ok, holding an HList of all the accumulated
    /// results. Otherwise, it will become a Result::Err with a list of all accumulated errors.
    ///
    /// ```
    /// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
    ///
    /// #[derive(PartialEq, Eq, Debug)]
    /// struct Person {
    ///     age: i32,
    ///     name: String,
    /// }
    ///
    /// fn get_name() -> Result<String, String> {
    ///     Result::Ok("James".to_owned())
    /// }
    ///
    /// fn get_age() -> Result<i32, String> {
    ///     Result::Ok(32)
    /// }
    ///
    /// let v = get_name().into_validated() + get_age();
    /// let person = v.into_result()
    ///                .map(|hlist| {
    ///                     let (name, age) = hlist.into_tuple2();
    ///                     Person {
    ///                         name: name,
    ///                         age: age,
    ///                     }
    ///                 });
    ///
    ///  assert_eq!(person.unwrap(),
    ///             Person {
    ///                 name: "James".to_owned(),
    ///                 age: 32,
    ///             });
    /// # }
    pub fn into_result(self) -> Result<T, Vec<E>> {
        match self {
            Validated::Ok(h) => Result::Ok(h),
            Validated::Err(errors) => Result::Err(errors),
        }
    }
}

/// Trait for "lifting" a given type into a Validated
pub trait IntoValidated<T, E> {
    /// Consumes the current Result into a Validated so that we can begin chaining
    ///
    /// ```
    /// # use frunk::validated::*;
    ///
    /// let r1: Result<String, i32> = Result::Err(32);
    /// let v = r1.into_validated();
    /// assert!(v.is_err());
    /// ```
    fn into_validated(self) -> Validated<HCons<T, HNil>, E>;
}

impl<T, E> IntoValidated<T, E> for Result<T, E> {
    fn into_validated(self) -> Validated<HCons<T, HNil>, E> {
        match self {
            Result::Err(e) => Validated::Err(vec![e]),
            Result::Ok(v) => {
                Validated::Ok(HCons {
                    head: v,
                    tail: HNil,
                })
            }
        }
    }
}

/// Implements Add for the current Validated with a Result, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
///
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v = r1.into_validated() + r2;
/// assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
///
impl<T, E, T2> Add<Result<T2, E>> for Validated<T, E>
    where T: HList + Add<HCons<T2, HNil>>,
          <T as Add<HCons<T2, HNil>>>::Output: HList
{
    type Output = Validated<<T as Add<HCons<T2, HNil>>>::Output, E>;

    fn add(self, other: Result<T2, E>) -> Self::Output {
        let other_as_validated = other.into_validated();
        self + other_as_validated
    }
}

/// Implements Add for the current Validated with another Validated, returning a new Validated.
///
/// ```
/// # #[macro_use] extern crate frunk; use frunk::hlist::*; use frunk::validated::*; fn main() {
/// let r1: Result<String, String> = Result::Ok(String::from("hello"));
/// let r2: Result<i32, String> = Result::Ok(1);
/// let v1 = r1.into_validated();
/// let v2 = r2.into_validated();
/// let v3 = v1 + v2;
/// assert_eq!(v3, Validated::Ok(hlist!(String::from("hello"), 1)))
/// # }
/// ```
impl<T, E, T2> Add<Validated<T2, E>> for Validated<T, E>
    where T: HList + Add<T2>,
          T2: HList,
          <T as Add<T2>>::Output: HList
{
    type Output = Validated<<T as Add<T2>>::Output, E>;

    fn add(self, other: Validated<T2, E>) -> Self::Output {
        match (self, other) {
            (Validated::Err(mut errs), Validated::Err(errs2)) => {
                errs.extend(errs2);
                Validated::Err(errs)
            }
            (Validated::Err(errs), _) => Validated::Err(errs),
            (_, Validated::Err(errs)) => Validated::Err(errs),
            (Validated::Ok(h1), Validated::Ok(h2)) => Validated::Ok(h1 + h2),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::super::hlist::*;
    use super::*;

    #[test]
    fn test_adding_ok_results() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let v = r1.into_validated() + r2;
        assert_eq!(v, Validated::Ok(hlist!(String::from("hello"), 1)))
    }

    #[test]
    fn test_adding_validated_oks() {
        let r1: Result<String, String> = Result::Ok(String::from("hello"));
        let r2: Result<i32, String> = Result::Ok(1);
        let r3: Result<i32, String> = Result::Ok(3);
        let v1 = r1.into_validated();
        let v2 = r2.into_validated();
        let v3 = r3.into_validated();
        let comb = v1 + v2 + v3;
        assert_eq!(comb, Validated::Ok(hlist!(String::from("hello"), 1, 3)))
    }

    #[test]
    fn test_adding_err_results() {
        let r1: Result<i16, String> = Result::Ok(1);
        let r2: Result<i16, String> = Result::Err(String::from("NO!"));
        let v1 = r1.into_validated() + r2;
        assert!(v1.is_err());
        assert_eq!(v1, Validated::Err(vec!["NO!".to_owned()]))
    }

    #[derive(PartialEq, Eq, Debug)]
    struct Person {
        age: i32,
        name: String,
        email: String,
    }

    #[derive(PartialEq, Eq, Debug)]
    pub enum YahNah {
        Yah,
        Nah,
    }

    /// Our Errors
    #[derive(PartialEq, Eq, Debug)]
    pub enum Nope {
        NameNope,
        AgeNope,
        EmailNope,
    }

    fn get_name(yah_nah: YahNah) -> Result<String, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok("James".to_owned()),
            _ => Result::Err(Nope::NameNope),
        }
    }

    fn get_age(yah_nah: YahNah) -> Result<i32, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok(32),
            _ => Result::Err(Nope::AgeNope),
        }
    }

    fn get_email(yah_nah: YahNah) -> Result<String, Nope> {
        match yah_nah {
            YahNah::Yah => Result::Ok("hello@world.com".to_owned()),
            _ => Result::Err(Nope::EmailNope),
        }
    }

    #[test]
    fn test_to_result_ok() {
        let v = get_name(YahNah::Yah).into_validated() + get_age(YahNah::Yah) +
                get_email(YahNah::Yah);
        let person = v.into_result()
                      .map(|hlist| {
                          let (name, (age, email)) = hlist.into_tuple2();
                          Person {
                              name: name,
                              age: age,
                              email: email,
                          }
                      });

        assert_eq!(person.unwrap(),
                   Person {
                       name: "James".to_owned(),
                       age: 32,
                       email: "hello@world.com".to_owned(),
                   });
    }

    #[test]
    fn test_to_result_all_faulty() {
        let v = get_name(YahNah::Nah).into_validated() + get_age(YahNah::Nah) +
                get_email(YahNah::Nah);
        let person = v.into_result()
                      .map(|_| unimplemented!());

        assert_eq!(person.unwrap_err(),
                   vec![Nope::NameNope, Nope::AgeNope, Nope::EmailNope]);
    }

    #[test]
    fn test_to_result_one_faulty() {
        let v = get_name(YahNah::Nah).into_validated() + get_age(YahNah::Yah) +
                get_email(YahNah::Nah);
        let person = v.into_result()
                      .map(|_| unimplemented!());

        assert_eq!(person.unwrap_err(),
                   vec![Nope::NameNope, Nope::EmailNope]);
    }

}
<|endoftext|>


<commit_before>
use ::c;
use std::str;
use std::ffi::{CStr};

pub struct XmpString {
    ptr: *mut c::XmpString
}

impl XmpString {
    pub fn new() -> XmpString {
        XmpString { ptr: unsafe { c::xmp_string_new() } }
    }

    pub fn is_null(&self) -> bool {
        self.ptr.is_null()
    }

    pub fn as_ptr(&self) -> *const c::XmpString {
        self.ptr
    }

    pub fn as_mut_ptr(&mut self) -> *mut c::XmpString {
        self.ptr
    }

    // XXX properly deal with the utf8 error
    pub fn to_str(&self) -> &str {
        unsafe {
            let s = CStr::from_ptr(c::xmp_string_cstr(self.ptr));
            // we are supposed to receive UTF8 from the library.
            str::from_utf8_unchecked(s.to_bytes())
        }
    }
}

impl Drop for XmpString {
    fn drop(&mut self) {
        if !self.is_null() {
            unsafe { c::xmp_string_free(self.ptr) };
        }
    }
}
<commit_msg>Implement Eq trait for XmpString<commit_after>
use ::c;
use std::str;
use std::ffi::{CStr};

pub struct XmpString {
    ptr: *mut c::XmpString
}

impl XmpString {
    pub fn new() -> XmpString {
        XmpString { ptr: unsafe { c::xmp_string_new() } }
    }

    pub fn is_null(&self) -> bool {
        self.ptr.is_null()
    }

    pub fn as_ptr(&self) -> *const c::XmpString {
        self.ptr
    }

    pub fn as_mut_ptr(&mut self) -> *mut c::XmpString {
        self.ptr
    }

    // XXX properly deal with the utf8 error
    pub fn to_str(&self) -> &str {
        unsafe {
            let s = CStr::from_ptr(c::xmp_string_cstr(self.ptr));
            // we are supposed to receive UTF8 from the library.
            str::from_utf8_unchecked(s.to_bytes())
        }
    }
}

impl Drop for XmpString {
    fn drop(&mut self) {
        if !self.is_null() {
            unsafe { c::xmp_string_free(self.ptr) };
        }
    }
}

impl Eq for XmpString {

}
impl PartialEq for XmpString {
    fn eq(&self, other: &XmpString) -> bool {
        self.to_str() == other.to_str()
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

use capnp::message::TypedReader;
use capnp::serialize::OwnedSegments;
use std::sync::mpsc;
use std::thread;

pub mod addressbook {
    use addressbook_capnp::{address_book, person};
    use capnp::{serialize};
    use capnp::message::TypedReader;

    pub fn build_address_book() -> TypedReader<serialize::OwnedSegments, address_book::Owned> {
        let mut message = ::capnp::message::Builder::new_default();
        {
            let address_book = message.init_root::<address_book::Builder>();

            let mut people = address_book.init_people(2);

            {
                let mut alice = people.borrow().get(0);
                alice.set_id(123);
                alice.set_name("Alice");
                alice.set_email("alice@example.com");
                {
                    let mut alice_phones = alice.borrow().init_phones(1);
                    alice_phones.borrow().get(0).set_number("555-1212");
                    alice_phones.borrow().get(0).set_type(person::phone_number::Type::Mobile);
                }
                alice.get_employment().set_school("MIT");
            }

            {
                let mut bob = people.get(1);
                bob.set_id(456);
                bob.set_name("Bob");
                bob.set_email("bob@example.com");
                {
                    let mut bob_phones = bob.borrow().init_phones(2);
                    bob_phones.borrow().get(0).set_number("555-4567");
                    bob_phones.borrow().get(0).set_type(person::phone_number::Type::Home);
                    bob_phones.borrow().get(1).set_number("555-7654");
                    bob_phones.borrow().get(1).set_type(person::phone_number::Type::Work);
                }
                bob.get_employment().set_unemployed(());
            }
        }

        let mut buffer = Vec::new();
        ::capnp::serialize::write_message(&mut buffer, &message).unwrap();

        // Unwrap here is safe because we just created the message above
        let message_reader = ::capnp::serialize::read_message(
            &mut buffer.as_slice(),
            ::capnp::message::ReaderOptions::new()
        ).unwrap();

        TypedReader::new(message_reader)
    }
}

pub fn main() {

    let book = addressbook::build_address_book();

    let (tx_book, rx_book) = mpsc::channel::<TypedReader<OwnedSegments, addressbook_capnp::address_book::Owned>>();
    let (tx_id, rx_id) = mpsc::channel::<u32>();

    thread::spawn(move || {
        let addressbook_reader = rx_book.recv().unwrap();
        let addressbook = addressbook_reader.get().unwrap();
        let first_person = addressbook.get_people().unwrap().get(0);
        let first_id = first_person.get_id();
        tx_id.send(first_id)
    });

    tx_book.send(book).unwrap();
    let first_id = rx_id.recv().unwrap();
    assert_eq!(first_id, 123);
}
<commit_msg>Update addressbook_send.rs<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

use capnp::message::{Builder, HeapAllocator, TypedReader};
use std::sync::mpsc;
use std::thread;

pub mod addressbook {
    use addressbook_capnp::{address_book, person};
    use capnp::message::{Builder, HeapAllocator, TypedReader};

    pub fn build_address_book() -> TypedReader<Builder<HeapAllocator>, address_book::Owned> {
        let mut message = Builder::new_default();
        {
            let address_book = message.init_root::<address_book::Builder>();

            let mut people = address_book.init_people(2);

            {
                let mut alice = people.borrow().get(0);
                alice.set_id(123);
                alice.set_name("Alice");
                alice.set_email("alice@example.com");
                {
                    let mut alice_phones = alice.borrow().init_phones(1);
                    alice_phones.borrow().get(0).set_number("555-1212");
                    alice_phones.borrow().get(0).set_type(person::phone_number::Type::Mobile);
                }
                alice.get_employment().set_school("MIT");
            }

            {
                let mut bob = people.get(1);
                bob.set_id(456);
                bob.set_name("Bob");
                bob.set_email("bob@example.com");
                {
                    let mut bob_phones = bob.borrow().init_phones(2);
                    bob_phones.borrow().get(0).set_number("555-4567");
                    bob_phones.borrow().get(0).set_type(person::phone_number::Type::Home);
                    bob_phones.borrow().get(1).set_number("555-7654");
                    bob_phones.borrow().get(1).set_type(person::phone_number::Type::Work);
                }
                bob.get_employment().set_unemployed(());
            }
        }

        message.into_typed()
    }
}

pub fn main() {

    let book = addressbook::build_address_book();

    let (tx_book, rx_book) = mpsc::channel::<TypedReader<Builder<HeapAllocator>, addressbook_capnp::address_book::Owned>>();
    let (tx_id, rx_id) = mpsc::channel::<u32>();

    thread::spawn(move || {
        let addressbook_reader = rx_book.recv().unwrap();
        let addressbook = addressbook_reader.get().unwrap();
        let first_person = addressbook.get_people().unwrap().get(0);
        let first_id = first_person.get_id();
        tx_id.send(first_id)
    });

    tx_book.send(book).unwrap();
    let first_id = rx_id.recv().unwrap();
    assert_eq!(first_id, 123);
}
<|endoftext|>


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

extern crate cmake;

use std::env;
use std::path::{Path, PathBuf};

fn build_shaderc(shaderc_dir: &PathBuf) -> PathBuf {
        cmake::Config::new(shaderc_dir)
            .profile("Release")
            .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
            .define("SPIRV_SKIP_EXECUTABLES", "ON")
            .define("SHADERC_SKIP_TESTS", "ON")
            .define("CMAKE_INSTALL_LIBDIR", "lib")
            .build()
}

fn build_shaderc_msvc(shaderc_dir: &PathBuf) -> PathBuf {
    cmake::Config::new(shaderc_dir)
            .profile("Release")
            .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
            .define("SPIRV_SKIP_EXECUTABLES", "ON")
            .define("SHADERC_SKIP_TESTS", "ON")
            // cmake-rs tries to be clever on Windows by injecting several
            // C/C++ flags, which causes problems. So I have to manually
            // define CMAKE_*_FLAGS_* here to suppress that.
            .define("CMAKE_C_FLAGS", " /nologo /EHsc")
            .define("CMAKE_CXX_FLAGS", " /nologo /EHsc")
            .define("CMAKE_C_FLAGS_RELEASE", " /nologo /EHsc")
            .define("CMAKE_CXX_FLAGS_RELEASE", " /nologo /EHsc")
            .define("CMAKE_INSTALL_LIBDIR", "lib")
            .build()
}

fn main() {
    if env::var("CARGO_FEATURE_BUILD_NATIVE_SHADERC").is_err() {
        println!("cargo:warning=requested to skip building native C++ shaderc");
        return
    }

    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let shaderc_dir = Path::new(&manifest_dir).join("build");

    let mut lib_path = if target_env == "msvc" {
        build_shaderc_msvc(&shaderc_dir)
    } else {
        build_shaderc(&shaderc_dir)
    };

    lib_path.push("lib");

    println!("cargo:rustc-link-search=native={}", lib_path.display());
    if target_os == "windows" {
        println!("cargo:rustc-link-lib=static=shaderc_combined");
    } else {
        println!("cargo:rustc-link-lib=dylib=shaderc_shared");
    }
}
<commit_msg>Link static library on Linux and MacOS<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate cmake;

use std::env;
use std::path::{Path, PathBuf};

fn build_shaderc(shaderc_dir: &PathBuf) -> PathBuf {
        cmake::Config::new(shaderc_dir)
            .profile("Release")
            .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
            .define("SPIRV_SKIP_EXECUTABLES", "ON")
            .define("SHADERC_SKIP_TESTS", "ON")
            .define("CMAKE_INSTALL_LIBDIR", "lib")
            .build()
}

fn build_shaderc_msvc(shaderc_dir: &PathBuf) -> PathBuf {
    cmake::Config::new(shaderc_dir)
            .profile("Release")
            .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
            .define("SPIRV_SKIP_EXECUTABLES", "ON")
            .define("SHADERC_SKIP_TESTS", "ON")
            // cmake-rs tries to be clever on Windows by injecting several
            // C/C++ flags, which causes problems. So I have to manually
            // define CMAKE_*_FLAGS_* here to suppress that.
            .define("CMAKE_C_FLAGS", " /nologo /EHsc")
            .define("CMAKE_CXX_FLAGS", " /nologo /EHsc")
            .define("CMAKE_C_FLAGS_RELEASE", " /nologo /EHsc")
            .define("CMAKE_CXX_FLAGS_RELEASE", " /nologo /EHsc")
            .define("CMAKE_INSTALL_LIBDIR", "lib")
            .build()
}

fn main() {
    if env::var("CARGO_FEATURE_BUILD_NATIVE_SHADERC").is_err() {
        println!("cargo:warning=requested to skip building native C++ shaderc");
        return
    }

    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let shaderc_dir = Path::new(&manifest_dir).join("build");

    let mut lib_path = if target_env == "msvc" {
        build_shaderc_msvc(&shaderc_dir)
    } else {
        build_shaderc(&shaderc_dir)
    };

    lib_path.push("lib");

    println!("cargo:rustc-link-search=native={}", lib_path.display());
    println!("cargo:rustc-link-lib=static=shaderc_combined");
    if target_os == "linux" {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    } else if target_os == "macos" {
        println!("cargo:rustc-link-lib=dylib=c++");
    }
}
<|endoftext|>


<commit_before><commit_msg>Default clap app builder: Allow external subcommands<commit_after><|endoftext|>


<commit_before>use graphics::*;

// Local crate.
use Vector2d = vector2d::Vector2d;

static EPSILON: f64 = 0.0000000001;

pub fn area(contour: &[Vector2d]) -> f64 {
    let n = contour.len();
    let mut A = 0.0_f64;

    for i in range(0, n) {
        let q = i;
        let p = (i + n - 1) % n;
        A += contour.get(p).unwrap().get_x() * contour.get(q).unwrap().get_y()
            - contour.get(q).unwrap().get_x() * contour.get(p).unwrap().get_y();
    }

    A * 0.5_f64
}

/// InsideTriangle decides if a point P is Inside of the triangle
/// defined by A, B, C.
pub fn inside_triangle(
    Ax: f64, Ay: f64,
    Bx: f64, By: f64,
    Cx: f64, Cy: f64,
    Px: f64, Py: f64
) -> bool {

    let ax = Cx - Bx;
    let ay = Cy - By;
    let bx = Ax - Cx;
    let by = Ay - Cy;
    let cx = Bx - Ax;
    let cy = By - Ay;
    let apx = Px - Ax;
    let apy = Py - Ay;
    let bpx = Px - Bx;
    let bpy = Py - By;
    let cpx = Px - Cx;
    let cpy = Py - Cy;

    let aCROSSbp = ax*bpy - ay*bpx;
    let cCROSSap = cx*apy - cy*apx;
    let bCROSScp = bx*cpy - by*cpx;

    (
        (aCROSSbp >= 0.0_f64)
        && (bCROSScp >= 0.0_f64)
        && (cCROSSap >= 0.0_f64)
    )
}

pub fn snip(
    contour: &[Vector2d],
    u: uint,
    v: uint,
    w: uint,
    n: uint,
    V: &mut Vec<uint>
) -> bool {

    let Ax = contour.get(*V.get(u)).unwrap().get_x();
    let Ay = contour.get(*V.get(u)).unwrap().get_y();

    let Bx = contour.get(*V.get(v)).unwrap().get_x();
    let By = contour.get(*V.get(v)).unwrap().get_y();

    let Cx = contour.get(*V.get(w)).unwrap().get_x();
    let Cy = contour.get(*V.get(w)).unwrap().get_y();

    if EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) {
        return false;
    }

    for p in range(0, n) {
        if (p == u) || (p == v) || (p == w) { continue; }

        let Px = contour.get(*V.get(p)).unwrap().get_x();
        let Py = contour.get(*V.get(p)).unwrap().get_y();

        if inside_triangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py) { return false; }
    }

    return true;
}

pub fn process(
    contour: &[Vector2d]
) -> Option<Vec<Vector2d>> {
    /* allocate and initialize list of Vertices in polygon */

    let n = contour.len();
    if n < 3 { return None; }

    let mut result: Vec<Vector2d> = Vec::new();
    let mut V: Vec<uint> = Vec::with_capacity(n);

    /* we want a counter-clockwise polygon in V */

    // Computes the area which has opposite signs
    // whether the polygon is clock-wise or counter-clockwise.
    if 0.0_f64 < area(contour) {
        for v in range(0, n) { V.push(v); }
    } else {
        for v in range(0, n) { V.push((n-1)-v); }
    }

    let mut number_of_vertices = n;

    /*  remove nv-2 Vertices, creating 1 triangle every time */
    let mut count = 2 * number_of_vertices;   /* error detection */

    let mut m = 0;
    let mut v = number_of_vertices - 1;
    while number_of_vertices > 2 {
        /* if we loop, it is probably a non-simple polygon */
        if count <= 0 {
            //** Triangulate: ERROR - probable bad polygon!
            return None;
        }

        count -= 1;

        /* three consecutive vertices in current polygon, <u,v,w> */
        let u = v;
        v = vecmath::modular_offset_index(number_of_vertices, v, 1);
        let w = vecmath::modular_offset_index(number_of_vertices, v, 1);

        if snip(contour, u, v, w, number_of_vertices, &mut V) {
            for &i in [u, v, w].iter() {
                result.push(*contour.get(*V.get(i)).unwrap());
            }

            m += 1;

            /* remove v from remaining polygon */
            for i in range(0, number_of_vertices - 3) {
                let s = v + i;
                let t = v + i + 1;

                *V.get_mut(s) = *V.get(t);
            }

            // "Removed" a vertex.
            number_of_vertices -= 1;

            /* resest error detection counter */
            count = 2 * number_of_vertices;
        }
    }

    Some(result)
}

<commit_msg>Simplified to triangle<commit_after>use graphics::*;

// Local crate.
use Vector2d = vector2d::Vector2d;

static EPSILON: f64 = 0.0000000001;

pub fn area(contour: &[Vector2d]) -> f64 {
    let n = contour.len();
    let mut A = 0.0_f64;

    for i in range(0, n) {
        let q = i;
        let p = (i + n - 1) % n;
        A += contour.get(p).unwrap().get_x() * contour.get(q).unwrap().get_y()
            - contour.get(q).unwrap().get_x() * contour.get(p).unwrap().get_y();
    }

    A * 0.5_f64
}

/// InsideTriangle decides if a point P is Inside of the triangle
/// defined by A, B, C.
pub fn inside_triangle(
    Ax: f64, Ay: f64,
    Bx: f64, By: f64,
    Cx: f64, Cy: f64,
    Px: f64, Py: f64
) -> bool {

    let ax = Cx - Bx;
    let ay = Cy - By;
    let bx = Ax - Cx;
    let by = Ay - Cy;
    let cx = Bx - Ax;
    let cy = By - Ay;
    let apx = Px - Ax;
    let apy = Py - Ay;
    let bpx = Px - Bx;
    let bpy = Py - By;
    let cpx = Px - Cx;
    let cpy = Py - Cy;

    let aCROSSbp = ax*bpy - ay*bpx;
    let cCROSSap = cx*apy - cy*apx;
    let bCROSScp = bx*cpy - by*cpx;

    (
        (aCROSSbp >= 0.0_f64)
        && (bCROSScp >= 0.0_f64)
        && (cCROSSap >= 0.0_f64)
    )
}

pub fn snip(
    contour: &[Vector2d],
    u: uint,
    v: uint,
    w: uint,
    n: uint,
    V: &mut Vec<uint>
) -> bool {

    let Ax = contour.get(*V.get(u)).unwrap().get_x();
    let Ay = contour.get(*V.get(u)).unwrap().get_y();

    let Bx = contour.get(*V.get(v)).unwrap().get_x();
    let By = contour.get(*V.get(v)).unwrap().get_y();

    let Cx = contour.get(*V.get(w)).unwrap().get_x();
    let Cy = contour.get(*V.get(w)).unwrap().get_y();

    if EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) {
        return false;
    }

    for p in range(0, n) {
        if (p == u) || (p == v) || (p == w) { continue; }

        let Px = contour.get(*V.get(p)).unwrap().get_x();
        let Py = contour.get(*V.get(p)).unwrap().get_y();

        if inside_triangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py) { return false; }
    }

    return true;
}

pub fn process(
    contour: &[Vector2d]
) -> Option<Vec<Vector2d>> {
    /* allocate and initialize list of Vertices in polygon */

    let n = contour.len();
    if n < 3 { return None; }

    let mut result: Vec<Vector2d> = Vec::new();
    let mut V: Vec<uint> = Vec::with_capacity(n);

    /* we want a counter-clockwise polygon in V */

    // Computes the area which has opposite signs
    // whether the polygon is clock-wise or counter-clockwise.
    if 0.0_f64 < area(contour) {
        for v in range(0, n) { V.push(v); }
    } else {
        for v in range(0, n) { V.push((n-1)-v); }
    }

    let mut number_of_vertices = n;

    /*  remove nv-2 Vertices, creating 1 triangle every time */
    let mut count = 2 * number_of_vertices;   /* error detection */

    let mut m = 0;
    let mut v = number_of_vertices - 1;
    while number_of_vertices > 2 {
        /* if we loop, it is probably a non-simple polygon */
        if count <= 0 {
            //** Triangulate: ERROR - probable bad polygon!
            return None;
        }

        count -= 1;

        /* three consecutive vertices in current polygon, <u,v,w> */
        let triangle = [
            v,
            vecmath::modular_offset_index(number_of_vertices, v, 1),
            vecmath::modular_offset_index(number_of_vertices, v, 2)
        ];
        v = triangle[1];

        if snip(contour, triangle[0], triangle[1], triangle[2], number_of_vertices, &mut V) {
            for &i in triangle.iter() {
                result.push(*contour.get(*V.get(i)).unwrap());
            }

            m += 1;

            /* remove v from remaining polygon */
            for i in range(0, number_of_vertices - 3) {
                let s = v + i;
                let t = v + i + 1;

                *V.get_mut(s) = *V.get(t);
            }

            // "Removed" a vertex.
            number_of_vertices -= 1;

            /* resest error detection counter */
            count = 2 * number_of_vertices;
        }
    }

    Some(result)
}

<|endoftext|>