<commit_before>/*
    This file is a part of cargo-esr.

    Copyright (C) 2017 Mohammad AlSaleh <CE.Mohammad.AlSaleh at gmail.com>
    https://github.com/rust-alt/cargo-esr

    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 term_painter::{Style, ToStyle};
use term_painter::Attr::{Plain, Bold};
use term_painter::Color::{Red, Cyan, Yellow, Green, Blue};

use esr_errors::*;

#[derive(Clone)]
pub struct EsrFormatter {
    style: Style,
    text: String,
    trail: String,
}

impl EsrFormatter {
    pub fn new(style: Style, text: &str, trail: &str) -> Self {
        Self {
            style,
            text: String::from(text),
            trail: String::from(trail),
        }
    }

    pub fn trail_only(trail: &str) -> Self {
        Self {
            style: Plain.to_style(),
            text: String::new(),
            trail: String::from(trail),
        }
    }

    pub fn empty() -> Self {
        Self {
            style: Plain.to_style(),
            text: String::new(),
            trail: String::new(),
        }
    }

    pub fn print(&self, formatted: bool) {
        if formatted {
            print!("{}{}", self.style.paint(&self.text), self.trail);
        } else {
            print!("{}{}", &self.text, self.trail);
        }
    }

    pub fn print_grp(grp: &[Self], formatted: bool) {
        for f in grp {
            f.print(formatted);
        }
        println!("");
    }
}

pub struct EsrPrinter;

impl EsrPrinter {
    pub fn msg_pair(msg: &str, val: &str) -> [EsrFormatter; 2] {
        [
            EsrFormatter::new(Cyan.bold(), msg, ": "),
            EsrFormatter::new(Bold.to_style(), val, "\n "),
        ]
    }

    pub fn msg_pair_complex(msg: &str, val: &[EsrFormatter]) -> Vec<EsrFormatter> {
        let mut ret = Vec::with_capacity(val.len() + 1);
        ret.push(EsrFormatter::new(Cyan.bold(), msg, ": "));
        ret.extend_from_slice(val);
        ret
    }

    pub fn id(id: &str) -> EsrFormatter {
        EsrFormatter::new(Blue.bold(), id, " ")
    }

    pub fn err(val: &str) -> EsrFormatter {
        EsrFormatter::new(Red.bold(), val, "\n")
    }

    pub fn all_yanked() -> EsrFormatter {
        EsrFormatter::new(Red.bold(), "(empty/all yanked)", "\n ")
    }

    pub fn desc(orig_desc: &str) -> String {
        let desc = String::from(orig_desc);

        // Replace white-space with a single space
        let mut tmp = desc.replace(&['\t', '\n'][..], " ");
        let fixed_ws = loop {
            let curr = tmp.replace("  ", " ");
            if curr == tmp {
                break curr.trim().to_string();
            }
            tmp = curr;
        };

        // Multi-line
        let mut last_n = fixed_ws.rfind('\n').unwrap_or(0);
        let mut multi_line = fixed_ws;

        while multi_line.len() - last_n > 64 {
            let new_n = multi_line[last_n+1..last_n+64].rfind(' ').unwrap_or(last_n);
            if new_n != last_n {
                assert!(last_n+new_n+1 < multi_line.len());
                unsafe { multi_line.as_mut_vec()[last_n+new_n+1] = b'\0' };
                multi_line = multi_line.replace('\0', "\n              ");
                last_n += new_n + " Discription: ".len();
            }
            else {
                break;
            }
        }

        multi_line
    }

    pub fn release(ver_opt: Option<&str>, age_res_opt: Option<Result<f64>>) -> String {
        match (ver_opt, age_res_opt) {
            (Some(ver), Some(Ok(age))) => format!("{} (released {:.1} months ago)", ver, age),
            _ => "N/A".into(),
        }
    }

    pub fn releases(stable: usize, non_yanked_pre: usize, yanked: usize) -> [EsrFormatter; 3] {
        [
            EsrFormatter::new(Green.bold(), &format!("{}", stable), "+"),
            EsrFormatter::new(Yellow.bold(), &format!("{}", non_yanked_pre), "+"),
            EsrFormatter::new(Red.bold(), &format!("{}", yanked), "\n "),
        ]
    }

    pub fn score_error(msg: &str) -> [EsrFormatter; 2] {
        [
            EsrFormatter::new(Red.bold(), msg, ": "),
            EsrFormatter::new(Bold.to_style(), "Error", "\n "),
        ]
    }

    pub fn score_na(msg: &str) -> [EsrFormatter; 2] {
        Self::msg_pair(msg, "N/A")
    }

    pub fn score_overview(msg: &str, pos: f64, neg: f64) -> [EsrFormatter; 4] {
        [
            EsrFormatter::new(Cyan.bold(), msg, ": "),
            EsrFormatter::new(Yellow.bold(), &format!("{:.3}", pos + neg) , " ("),
            EsrFormatter::new(Green.bold(), &format!("+{:.3}", pos) , " / "),
            EsrFormatter::new(Red.bold(), &format!("{:.3}", neg) , ")\n "),
        ]
    }

    pub fn score_details(msg: &str, table: &[(String, String, String)]) -> Vec<EsrFormatter> {
        let msg = format!("{: ^44}", msg);
        let frame = format!("{: ^44}", "-".repeat(msg.len()));

        let mut score_formatted = Vec::with_capacity(4096);
        score_formatted.push(EsrFormatter::new(Cyan.bold(), &*frame, "\n"));
        score_formatted.push(EsrFormatter::new(Cyan.bold(), &*msg, "\n"));
        score_formatted.push(EsrFormatter::new(Cyan.bold(), &*frame, "\n"));

        for line in table {
            if line.1.find("* -").is_some() {
                score_formatted.push(EsrFormatter::new(Yellow.bold(), &*line.0, " | "));
                score_formatted.push(EsrFormatter::new(Red.bold(), &*line.1, " | "));
                score_formatted.push(EsrFormatter::new(Red.bold(), &*line.2, "\n"));
            } else {
                score_formatted.push(EsrFormatter::new(Yellow.bold(), &*line.0, " | "));
                score_formatted.push(EsrFormatter::new(Red.bold(), &*line.1, " | "));
                score_formatted.push(EsrFormatter::new(Red.bold(), &*("+".to_string() + &*line.2), "\n"));
            }
        }
        score_formatted
    }

    pub fn crate_no_score(id: &str) {
        let msg = format!("Failed to get scores for crate \"{}\". Maybe it does not exist!", id);
        println!("{}", Red.bold().paint(&msg));
    }

    pub fn search_no_results(search_pattern: &str) {
        let msg = format!("Searching for \"{}\" returned no results.", search_pattern);
        println!("{}", Yellow.bold().paint(&msg));
    }

    pub fn search_failed(search_pattern: &str) {
        let msg = format!("Search for \"{}\" failed.", search_pattern);
        println!("{}", Red.bold().paint(&msg));
    }

    pub fn limit_out_of_range(limit: usize, min: usize, max: usize) {
        let msg = format!("{} is out of the range of valid limits. \
                          Please pass a value between {} and {}.", limit, min, max);
        println!("{}", Yellow.bold().paint(&msg));
    }

    pub fn limit_invalid(limit: &str) {
        let msg = format!("\"{}\" is an invalid limit value.", limit);
        println!("{}", Yellow.bold().paint(&msg));
    }

    pub fn no_token() {
        let msg = "Accessing GitHub's API wothout hitting rate-limits requires providing an access\
                   token.\n\n\
                   You can pass a token via -g/--gh-token option.\n\
                   Or by setting the variable CARGO_ESR_GH_TOKEN in the environment.\n\n\
                   To a acquire an access token, visit: <https://github.com/settings/tokens/new>\n\n\
                   Alternatively, you can pass -o/--crate-only to skip getting repository info.";
        println!("{}", Yellow.bold().paint(msg));
    }
}
<commit_msg>esr_printer: Fix printing positive detailed scores in green<commit_after>/*
    This file is a part of cargo-esr.

    Copyright (C) 2017 Mohammad AlSaleh <CE.Mohammad.AlSaleh at gmail.com>
    https://github.com/rust-alt/cargo-esr

    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 term_painter::{Style, ToStyle};
use term_painter::Attr::{Plain, Bold};
use term_painter::Color::{Red, Cyan, Yellow, Green, Blue};

use esr_errors::*;

#[derive(Clone)]
pub struct EsrFormatter {
    style: Style,
    text: String,
    trail: String,
}

impl EsrFormatter {
    pub fn new(style: Style, text: &str, trail: &str) -> Self {
        Self {
            style,
            text: String::from(text),
            trail: String::from(trail),
        }
    }

    pub fn trail_only(trail: &str) -> Self {
        Self {
            style: Plain.to_style(),
            text: String::new(),
            trail: String::from(trail),
        }
    }

    pub fn empty() -> Self {
        Self {
            style: Plain.to_style(),
            text: String::new(),
            trail: String::new(),
        }
    }

    pub fn print(&self, formatted: bool) {
        if formatted {
            print!("{}{}", self.style.paint(&self.text), self.trail);
        } else {
            print!("{}{}", &self.text, self.trail);
        }
    }

    pub fn print_grp(grp: &[Self], formatted: bool) {
        for f in grp {
            f.print(formatted);
        }
        println!("");
    }
}

pub struct EsrPrinter;

impl EsrPrinter {
    pub fn msg_pair(msg: &str, val: &str) -> [EsrFormatter; 2] {
        [
            EsrFormatter::new(Cyan.bold(), msg, ": "),
            EsrFormatter::new(Bold.to_style(), val, "\n "),
        ]
    }

    pub fn msg_pair_complex(msg: &str, val: &[EsrFormatter]) -> Vec<EsrFormatter> {
        let mut ret = Vec::with_capacity(val.len() + 1);
        ret.push(EsrFormatter::new(Cyan.bold(), msg, ": "));
        ret.extend_from_slice(val);
        ret
    }

    pub fn id(id: &str) -> EsrFormatter {
        EsrFormatter::new(Blue.bold(), id, " ")
    }

    pub fn err(val: &str) -> EsrFormatter {
        EsrFormatter::new(Red.bold(), val, "\n")
    }

    pub fn all_yanked() -> EsrFormatter {
        EsrFormatter::new(Red.bold(), "(empty/all yanked)", "\n ")
    }

    pub fn desc(orig_desc: &str) -> String {
        let desc = String::from(orig_desc);

        // Replace white-space with a single space
        let mut tmp = desc.replace(&['\t', '\n'][..], " ");
        let fixed_ws = loop {
            let curr = tmp.replace("  ", " ");
            if curr == tmp {
                break curr.trim().to_string();
            }
            tmp = curr;
        };

        // Multi-line
        let mut last_n = fixed_ws.rfind('\n').unwrap_or(0);
        let mut multi_line = fixed_ws;

        while multi_line.len() - last_n > 64 {
            let new_n = multi_line[last_n+1..last_n+64].rfind(' ').unwrap_or(last_n);
            if new_n != last_n {
                assert!(last_n+new_n+1 < multi_line.len());
                unsafe { multi_line.as_mut_vec()[last_n+new_n+1] = b'\0' };
                multi_line = multi_line.replace('\0', "\n              ");
                last_n += new_n + " Discription: ".len();
            }
            else {
                break;
            }
        }

        multi_line
    }

    pub fn release(ver_opt: Option<&str>, age_res_opt: Option<Result<f64>>) -> String {
        match (ver_opt, age_res_opt) {
            (Some(ver), Some(Ok(age))) => format!("{} (released {:.1} months ago)", ver, age),
            _ => "N/A".into(),
        }
    }

    pub fn releases(stable: usize, non_yanked_pre: usize, yanked: usize) -> [EsrFormatter; 3] {
        [
            EsrFormatter::new(Green.bold(), &format!("{}", stable), "+"),
            EsrFormatter::new(Yellow.bold(), &format!("{}", non_yanked_pre), "+"),
            EsrFormatter::new(Red.bold(), &format!("{}", yanked), "\n "),
        ]
    }

    pub fn score_error(msg: &str) -> [EsrFormatter; 2] {
        [
            EsrFormatter::new(Red.bold(), msg, ": "),
            EsrFormatter::new(Bold.to_style(), "Error", "\n "),
        ]
    }

    pub fn score_na(msg: &str) -> [EsrFormatter; 2] {
        Self::msg_pair(msg, "N/A")
    }

    pub fn score_overview(msg: &str, pos: f64, neg: f64) -> [EsrFormatter; 4] {
        [
            EsrFormatter::new(Cyan.bold(), msg, ": "),
            EsrFormatter::new(Yellow.bold(), &format!("{:.3}", pos + neg) , " ("),
            EsrFormatter::new(Green.bold(), &format!("+{:.3}", pos) , " / "),
            EsrFormatter::new(Red.bold(), &format!("{:.3}", neg) , ")\n "),
        ]
    }

    pub fn score_details(msg: &str, table: &[(String, String, String)]) -> Vec<EsrFormatter> {
        let msg = format!("{: ^44}", msg);
        let frame = format!("{: ^44}", "-".repeat(msg.len()));

        let mut score_formatted = Vec::with_capacity(4096);
        score_formatted.push(EsrFormatter::new(Cyan.bold(), &*frame, "\n"));
        score_formatted.push(EsrFormatter::new(Cyan.bold(), &*msg, "\n"));
        score_formatted.push(EsrFormatter::new(Cyan.bold(), &*frame, "\n"));

        for line in table {
            if line.1.find("* -").is_some() {
                score_formatted.push(EsrFormatter::new(Yellow.bold(), &*line.0, " | "));
                score_formatted.push(EsrFormatter::new(Red.bold(), &*line.1, " | "));
                score_formatted.push(EsrFormatter::new(Red.bold(), &*line.2, "\n"));
            } else {
                score_formatted.push(EsrFormatter::new(Yellow.bold(), &*line.0, " | "));
                score_formatted.push(EsrFormatter::new(Green.bold(), &*line.1, " | "));
                score_formatted.push(EsrFormatter::new(Green.bold(), &*("+".to_string() + &*line.2), "\n"));
            }
        }
        score_formatted
    }

    pub fn crate_no_score(id: &str) {
        let msg = format!("Failed to get scores for crate \"{}\". Maybe it does not exist!", id);
        println!("{}", Red.bold().paint(&msg));
    }

    pub fn search_no_results(search_pattern: &str) {
        let msg = format!("Searching for \"{}\" returned no results.", search_pattern);
        println!("{}", Yellow.bold().paint(&msg));
    }

    pub fn search_failed(search_pattern: &str) {
        let msg = format!("Search for \"{}\" failed.", search_pattern);
        println!("{}", Red.bold().paint(&msg));
    }

    pub fn limit_out_of_range(limit: usize, min: usize, max: usize) {
        let msg = format!("{} is out of the range of valid limits. \
                          Please pass a value between {} and {}.", limit, min, max);
        println!("{}", Yellow.bold().paint(&msg));
    }

    pub fn limit_invalid(limit: &str) {
        let msg = format!("\"{}\" is an invalid limit value.", limit);
        println!("{}", Yellow.bold().paint(&msg));
    }

    pub fn no_token() {
        let msg = "Accessing GitHub's API wothout hitting rate-limits requires providing an access\
                   token.\n\n\
                   You can pass a token via -g/--gh-token option.\n\
                   Or by setting the variable CARGO_ESR_GH_TOKEN in the environment.\n\n\
                   To a acquire an access token, visit: <https://github.com/settings/tokens/new>\n\n\
                   Alternatively, you can pass -o/--crate-only to skip getting repository info.";
        println!("{}", Yellow.bold().paint(msg));
    }
}
<|endoftext|>


<commit_before>extern crate readline;
extern crate rlisp;

use std::os;

static PROMPT: &'static str = "rlisp> ";

fn main() {
    os::setenv("RUST_BACKTRACE", "1");

    println!("RLisp");

    let mut rlisp = rlisp::Rlisp::new();

    loop {
        let line = match readline::read(PROMPT) {
            Some(line) => line, None => return
        };

        println!("{}", rlisp.execute(line[]));
    }
}<commit_msg>use const for constatns<commit_after>extern crate readline;
extern crate rlisp;

use std::os;

const PROMPT: &'static str = "rlisp> ";

fn main() {
    os::setenv("RUST_BACKTRACE", "1");

    println!("RLisp");

    let mut rlisp = rlisp::Rlisp::new();

    loop {
        let line = match readline::read(PROMPT) {
            Some(line) => line, None => return
        };

        println!("{}", rlisp.execute(line[]));
    }
}<|endoftext|>


<commit_before>use super::{
    Attributes, AttributesReader, AttributesV10, AttributesWriter, Data, ExtensionValue,
    SpecVersion,
};
use crate::event::attributes::DataAttributesWriter;
use chrono::{DateTime, Utc};
use delegate::delegate;
use std::convert::TryFrom;

/// Data structure that represents a [CloudEvent](https://github.com/cloudevents/spec/blob/master/spec.md).
/// It provides methods to get the attributes through [`AttributesReader`]
/// and write them through [`AttributesWriter`].
/// It also provides methods to read and write the [event data](https://github.com/cloudevents/spec/blob/master/spec.md#event-data).
///
/// You can build events using [`EventBuilder`]
/// ```
/// use cloudevents::Event;
/// use cloudevents::event::AttributesReader;
///
/// // Create an event using the Default trait
/// let mut e = Event::default();
/// e.write_data(
///     "application/json",
///     serde_json::json!({"hello": "world"})
/// );
///
/// // Print the event id
/// println!("Event id: {}", e.get_id());
///
/// // Get the event data
/// let data: serde_json::Value = e.try_get_data().unwrap().unwrap();
/// println!("Event data: {}", data)
/// ```
#[derive(PartialEq, Debug, Clone)]
pub struct Event {
    pub attributes: Attributes,
    pub data: Option<Data>,
}

impl AttributesReader for Event {
    delegate! {
        to self.attributes {
            fn get_id(&self) -> &str;
            fn get_source(&self) -> &str;
            fn get_specversion(&self) -> SpecVersion;
            fn get_type(&self) -> &str;
            fn get_datacontenttype(&self) -> Option<&str>;
            fn get_dataschema(&self) -> Option<&str>;
            fn get_subject(&self) -> Option<&str>;
            fn get_time(&self) -> Option<&DateTime<Utc>>;
            fn get_extension(&self, extension_name: &str) -> Option<&ExtensionValue>;
            fn get_extensions(&self) -> Vec<(&str, &ExtensionValue)>;
        }
    }
}

impl AttributesWriter for Event {
    delegate! {
        to self.attributes {
            fn set_id(&mut self, id: impl Into<String>);
            fn set_source(&mut self, source: impl Into<String>);
            fn set_type(&mut self, ty: impl Into<String>);
            fn set_subject(&mut self, subject: Option<impl Into<String>>);
            fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>);
            fn set_extension<'name, 'event: 'name>(
                &'event mut self,
                extension_name: &'name str,
                extension_value: impl Into<ExtensionValue>,
            );
            fn remove_extension<'name, 'event: 'name>(
                &'event mut self,
                extension_name: &'name str,
            ) -> Option<ExtensionValue>;
        }
    }
}

impl Default for Event {
    fn default() -> Self {
        Event {
            attributes: Attributes::V10(AttributesV10::default()),
            data: None,
        }
    }
}

impl Event {
    pub fn remove_data(&mut self) {
        self.data = None;
        self.attributes.set_dataschema(None as Option<String>);
        self.attributes.set_datacontenttype(None as Option<String>);
    }

    /// Write data into the `Event` with the specified `datacontenttype`.
    ///
    /// ```
    /// use cloudevents::Event;
    /// use serde_json::json;
    /// use std::convert::Into;
    ///
    /// let mut e = Event::default();
    /// e.write_data("application/json", json!({}))
    /// ```
    pub fn write_data(&mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) {
        self.attributes.set_datacontenttype(Some(datacontenttype));
        self.attributes.set_dataschema(None as Option<&str>);
        self.data = Some(data.into());
    }

    /// Write data into the `Event` with the specified `datacontenttype` and `dataschema`.
    ///
    /// ```
    /// use cloudevents::Event;
    /// use serde_json::json;
    /// use std::convert::Into;
    ///
    /// let mut e = Event::default();
    /// e.write_data_with_schema("application/json", "http://myapplication.com/schema", json!({}))
    /// ```
    pub fn write_data_with_schema(
        &mut self,
        datacontenttype: impl Into<String>,
        dataschema: impl Into<String>,
        data: impl Into<Data>,
    ) {
        self.attributes.set_datacontenttype(Some(datacontenttype));
        self.attributes.set_dataschema(Some(dataschema));
        self.data = Some(data.into());
    }

    pub fn get_data<T: Sized + From<Data>>(&self) -> Option<T> {
        match self.data.as_ref() {
            Some(d) => Some(T::from(d.clone())),
            None => None,
        }
    }

    pub fn try_get_data<T: Sized + TryFrom<Data, Error = E>, E: std::error::Error>(
        &self,
    ) -> Option<Result<T, E>> {
        match self.data.as_ref() {
            Some(d) => Some(T::try_from(d.clone())),
            None => None,
        }
    }

    pub fn into_data<T: Sized + TryFrom<Data, Error = E>, E: std::error::Error>(
        self,
    ) -> Option<Result<T, E>> {
        match self.data {
            Some(d) => Some(T::try_from(d)),
            None => None,
        }
    }
}

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

    #[test]
    fn try_get_data_json() {
        let expected_data = serde_json::json!({
            "hello": "world"
        });

        let mut e = Event::default();
        e.write_data_with_schema(
            "application/json",
            "http://localhost:8080/schema",
            expected_data.clone(),
        );

        let data: serde_json::Value = e.try_get_data().unwrap().unwrap();
        assert_eq!(expected_data, data);
        assert_eq!("application/json", e.get_datacontenttype().unwrap());
        assert_eq!("http://localhost:8080/schema", e.get_dataschema().unwrap())
    }

    #[test]
    fn remove_data() {
        let mut e = Event::default();
        e.write_data(
            "application/json",
            serde_json::json!({
                "hello": "world"
            }),
        );

        e.remove_data();

        assert!(e
            .try_get_data::<serde_json::Value, serde_json::Error>()
            .is_none());
        assert!(e.get_dataschema().is_none());
        assert!(e.get_datacontenttype().is_none());
    }
}
<commit_msg>Reworked try_get_data (#17)<commit_after>use super::{
    Attributes, AttributesReader, AttributesV10, AttributesWriter, Data, ExtensionValue,
    SpecVersion,
};
use crate::event::attributes::DataAttributesWriter;
use chrono::{DateTime, Utc};
use delegate::delegate;
use std::convert::TryFrom;

/// Data structure that represents a [CloudEvent](https://github.com/cloudevents/spec/blob/master/spec.md).
/// It provides methods to get the attributes through [`AttributesReader`]
/// and write them through [`AttributesWriter`].
/// It also provides methods to read and write the [event data](https://github.com/cloudevents/spec/blob/master/spec.md#event-data).
///
/// You can build events using [`EventBuilder`]
/// ```
/// use cloudevents::Event;
/// use cloudevents::event::AttributesReader;
///
/// // Create an event using the Default trait
/// let mut e = Event::default();
/// e.write_data(
///     "application/json",
///     serde_json::json!({"hello": "world"})
/// );
///
/// // Print the event id
/// println!("Event id: {}", e.get_id());
///
/// // Get the event data
/// let data: serde_json::Value = e.try_get_data().unwrap().unwrap();
/// println!("Event data: {}", data)
/// ```
#[derive(PartialEq, Debug, Clone)]
pub struct Event {
    pub attributes: Attributes,
    pub data: Option<Data>,
}

impl AttributesReader for Event {
    delegate! {
        to self.attributes {
            fn get_id(&self) -> &str;
            fn get_source(&self) -> &str;
            fn get_specversion(&self) -> SpecVersion;
            fn get_type(&self) -> &str;
            fn get_datacontenttype(&self) -> Option<&str>;
            fn get_dataschema(&self) -> Option<&str>;
            fn get_subject(&self) -> Option<&str>;
            fn get_time(&self) -> Option<&DateTime<Utc>>;
            fn get_extension(&self, extension_name: &str) -> Option<&ExtensionValue>;
            fn get_extensions(&self) -> Vec<(&str, &ExtensionValue)>;
        }
    }
}

impl AttributesWriter for Event {
    delegate! {
        to self.attributes {
            fn set_id(&mut self, id: impl Into<String>);
            fn set_source(&mut self, source: impl Into<String>);
            fn set_type(&mut self, ty: impl Into<String>);
            fn set_subject(&mut self, subject: Option<impl Into<String>>);
            fn set_time(&mut self, time: Option<impl Into<DateTime<Utc>>>);
            fn set_extension<'name, 'event: 'name>(
                &'event mut self,
                extension_name: &'name str,
                extension_value: impl Into<ExtensionValue>,
            );
            fn remove_extension<'name, 'event: 'name>(
                &'event mut self,
                extension_name: &'name str,
            ) -> Option<ExtensionValue>;
        }
    }
}

impl Default for Event {
    fn default() -> Self {
        Event {
            attributes: Attributes::V10(AttributesV10::default()),
            data: None,
        }
    }
}

impl Event {
    pub fn remove_data(&mut self) {
        self.data = None;
        self.attributes.set_dataschema(None as Option<String>);
        self.attributes.set_datacontenttype(None as Option<String>);
    }

    /// Write data into the `Event` with the specified `datacontenttype`.
    ///
    /// ```
    /// use cloudevents::Event;
    /// use serde_json::json;
    /// use std::convert::Into;
    ///
    /// let mut e = Event::default();
    /// e.write_data("application/json", json!({}))
    /// ```
    pub fn write_data(&mut self, datacontenttype: impl Into<String>, data: impl Into<Data>) {
        self.attributes.set_datacontenttype(Some(datacontenttype));
        self.attributes.set_dataschema(None as Option<&str>);
        self.data = Some(data.into());
    }

    /// Write data into the `Event` with the specified `datacontenttype` and `dataschema`.
    ///
    /// ```
    /// use cloudevents::Event;
    /// use serde_json::json;
    /// use std::convert::Into;
    ///
    /// let mut e = Event::default();
    /// e.write_data_with_schema("application/json", "http://myapplication.com/schema", json!({}))
    /// ```
    pub fn write_data_with_schema(
        &mut self,
        datacontenttype: impl Into<String>,
        dataschema: impl Into<String>,
        data: impl Into<Data>,
    ) {
        self.attributes.set_datacontenttype(Some(datacontenttype));
        self.attributes.set_dataschema(Some(dataschema));
        self.data = Some(data.into());
    }

    pub fn get_data<T: Sized + From<Data>>(&self) -> Option<T> {
        match self.data.as_ref() {
            Some(d) => Some(T::from(d.clone())),
            None => None,
        }
    }

    pub fn try_get_data<T: Sized + TryFrom<Data>>(&self) -> Result<Option<T>, T::Error> {
        match self.data.as_ref() {
            Some(d) => Some(T::try_from(d.clone())),
            None => None,
        }
        .transpose()
    }

    pub fn into_data<T: Sized + TryFrom<Data>>(self) -> Result<Option<T>, T::Error> {
        match self.data {
            Some(d) => Some(T::try_from(d)),
            None => None,
        }
        .transpose()
    }
}

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

    #[test]
    fn try_get_data_json() {
        let expected_data = serde_json::json!({
            "hello": "world"
        });

        let mut e = Event::default();
        e.write_data_with_schema(
            "application/json",
            "http://localhost:8080/schema",
            expected_data.clone(),
        );

        let data: serde_json::Value = e.try_get_data().unwrap().unwrap();
        assert_eq!(expected_data, data);
        assert_eq!("application/json", e.get_datacontenttype().unwrap());
        assert_eq!("http://localhost:8080/schema", e.get_dataschema().unwrap())
    }

    #[test]
    fn remove_data() {
        let mut e = Event::default();
        e.write_data(
            "application/json",
            serde_json::json!({
                "hello": "world"
            }),
        );

        e.remove_data();

        assert!(e.try_get_data::<serde_json::Value>().unwrap().is_none());
        assert!(e.get_dataschema().is_none());
        assert!(e.get_datacontenttype().is_none());
    }
}
<|endoftext|>


<commit_before>//! Entry point for the CSS filters infrastructure.

use cssparser::{BasicParseError, Parser};
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use std::time::Instant;

use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::{ElementError, ParseError, RenderingError};
use crate::length::*;
use crate::node::{Node, NodeBorrow};
use crate::paint_server::UserSpacePaintSource;
use crate::parsers::{CustomIdent, Parse, ParseValue};
use crate::properties::ComputedValues;
use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::transform::Transform;
use crate::xml::Attributes;

mod bounds;
use self::bounds::BoundsBuilder;

pub mod context;
use self::context::{FilterContext, FilterOutput, FilterResult};

mod error;
use self::error::FilterError;

/// A filter primitive interface.
pub trait FilterEffect: SetAttributes + Draw {
    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError>;
}

// Filter Effects do not need to draw themselves
impl<T: FilterEffect> Draw for T {}

pub mod blend;
pub mod color_matrix;
pub mod component_transfer;
pub mod composite;
pub mod convolve_matrix;
pub mod displacement_map;
pub mod flood;
pub mod gaussian_blur;
pub mod image;
pub mod lighting;
pub mod merge;
pub mod morphology;
pub mod offset;
pub mod tile;
pub mod turbulence;

/// Resolved parameters for each filter primitive.
///
/// These gather all the data that a primitive may need during rendering:
/// the `feFoo` element's attributes, any computed values from its properties,
/// and parameters extracted from the element's children (for example,
/// `feMerge` gathers info from its `feMergNode` children).
pub enum PrimitiveParams {
    Blend(blend::Blend),
    ColorMatrix(color_matrix::ColorMatrix),
    ComponentTransfer(component_transfer::ComponentTransfer),
    Composite(composite::Composite),
    ConvolveMatrix(convolve_matrix::ConvolveMatrix),
    DiffuseLighting(lighting::DiffuseLighting),
    DisplacementMap(displacement_map::DisplacementMap),
    Flood(flood::Flood),
    GaussianBlur(gaussian_blur::GaussianBlur),
    Image(image::Image),
    Merge(merge::Merge),
    Morphology(morphology::Morphology),
    Offset(offset::Offset),
    SpecularLighting(lighting::SpecularLighting),
    Tile(tile::Tile),
    Turbulence(turbulence::Turbulence),
}

/// The base filter primitive node containing common properties.
#[derive(Default, Clone)]
pub struct Primitive {
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<ULength<Horizontal>>,
    height: Option<ULength<Vertical>>,
    result: Option<CustomIdent>,
}

pub struct ResolvedPrimitive {
    x: Option<f64>,
    y: Option<f64>,
    width: Option<f64>,
    height: Option<f64>,
    result: Option<CustomIdent>,
}

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Input {
    Unspecified,
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterOutput(CustomIdent),
}

enum_default!(Input, Input::Unspecified);

impl Parse for Input {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        parser
            .try_parse(|p| {
                Ok(parse_identifiers!(
                    p,
                    "SourceGraphic" => Input::SourceGraphic,
                    "SourceAlpha" => Input::SourceAlpha,
                    "BackgroundImage" => Input::BackgroundImage,
                    "BackgroundAlpha" => Input::BackgroundAlpha,
                    "FillPaint" => Input::FillPaint,
                    "StrokePaint" => Input::StrokePaint,
                )?)
            })
            .or_else(|_: BasicParseError<'_>| {
                let ident = CustomIdent::parse(parser)?;
                Ok(Input::FilterOutput(ident))
            })
    }
}

impl Primitive {
    fn resolve(
        &self,
        ctx: &FilterContext,
        values: &ComputedValues,
        draw_ctx: &DrawingCtx,
    ) -> Result<ResolvedPrimitive, FilterError> {
        let params = draw_ctx.push_coord_units(ctx.primitive_units());

        let x = self.x.map(|l| l.normalize(values, &params));
        let y = self.y.map(|l| l.normalize(values, &params));
        let width = self.width.map(|l| l.normalize(values, &params));
        let height = self.height.map(|l| l.normalize(values, &params));

        Ok(ResolvedPrimitive {
            x,
            y,
            width,
            height,
            result: self.result.clone(),
        })
    }
}

impl ResolvedPrimitive {
    /// Validates attributes and returns the `BoundsBuilder` for bounds computation.
    #[inline]
    fn get_bounds(&self, ctx: &FilterContext) -> BoundsBuilder {
        BoundsBuilder::new(self.x, self.y, self.width, self.height, ctx.paffine())
    }
}

impl Primitive {
    fn parse_standard_attributes(
        &mut self,
        attrs: &Attributes,
    ) -> Result<(Input, Input), ElementError> {
        let mut input_1 = Input::Unspecified;
        let mut input_2 = Input::Unspecified;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "x") => self.x = attr.parse(value)?,
                expanded_name!("", "y") => self.y = attr.parse(value)?,
                expanded_name!("", "width") => self.width = attr.parse(value)?,
                expanded_name!("", "height") => self.height = attr.parse(value)?,
                expanded_name!("", "result") => self.result = attr.parse(value)?,
                expanded_name!("", "in") => input_1 = attr.parse(value)?,
                expanded_name!("", "in2") => input_2 = attr.parse(value)?,
                _ => (),
            }
        }

        Ok((input_1, input_2))
    }

    pub fn parse_no_inputs(&mut self, attrs: &Attributes) -> ElementResult {
        let (_, _) = self.parse_standard_attributes(attrs)?;
        Ok(())
    }

    pub fn parse_one_input(&mut self, attrs: &Attributes) -> Result<Input, ElementError> {
        let (input_1, _) = self.parse_standard_attributes(attrs)?;
        Ok(input_1)
    }

    pub fn parse_two_inputs(&mut self, attrs: &Attributes) -> Result<(Input, Input), ElementError> {
        self.parse_standard_attributes(attrs)
    }
}

/// Applies a filter and returns the resulting surface.
pub fn render(
    filter_node: &Node,
    stroke_paint_source: UserSpacePaintSource,
    fill_paint_source: UserSpacePaintSource,
    source_surface: SharedImageSurface,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
    transform: Transform,
    node_bbox: BoundingBox,
) -> Result<SharedImageSurface, RenderingError> {
    let filter_node = &*filter_node;
    assert!(is_element_of_type!(filter_node, Filter));

    let filter_element = filter_node.borrow_element();

    if filter_element.is_in_error() {
        return Ok(source_surface);
    }

    let filter_values = filter_element.get_computed_values();

    let filter = borrow_element_as!(filter_node, Filter);

    let resolved_filter = {
        // This is in a temporary scope so we don't leave the coord_units pushed during
        // the execution of all the filter primitives.
        let params = draw_ctx.push_coord_units(filter.get_filter_units());
        filter.resolve(filter_values, &params)
    };

    if let Ok(mut filter_ctx) = FilterContext::new(
        &resolved_filter,
        stroke_paint_source,
        fill_paint_source,
        &source_surface,
        transform,
        node_bbox,
    ) {
        let primitives = filter_node
            .children()
            .filter(|c| c.is_element())
            // Skip nodes in error.
            .filter(|c| {
                let in_error = c.borrow_element().is_in_error();

                if in_error {
                    rsvg_log!("(ignoring filter primitive {} because it is in error)", c);
                }

                !in_error
            })
            // Keep only filter primitives (those that implement the Filter trait)
            .filter(|c| c.borrow_element().as_filter_effect().is_some());

        for primitive_node in primitives {
            let elt = primitive_node.borrow_element();
            let filter = elt.as_filter_effect().unwrap();

            let primitive_values = elt.get_computed_values();

            let start = Instant::now();

            if let Err(err) = filter
                .resolve(&primitive_node)
                .and_then(|(primitive, params)| {
                    let resolved_primitive =
                        primitive.resolve(&filter_ctx, primitive_values, draw_ctx)?;
                    Ok((resolved_primitive, params))
                })
                .and_then(|(resolved_primitive, params)| {
                    let output = render_primitive(
                        &resolved_primitive,
                        &params,
                        &filter_ctx,
                        acquired_nodes,
                        draw_ctx,
                    )?;

                    Ok(FilterResult {
                        name: resolved_primitive.result,
                        output,
                    })
                })
                .and_then(|result| filter_ctx.store_result(result))
            {
                rsvg_log!(
                    "(filter primitive {} returned an error: {})",
                    primitive_node,
                    err
                );

                // Exit early on Cairo errors. Continue rendering otherwise.
                if let FilterError::CairoError(status) = err {
                    return Err(RenderingError::from(status));
                }
            }

            let elapsed = start.elapsed();
            rsvg_log!(
                "(rendered filter primitive {} in\n    {} seconds)",
                primitive_node,
                elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9
            );
        }

        Ok(filter_ctx.into_output()?)
    } else {
        // Ignore errors that happened when creating the FilterContext
        Ok(SharedImageSurface::empty(
            source_surface.width(),
            source_surface.height(),
            SurfaceType::AlphaOnly,
        )?)
    }
}

#[rustfmt::skip]
fn render_primitive(
    primitive: &ResolvedPrimitive,
    params: &PrimitiveParams,
    ctx: &FilterContext,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
) -> Result<FilterOutput, FilterError> {
    use PrimitiveParams::*;

    let bounds_builder = primitive.get_bounds(ctx);

    match params {
        Blend(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ColorMatrix(p)       => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ComponentTransfer(p) => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Composite(p)         => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ConvolveMatrix(p)    => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DiffuseLighting(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DisplacementMap(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Flood(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        GaussianBlur(p)      => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Image(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Merge(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Morphology(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Offset(p)            => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        SpecularLighting(p)  => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Tile(p)              => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Turbulence(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
    }
}

impl From<ColorInterpolationFilters> for SurfaceType {
    fn from(c: ColorInterpolationFilters) -> Self {
        match c {
            ColorInterpolationFilters::LinearRgb => SurfaceType::LinearRgb,
            _ => SurfaceType::SRgb,
        }
    }
}
<commit_msg>Primitive.resolve does not need to return a Result anymore<commit_after>//! Entry point for the CSS filters infrastructure.

use cssparser::{BasicParseError, Parser};
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use std::time::Instant;

use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::{ElementError, ParseError, RenderingError};
use crate::length::*;
use crate::node::{Node, NodeBorrow};
use crate::paint_server::UserSpacePaintSource;
use crate::parsers::{CustomIdent, Parse, ParseValue};
use crate::properties::ComputedValues;
use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::transform::Transform;
use crate::xml::Attributes;

mod bounds;
use self::bounds::BoundsBuilder;

pub mod context;
use self::context::{FilterContext, FilterOutput, FilterResult};

mod error;
use self::error::FilterError;

/// A filter primitive interface.
pub trait FilterEffect: SetAttributes + Draw {
    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError>;
}

// Filter Effects do not need to draw themselves
impl<T: FilterEffect> Draw for T {}

pub mod blend;
pub mod color_matrix;
pub mod component_transfer;
pub mod composite;
pub mod convolve_matrix;
pub mod displacement_map;
pub mod flood;
pub mod gaussian_blur;
pub mod image;
pub mod lighting;
pub mod merge;
pub mod morphology;
pub mod offset;
pub mod tile;
pub mod turbulence;

/// Resolved parameters for each filter primitive.
///
/// These gather all the data that a primitive may need during rendering:
/// the `feFoo` element's attributes, any computed values from its properties,
/// and parameters extracted from the element's children (for example,
/// `feMerge` gathers info from its `feMergNode` children).
pub enum PrimitiveParams {
    Blend(blend::Blend),
    ColorMatrix(color_matrix::ColorMatrix),
    ComponentTransfer(component_transfer::ComponentTransfer),
    Composite(composite::Composite),
    ConvolveMatrix(convolve_matrix::ConvolveMatrix),
    DiffuseLighting(lighting::DiffuseLighting),
    DisplacementMap(displacement_map::DisplacementMap),
    Flood(flood::Flood),
    GaussianBlur(gaussian_blur::GaussianBlur),
    Image(image::Image),
    Merge(merge::Merge),
    Morphology(morphology::Morphology),
    Offset(offset::Offset),
    SpecularLighting(lighting::SpecularLighting),
    Tile(tile::Tile),
    Turbulence(turbulence::Turbulence),
}

/// The base filter primitive node containing common properties.
#[derive(Default, Clone)]
pub struct Primitive {
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<ULength<Horizontal>>,
    height: Option<ULength<Vertical>>,
    result: Option<CustomIdent>,
}

pub struct ResolvedPrimitive {
    x: Option<f64>,
    y: Option<f64>,
    width: Option<f64>,
    height: Option<f64>,
    result: Option<CustomIdent>,
}

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Input {
    Unspecified,
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterOutput(CustomIdent),
}

enum_default!(Input, Input::Unspecified);

impl Parse for Input {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        parser
            .try_parse(|p| {
                Ok(parse_identifiers!(
                    p,
                    "SourceGraphic" => Input::SourceGraphic,
                    "SourceAlpha" => Input::SourceAlpha,
                    "BackgroundImage" => Input::BackgroundImage,
                    "BackgroundAlpha" => Input::BackgroundAlpha,
                    "FillPaint" => Input::FillPaint,
                    "StrokePaint" => Input::StrokePaint,
                )?)
            })
            .or_else(|_: BasicParseError<'_>| {
                let ident = CustomIdent::parse(parser)?;
                Ok(Input::FilterOutput(ident))
            })
    }
}

impl Primitive {
    fn resolve(
        &self,
        ctx: &FilterContext,
        values: &ComputedValues,
        draw_ctx: &DrawingCtx,
    ) -> ResolvedPrimitive {
        let params = draw_ctx.push_coord_units(ctx.primitive_units());

        let x = self.x.map(|l| l.normalize(values, &params));
        let y = self.y.map(|l| l.normalize(values, &params));
        let width = self.width.map(|l| l.normalize(values, &params));
        let height = self.height.map(|l| l.normalize(values, &params));

        ResolvedPrimitive {
            x,
            y,
            width,
            height,
            result: self.result.clone(),
        }
    }
}

impl ResolvedPrimitive {
    /// Validates attributes and returns the `BoundsBuilder` for bounds computation.
    #[inline]
    fn get_bounds(&self, ctx: &FilterContext) -> BoundsBuilder {
        BoundsBuilder::new(self.x, self.y, self.width, self.height, ctx.paffine())
    }
}

impl Primitive {
    fn parse_standard_attributes(
        &mut self,
        attrs: &Attributes,
    ) -> Result<(Input, Input), ElementError> {
        let mut input_1 = Input::Unspecified;
        let mut input_2 = Input::Unspecified;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "x") => self.x = attr.parse(value)?,
                expanded_name!("", "y") => self.y = attr.parse(value)?,
                expanded_name!("", "width") => self.width = attr.parse(value)?,
                expanded_name!("", "height") => self.height = attr.parse(value)?,
                expanded_name!("", "result") => self.result = attr.parse(value)?,
                expanded_name!("", "in") => input_1 = attr.parse(value)?,
                expanded_name!("", "in2") => input_2 = attr.parse(value)?,
                _ => (),
            }
        }

        Ok((input_1, input_2))
    }

    pub fn parse_no_inputs(&mut self, attrs: &Attributes) -> ElementResult {
        let (_, _) = self.parse_standard_attributes(attrs)?;
        Ok(())
    }

    pub fn parse_one_input(&mut self, attrs: &Attributes) -> Result<Input, ElementError> {
        let (input_1, _) = self.parse_standard_attributes(attrs)?;
        Ok(input_1)
    }

    pub fn parse_two_inputs(&mut self, attrs: &Attributes) -> Result<(Input, Input), ElementError> {
        self.parse_standard_attributes(attrs)
    }
}

/// Applies a filter and returns the resulting surface.
pub fn render(
    filter_node: &Node,
    stroke_paint_source: UserSpacePaintSource,
    fill_paint_source: UserSpacePaintSource,
    source_surface: SharedImageSurface,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
    transform: Transform,
    node_bbox: BoundingBox,
) -> Result<SharedImageSurface, RenderingError> {
    let filter_node = &*filter_node;
    assert!(is_element_of_type!(filter_node, Filter));

    let filter_element = filter_node.borrow_element();

    if filter_element.is_in_error() {
        return Ok(source_surface);
    }

    let filter_values = filter_element.get_computed_values();

    let filter = borrow_element_as!(filter_node, Filter);

    let resolved_filter = {
        // This is in a temporary scope so we don't leave the coord_units pushed during
        // the execution of all the filter primitives.
        let params = draw_ctx.push_coord_units(filter.get_filter_units());
        filter.resolve(filter_values, &params)
    };

    if let Ok(mut filter_ctx) = FilterContext::new(
        &resolved_filter,
        stroke_paint_source,
        fill_paint_source,
        &source_surface,
        transform,
        node_bbox,
    ) {
        let primitives = filter_node
            .children()
            .filter(|c| c.is_element())
            // Skip nodes in error.
            .filter(|c| {
                let in_error = c.borrow_element().is_in_error();

                if in_error {
                    rsvg_log!("(ignoring filter primitive {} because it is in error)", c);
                }

                !in_error
            })
            // Keep only filter primitives (those that implement the Filter trait)
            .filter(|c| c.borrow_element().as_filter_effect().is_some());

        for primitive_node in primitives {
            let elt = primitive_node.borrow_element();
            let filter = elt.as_filter_effect().unwrap();

            let primitive_values = elt.get_computed_values();

            let start = Instant::now();

            if let Err(err) = filter
                .resolve(&primitive_node)
                .and_then(|(primitive, params)| {
                    let resolved_primitive =
                        primitive.resolve(&filter_ctx, primitive_values, draw_ctx);

                    let output = render_primitive(
                        &resolved_primitive,
                        &params,
                        &filter_ctx,
                        acquired_nodes,
                        draw_ctx,
                    )?;

                    Ok(FilterResult {
                        name: resolved_primitive.result,
                        output,
                    })
                })
                .and_then(|result| filter_ctx.store_result(result))
            {
                rsvg_log!(
                    "(filter primitive {} returned an error: {})",
                    primitive_node,
                    err
                );

                // Exit early on Cairo errors. Continue rendering otherwise.
                if let FilterError::CairoError(status) = err {
                    return Err(RenderingError::from(status));
                }
            }

            let elapsed = start.elapsed();
            rsvg_log!(
                "(rendered filter primitive {} in\n    {} seconds)",
                primitive_node,
                elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9
            );
        }

        Ok(filter_ctx.into_output()?)
    } else {
        // Ignore errors that happened when creating the FilterContext
        Ok(SharedImageSurface::empty(
            source_surface.width(),
            source_surface.height(),
            SurfaceType::AlphaOnly,
        )?)
    }
}

#[rustfmt::skip]
fn render_primitive(
    primitive: &ResolvedPrimitive,
    params: &PrimitiveParams,
    ctx: &FilterContext,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
) -> Result<FilterOutput, FilterError> {
    use PrimitiveParams::*;

    let bounds_builder = primitive.get_bounds(ctx);

    match params {
        Blend(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ColorMatrix(p)       => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ComponentTransfer(p) => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Composite(p)         => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ConvolveMatrix(p)    => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DiffuseLighting(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DisplacementMap(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Flood(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        GaussianBlur(p)      => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Image(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Merge(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Morphology(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Offset(p)            => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        SpecularLighting(p)  => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Tile(p)              => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Turbulence(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
    }
}

impl From<ColorInterpolationFilters> for SurfaceType {
    fn from(c: ColorInterpolationFilters) -> Self {
        match c {
            ColorInterpolationFilters::LinearRgb => SurfaceType::LinearRgb,
            _ => SurfaceType::SRgb,
        }
    }
}
<|endoftext|>


<commit_before>macro_rules! check_mods {
    ($errors:ident, $context:expr, $actual:ident, [$($allowed:ident),*] ) => {{
        let allowed_mods = [$(Keyword::$allowed),*];
        $errors.extend_from_slice(
            &check_allowed_modifier(&$actual, &allowed_mods, $context)
        );
    }}
}

pub mod java8;

use ast;
use lex;
use base::diag::Report;
use base::code::{Span, BytePos};

type Mods = [ast::Spanned<lex::Keyword>];

// some helper functions
fn check_allowed_modifier(actual: &Mods, allowed: &[lex::Keyword], ctx: &str)
    -> Vec<Report>
{
    let mut seen: Vec<ast::Spanned<lex::Keyword>> = Vec::new();
    actual.iter().flat_map(|&m| {
        // collect all reports
        let mut reps = Vec::new();

        // check for duplicate modifiers
        let dupe = seen
            .iter()
            .find(|hay| hay.inner == m.inner)
            .map(|m| m.span);
        if let Some(prev_span) = dupe {
            reps.push(Report::simple_error(
                format!("duplicate `{:?}` modifier", m.inner),
                m.span,
            ).with_span_note(
                format!("the first `{:?}` modifier is already here", m.inner),
                prev_span,
            ));
        } else {
            seen.push(m);
        }

        // check if modifier is valid
        if !allowed.contains(&m.inner) {
            let msg = format!("modifier `{}` is illegal in this context", m.inner);
            let note = format!("valid `{}` modifier are: {:?}", ctx, allowed);
            reps.push(Report::simple_error(msg, m.span).with_note(note));
        }
        reps.into_iter()
    }).collect()
}

fn get_visibility(mods: &Mods, errors: &mut Vec<Report>)
    -> Option<ast::Visibility>
{
    use lex::{Token, Keyword};

    let mut vis = None;
    let mut first_vis = None;

    for &ast::Spanned { inner: modifier, span } in mods {
        match modifier {
            Keyword::Public | Keyword::Private | Keyword::Protected => {
                // check if there was a visibility modifier before this one
                if let Some(prev_span) = first_vis {
                    let e = Report::simple_error(
                        "duplicate visibility modifier",
                        span
                    ).with_span_note(
                        "the first visibility modifier is already here",
                        prev_span
                    );
                    errors.push(e);
                } else {
                    first_vis = Some(span);
                    vis = Some(match modifier {
                        Keyword::Public => ast::Visibility::Public,
                        Keyword::Private => ast::Visibility::Private,
                        Keyword::Protected => ast::Visibility::Protected,
                        _ => unreachable!(),
                    });
                }
            },
            _ => {},
        }
    }

    vis
}

macro_rules! gen_finder {
    ($name:ident, $keyword:ident) => {
        /// Returns if the modifier for the given property is in the list of
        /// modifiers. Does NOT check duplicate modifier.
        fn $name(mods: &Mods) -> Option<Span> {
            mods.iter()
                .find(|m| m.inner == lex::Keyword::$keyword)
                .map(|m| m.span)
        }
    }
}

gen_finder!(get_abstract, Abstract);
gen_finder!(get_default, Default);
gen_finder!(get_final, Final);
gen_finder!(get_native, Native);
gen_finder!(get_static, Static);
gen_finder!(get_strictfp, Strictfp);
gen_finder!(get_synchronized, Synchronized);

fn unwrap_keyword(tok: &lex::Token) -> lex::Keyword {
    if let &lex::Token::KeyW(kw) = tok { kw } else { unreachable!() }
}
<commit_msg>Remove warning<commit_after>macro_rules! check_mods {
    ($errors:ident, $context:expr, $actual:ident, [$($allowed:ident),*] ) => {{
        let allowed_mods = [$(Keyword::$allowed),*];
        $errors.extend_from_slice(
            &check_allowed_modifier(&$actual, &allowed_mods, $context)
        );
    }}
}

pub mod java8;

use ast;
use lex;
use base::diag::Report;
use base::code::{Span, BytePos};

type Mods = [ast::Spanned<lex::Keyword>];

// some helper functions
fn check_allowed_modifier(actual: &Mods, allowed: &[lex::Keyword], ctx: &str)
    -> Vec<Report>
{
    let mut seen: Vec<ast::Spanned<lex::Keyword>> = Vec::new();
    actual.iter().flat_map(|&m| {
        // collect all reports
        let mut reps = Vec::new();

        // check for duplicate modifiers
        let dupe = seen
            .iter()
            .find(|hay| hay.inner == m.inner)
            .map(|m| m.span);
        if let Some(prev_span) = dupe {
            reps.push(Report::simple_error(
                format!("duplicate `{:?}` modifier", m.inner),
                m.span,
            ).with_span_note(
                format!("the first `{:?}` modifier is already here", m.inner),
                prev_span,
            ));
        } else {
            seen.push(m);
        }

        // check if modifier is valid
        if !allowed.contains(&m.inner) {
            let msg = format!("modifier `{}` is illegal in this context", m.inner);
            let note = format!("valid `{}` modifier are: {:?}", ctx, allowed);
            reps.push(Report::simple_error(msg, m.span).with_note(note));
        }
        reps.into_iter()
    }).collect()
}

fn get_visibility(mods: &Mods, errors: &mut Vec<Report>)
    -> Option<ast::Visibility>
{
    use lex::Keyword;

    let mut vis = None;
    let mut first_vis = None;

    for &ast::Spanned { inner: modifier, span } in mods {
        match modifier {
            Keyword::Public | Keyword::Private | Keyword::Protected => {
                // check if there was a visibility modifier before this one
                if let Some(prev_span) = first_vis {
                    let e = Report::simple_error(
                        "duplicate visibility modifier",
                        span
                    ).with_span_note(
                        "the first visibility modifier is already here",
                        prev_span
                    );
                    errors.push(e);
                } else {
                    first_vis = Some(span);
                    vis = Some(match modifier {
                        Keyword::Public => ast::Visibility::Public,
                        Keyword::Private => ast::Visibility::Private,
                        Keyword::Protected => ast::Visibility::Protected,
                        _ => unreachable!(),
                    });
                }
            },
            _ => {},
        }
    }

    vis
}

macro_rules! gen_finder {
    ($name:ident, $keyword:ident) => {
        /// Returns if the modifier for the given property is in the list of
        /// modifiers. Does NOT check duplicate modifier.
        fn $name(mods: &Mods) -> Option<Span> {
            mods.iter()
                .find(|m| m.inner == lex::Keyword::$keyword)
                .map(|m| m.span)
        }
    }
}

gen_finder!(get_abstract, Abstract);
gen_finder!(get_default, Default);
gen_finder!(get_final, Final);
gen_finder!(get_native, Native);
gen_finder!(get_static, Static);
gen_finder!(get_strictfp, Strictfp);
gen_finder!(get_synchronized, Synchronized);

fn unwrap_keyword(tok: &lex::Token) -> lex::Keyword {
    if let &lex::Token::KeyW(kw) = tok { kw } else { unreachable!() }
}
<|endoftext|>


<commit_before>// represent a philosopher
struct Philosopher {
    name: String,
}

// define things on Philosopher structs
impl Philosopher {
    // argument: name, of type &str
    // return: an instance of Philosopher struct
    fn new(name: &str) -> Philosopher {
        // create a new Philosopher
        Philosopher {
            // set its name
            name: name.to_string(), // to_string return a copy of name(&str)
        }
        // the last expression is automatically returned
    }

    fn eat(&self) {
        println!("{} is done eating", self.name);
    }
}

fn main() {
    // define a vector, Vec<T>
    let philosophers = vec![
        Philosopher::new("A"),
        Philosopher::new("B"),
        Philosopher::new("C"),
        Philosopher::new("D"),
        Philosopher::new("E"),
    ];

    // iterate the philosophers, Vec<T>
    for p in &philosophers {
        p.eat();
    }
}
<commit_msg>operating in a concurrent fashion<commit_after>use std::thread;

// represent a philosopher
struct Philosopher {
    name: String,
}

// define things on Philosopher structs
impl Philosopher {
    // argument: name, of type &str
    // return: an instance of Philosopher struct
    fn new(name: &str) -> Philosopher {
        // create a new Philosopher
        Philosopher {
            // set its name
            name: name.to_string(), // to_string return a copy of name(&str)
        }
        // the last expression is automatically returned
    }

    fn eat(&self) {
        println!("{} is eating...", self.name);

        thread::sleep_ms(1000);

        println!("{} is done eating", self.name);
    }
}

fn main() {
    // define a vector, Vec<T>
    let philosophers = vec![
        Philosopher::new("A"),
        Philosopher::new("B"),
        Philosopher::new("C"),
        Philosopher::new("D"),
        Philosopher::new("E"),
    ];

    // iterate the philosophers, Vec<T>
    // for p in &philosophers {
    //     p.eat();
    // }

    /* operating in a concurrent fashion */

    // `handles` is a `Vec` of handle of threads,
    // `Vec<_>` let Rust figure out what type in the Vec
    // `into_iter` create an iterator, then call `map` on it
    let handles: Vec<_> = philosophers.into_iter().map(|p| {
        // `thread::spawn` takes a closure as an argument
        //   and executes it in a new thread.
        // `move` means the closure take ownership of the values
        //   it's capturing
        thread::spawn(move || {
            // call `eat` on p
            p.eat();
        })
    }).collect(); // collect the result of `map` calls

    for h in handles {
        // `join` block execution until the thread has completed execution
        h.join().unwrap();
    }
}
<|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 foxbox_taxonomy::manager::*;
use hyper::net::{ NetworkListener };
use iron::{ AfterMiddleware, Chain, Handler,
            HttpServerFactory, Iron, IronResult, Request,
            Response, ServerFactory };
use iron_cors::CORS;
use iron::error::{ IronError };
use iron::method::Method;
use iron::status::Status;
use mount::Mount;
use router::NoRoute;
use static_router;
use std::net::SocketAddr;
use std::sync::Arc;
use std::thread;
use taxonomy_router;
use tls::SniServerFactory;
use traits::Controller;

const THREAD_COUNT: usize = 8;

struct Custom404;

impl AfterMiddleware for Custom404 {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        use std::io::Error as StdError;
        use std::io::ErrorKind;

        if let Some(_) = err.error.downcast::<NoRoute>() {
            // Router error
            return Ok(Response::with((Status::NotFound,
                                      format!("Unknown resource: {}", err))));
        } else if let Some(err) = err.error.downcast::<StdError>() {
            // StaticFile error
            if err.kind() == ErrorKind::NotFound {
                return Ok(Response::with((Status::NotFound,
                                          format!("Unknown resource: {}", err))));
            }
        }

        // Just let other errors go through, like 401.
        Err(err)
    }
}

struct Ping;

impl Handler for Ping {
    fn handle (&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::with(Status::Ok))
    }
}

pub struct HttpServer<T: Controller> {
    controller: T
}

impl<T: Controller> HttpServer<T> {
    pub fn new(controller: T) -> Self {
        HttpServer { controller: controller }
    }

    pub fn start(&mut self, adapter_api: &Arc<AdapterManager>) {
        let taxonomy_chain = taxonomy_router::create(self.controller.clone(),
                                                      adapter_api);

        let users_manager = self.controller.get_users_manager();
        let mut mount = Mount::new();
        mount.mount("/", static_router::create(users_manager.clone()))
             .mount("/ping", Ping)
             .mount("/api/v1", taxonomy_chain)
             .mount("/users", users_manager.get_router_chain());

        let mut chain = Chain::new(mount);
        chain.link_after(Custom404);

        let cors = CORS::new(vec![
            (vec![Method::Get], "ping".to_owned()),
            (vec![Method::Get, Method::Post, Method::Put, Method::Delete],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned()),

            // Taxonomy router paths. Keep in sync with taxonomy_router.rs
            (vec![Method::Get, Method::Post], "api/v1/services".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/services/tags".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/getters".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/setters".to_owned()),
            (vec![Method::Put], "api/v1/channels/get".to_owned()),
            (vec![Method::Put], "api/v1/channels/set".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/getters/tags".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/setters/tags".to_owned())
        ]);
        chain.link_after(cors);

        let addrs: Vec<_> = self.controller.http_as_addrs().unwrap().collect();

        if self.controller.get_tls_enabled() {
            let mut certificate_manager = self.controller.get_certificate_manager();
            let server_factory = SniServerFactory::new(&mut certificate_manager);
            start_server(addrs, chain, server_factory);
        } else {
            start_server(addrs, chain, HttpServerFactory {});
        }
    }
}

fn start_server<TListener, T>(addrs: Vec<SocketAddr>, chain: Chain, factory: T)
    where TListener: NetworkListener + Send + 'static,
          T: ServerFactory<TListener> + Send + 'static {

    thread::Builder::new().name("HttpServer".to_owned())
                          .spawn(move || {
        Iron::new(chain)
             .listen_with(addrs[0], THREAD_COUNT, &factory, None)
             .unwrap();
    }).unwrap();
}

#[cfg(test)]
describe! ping {
    before_each {
        use mount::Mount;
        use iron::Headers;
        use iron::status::Status;
        use iron_test::request;
        use super::Ping;

        let mut mount = Mount::new();
        mount.mount("/ping", Ping);
    }

    it "should response 200 Ok" {
        let response = request::get("http://localhost:3000/ping",
                                    Headers::new(),
                                    &mount).unwrap();
        assert_eq!(response.status.unwrap(), Status::Ok);
    }
}

#[cfg(test)]
describe! http_server {
    before_each {
        extern crate hyper;

        use foxbox_taxonomy::manager::AdapterManager;
        use std::thread;
        use std::sync::Arc;
        use std::time::Duration;
        use stubs::controller::ControllerStub;

        let taxo_manager = Arc::new(AdapterManager::new(None));

        let mut http_server = HttpServer::new(ControllerStub::new());
        http_server.start(&taxo_manager);
        // HACK: Let some time for the http server to start.
        thread::sleep(Duration::new(3, 0));
    }

    it "should get the appropriate CORS headers" {
        use iron::headers;
        use iron::method::Method;

        let endpoints = vec![
            (vec![Method::Get, Method::Post, Method::Put],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned())
        ];
        let client = hyper::Client::new();
        for endpoint in endpoints {
            let (_, path) = endpoint;
            let path = "http://localhost:3000/".to_owned() +
                       &(path.replace(":", "foo"));
            let res = client.get(&path).send();
            let headers = &res.unwrap().headers;
            assert!(headers.has::<headers::AccessControlAllowOrigin>());
            assert!(headers.has::<headers::AccessControlAllowHeaders>());
            assert!(headers.has::<headers::AccessControlAllowMethods>());
        };
    }

    it "should respond with 404" {
        use iron::status::Status;
        use std::io::Read;

        let client = hyper::Client::new();
        let path = "http://localhost:3000/foo/bar".to_owned();
        let mut res = client.get(&path).send().unwrap();
        assert_eq!(res.status, Status::NotFound);
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "Unknown resource: No such file or \
                   directory (os error 2)".to_owned());
    }
}
<commit_msg>Switch the /ping endpoint to return 204 instead of 200 (#426). r=ferjm<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 foxbox_taxonomy::manager::*;
use hyper::net::{ NetworkListener };
use iron::{ AfterMiddleware, Chain, Handler,
            HttpServerFactory, Iron, IronResult, Request,
            Response, ServerFactory };
use iron_cors::CORS;
use iron::error::{ IronError };
use iron::method::Method;
use iron::status::Status;
use mount::Mount;
use router::NoRoute;
use static_router;
use std::net::SocketAddr;
use std::sync::Arc;
use std::thread;
use taxonomy_router;
use tls::SniServerFactory;
use traits::Controller;

const THREAD_COUNT: usize = 8;

struct Custom404;

impl AfterMiddleware for Custom404 {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        use std::io::Error as StdError;
        use std::io::ErrorKind;

        if let Some(_) = err.error.downcast::<NoRoute>() {
            // Router error
            return Ok(Response::with((Status::NotFound,
                                      format!("Unknown resource: {}", err))));
        } else if let Some(err) = err.error.downcast::<StdError>() {
            // StaticFile error
            if err.kind() == ErrorKind::NotFound {
                return Ok(Response::with((Status::NotFound,
                                          format!("Unknown resource: {}", err))));
            }
        }

        // Just let other errors go through, like 401.
        Err(err)
    }
}

struct Ping;

impl Handler for Ping {
    fn handle (&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::with(Status::NoContent))
    }
}

pub struct HttpServer<T: Controller> {
    controller: T
}

impl<T: Controller> HttpServer<T> {
    pub fn new(controller: T) -> Self {
        HttpServer { controller: controller }
    }

    pub fn start(&mut self, adapter_api: &Arc<AdapterManager>) {
        let taxonomy_chain = taxonomy_router::create(self.controller.clone(),
                                                      adapter_api);

        let users_manager = self.controller.get_users_manager();
        let mut mount = Mount::new();
        mount.mount("/", static_router::create(users_manager.clone()))
             .mount("/ping", Ping)
             .mount("/api/v1", taxonomy_chain)
             .mount("/users", users_manager.get_router_chain());

        let mut chain = Chain::new(mount);
        chain.link_after(Custom404);

        let cors = CORS::new(vec![
            (vec![Method::Get], "ping".to_owned()),
            (vec![Method::Get, Method::Post, Method::Put, Method::Delete],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned()),

            // Taxonomy router paths. Keep in sync with taxonomy_router.rs
            (vec![Method::Get, Method::Post], "api/v1/services".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/services/tags".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/getters".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/setters".to_owned()),
            (vec![Method::Put], "api/v1/channels/get".to_owned()),
            (vec![Method::Put], "api/v1/channels/set".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/getters/tags".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/setters/tags".to_owned())
        ]);
        chain.link_after(cors);

        let addrs: Vec<_> = self.controller.http_as_addrs().unwrap().collect();

        if self.controller.get_tls_enabled() {
            let mut certificate_manager = self.controller.get_certificate_manager();
            let server_factory = SniServerFactory::new(&mut certificate_manager);
            start_server(addrs, chain, server_factory);
        } else {
            start_server(addrs, chain, HttpServerFactory {});
        }
    }
}

fn start_server<TListener, T>(addrs: Vec<SocketAddr>, chain: Chain, factory: T)
    where TListener: NetworkListener + Send + 'static,
          T: ServerFactory<TListener> + Send + 'static {

    thread::Builder::new().name("HttpServer".to_owned())
                          .spawn(move || {
        Iron::new(chain)
             .listen_with(addrs[0], THREAD_COUNT, &factory, None)
             .unwrap();
    }).unwrap();
}

#[cfg(test)]
describe! ping {
    before_each {
        use mount::Mount;
        use iron::Headers;
        use iron::status::Status;
        use iron_test::request;
        use super::Ping;

        let mut mount = Mount::new();
        mount.mount("/ping", Ping);
    }

    it "should response 204 NoContent" {
        let response = request::get("http://localhost:3000/ping",
                                    Headers::new(),
                                    &mount).unwrap();
        assert_eq!(response.status.unwrap(), Status::NoContent);
    }
}

#[cfg(test)]
describe! http_server {
    before_each {
        extern crate hyper;

        use foxbox_taxonomy::manager::AdapterManager;
        use std::thread;
        use std::sync::Arc;
        use std::time::Duration;
        use stubs::controller::ControllerStub;

        let taxo_manager = Arc::new(AdapterManager::new(None));

        let mut http_server = HttpServer::new(ControllerStub::new());
        http_server.start(&taxo_manager);
        // HACK: Let some time for the http server to start.
        thread::sleep(Duration::new(3, 0));
    }

    it "should get the appropriate CORS headers" {
        use iron::headers;
        use iron::method::Method;

        let endpoints = vec![
            (vec![Method::Get, Method::Post, Method::Put],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned())
        ];
        let client = hyper::Client::new();
        for endpoint in endpoints {
            let (_, path) = endpoint;
            let path = "http://localhost:3000/".to_owned() +
                       &(path.replace(":", "foo"));
            let res = client.get(&path).send();
            let headers = &res.unwrap().headers;
            assert!(headers.has::<headers::AccessControlAllowOrigin>());
            assert!(headers.has::<headers::AccessControlAllowHeaders>());
            assert!(headers.has::<headers::AccessControlAllowMethods>());
        };
    }

    it "should respond with 404" {
        use iron::status::Status;
        use std::io::Read;

        let client = hyper::Client::new();
        let path = "http://localhost:3000/foo/bar".to_owned();
        let mut res = client.get(&path).send().unwrap();
        assert_eq!(res.status, Status::NotFound);
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "Unknown resource: No such file or \
                   directory (os error 2)".to_owned());
    }
}
<|endoftext|>


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

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gltypes = gl::types;
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4
};
use cgmath::vector::{
  Vec3,
  Vec2
};
use cgmath::projection;
use cgmath::angle;

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

pub mod misc {
  use cgmath::matrix::Mat4;
  use std;

  pub fn print_mat4(name: &str, mat: Mat4<f32>) {
    println!("{}:", name);
    for i in range(0u, 4) {
      for j in range(0u, 4) {
        print!("{} ", *mat.cr(i, j));
      }
      println("");
    }
    println("");
  }

  /// usage: let s = mvp_matrix; println(type_of(&s));
  pub fn type_of<T>(_: &T) -> &'static str {
    unsafe {
      (*std::unstable::intrinsics::get_tydesc::<T>()).name
    }
  }
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<u32> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [gltypes::GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, shader_type: gltypes::GLenum) -> gltypes::GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut gltypes::GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(
    vertex_shader: gltypes::GLuint,
    fragment_shader: gltypes::GLuint
) -> gltypes::GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len: gltypes::GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut gltypes::GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

struct Win {
  vertex_shader: gltypes::GLuint,
  fragment_shader: gltypes::GLuint,
  program: gltypes::GLuint,
  vertex_array_obj: gltypes::GLuint,
  vertex_buffer_obj: gltypes::GLuint,
  matrix_id: gltypes::GLint,
  projection_matrix: Mat4<f32>,
  window: glfw::Window
}

fn get_projection_matrix() -> Mat4<f32> {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  projection::perspective(
    fov, ratio, display_range_min, display_range_max
  )
}

impl Win {
  fn new() -> Win {
    let mut win = Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      projection_matrix: get_projection_matrix(),
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };
    win.init_opengl();
    win
  }

  fn init_opengl(&mut self) {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    self.window.make_context_current();
    self.window.set_cursor_pos_callback(~CursorPosContext);
    self.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    self.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    self.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    self.program = link_program(self.vertex_shader, self.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut self.vertex_array_obj);
      gl::BindVertexArray(self.vertex_array_obj);

      // Create a Vertex Buffer Object
      gl::GenBuffers(1, &mut self.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);

      // Copy vertex data to VBO
      let float_size = std::mem::size_of::<gltypes::GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as gltypes::GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(self.program);
      gl::BindFragDataLocation(
        self.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        self.program, "position".to_c_str().unwrap()) as gltypes::GLuint;
      gl::EnableVertexAttribArray(pos_attr);

      let size = 3;
      let normalized = gl::FALSE as gltypes::GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      self.matrix_id = gl::GetUniformLocation(
        self.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }
  }

  fn cleanup(&self) {
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let mut mvp_matrix = self.projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);

      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform for each model
      // you render, since the model_view_proj_matrix will be
      // different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);
    self.window.swap_buffers();
  }

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

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    if action != glfw::Press {
      return;
    }
    match key {
      glfw::KeyEscape | glfw::KeyQ
                     => window.set_should_close(true),
      glfw::KeySpace => println!("space"),
      glfw::KeyUp    => unsafe { CAMERA_POS.y -= distance },
      glfw::KeyDown  => unsafe { CAMERA_POS.y += distance },
      glfw::KeyRight => unsafe { CAMERA_POS.x -= distance },
      glfw::KeyLeft  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Updated for lated Rust: as_mut_ptr() and native::start()<commit_after>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;
extern mod native;

use gltypes = gl::types;
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4
};
use cgmath::vector::{
  Vec3,
  Vec2
};
use cgmath::projection;
use cgmath::angle;

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

pub mod misc {
  use cgmath::matrix::Mat4;
  use std;

  pub fn print_mat4(name: &str, mat: Mat4<f32>) {
    println!("{}:", name);
    for i in range(0u, 4) {
      for j in range(0u, 4) {
        print!("{} ", *mat.cr(i, j));
      }
      println("");
    }
    println("");
  }

  /// usage: let s = mvp_matrix; println(type_of(&s));
  pub fn type_of<T>(_: &T) -> &'static str {
    unsafe {
      (*std::unstable::intrinsics::get_tydesc::<T>()).name
    }
  }
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<u32> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [gltypes::GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, shader_type: gltypes::GLenum) -> gltypes::GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut gltypes::GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(
    vertex_shader: gltypes::GLuint,
    fragment_shader: gltypes::GLuint
) -> gltypes::GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as gltypes::GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    if status != (gl::TRUE as gltypes::GLint) {
      let mut len: gltypes::GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut gltypes::GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

struct Win {
  vertex_shader: gltypes::GLuint,
  fragment_shader: gltypes::GLuint,
  program: gltypes::GLuint,
  vertex_array_obj: gltypes::GLuint,
  vertex_buffer_obj: gltypes::GLuint,
  matrix_id: gltypes::GLint,
  projection_matrix: Mat4<f32>,
  window: glfw::Window
}

fn get_projection_matrix() -> Mat4<f32> {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  projection::perspective(
    fov, ratio, display_range_min, display_range_max
  )
}

impl Win {
  fn new() -> Win {
    let mut win = Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      projection_matrix: get_projection_matrix(),
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };
    win.init_opengl();
    win
  }

  fn init_opengl(&mut self) {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    self.window.make_context_current();
    self.window.set_cursor_pos_callback(~CursorPosContext);
    self.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    self.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    self.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    self.program = link_program(self.vertex_shader, self.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut self.vertex_array_obj);
      gl::BindVertexArray(self.vertex_array_obj);

      // Create a Vertex Buffer Object
      gl::GenBuffers(1, &mut self.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);

      // Copy vertex data to VBO
      let float_size = std::mem::size_of::<gltypes::GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as gltypes::GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(self.program);
      gl::BindFragDataLocation(
        self.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        self.program, "position".to_c_str().unwrap()) as gltypes::GLuint;
      gl::EnableVertexAttribArray(pos_attr);

      let size = 3;
      let normalized = gl::FALSE as gltypes::GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      self.matrix_id = gl::GetUniformLocation(
        self.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }
  }

  fn cleanup(&self) {
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let mut mvp_matrix = self.projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);

      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform for each model
      // you render, since the model_view_proj_matrix will be
      // different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);
    self.window.swap_buffers();
  }

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

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    if action != glfw::Press {
      return;
    }
    match key {
      glfw::KeyEscape | glfw::KeyQ
                     => window.set_should_close(true),
      glfw::KeySpace => println!("space"),
      glfw::KeyUp    => unsafe { CAMERA_POS.y -= distance },
      glfw::KeyDown  => unsafe { CAMERA_POS.y += distance },
      glfw::KeyRight => unsafe { CAMERA_POS.x -= distance },
      glfw::KeyLeft  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  native::start(argc, argv, main)
}

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