<commit_before>#![feature(plugin)]
#![plugin(peg_syntax_ext)]

pub use self::param::*;

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Equation{
    pub left: Operand,
    pub right: Operand
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Function{
    pub function:String,
    pub params:Vec<Operand>,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Operand{
    Column(String),
    Function(Function),
    Number(i64),
    Boolean(bool)
}

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Connector{
    AND,
    OR,
}
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Direction{
    ASC,
    DESC,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Order{
    pub column: String,
    pub direction: Direction,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Equality{
    EQ, // = ,
    NEQ, // != ,
    LT, // <,
    LTE, // <=,
    GT, // >,
    GTE, // >=,
    IN, // IN
    NOT_IN,//NOT IN,
    IS,// IS
    IS_NOT,// IS NOT
    LIKE, // LIKE
    ILIKE, // ILIKE case insensitive like, postgresql specific
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Condition{
    pub left:Operand,
    pub equality:Equality,
    pub right:Operand,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Filter{
    pub connector: Option<Connector>,
    pub condition: Condition,
    pub subfilter: Vec<Filter>,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Params{
    pub filters: Vec<Filter>,
    pub equations: Vec<Equation>,
}

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Default)]
pub struct Query{
    pub from: Vec<Operand>,
    pub filters: Vec<Filter>,
    pub group_by: Vec<Operand>,
    pub having: Vec<Filter>,
    pub order_by: Vec<Order>,
    pub page: Option<i64>,
    pub page_size: Option<i64>,
    pub equations: Vec<Equation>,
}

peg! param(r#"
use super::*;

#[pub]
name -> String
  	= [a-zA-Z0-9_]+ { match_str.to_string() }

#[pub]
number -> i64
	= [0-9]+ { match_str.parse().unwrap() }

#[pub]
boolean -> bool
	= "true" { true }
	/ "false" { false }

#[pub]
column_name -> String
	= t:name "." c:name { format!("{}.{}", t,c) }
	/ c:name { format!("{}", c) }

#[pub]
equation -> Equation
    = l:operand "=" r:operand { Equation{left:l, right:r} }

#[pub]
operand -> Operand
	= f:function { Operand::Function(f) }
	/ b:boolean { Operand::Boolean(b) }
	/ n:number { Operand::Number(n) }
	/ c:column_name { Operand::Column(c) }

#[pub]
function -> Function
	= f:name "(" p:operand ")" { Function {function: f, params: vec![p]}}

#[pub]
equality -> Equality
	= "eq"     { Equality::EQ }
	/ "neq"    { Equality::NEQ }
	/ "lt" e:"e"?     {
			match e {
				None => Equality::LT,
				Some(e) => Equality::LTE,
			}
	}
	/ "gt" e:"e"?     {
			match e {
				None => Equality::GT,
				Some(e) => Equality::GTE,
			}
	}
    / "in"     { Equality::IN }
    / "not_in" { Equality::NOT_IN }
    / "is" _not:"_not"?     {
			match _not {
				None => Equality::IS,
				Some(e) => Equality::IS_NOT,
			}
	}
    / "like"   { Equality::LIKE }
    / "ilike"   { Equality::ILIKE }

#[pub]
condition -> Condition
	= l:operand "=" eq:equality "." r:operand {
		Condition{left: l, equality: eq, right: r}
	}

#[pub]
direction -> Direction
	= "asc" { Direction::ASC }
	/ "desc" { Direction::DESC }

#[pub]
order -> Order
	= c:name "." d:direction { Order{ column: c, direction: d} }

#[pub]
order_by -> Vec<Order>
	= "order_by" "=" o:order++ "," {o}

#[pub]
group_by -> Vec<Operand>
	= "group_by" "=" fields:operand++ "," { fields }

#[pub]
from -> Vec<Operand>
	= "from" "=" from:operand++ "," { from }

#[pub]
having -> Vec<Filter>
	= "having" "=" f:filter { vec![f] }

#[pub]
page -> i64
	= "page" "=" p:number { p }

and_page -> i64
	= "&" ? p: page { p }

page_size -> i64
	= "page_size" "=" ps:number { ps }

and_page_size -> i64
	= "&" ? ps: page_size { ps }

#[pub]
connector -> Connector
	= "&" { Connector::AND }
	/ "|" { Connector::OR }

#[pub]
filter -> Filter
    = c: condition conn: connector f: filter {
    	let rf = Filter{
    		connector:Some(conn),
    		condition: f.condition,
    		subfilter: f.subfilter
    	};
		Filter{
    		connector: None,
    		condition: c,
    		subfilter: vec![rf]
    	}
    }
    / "(" f:filter ")" {
			f
	}
    / c: condition{
    	Filter{
    		connector: None,
    		condition: c,
    		subfilter: vec![]
    	}
    }

and_order_by -> Vec<Order>
	=  "&"? o:order_by { o }

and_group_by -> Vec<Operand>
	=  "&"? g:group_by { g }

and_having -> Vec<Filter>
	=  "&"? h:having { h }

and_equations -> Vec<Equation>
	=  "&"? e:equation ** "&" { e }

and_filters -> Vec<Filter>
	=  "&"? f:filter { vec![f] }

#[pub]
params -> Params
 = f:and_filters? g:and_group_by? h:and_having? o:and_order_by? p:and_page? ps: and_page_size? e:and_equations? {
 	Params{
     		filters: match f{
     						Some(f)=> f,
     						None => vec![]
 						},
     		equations: match e{
     						Some(e)=> e,
     						None => vec![]
 						},
     	}
 }

#[pub]
query -> Query
 = f:and_filters? g:and_group_by? h:and_having? o:and_order_by? p:and_page? ps: and_page_size? e:and_equations? {
 	Query{
 			from:vec![],
     		filters: match f{
     						Some(f)=> f,
     						None => vec![]
 						},
     		group_by: match g{
     						Some(g)=> g,
     						None => vec![]
 						},
 			having: match h{
 					Some(h) => h,
 					None => vec![]
 			},
     		order_by: match o{
     						Some(o)=> o,
     						None => vec![]
 						},
 			page: p,
 			page_size: ps,
     		equations: match e{
     						Some(e)=> e,
     						None => vec![]
 						},
     	}
 }
"#);

#[test]
fn test_boolean_true(){
    assert_eq!(
        Ok(true),
        boolean("true"));
}
#[test]
fn test_boolean_false(){
    assert_eq!(
        Ok(false),
        boolean("false"));
}

#[test]
fn test_number(){
    assert_eq!(
        Ok(123),
        number("123"));
}

#[test]
fn test_name(){
    assert_eq!(
        Ok("age".to_owned()),
        name("age"));
}

#[test]
fn test_column(){
    assert_eq!(
        Ok(Operand::Column("age".to_owned())),
        operand("age"));
}

#[test]
fn test_table_column(){
    assert_eq!(
        Ok(Operand::Column("person.age".to_owned())),
        operand("person.age"));
}

#[test]
fn test_function(){
    assert_eq!(
        Ok(Function{
            function: "min".to_owned(),
            params: vec![Operand::Column("age".to_owned())],
        }),
        function("min(age)"));
}

#[test]
fn test_order(){
    assert_eq!(
        Ok(Order{
            column: "age".to_owned(),
            direction: Direction::DESC,
        }),
        order("age.desc"));
}

#[test]
fn test_euqation(){
    assert_eq!(
        Ok(Equation {
                left: Operand::Column("x".to_owned()),
                right: Operand::Number(123)
            }),
        equation("x=123"));
}

#[test]
fn test_condition(){
    assert_eq!(
        Ok(Condition{
            left:Operand::Column("age".to_owned()),
            equality:Equality::EQ,
            right:Operand::Number(13)
        }),
        condition("age=eq.13"));
}

#[test]
fn test_filter(){
    assert_eq!(
        Ok(Filter{
                connector: None,
                condition: Condition{left:Operand::Column("student".to_owned()),
                                    equality:Equality::EQ,
                                    right: Operand::Boolean(true)
                            },
                subfilter: vec![]
                }),
        filter("student=eq.true"))
}
<commit_msg>removed unncessary matching in params<commit_after>#![feature(plugin)]
#![plugin(peg_syntax_ext)]

pub use self::param::*;

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Equation{
    pub left: Operand,
    pub right: Operand
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Function{
    pub function:String,
    pub params:Vec<Operand>,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Operand{
    Column(String),
    Function(Function),
    Number(i64),
    Boolean(bool)
}

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Connector{
    AND,
    OR,
}
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Direction{
    ASC,
    DESC,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Order{
    pub column: String,
    pub direction: Direction,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Equality{
    EQ, // = ,
    NEQ, // != ,
    LT, // <,
    LTE, // <=,
    GT, // >,
    GTE, // >=,
    IN, // IN
    NOT_IN,//NOT IN,
    IS,// IS
    IS_NOT,// IS NOT
    LIKE, // LIKE
    ILIKE, // ILIKE case insensitive like, postgresql specific
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Condition{
    pub left:Operand,
    pub equality:Equality,
    pub right:Operand,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Filter{
    pub connector: Option<Connector>,
    pub condition: Condition,
    pub subfilter: Vec<Filter>,
}

#[derive(Debug)]
#[derive(PartialEq)]
pub struct Params{
    pub filters: Vec<Filter>,
    pub equations: Vec<Equation>,
}

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Default)]
pub struct Query{
    pub from: Vec<Operand>,
    pub filters: Vec<Filter>,
    pub group_by: Vec<Operand>,
    pub having: Vec<Filter>,
    pub order_by: Vec<Order>,
    pub page: Option<i64>,
    pub page_size: Option<i64>,
    pub equations: Vec<Equation>,
}

peg! param(r#"
use super::*;

#[pub]
name -> String
  	= [a-zA-Z0-9_]+ { match_str.to_string() }

#[pub]
number -> i64
	= [0-9]+ { match_str.parse().unwrap() }

#[pub]
boolean -> bool
	= "true" { true }
	/ "false" { false }

#[pub]
column_name -> String
	= t:name "." c:name { format!("{}.{}", t,c) }
	/ c:name { format!("{}", c) }

#[pub]
equation -> Equation
    = l:operand "=" r:operand { Equation{left:l, right:r} }

#[pub]
operand -> Operand
	= f:function { Operand::Function(f) }
	/ b:boolean { Operand::Boolean(b) }
	/ n:number { Operand::Number(n) }
	/ c:column_name { Operand::Column(c) }

#[pub]
function -> Function
	= f:name "(" p:operand ")" { Function {function: f, params: vec![p]}}

#[pub]
equality -> Equality
	= "eq"     { Equality::EQ }
	/ "neq"    { Equality::NEQ }
	/ "lt" e:"e"?     {
			match e {
				None => Equality::LT,
				Some(e) => Equality::LTE,
			}
	}
	/ "gt" e:"e"?     {
			match e {
				None => Equality::GT,
				Some(e) => Equality::GTE,
			}
	}
    / "in"     { Equality::IN }
    / "not_in" { Equality::NOT_IN }
    / "is" _not:"_not"?     {
			match _not {
				None => Equality::IS,
				Some(e) => Equality::IS_NOT,
			}
	}
    / "like"   { Equality::LIKE }
    / "ilike"   { Equality::ILIKE }

#[pub]
condition -> Condition
	= l:operand "=" eq:equality "." r:operand {
		Condition{left: l, equality: eq, right: r}
	}

#[pub]
direction -> Direction
	= "asc" { Direction::ASC }
	/ "desc" { Direction::DESC }

#[pub]
order -> Order
	= c:name "." d:direction { Order{ column: c, direction: d} }

#[pub]
order_by -> Vec<Order>
	= "order_by" "=" o:order++ "," {o}

#[pub]
group_by -> Vec<Operand>
	= "group_by" "=" fields:operand++ "," { fields }

#[pub]
from -> Vec<Operand>
	= "from" "=" from:operand++ "," { from }

#[pub]
having -> Vec<Filter>
	= "having" "=" f:filter { vec![f] }

#[pub]
page -> i64
	= "page" "=" p:number { p }

and_page -> i64
	= "&" ? p: page { p }

page_size -> i64
	= "page_size" "=" ps:number { ps }

and_page_size -> i64
	= "&" ? ps: page_size { ps }

#[pub]
connector -> Connector
	= "&" { Connector::AND }
	/ "|" { Connector::OR }

#[pub]
filter -> Filter
    = c: condition conn: connector f: filter {
    	let rf = Filter{
    		connector:Some(conn),
    		condition: f.condition,
    		subfilter: f.subfilter
    	};
		Filter{
    		connector: None,
    		condition: c,
    		subfilter: vec![rf]
    	}
    }
    / "(" f:filter ")" {
			f
	}
    / c: condition{
    	Filter{
    		connector: None,
    		condition: c,
    		subfilter: vec![]
    	}
    }

and_order_by -> Vec<Order>
	=  "&"? o:order_by { o }

and_group_by -> Vec<Operand>
	=  "&"? g:group_by { g }

and_having -> Vec<Filter>
	=  "&"? h:having { h }

and_equations -> Vec<Equation>
	=  "&"? e:equation ** "&" { e }

and_filters -> Vec<Filter>
	=  "&"? f:filter { vec![f] }

#[pub]
params -> Params
 = f:and_filters? e:and_equations? {
 	Params{
     		filters: match f{
     						Some(f)=> f,
     						None => vec![]
 						},
     		equations: match e{
     						Some(e)=> e,
     						None => vec![]
 						},
     	}
 }

#[pub]
query -> Query
 = f:and_filters? g:and_group_by? h:and_having? o:and_order_by? p:and_page? ps: and_page_size? e:and_equations? {
 	Query{
 			from:vec![],
     		filters: match f{
     						Some(f)=> f,
     						None => vec![]
 						},
     		group_by: match g{
     						Some(g)=> g,
     						None => vec![]
 						},
 			having: match h{
 					Some(h) => h,
 					None => vec![]
 			},
     		order_by: match o{
     						Some(o)=> o,
     						None => vec![]
 						},
 			page: p,
 			page_size: ps,
     		equations: match e{
     						Some(e)=> e,
     						None => vec![]
 						},
     	}
 }
"#);

#[test]
fn test_boolean_true(){
    assert_eq!(
        Ok(true),
        boolean("true"));
}
#[test]
fn test_boolean_false(){
    assert_eq!(
        Ok(false),
        boolean("false"));
}

#[test]
fn test_number(){
    assert_eq!(
        Ok(123),
        number("123"));
}

#[test]
fn test_name(){
    assert_eq!(
        Ok("age".to_owned()),
        name("age"));
}

#[test]
fn test_column(){
    assert_eq!(
        Ok(Operand::Column("age".to_owned())),
        operand("age"));
}

#[test]
fn test_table_column(){
    assert_eq!(
        Ok(Operand::Column("person.age".to_owned())),
        operand("person.age"));
}

#[test]
fn test_function(){
    assert_eq!(
        Ok(Function{
            function: "min".to_owned(),
            params: vec![Operand::Column("age".to_owned())],
        }),
        function("min(age)"));
}

#[test]
fn test_order(){
    assert_eq!(
        Ok(Order{
            column: "age".to_owned(),
            direction: Direction::DESC,
        }),
        order("age.desc"));
}

#[test]
fn test_euqation(){
    assert_eq!(
        Ok(Equation {
                left: Operand::Column("x".to_owned()),
                right: Operand::Number(123)
            }),
        equation("x=123"));
}

#[test]
fn test_condition(){
    assert_eq!(
        Ok(Condition{
            left:Operand::Column("age".to_owned()),
            equality:Equality::EQ,
            right:Operand::Number(13)
        }),
        condition("age=eq.13"));
}

#[test]
fn test_filter(){
    assert_eq!(
        Ok(Filter{
                connector: None,
                condition: Condition{left:Operand::Column("student".to_owned()),
                                    equality:Equality::EQ,
                                    right: Operand::Boolean(true)
                            },
                subfilter: vec![]
                }),
        filter("student=eq.true"))
}
<|endoftext|>


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

//! # TameTree
//!
//! TameTree is a library for synchronising trees and reacting to change.
//!
//! ## The Why
//!
//! While 'synchronising trees' is what TameTree does, that doesn't really describe why one might choose to use
//! it. Here's why: TameTree is a method for building large programs and systems from small programs. Small
//! programs are easier to implement and maintain than larger programs, but composing programs is difficult.
//!
//! Modern languages have a lot of composition functionality built in, so it's much more common to do the
//! composition there. The problem is that this often means components aren't particular isolated from one
//! another and it's easy to end up with a web of dependencies that can make it very hard to maintain or change
//! the individual parts.
//!
//! A TameTree component deals with data in the form of a tree. It monitors an input tree for changes, and it
//! modifies an output tree in response.
//!
//! These trees are abstract: this means it doesn't matter much to a component if its input comes from the same
//! application or if it is from another process or from a server running over the internet.
//!
//! This abstraction has one other important advantage: components can be implemented on their own terms without
//! needing to take dependencies on other components for APIs or data type definitions. Components can easily
//! maintain a high level of isolation with respect to each other, while still being able to communicate.
//!
//! ## An observation
//!
//! Take a typically modern web app. Its gross structure is typically a database, a web server, and a front-end.
//! The server will talk to a web browser and supply the front-end as HTML, JavaScript and CSS so the browser
//! can run it. In order to interact with the user, the front-end will then talk back to the server using JSON.
//! In turn, the server will talk to the database using whatever query language it uses and format the responses
//! in JSON once again so the front-end can understand them.
//!
//! If the app is particularly modern, it will use microservices: multiple webservers that talk amongst themselves
//! and with the front-end using JSON.
//!
//! What's interesting is that all this communication is done with various forms of tree structure: JSON, HTML,
//! CSS and even the database queries and responses are all types of tree structure. However, code must be written
//! in order to decode these trees and move data around so that the various parts of the application can communicate.
//! Complicating things further is that the data being sent is often updates telling the various parts how to
//! change their state, which can make it hard to determine information about the state of the system as a whole.
//!
//! Why is this? The full reason is complicated: the technology stack has aggregated over time to solve a series
//! of small problems and has come up with different solutions to them, which have been brought together to create
//! what's recognisable as a modern web app. What's interesting is that there's a common thread: when two isolated
//! systems - such as the server and the web browser - want to communicate, they do it by determining how they want
//! the state of the other side to change, encode that change into a tree structure, further encode that structure
//! into a stream of bytes, send the bytes, decode them back into a tree and then go through and apply the changes.
//!
//! The root of all this work is a concept that is now old enough that many have forgotten it had to be invented.
//! When UNIX was being designed, it was necessary to find a way to connect two processes so they could communicate.
//! The solution to this was to use streams: the I/O ports of the computers UNIX was running on worked using
//! streams of bytes so this would enable processes to talk to each other just like they would talk with the outside
//! world. The data would be in a textual form so that humans could read them by hooking up a teletype printer and
//! telling the processes to talk to that instead of each other, which was handy for troubleshooting.
//!
//! This decision - use streams for communication - has shaped how the internet works: the socket protocols in
//! general and HTTP in particular all present themselves as streams of bytes. However, we don't use teletypes
//! any more, and it turns out programs really want to send more structured data. The end result is that
//! developers spend a lot of time turning things from streams into trees and back again, and are impressed when
//! it turns out that JSON makes that process a lot simpler than XML.
//!
//! TameTree is a 'what if' project: what if the underlying abstraction processes used to communicate was trees of
//! data instead of streams. It adds in a few modern concepts: most notably the idea of being 'reactive' (essentially
//! watching for changes instead of requesting them)
//!
//! The most interesting thing it allows is feedback loops: certainly in the case of our web app. If the HTML is a
//! tree and we have feedback, then updating the HTML on the server will cause it to update on the client, and events
//! relating to the HTML displayed on the client will go straight back to the server. That would seem to make quite
//! lot of that client-side javascript with all of its JSON encoding and decoding obsolete...

extern crate rustc_serialize;

#[macro_use]
pub mod tree;
pub mod component;
mod util;
<commit_msg>Disable the component module for now (uses the old tree change extensively and all the test/compilation failures will be annoying to deal with)<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//! # TameTree
//!
//! TameTree is a library for synchronising trees and reacting to change.
//!
//! ## The Why
//!
//! While 'synchronising trees' is what TameTree does, that doesn't really describe why one might choose to use
//! it. Here's why: TameTree is a method for building large programs and systems from small programs. Small
//! programs are easier to implement and maintain than larger programs, but composing programs is difficult.
//!
//! Modern languages have a lot of composition functionality built in, so it's much more common to do the
//! composition there. The problem is that this often means components aren't particular isolated from one
//! another and it's easy to end up with a web of dependencies that can make it very hard to maintain or change
//! the individual parts.
//!
//! A TameTree component deals with data in the form of a tree. It monitors an input tree for changes, and it
//! modifies an output tree in response.
//!
//! These trees are abstract: this means it doesn't matter much to a component if its input comes from the same
//! application or if it is from another process or from a server running over the internet.
//!
//! This abstraction has one other important advantage: components can be implemented on their own terms without
//! needing to take dependencies on other components for APIs or data type definitions. Components can easily
//! maintain a high level of isolation with respect to each other, while still being able to communicate.
//!
//! ## An observation
//!
//! Take a typically modern web app. Its gross structure is typically a database, a web server, and a front-end.
//! The server will talk to a web browser and supply the front-end as HTML, JavaScript and CSS so the browser
//! can run it. In order to interact with the user, the front-end will then talk back to the server using JSON.
//! In turn, the server will talk to the database using whatever query language it uses and format the responses
//! in JSON once again so the front-end can understand them.
//!
//! If the app is particularly modern, it will use microservices: multiple webservers that talk amongst themselves
//! and with the front-end using JSON.
//!
//! What's interesting is that all this communication is done with various forms of tree structure: JSON, HTML,
//! CSS and even the database queries and responses are all types of tree structure. However, code must be written
//! in order to decode these trees and move data around so that the various parts of the application can communicate.
//! Complicating things further is that the data being sent is often updates telling the various parts how to
//! change their state, which can make it hard to determine information about the state of the system as a whole.
//!
//! Why is this? The full reason is complicated: the technology stack has aggregated over time to solve a series
//! of small problems and has come up with different solutions to them, which have been brought together to create
//! what's recognisable as a modern web app. What's interesting is that there's a common thread: when two isolated
//! systems - such as the server and the web browser - want to communicate, they do it by determining how they want
//! the state of the other side to change, encode that change into a tree structure, further encode that structure
//! into a stream of bytes, send the bytes, decode them back into a tree and then go through and apply the changes.
//!
//! The root of all this work is a concept that is now old enough that many have forgotten it had to be invented.
//! When UNIX was being designed, it was necessary to find a way to connect two processes so they could communicate.
//! The solution to this was to use streams: the I/O ports of the computers UNIX was running on worked using
//! streams of bytes so this would enable processes to talk to each other just like they would talk with the outside
//! world. The data would be in a textual form so that humans could read them by hooking up a teletype printer and
//! telling the processes to talk to that instead of each other, which was handy for troubleshooting.
//!
//! This decision - use streams for communication - has shaped how the internet works: the socket protocols in
//! general and HTTP in particular all present themselves as streams of bytes. However, we don't use teletypes
//! any more, and it turns out programs really want to send more structured data. The end result is that
//! developers spend a lot of time turning things from streams into trees and back again, and are impressed when
//! it turns out that JSON makes that process a lot simpler than XML.
//!
//! TameTree is a 'what if' project: what if the underlying abstraction processes used to communicate was trees of
//! data instead of streams. It adds in a few modern concepts: most notably the idea of being 'reactive' (essentially
//! watching for changes instead of requesting them)
//!
//! The most interesting thing it allows is feedback loops: certainly in the case of our web app. If the HTML is a
//! tree and we have feedback, then updating the HTML on the server will cause it to update on the client, and events
//! relating to the HTML displayed on the client will go straight back to the server. That would seem to make quite
//! lot of that client-side javascript with all of its JSON encoding and decoding obsolete...

extern crate rustc_serialize;

#[macro_use]
pub mod tree;
// pub mod component;           // TODO: new tree change
mod util;
<|endoftext|>


<commit_before>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Metadata (such as doc comments) is allowed on each ref.

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, allow_internal_unstable, core_intrinsics))]

#[cfg(not(feature="nightly"))]
pub mod lazy;

#[cfg(feature="nightly")]
#[path="nightly_lazy.rs"]
pub mod lazy;

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        impl ::std::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        __lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        lazy_static!($($t)*);
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Allow the macro to coexist with deny(unsafe_code)<commit_after>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

Metadata (such as doc comments) is allowed on each ref.

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.

*/

#![cfg_attr(feature="nightly", feature(const_fn, allow_internal_unstable, core_intrinsics))]

#[cfg(not(feature="nightly"))]
pub mod lazy;

#[cfg(feature="nightly")]
#[path="nightly_lazy.rs"]
pub mod lazy;

#[macro_export]
#[cfg_attr(feature="nightly", allow_internal_unstable)]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(@MAKE TY, $VIS, $(#[$attr])*, $N);
        impl ::std::ops::Deref for $N {
            type Target = $T;
            #[allow(unsafe_code)]
            fn deref<'a>(&'a self) -> &'a $T {
                unsafe {
                    #[inline(always)]
                    fn __static_ref_initialize() -> $T { $e }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        __lazy_static_create!(LAZY, $T);
                        LAZY.get(__static_ref_initialize)
                    }
                    __stability()
                }
            }
        }
        lazy_static!($($t)*);
    };
    (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(test)]
mod tests {
    use super::*;
    use std::mem;
    use std::ptr;
    use std::ffi::CString;
    use std::ffi::CStr;

    #[test]
    fn constants() {
        assert_eq!(
            CUPS_FORMAT_TEXT,
            CString::new("text/plain").unwrap().as_bytes_with_nul()
        );
        assert_eq!(CUPS_JOBID_CURRENT, 0);
    }

    #[test]
    fn list_printers() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            std::slice::from_raw_parts(dests, num_dests as usize);
            cupsFreeDests(num_dests, dests);
        }
    }

    #[test]
    fn default_printer() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            cupsGetDest(ptr::null(), ptr::null(), num_dests, dests);
            cupsFreeDests(num_dests, dests);
        }
    }

    #[test]
    fn printer_info() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            let destinations = std::slice::from_raw_parts(dests, num_dests as usize);

            for destination in destinations {
                let c_printer_name = CStr::from_ptr((*destination).name);
                let printer_name = c_printer_name.to_string_lossy();

                let c_make_and_model = cupsGetOption(
                    CString::new("printer-make-and-model").unwrap().as_ptr(),
                    destination.num_options,
                    destination.options,
                );
                let make_and_model = CStr::from_ptr(c_make_and_model).to_string_lossy();
                println!("{} ({})", printer_name, make_and_model);
                cupsFreeDests(num_dests, dests);
            }
        }

        #[test]
        #[ignore]
        fn test_print_page() {
            unsafe {
                let mut dests: *mut cups_dest_t = mem::zeroed();
                let num_dests = cupsGetDests(&mut dests as *mut _);
                let destinations = std::slice::from_raw_parts(dests, num_dests as usize);
                for dest in destinations {
                    let printer_name = CStr::from_ptr((*dest).name).to_string_lossy();
                    let make_and_model = CStr::from_ptr(cupsGetOption(
                        CString::new("printer-make-and-model").unwrap().as_ptr(),
                        dest.num_options,
                        dest.options
                    )).to_string_lossy();
                    println!("{} ({})", printer_name, make_and_model);

                    let job_id: i32 = cupsPrintFile(
                        dest.name,
                        CString::new("./test-resources/testPrintFile.txt").unwrap()
                            .as_ptr(),
                        CString::new("Test Print")
                            .unwrap()
                            .as_ptr(),
                        dest.num_options,
                        dest.options
                    );
                    println!("{}", job_id);

                    cupsFreeDests(num_dests, dests);
                }
            }
        }
    }
}
<commit_msg>Fix incorrectly ignored test.<commit_after>#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(test)]
mod tests {
    use super::*;
    use std::mem;
    use std::ptr;
    use std::ffi::CString;
    use std::ffi::CStr;

    #[test]
    fn constants() {
        assert_eq!(
            CUPS_FORMAT_TEXT,
            CString::new("text/plain").unwrap().as_bytes_with_nul()
        );
        assert_eq!(CUPS_JOBID_CURRENT, 0);
    }

    #[test]
    fn list_printers() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            std::slice::from_raw_parts(dests, num_dests as usize);
            cupsFreeDests(num_dests, dests);
        }
    }

    #[test]
    fn default_printer() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            cupsGetDest(ptr::null(), ptr::null(), num_dests, dests);
            cupsFreeDests(num_dests, dests);
        }
    }

    #[test]
    fn printer_info() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            let destinations = std::slice::from_raw_parts(dests, num_dests as usize);

            for destination in destinations {
                let c_printer_name = CStr::from_ptr((*destination).name);
                let printer_name = c_printer_name.to_string_lossy();

                let c_make_and_model = cupsGetOption(
                    CString::new("printer-make-and-model").unwrap().as_ptr(),
                    destination.num_options,
                    destination.options,
                );
                let make_and_model = CStr::from_ptr(c_make_and_model).to_string_lossy();
                println!("{} ({})", printer_name, make_and_model);
                cupsFreeDests(num_dests, dests);
            }
        }
    }

    #[test]
    #[ignore]
    fn test_print_page() {
        unsafe {
            let mut dests: *mut cups_dest_t = mem::zeroed();
            let num_dests = cupsGetDests(&mut dests as *mut _);
            let destinations = std::slice::from_raw_parts(dests, num_dests as usize);
            for dest in destinations {
                let printer_name = CStr::from_ptr((*dest).name).to_string_lossy();
                let make_and_model = CStr::from_ptr(cupsGetOption(
                    CString::new("printer-make-and-model").unwrap().as_ptr(),
                    dest.num_options,
                    dest.options
                )).to_string_lossy();
                println!("{} ({})", printer_name, make_and_model);

                let job_id: i32 = cupsPrintFile(
                    dest.name,
                    CString::new("./test-resources/testPrintFile.txt").unwrap()
                        .as_ptr(),
                    CString::new("Test Print")
                        .unwrap()
                        .as_ptr(),
                    dest.num_options,
                    dest.options
                );
                println!("{}", job_id);

                cupsFreeDests(num_dests, dests);
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate curl;
extern crate rustc_serialize;

use std::thread;
use std::time::Duration;
use std::env::{self, VarError};
use std::str::FromStr;
use std::num::ParseIntError;
use rustc_serialize::json;
use curl::http;

const USER_AGENT:         &'static str = concat!("travis-after-all/", env!("CARGO_PKG_VERSION"));
const TRAVIS_JOB_NUMBER : &'static str = "TRAVIS_JOB_NUMBER";
const TRAVIS_BUILD_ID:    &'static str = "TRAVIS_BUILD_ID";
const TRAVIS_API_URL:     &'static str = "https://api.travis-ci.org";
const POLLING_INTERVAL:   &'static str = "LEADER_POLLING_INTERVAL";

#[derive(Debug)]
pub enum Error {
    Generic(String),
    NoMatrix,
    NotLeader,
    FailedBuilds,
}

impl Error {
    pub fn from_str(message: &str) -> Error {
        Error::Generic(message.into())
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        std::fmt::Debug::fmt(self, f)
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Generic(ref s) => s,
            Error::NoMatrix => "No matrix found. Call `build_matrix` first.",
            Error::NotLeader => "This build is not the leader",
            Error::FailedBuilds => "Some builds failed",
        }
    }
}

impl From<VarError> for Error {
    fn from(err: VarError) -> Error {
        match err {
            VarError::NotPresent => Error::Generic("Environment variable not present".into()),
            VarError::NotUnicode(_) => Error::Generic("Environment variable not valid".into())
        }
    }
}

impl From<ParseIntError> for Error {
    fn from(_err: ParseIntError) -> Error {
        Error::Generic("Can't parse what should be an integer".into())
    }
}

pub struct Build {
    travis_api_url: String,
    build_id: String,
    job_number: String,
    polling_interval: u64,
    matrix: Option<Matrix>,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct MatrixElement {
    finished_at: Option<String>,
    result: Option<u32>,
    number: String,
    id: Option<u32>,
}

impl MatrixElement {
    pub fn id(&self) -> u32 {
        self.id.unwrap()
    }

    pub fn is_leader(&self) -> bool {
        is_leader(&self.number)
    }

    pub fn is_succeeded(&self) -> bool {
        if !self.is_finished() {
           return false;
        }

        match self.result {
            None => false,
            Some(0) => true,
            Some(_) => false,
        }
    }

    pub fn is_finished(&self) -> bool {
        self.finished_at.is_some()
    }
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Matrix {
    id: u32,
    matrix: Vec<MatrixElement>,
}

impl Matrix {
    pub fn builds(&self) -> &[MatrixElement] {
        &self.matrix
    }

    pub fn others_finished(&self) -> bool {
        self.matrix.iter()
            .filter(|build| !build.is_leader())
            .all(|build| build.is_finished())
    }

    pub fn others_succeeded(&self) -> bool {
        self.matrix.iter()
            .filter(|build| !build.is_leader())
            .all(|build| build.is_succeeded())
    }
}

pub fn is_leader(job: &str) -> bool {
    job.ends_with('1')
}

impl Build {
    pub fn from_env() -> Result<Build, Error> {
        let build_id = try!(env::var(TRAVIS_BUILD_ID));
        let job_number = try!(env::var(TRAVIS_JOB_NUMBER));

        let polling_interval = match env::var(POLLING_INTERVAL) {
            Err(_) => 5,
            Ok(val) => try!(FromStr::from_str(&val))
        };

        Ok(Build {
            travis_api_url: TRAVIS_API_URL.into(),
            build_id: build_id,
            job_number: job_number,
            polling_interval: polling_interval,
            matrix: None,
        })

    }

    pub fn is_leader(&self) -> bool {
        is_leader(&self.job_number)
    }

    pub fn build_matrix(&mut self) -> &Matrix {
        if self.matrix.is_some() {
            return self.matrix.as_ref().unwrap();
        }
        let url = format!("{}/builds/{}", self.travis_api_url, self.build_id);
        let res = http::handle()
            .get(url)
            .follow_redirects(true)
            .header("User-Agent", USER_AGENT)
            .exec()
            .unwrap();

        let body = String::from_utf8(res.move_body()).unwrap();
        println!("=== BODY ===");
        println!("{}", body);
        println!("");
        println!("=== /BODY ===");
        self.matrix = Some(json::decode(&body).unwrap());
        self.matrix.as_ref().unwrap()
    }

    pub fn wait_for_others(&self) -> Result<(), Error> {
        if self.matrix.is_none() {
            return Err(Error::NoMatrix);
        }

        if self.is_leader() {
            return Err(Error::NotLeader)
        }

        let matrix = self.matrix.as_ref().unwrap();
        let dur = Duration::new(self.polling_interval, 0);
        while !matrix.others_finished() {
            thread::sleep(dur);
        }

        match matrix.others_succeeded() {
            true => Ok(()),
            false => Err(Error::FailedBuilds)
        }
    }
}

<commit_msg>Don't wait if not the leader<commit_after>extern crate curl;
extern crate rustc_serialize;

use std::thread;
use std::time::Duration;
use std::env::{self, VarError};
use std::str::FromStr;
use std::num::ParseIntError;
use rustc_serialize::json;
use curl::http;

const USER_AGENT:         &'static str = concat!("travis-after-all/", env!("CARGO_PKG_VERSION"));
const TRAVIS_JOB_NUMBER : &'static str = "TRAVIS_JOB_NUMBER";
const TRAVIS_BUILD_ID:    &'static str = "TRAVIS_BUILD_ID";
const TRAVIS_API_URL:     &'static str = "https://api.travis-ci.org";
const POLLING_INTERVAL:   &'static str = "LEADER_POLLING_INTERVAL";

#[derive(Debug)]
pub enum Error {
    Generic(String),
    NoMatrix,
    NotLeader,
    FailedBuilds,
}

impl Error {
    pub fn from_str(message: &str) -> Error {
        Error::Generic(message.into())
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        std::fmt::Debug::fmt(self, f)
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Generic(ref s) => s,
            Error::NoMatrix => "No matrix found. Call `build_matrix` first.",
            Error::NotLeader => "This build is not the leader",
            Error::FailedBuilds => "Some builds failed",
        }
    }
}

impl From<VarError> for Error {
    fn from(err: VarError) -> Error {
        match err {
            VarError::NotPresent => Error::Generic("Environment variable not present".into()),
            VarError::NotUnicode(_) => Error::Generic("Environment variable not valid".into())
        }
    }
}

impl From<ParseIntError> for Error {
    fn from(_err: ParseIntError) -> Error {
        Error::Generic("Can't parse what should be an integer".into())
    }
}

pub struct Build {
    travis_api_url: String,
    build_id: String,
    job_number: String,
    polling_interval: u64,
    matrix: Option<Matrix>,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct MatrixElement {
    finished_at: Option<String>,
    result: Option<u32>,
    number: String,
    id: Option<u32>,
}

impl MatrixElement {
    pub fn id(&self) -> u32 {
        self.id.unwrap()
    }

    pub fn is_leader(&self) -> bool {
        is_leader(&self.number)
    }

    pub fn is_succeeded(&self) -> bool {
        if !self.is_finished() {
           return false;
        }

        match self.result {
            None => false,
            Some(0) => true,
            Some(_) => false,
        }
    }

    pub fn is_finished(&self) -> bool {
        self.finished_at.is_some()
    }
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Matrix {
    id: u32,
    matrix: Vec<MatrixElement>,
}

impl Matrix {
    pub fn builds(&self) -> &[MatrixElement] {
        &self.matrix
    }

    pub fn others_finished(&self) -> bool {
        self.matrix.iter()
            .filter(|build| !build.is_leader())
            .all(|build| build.is_finished())
    }

    pub fn others_succeeded(&self) -> bool {
        self.matrix.iter()
            .filter(|build| !build.is_leader())
            .all(|build| build.is_succeeded())
    }
}

pub fn is_leader(job: &str) -> bool {
    job.ends_with('1')
}

impl Build {
    pub fn from_env() -> Result<Build, Error> {
        let build_id = try!(env::var(TRAVIS_BUILD_ID));
        let job_number = try!(env::var(TRAVIS_JOB_NUMBER));

        let polling_interval = match env::var(POLLING_INTERVAL) {
            Err(_) => 5,
            Ok(val) => try!(FromStr::from_str(&val))
        };

        Ok(Build {
            travis_api_url: TRAVIS_API_URL.into(),
            build_id: build_id,
            job_number: job_number,
            polling_interval: polling_interval,
            matrix: None,
        })

    }

    pub fn is_leader(&self) -> bool {
        is_leader(&self.job_number)
    }

    pub fn build_matrix(&mut self) -> &Matrix {
        if self.matrix.is_some() {
            return self.matrix.as_ref().unwrap();
        }
        let url = format!("{}/builds/{}", self.travis_api_url, self.build_id);
        let res = http::handle()
            .get(url)
            .follow_redirects(true)
            .header("User-Agent", USER_AGENT)
            .exec()
            .unwrap();

        let body = String::from_utf8(res.move_body()).unwrap();
        println!("=== BODY ===");
        println!("{}", body);
        println!("");
        println!("=== /BODY ===");
        self.matrix = Some(json::decode(&body).unwrap());
        self.matrix.as_ref().unwrap()
    }

    pub fn wait_for_others(&self) -> Result<(), Error> {
        if self.matrix.is_none() {
            return Err(Error::NoMatrix);
        }

        if !self.is_leader() {
            return Err(Error::NotLeader)
        }

        let matrix = self.matrix.as_ref().unwrap();
        let dur = Duration::new(self.polling_interval, 0);
        while !matrix.others_finished() {
            thread::sleep(dur);
        }

        match matrix.others_succeeded() {
            true => Ok(()),
            false => Err(Error::FailedBuilds)
        }
    }
}

<|endoftext|>


<commit_before>/*!
Simple persistent generic HashMap/Key-value store.

Basic usage:

```
extern crate kv_cab;

use kv_cab::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab");

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
extern crate kv_cab;
extern crate rustc_serialize;

use kv_cab::KV;

#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
enum MyKey {
    String(String),
    Int(i32),
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
enum MyValue {
    String(String),
    Int(i32),
}

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab");

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

extern crate bincode;
extern crate rustc_serialize;
#[macro_use]
extern crate log;

use std::collections::HashMap;
use std::fs;
use std::fs::{ File, OpenOptions };
use std::io::prelude::*;
use std::hash::Hash;

use bincode::SizeLimit;
use bincode::rustc_serialize::{ encode, decode };

use rustc_serialize::{ Encodable, Decodable };

/// The maximum number of retries the cab will make
const MAX_RETRIES:i32 = 10;

/// Definition of a macro for retrying an operation
macro_rules! retry {
    ($i:ident, $b:block) => (
        for $i in 0..MAX_RETRIES {
            if $i != 0 {
                std::thread::park_timeout(std::time::Duration::new(0u64, 1000u32));
            }

            $b
        }
    )
}

/// A default value type to use with KV
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum Value {
    String(String),
    Int(i32),
    Float(f32),
    Map(HashMap<String, Value>),
}

/// Type alias for results from KV
type KVResult = Result<bool, &'static str>;

/// The type that represents the key-value store
pub struct KV<K,V> {
    cab: HashMap<K, V>,
    file: File,
}

impl<K: Clone + Encodable + Decodable + Eq + Hash, V: Clone + Encodable + Decodable> KV<K,V> {
    /// Creates a new instance of the KV store
    pub fn new(p:&'static str) -> KV<K,V> {
        // if the cab doesn't exist create it
        retry!(i, {
            match OpenOptions::new().write(true).create(true).open(p) {
                Ok(_) => break,
                Err(e) => {
                    // handle if the db is already in place
                    if e.kind() == std::io::ErrorKind::PermissionDenied ||
                        e.kind() == std::io::ErrorKind::AlreadyExists {
                        break;
                    }
                    error!("{}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not create file after retries");
                    }
                    continue;
                },
            }
        });

        // Retry to get a reference to the cab file at path p
        fn retry_get_file(p:&'static str) -> File {
            retry!(i, {
                // make sure it is writeable on open
                let mut perms = match fs::metadata(p) {
                    Ok(f) => f.permissions(),
                    Err(e) => {
                        error!("{}", e);
                        continue;
                    },
                };
                perms.set_readonly(false);
                match fs::set_permissions(p, perms) {
                    Ok(_) => (),
                    Err(e) => {
                        error!("{}", e);
                        continue;
                    }
                }

                match OpenOptions::new().read(true).write(true).open(p) {
                    Ok(f) => { return f; },
                    Err(e) => {
                        error!("{}", e);
                        if i >= MAX_RETRIES - 1 {
                            panic!("Could not open file after retries");
                        }
                        continue;
                    }
                };

            });
            panic!("retry_get_file: Failed to get file");
        }

        // create the KV instance
        let mut store = KV {
            cab: HashMap::new(),
            file: retry_get_file(p),
        };

        // lock the cab for writes
        store.lock_cab(true);

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                warn!("{}", e);
            },
        };

        store
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Option<V> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Some((*v).clone()),
            None => None
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Vec<K> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // create a vec from the cabs keys
        self.cab.keys().map(|k| k.clone()).collect()
    }

    /// Locks/unlocks cab for writing purposes
    fn lock_cab(&mut self, readonly:bool) {
        retry!(i, {
            // set not readonly while writing
            let mut perms = match self.file.metadata() {
                Ok(f) => f.permissions(),
                Err(e) => {
                    error!("{}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not set permissions after retries");
                    }
                    continue;
                },
            };
            perms.set_readonly(readonly);

            match self.file.set_permissions(perms) {
                Ok(_) => {
                    let _ = self.file.sync_all();
                    break;
                },
                Err(e) => {
                    error!("{}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not set permissions after retries");
                    }
                    continue;
                },
            }
        });
    }

    /// Waits for the cab to become free
    fn wait_for_free(&mut self, lock:bool) -> KVResult {
        loop {
            // check if the cab is being written to
            let _ = self.file.sync_all();
            let metadata = match self.file.metadata() {
                Ok(m) => m,
                Err(_) => return Err("File doesn't exist or is not readeable"),
            };

            if metadata.permissions().readonly() {
                if lock {
                    self.lock_cab(false);
                }
                break;
            }
        }

        Ok(true)
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // encode the cab as a u8 vec
        let byte_vec: Vec<u8> = match encode(&mut self.cab, SizeLimit::Infinite) {
            Ok(bv) => bv,
            Err(e) => {
                error!("encode: {}", e);
                return Err("Could not encode cab");
            },
        };

        if !self.wait_for_free(true).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }
        // attempt to write to the cab
        retry!(i, {
            // write the bytes to it
            match self.file.write_all(byte_vec.as_slice()) {
                Ok(_) => (),
                Err(e) => {
                    error!("file.write_all/retry: {}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not write to file after retries");
                    }
                    continue;
                },
            }

            // flush to disk
            let _ = self.file.flush();
            self.lock_cab(true);
            // leave the retry loop as successful
            break;
        });

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        // byte vec to read into
        let mut byte_vec = Vec::new();

        // wait/lock the cab and read the bytes
        if !self.wait_for_free(false).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }
        let _ = self.file.read_to_end(&mut byte_vec);

        // decode u8 vec back into HashMap
        let decoded: HashMap<K, V> = match decode(byte_vec.as_slice()) {
            Ok(f) => f,
            Err(e) => {
                warn!("{}", e);
                return Err("Couldn't decode cab");
            },
        };
        // assign read HashMap back to self
        self.cab = decoded;

        Ok(true)
    }
}
<commit_msg>Tidied up/simplified the cab creation and getting a ref to the cab File<commit_after>/*!
Simple persistent generic HashMap/Key-value store.

Basic usage:

```
extern crate kv_cab;

use kv_cab::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab");

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
extern crate kv_cab;
extern crate rustc_serialize;

use kv_cab::KV;

#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
enum MyKey {
    String(String),
    Int(i32),
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
enum MyValue {
    String(String),
    Int(i32),
}

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab");

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

extern crate bincode;
extern crate rustc_serialize;
#[macro_use]
extern crate log;

use std::collections::HashMap;
use std::fs;
use std::fs::{ File, OpenOptions };
use std::io::prelude::*;
use std::hash::Hash;

use bincode::SizeLimit;
use bincode::rustc_serialize::{ encode, decode };

use rustc_serialize::{ Encodable, Decodable };

/// The maximum number of retries the cab will make
const MAX_RETRIES:i32 = 10;

/// Definition of a macro for retrying an operation
macro_rules! retry {
    ($i:ident, $b:block) => (
        for $i in 0..MAX_RETRIES {
            if $i != 0 {
                std::thread::park_timeout(std::time::Duration::new(0u64, 1000u32));
            }

            $b
        }
    )
}

/// A default value type to use with KV
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum Value {
    String(String),
    Int(i32),
    Float(f32),
    Map(HashMap<String, Value>),
}

/// Type alias for results from KV
type KVResult = Result<bool, &'static str>;

/// The type that represents the key-value store
pub struct KV<K,V> {
    cab: HashMap<K, V>,
    file: File,
}

impl<K: Clone + Encodable + Decodable + Eq + Hash, V: Clone + Encodable + Decodable> KV<K,V> {
    /// Creates a new instance of the KV store
    pub fn new(p:&'static str) -> KV<K,V> {
        // Retry to get a reference to the cab file at path p and create if doesn't exist
        fn retry_get_file(p:&'static str) -> File {
            retry!(i, {
                // make sure it is writeable on open
                match fs::metadata(p) {
                    Ok(f) => {
                        let mut perms = f.permissions();
                        perms.set_readonly(false);

                        match fs::set_permissions(p, perms) {
                            Ok(_) => (),
                            Err(e) => {
                                error!("{}", e);
                                continue;
                            }
                        }
                    },
                    Err(e) => {
                        if e.kind() != std::io::ErrorKind::NotFound {
                            error!("{}", e);
                            continue;
                        }
                    },
                }

                match OpenOptions::new().read(true).write(true).create(true).open(p) {
                    Ok(f) => { return f; },
                    Err(e) => {
                        error!("{}", e);
                        if i >= MAX_RETRIES - 1 {
                            panic!("Could not open file after retries");
                        }
                        continue;
                    }
                };

            });
            panic!("retry_get_file: Failed to get file");
        }

        // create the KV instance
        let mut store = KV {
            cab: HashMap::new(),
            file: retry_get_file(p),
        };

        // lock the cab for writes
        store.lock_cab(true);

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                warn!("{}", e);
            },
        };

        store
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Option<V> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Some((*v).clone()),
            None => None
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Vec<K> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // create a vec from the cabs keys
        self.cab.keys().map(|k| k.clone()).collect()
    }

    /// Locks/unlocks cab for writing purposes
    fn lock_cab(&mut self, readonly:bool) {
        retry!(i, {
            // set not readonly while writing
            let mut perms = match self.file.metadata() {
                Ok(f) => f.permissions(),
                Err(e) => {
                    error!("{}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not set permissions after retries");
                    }
                    continue;
                },
            };
            perms.set_readonly(readonly);

            match self.file.set_permissions(perms) {
                Ok(_) => {
                    let _ = self.file.sync_all();
                    break;
                },
                Err(e) => {
                    error!("{}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not set permissions after retries");
                    }
                    continue;
                },
            }
        });
    }

    /// Waits for the cab to become free
    fn wait_for_free(&mut self, lock:bool) -> KVResult {
        loop {
            // check if the cab is being written to
            let _ = self.file.sync_all();
            let metadata = match self.file.metadata() {
                Ok(m) => m,
                Err(_) => return Err("File doesn't exist or is not readeable"),
            };

            if metadata.permissions().readonly() {
                if lock {
                    self.lock_cab(false);
                }
                break;
            }
        }

        Ok(true)
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // encode the cab as a u8 vec
        let byte_vec: Vec<u8> = match encode(&mut self.cab, SizeLimit::Infinite) {
            Ok(bv) => bv,
            Err(e) => {
                error!("encode: {}", e);
                return Err("Could not encode cab");
            },
        };

        if !self.wait_for_free(true).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }
        // attempt to write to the cab
        retry!(i, {
            // write the bytes to it
            match self.file.write_all(byte_vec.as_slice()) {
                Ok(_) => (),
                Err(e) => {
                    error!("file.write_all/retry: {}", e);
                    if i >= MAX_RETRIES - 1 {
                        panic!("Could not write to file after retries");
                    }
                    continue;
                },
            }

            // flush to disk
            let _ = self.file.flush();
            self.lock_cab(true);
            // leave the retry loop as successful
            break;
        });

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        // byte vec to read into
        let mut byte_vec = Vec::new();

        // wait/lock the cab and read the bytes
        if !self.wait_for_free(false).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }
        let _ = self.file.read_to_end(&mut byte_vec);

        // decode u8 vec back into HashMap
        let decoded: HashMap<K, V> = match decode(byte_vec.as_slice()) {
            Ok(f) => f,
            Err(e) => {
                warn!("{}", e);
                return Err("Couldn't decode cab");
            },
        };
        // assign read HashMap back to self
        self.cab = decoded;

        Ok(true)
    }
}
<|endoftext|>


<commit_before>//! **Plexus** is a library for generating and manipulating 3D mesh data.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! extremely unstable!
#![allow(unknown_lints)] // Allow clippy lints.

extern crate arrayvec;
#[cfg(feature = "geometry-cgmath")]
extern crate cgmath;
extern crate decorum;
#[macro_use]
extern crate derivative;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate itertools;
#[cfg(feature = "geometry-nalgebra")]
extern crate nalgebra;
extern crate num;

pub mod buffer;
pub mod geometry;
pub mod graph;
pub mod primitive;

// Re-exported to avoid requiring a direct dependency on decorum.
pub use decorum::{R32, R64};

pub mod prelude {
    pub use geometry::{Duplet, Triplet};
    pub use primitive::{
        CollectWithIndexer, FlatIndexVertices, IndexVertices, IntoEdges, IntoSubdivisions,
        IntoTetrahedrons, IntoTriangles, IntoVertices, MapVertices, PolygonGenerator,
        PolygonsWithIndex, PolygonsWithPosition, PolygonsWithTexture, Triangulate, VertexGenerator,
        Vertices, VerticesWithPosition,
    };
}

trait BoolExt: Sized {
    fn option(self) -> Option<()>;

    fn some<T>(self, some: T) -> Option<T>;

    fn some_with<T, F>(self, f: F) -> Option<T>
    where
        F: Fn() -> T;
}

impl BoolExt for bool {
    fn option(self) -> Option<()> {
        if self {
            Some(())
        }
        else {
            None
        }
    }

    fn some<T>(self, some: T) -> Option<T> {
        if self {
            Some(some)
        }
        else {
            None
        }
    }

    fn some_with<T, F>(self, f: F) -> Option<T>
    where
        F: Fn() -> T,
    {
        if self {
            Some(f())
        }
        else {
            None
        }
    }
}

trait OptionExt<T> {
    fn and_if<F>(self, f: F) -> Self
    where
        F: Fn(&T) -> bool;
}

impl<T> OptionExt<T> for Option<T> {
    fn and_if<F>(mut self, f: F) -> Self
    where
        F: Fn(&T) -> bool,
    {
        match self.take() {
            Some(value) => if f(&value) {
                Some(value)
            }
            else {
                None
            },
            _ => None,
        }
    }
}
<commit_msg>Update library doc comment.<commit_after>//! **Plexus** is a library for generating and manipulating 2D and 3D mesh
//! data.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.
#![allow(unknown_lints)] // Allow clippy lints.

extern crate arrayvec;
#[cfg(feature = "geometry-cgmath")]
extern crate cgmath;
extern crate decorum;
#[macro_use]
extern crate derivative;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate itertools;
#[cfg(feature = "geometry-nalgebra")]
extern crate nalgebra;
extern crate num;

pub mod buffer;
pub mod geometry;
pub mod graph;
pub mod primitive;

// Re-exported to avoid requiring a direct dependency on decorum.
pub use decorum::{R32, R64};

pub mod prelude {
    pub use geometry::{Duplet, Triplet};
    pub use primitive::{
        CollectWithIndexer, FlatIndexVertices, IndexVertices, IntoEdges, IntoSubdivisions,
        IntoTetrahedrons, IntoTriangles, IntoVertices, MapVertices, PolygonGenerator,
        PolygonsWithIndex, PolygonsWithPosition, PolygonsWithTexture, Triangulate, VertexGenerator,
        Vertices, VerticesWithPosition,
    };
}

trait BoolExt: Sized {
    fn option(self) -> Option<()>;

    fn some<T>(self, some: T) -> Option<T>;

    fn some_with<T, F>(self, f: F) -> Option<T>
    where
        F: Fn() -> T;
}

impl BoolExt for bool {
    fn option(self) -> Option<()> {
        if self {
            Some(())
        }
        else {
            None
        }
    }

    fn some<T>(self, some: T) -> Option<T> {
        if self {
            Some(some)
        }
        else {
            None
        }
    }

    fn some_with<T, F>(self, f: F) -> Option<T>
    where
        F: Fn() -> T,
    {
        if self {
            Some(f())
        }
        else {
            None
        }
    }
}

trait OptionExt<T> {
    fn and_if<F>(self, f: F) -> Self
    where
        F: Fn(&T) -> bool;
}

impl<T> OptionExt<T> for Option<T> {
    fn and_if<F>(mut self, f: F) -> Self
    where
        F: Fn(&T) -> bool,
    {
        match self.take() {
            Some(value) => if f(&value) {
                Some(value)
            }
            else {
                None
            },
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! A simple interface to the Google URL Shortener API.
extern crate hyper;
extern crate rustc_serialize;
extern crate url;

use hyper::{HttpError};
use hyper::client::{Request};
use hyper::header::{ContentType};
use hyper::method::{Method};
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::status::{StatusCode};
use rustc_serialize::json::{BuilderError, Json};
use std::borrow::{ToOwned};
use std::io::{Read, Write};
use std::io::Error as IoError;
use url::{Url};
use url::ParseError as UrlError;
use url::form_urlencoded::{serialize};

const BASEURL: &'static str = "https://www.googleapis.com/urlshortener/v1/url";

/// Contains all possible errors you might get while shortening a URL
#[derive(Debug)]
pub enum Error {
    BadStatus(StatusCode, String),
    Http(HttpError),
    Io(IoError),
    Json(BuilderError),
    MissingId(Json),
    Url(UrlError),
}
impl From<HttpError> for Error {
    fn from(err: HttpError) -> Error {
        Error::Http(err)
    }
}
impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Error::Io(err)
    }
}
impl From<BuilderError> for Error {
    fn from(err: BuilderError) -> Error {
        Error::Json(err)
    }
}
impl From<UrlError> for Error {
    fn from(err: UrlError) -> Error {
        Error::Url(err)
    }
}

/// Shortens a URL using the Google URL Shortener API
pub fn shorten(key: &str, longurl: &str) -> Result<String, Error> {
    let query = [("key", key)];
    let query = serialize(query.iter().map(|&x| x));
    let url = format!("{}?{}", BASEURL, query);
    let url = try!(Url::parse(&url));
    let mut request = try!(Request::new(Method::Post, url));
    request.headers_mut().set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])));
    let mut request = try!(request.start());
    let body = vec![("longUrl".to_owned(), Json::String(longurl.to_owned()))];
    let body = Json::Object(body.into_iter().collect());
    try!(request.write_all(body.to_string().as_bytes()));
    let mut response = try!(request.send());
    let mut body = String::new();
    try!(response.read_to_string(&mut body));
    if response.status != StatusCode::Ok {
        return Err(Error::BadStatus(response.status, body))
    }
    let json = try!(Json::from_str(&*body));
    let id = json.find("id").and_then(|x| x.as_string());
    match id {
        Some(id) => Ok(id.to_owned()),
        None => Err(Error::MissingId(json.clone())), //FIXME - nonlexical borrows
    }
}
<commit_msg>Update hyper<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! A simple interface to the Google URL Shortener API.
extern crate hyper;
extern crate rustc_serialize;
extern crate url;

use hyper::Error as HttpError;
use hyper::client::{Request};
use hyper::header::{ContentType};
use hyper::method::{Method};
use hyper::mime::{Mime, SubLevel, TopLevel};
use hyper::status::{StatusCode};
use rustc_serialize::json::{BuilderError, Json};
use std::borrow::{ToOwned};
use std::io::{Read, Write};
use std::io::Error as IoError;
use url::{Url};
use url::ParseError as UrlError;
use url::form_urlencoded::{serialize};

const BASEURL: &'static str = "https://www.googleapis.com/urlshortener/v1/url";

/// Contains all possible errors you might get while shortening a URL
#[derive(Debug)]
pub enum Error {
    BadStatus(StatusCode, String),
    Http(HttpError),
    Io(IoError),
    Json(BuilderError),
    MissingId(Json),
    Url(UrlError),
}
impl From<HttpError> for Error {
    fn from(err: HttpError) -> Error {
        Error::Http(err)
    }
}
impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Error::Io(err)
    }
}
impl From<BuilderError> for Error {
    fn from(err: BuilderError) -> Error {
        Error::Json(err)
    }
}
impl From<UrlError> for Error {
    fn from(err: UrlError) -> Error {
        Error::Url(err)
    }
}

/// Shortens a URL using the Google URL Shortener API
pub fn shorten(key: &str, longurl: &str) -> Result<String, Error> {
    let query = [("key", key)];
    let query = serialize(query.iter().map(|&x| x));
    let url = format!("{}?{}", BASEURL, query);
    let url = try!(Url::parse(&url));
    let mut request = try!(Request::new(Method::Post, url));
    request.headers_mut().set(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])));
    let mut request = try!(request.start());
    let body = vec![("longUrl".to_owned(), Json::String(longurl.to_owned()))];
    let body = Json::Object(body.into_iter().collect());
    try!(request.write_all(body.to_string().as_bytes()));
    let mut response = try!(request.send());
    let mut body = String::new();
    try!(response.read_to_string(&mut body));
    if response.status != StatusCode::Ok {
        return Err(Error::BadStatus(response.status, body))
    }
    let json = try!(Json::from_str(&*body));
    let id = json.find("id").and_then(|x| x.as_string());
    match id {
        Some(id) => Ok(id.to_owned()),
        None => Err(Error::MissingId(json.clone())), //FIXME - nonlexical borrows
    }
}
<|endoftext|>


<commit_before>#![cfg(windows)]

extern crate winapi;

use com::{ComPtr, ToResult, HResult, as_ptr};
use std::ptr;
use winapi::shared::dxgi1_2::DXGI_SWAP_CHAIN_DESC1;
use winapi::shared::dxgi1_2::IDXGIFactory2;
use winapi::shared::minwindef::{TRUE, FALSE};
use winapi::shared::windef::HWND;
use winapi::shared::winerror::S_OK;
use winapi::um::d3d11::ID3D11Device;
use winapi::um::dcomp::IDCompositionDevice;
use winapi::um::dcomp::IDCompositionTarget;
use winapi::um::dcomp::IDCompositionVisual;

pub mod com;

pub struct DirectComposition {
    d3d_device: ComPtr<ID3D11Device>,
    dxgi_factory: ComPtr<IDXGIFactory2>,
    composition_device: ComPtr<IDCompositionDevice>,
    root_visual: ComPtr<IDCompositionVisual>,

    #[allow(unused)]  // Needs to be kept alive
    composition_target: ComPtr<IDCompositionTarget>,
}

impl DirectComposition {
    /// Initialize DirectComposition in the given window
    ///
    /// # Safety
    ///
    /// `hwnd` must be a valid handle to a window.
    pub unsafe fn new(hwnd: HWND) -> HResult<Self> {
        let mut feature_level_supported = 0;

        let d3d_device = ComPtr::new_with(|ptr_ptr| winapi::um::d3d11::D3D11CreateDevice(
            ptr::null_mut(),
            winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
            ptr::null_mut(),
            winapi::um::d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT |
            if cfg!(debug_assertions) {
                winapi::um::d3d11::D3D11_CREATE_DEVICE_DEBUG
            } else {
                0
            },
            ptr::null_mut(),
            0,
            winapi::um::d3d11::D3D11_SDK_VERSION,
            ptr_ptr,
            &mut feature_level_supported,
            ptr::null_mut(),
        ))?;

        let dxgi_device = d3d_device.cast::<winapi::shared::dxgi::IDXGIDevice>()?;

        // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404556(v=vs.85).aspx#code-snippet-1
        // “Because you can create a Direct3D device without creating a swap chain,
        //  you might need to retrieve the factory that is used to create the device
        //  in order to create a swap chain.”
        let adapter = ComPtr::new_with(|ptr_ptr| dxgi_device.GetAdapter(ptr_ptr))?;
        let dxgi_factory = ComPtr::<IDXGIFactory2>::new_with_uuid(|uuid, ptr_ptr| {
            adapter.GetParent(uuid, ptr_ptr)
        })?;

        // Create the DirectComposition device object.
        let composition_device = ComPtr::<IDCompositionDevice>::new_with_uuid(|uuid, ptr_ptr| {
            winapi::um::dcomp::DCompositionCreateDevice(&*dxgi_device, uuid,ptr_ptr)
        })?;

        // Create the composition target object based on the
        // specified application window.
        let composition_target = ComPtr::new_with(|ptr_ptr| {
            composition_device.CreateTargetForHwnd(hwnd, TRUE, ptr_ptr)
        })?;

        let root_visual = ComPtr::new_with(|ptr_ptr| composition_device.CreateVisual(ptr_ptr))?;
        composition_target.SetRoot(&*root_visual).to_result()?;

        Ok(DirectComposition {
            d3d_device, dxgi_factory, composition_device, composition_target, root_visual,
        })
    }

    /// Execute changes to the DirectComposition scene.
    pub fn commit(&self) -> HResult<()> {
        unsafe {
            self.composition_device.Commit().to_result()
        }
    }

    pub fn create_d3d_visual(&self, width: u32, height: u32) -> HResult<D3DVisual> {
        unsafe {
            let desc = DXGI_SWAP_CHAIN_DESC1 {
                Width: width,
                Height: height,
                Format: winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
                Stereo: FALSE,
                SampleDesc: winapi::shared::dxgitype::DXGI_SAMPLE_DESC {
                    Count: 1,
                    Quality: 0,
                },
                BufferUsage: winapi::shared::dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
                BufferCount: 2,
                Scaling: winapi::shared::dxgi1_2::DXGI_SCALING_STRETCH,
                SwapEffect: winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
                AlphaMode:  winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_IGNORE,
                Flags: 0,
            };
            let swap_chain = ComPtr::<winapi::shared::dxgi1_2::IDXGISwapChain1>::new_with(|ptr_ptr| {
                self.dxgi_factory.CreateSwapChainForComposition(
                    as_ptr(&self.d3d_device),
                    &desc,
                    ptr::null_mut(),
                    ptr_ptr,
                )
            })?;
            let visual = ComPtr::new_with(|ptr_ptr| self.composition_device.CreateVisual(ptr_ptr))?;
            visual.SetContent(&*****swap_chain).to_result()?;
            self.root_visual.AddVisual(&*visual, FALSE, ptr::null_mut()).to_result()?;

            Ok(D3DVisual { visual, swap_chain })
        }
    }
}

/// A DirectComposition "visual" configured for rendering with Direct3D.
pub struct D3DVisual {
    visual: ComPtr<IDCompositionVisual>,
    swap_chain: ComPtr<winapi::shared::dxgi1_2::IDXGISwapChain1>,
}

impl D3DVisual {
    pub fn set_offset_x(&self, offset_x: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetX_1(offset_x).to_result()
        }
    }

    pub fn set_offset_y(&self, offset_y: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetY_1(offset_y).to_result()
        }
    }

    pub fn render_and_present_solid_frame(&self, composition: &DirectComposition, rgba: &[f32; 4])
                                          -> HResult<()> {
        unsafe {
            let back_buffer = ComPtr::<winapi::um::d3d11::ID3D11Texture2D>::new_with_uuid(|uuid, ptr_ptr| {
                self.swap_chain.GetBuffer(0, uuid, ptr_ptr)
            })?;
            let render_target = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.CreateRenderTargetView(
                    as_ptr(&back_buffer), ptr::null_mut(), ptr_ptr,
                )
            })?;
            let context = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.GetImmediateContext(ptr_ptr);
                S_OK
            })?;

            // FIXME: arbitrary D3D rendering here?
            context.OMSetRenderTargets(1, &render_target.as_raw(), ptr::null_mut());
            context.ClearRenderTargetView(render_target.as_raw(), &rgba);

            self.swap_chain.Present(0, 0).to_result()
        }
    }
}
<commit_msg>Alpha transparency!<commit_after>#![cfg(windows)]

extern crate winapi;

use com::{ComPtr, ToResult, HResult, as_ptr};
use std::ptr;
use winapi::shared::dxgi1_2::DXGI_SWAP_CHAIN_DESC1;
use winapi::shared::dxgi1_2::IDXGIFactory2;
use winapi::shared::minwindef::{TRUE, FALSE};
use winapi::shared::windef::HWND;
use winapi::shared::winerror::S_OK;
use winapi::um::d3d11::ID3D11Device;
use winapi::um::dcomp::IDCompositionDevice;
use winapi::um::dcomp::IDCompositionTarget;
use winapi::um::dcomp::IDCompositionVisual;

pub mod com;

pub struct DirectComposition {
    d3d_device: ComPtr<ID3D11Device>,
    dxgi_factory: ComPtr<IDXGIFactory2>,
    composition_device: ComPtr<IDCompositionDevice>,
    root_visual: ComPtr<IDCompositionVisual>,

    #[allow(unused)]  // Needs to be kept alive
    composition_target: ComPtr<IDCompositionTarget>,
}

impl DirectComposition {
    /// Initialize DirectComposition in the given window
    ///
    /// # Safety
    ///
    /// `hwnd` must be a valid handle to a window.
    pub unsafe fn new(hwnd: HWND) -> HResult<Self> {
        let mut feature_level_supported = 0;

        let d3d_device = ComPtr::new_with(|ptr_ptr| winapi::um::d3d11::D3D11CreateDevice(
            ptr::null_mut(),
            winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
            ptr::null_mut(),
            winapi::um::d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT |
            if cfg!(debug_assertions) {
                winapi::um::d3d11::D3D11_CREATE_DEVICE_DEBUG
            } else {
                0
            },
            ptr::null_mut(),
            0,
            winapi::um::d3d11::D3D11_SDK_VERSION,
            ptr_ptr,
            &mut feature_level_supported,
            ptr::null_mut(),
        ))?;

        let dxgi_device = d3d_device.cast::<winapi::shared::dxgi::IDXGIDevice>()?;

        // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404556(v=vs.85).aspx#code-snippet-1
        // “Because you can create a Direct3D device without creating a swap chain,
        //  you might need to retrieve the factory that is used to create the device
        //  in order to create a swap chain.”
        let adapter = ComPtr::new_with(|ptr_ptr| dxgi_device.GetAdapter(ptr_ptr))?;
        let dxgi_factory = ComPtr::<IDXGIFactory2>::new_with_uuid(|uuid, ptr_ptr| {
            adapter.GetParent(uuid, ptr_ptr)
        })?;

        // Create the DirectComposition device object.
        let composition_device = ComPtr::<IDCompositionDevice>::new_with_uuid(|uuid, ptr_ptr| {
            winapi::um::dcomp::DCompositionCreateDevice(&*dxgi_device, uuid,ptr_ptr)
        })?;

        // Create the composition target object based on the
        // specified application window.
        let composition_target = ComPtr::new_with(|ptr_ptr| {
            composition_device.CreateTargetForHwnd(hwnd, TRUE, ptr_ptr)
        })?;

        let root_visual = ComPtr::new_with(|ptr_ptr| composition_device.CreateVisual(ptr_ptr))?;
        composition_target.SetRoot(&*root_visual).to_result()?;

        Ok(DirectComposition {
            d3d_device, dxgi_factory, composition_device, composition_target, root_visual,
        })
    }

    /// Execute changes to the DirectComposition scene.
    pub fn commit(&self) -> HResult<()> {
        unsafe {
            self.composition_device.Commit().to_result()
        }
    }

    pub fn create_d3d_visual(&self, width: u32, height: u32) -> HResult<D3DVisual> {
        unsafe {
            let desc = DXGI_SWAP_CHAIN_DESC1 {
                Width: width,
                Height: height,
                Format: winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
                Stereo: FALSE,
                SampleDesc: winapi::shared::dxgitype::DXGI_SAMPLE_DESC {
                    Count: 1,
                    Quality: 0,
                },
                BufferUsage: winapi::shared::dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
                BufferCount: 2,
                Scaling: winapi::shared::dxgi1_2::DXGI_SCALING_STRETCH,
                SwapEffect: winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
                AlphaMode:  winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
                Flags: 0,
            };
            let swap_chain = ComPtr::<winapi::shared::dxgi1_2::IDXGISwapChain1>::new_with(|ptr_ptr| {
                self.dxgi_factory.CreateSwapChainForComposition(
                    as_ptr(&self.d3d_device),
                    &desc,
                    ptr::null_mut(),
                    ptr_ptr,
                )
            })?;
            let visual = ComPtr::new_with(|ptr_ptr| self.composition_device.CreateVisual(ptr_ptr))?;
            visual.SetContent(&*****swap_chain).to_result()?;
            self.root_visual.AddVisual(&*visual, FALSE, ptr::null_mut()).to_result()?;

            Ok(D3DVisual { visual, swap_chain })
        }
    }
}

/// A DirectComposition "visual" configured for rendering with Direct3D.
pub struct D3DVisual {
    visual: ComPtr<IDCompositionVisual>,
    swap_chain: ComPtr<winapi::shared::dxgi1_2::IDXGISwapChain1>,
}

impl D3DVisual {
    pub fn set_offset_x(&self, offset_x: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetX_1(offset_x).to_result()
        }
    }

    pub fn set_offset_y(&self, offset_y: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetY_1(offset_y).to_result()
        }
    }

    pub fn render_and_present_solid_frame(&self, composition: &DirectComposition, rgba: &[f32; 4])
                                          -> HResult<()> {
        unsafe {
            let back_buffer = ComPtr::<winapi::um::d3d11::ID3D11Texture2D>::new_with_uuid(|uuid, ptr_ptr| {
                self.swap_chain.GetBuffer(0, uuid, ptr_ptr)
            })?;
            let render_target = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.CreateRenderTargetView(
                    as_ptr(&back_buffer), ptr::null_mut(), ptr_ptr,
                )
            })?;
            let context = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.GetImmediateContext(ptr_ptr);
                S_OK
            })?;

            // FIXME: arbitrary D3D rendering here?
            context.OMSetRenderTargets(1, &render_target.as_raw(), ptr::null_mut());
            context.ClearRenderTargetView(render_target.as_raw(), &rgba);

            self.swap_chain.Present(0, 0).to_result()
        }
    }
}
<|endoftext|>