<commit_before>extern crate git2;
extern crate chrono;

#[macro_use]
extern crate nom;

use git2::{ObjectType, Oid, Repository};
use chrono::{UTC, TimeZone, Datelike};
use nom::*;

use std::fmt;
use std::str;

#[derive(Debug)]
pub enum GitJournalError {
    GitError(git2::Error),
    ParserError,
    CommitMessageLengthError,
}

pub struct GitJournal {
    repo: Repository,
    tags: Vec<(Oid, String)>,
}

impl From<git2::Error> for GitJournalError {
    fn from(err: git2::Error) -> GitJournalError {
        GitJournalError::GitError(err)
    }
}

impl fmt::Display for GitJournalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GitJournalError::GitError(ref err) => write!(f, "Git error: {}", err),
            GitJournalError::ParserError => write!(f, "Parser error."),
            GitJournalError::CommitMessageLengthError => write!(f, "Commit message length too small."),
        }
    }
}

impl GitJournal {
    /// Constructs a new `GitJournal`.
    pub fn new(path: &str) -> Result<GitJournal, GitJournalError> {
        // Open the repository
        let new_repo = try!(Repository::open(path));

        // Get all available tags in some vector of tuples
        let mut new_tags = vec![];
        for name in try!(new_repo.tag_names(None)).iter() {
            let name = try!(name.ok_or(git2::Error::from_str("Could not receive tag name")));
            let obj = try!(new_repo.revparse_single(name));
            if let Ok(tag) = obj.into_tag() {
                let tag_name = try!(tag.name().ok_or(git2::Error::from_str("Could not parse tag name"))).to_owned();
                new_tags.push((tag.target_id(), tag_name));
            }
        }

        // Return the git journal object
        Ok(GitJournal {
            repo: new_repo,
            tags: new_tags,
        })
    }

    /// Parses a revision range for a `GitJournal`.
    pub fn parse_log(&self,
                     revision_range: &str,
                     tag_skip_pattern: &str,
                     max_tags_count: &u32,
                     all: &bool)
                     -> Result<(), GitJournalError> {

        let mut revwalk = try!(self.repo.revwalk());
        revwalk.set_sorting(git2::SORT_TIME);

        // Fill the revwalk with the selected revisions.
        let revspec = try!(self.repo.revparse(&revision_range));
        if revspec.mode().contains(git2::REVPARSE_SINGLE) {
            // A single commit was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            try!(revwalk.push(from.id()));
        } else {
            // A specific commit range was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            let to = try!(revspec.to().ok_or(git2::Error::from_str("Could not set revision range end")));
            try!(revwalk.push(to.id()));
            if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) {
                let base = try!(self.repo.merge_base(from.id(), to.id()));
                let o = try!(self.repo.find_object(base, Some(ObjectType::Commit)));
                try!(revwalk.push(o.id()));
            }
            try!(revwalk.hide(from.id()));
        }

        // Iterate over the git objects and collect them in a vector of tuples
        let mut result: Vec<(String, Vec<String>)> = vec![];
        let mut current_entries: Vec<String> = vec![];
        let today = UTC::today();
        let mut parsed_tags: u32 = 1;
        let mut current_tag = format!("Unreleased ({}-{}-{})",
                                      today.year(),
                                      today.month(),
                                      today.day());
        'revloop: for (index, id) in revwalk.enumerate() {
            let oid = try!(id);
            let commit = try!(self.repo.find_commit(oid));
            for tag in self.tags
                .iter()
                .filter(|tag| tag.0.as_bytes() == oid.as_bytes() && !tag.1.contains(tag_skip_pattern)) {

                // Parsing entries of the last tag done
                if !current_entries.is_empty() {
                    result.push((current_tag.clone(), current_entries.clone()));
                    current_entries.clear();
                }

                // If a single revision is given stop at the first seen tag
                if !all && index > 0 && parsed_tags > *max_tags_count {
                    break 'revloop;
                }

                // Format the tag and set as current
                parsed_tags += 1;
                let date = UTC.timestamp(commit.time().seconds(), 0).date();
                current_tag = format!("{} ({}-{}-{})",
                                      tag.1,
                                      date.year(),
                                      date.month(),
                                      date.day());
            }
            // Add the commit message to the current entries of the tag
            let message = try!(commit.message().ok_or(git2::Error::from_str("Could not parse commit message")));
            match self.parse_commit_message(message) {
                Ok(parsed_message) => current_entries.push(parsed_message),
                Err(e) => println!("Skip commit: {}", e),
            }
        }
        // Add the last processed items as well
        if !current_entries.is_empty() {
            result.push((current_tag, current_entries));
        }

        for (tag, mut commits) in result {
            println!("\n{}:", tag);
            commits.sort();
            for commit in commits {
                println!("{}", commit);
            }
        }
        Ok(())
    }

    /// Parses a single commit message and returns a changelog ready form
    fn parse_commit_message(&self, message: &str) -> Result<String, GitJournalError> {
        named!(commit_parser<(&str, &str, Vec<&str>)>,
            chain!(
                separated_pair!(alpha, char!('-'), digit)? ~
                space? ~
                cat: map_res!(
                    alt!(
                        tag!("Added") |
                        tag!("Changed") |
                        tag!("Fixed") |
                        tag!("Improved") |
                        tag!("Removed") |
                        tag!("Changed")),
                str::from_utf8) ~
                sum: map_res!(
                    take_until!("\n"),
                    str::from_utf8
                ) ~
                many1!(newline) ~
                items: many0!(
                    map_res!(
                        chain!(
                            tag!("-") ~
                            space? ~
                            r: take_until!("\n") ~
                            many1!(newline),
                            || r
                        ),
                        str::from_utf8
                    )
                ) ~
                rest,
            || (cat, sum, items))
        );
        match commit_parser(message.as_bytes()) {
             IResult::Done(_, parsed) => {
                 return Ok(format!("- [{}]{}{}", parsed.0, parsed.1, parsed.2.join("\n    - ")));
             },
             _ => {
                 println!("Could not parse:\n{}\n", message.lines().nth(0).unwrap());
                 return Err(GitJournalError::ParserError);
             },
        };
    }
}
<commit_msg>Use only things we really need<commit_after>extern crate git2;
extern crate chrono;

#[macro_use]
extern crate nom;

use git2::{ObjectType, Oid, Repository};
use chrono::{UTC, TimeZone, Datelike};
use nom::{IResult, alpha, alphanumeric, digit, newline, rest, space};

use std::fmt;
use std::str;

#[derive(Debug)]
pub enum GitJournalError {
    GitError(git2::Error),
    ParserError,
    CommitMessageLengthError,
}

pub struct GitJournal {
    repo: Repository,
    tags: Vec<(Oid, String)>,
}

impl From<git2::Error> for GitJournalError {
    fn from(err: git2::Error) -> GitJournalError {
        GitJournalError::GitError(err)
    }
}

impl fmt::Display for GitJournalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GitJournalError::GitError(ref err) => write!(f, "Git error: {}", err),
            GitJournalError::ParserError => write!(f, "Parser error."),
            GitJournalError::CommitMessageLengthError => write!(f, "Commit message length too small."),
        }
    }
}

impl GitJournal {
    /// Constructs a new `GitJournal`.
    pub fn new(path: &str) -> Result<GitJournal, GitJournalError> {
        // Open the repository
        let new_repo = try!(Repository::open(path));

        // Get all available tags in some vector of tuples
        let mut new_tags = vec![];
        for name in try!(new_repo.tag_names(None)).iter() {
            let name = try!(name.ok_or(git2::Error::from_str("Could not receive tag name")));
            let obj = try!(new_repo.revparse_single(name));
            if let Ok(tag) = obj.into_tag() {
                let tag_name = try!(tag.name().ok_or(git2::Error::from_str("Could not parse tag name"))).to_owned();
                new_tags.push((tag.target_id(), tag_name));
            }
        }

        // Return the git journal object
        Ok(GitJournal {
            repo: new_repo,
            tags: new_tags,
        })
    }

    /// Parses a revision range for a `GitJournal`.
    pub fn parse_log(&self,
                     revision_range: &str,
                     tag_skip_pattern: &str,
                     max_tags_count: &u32,
                     all: &bool)
                     -> Result<(), GitJournalError> {

        let mut revwalk = try!(self.repo.revwalk());
        revwalk.set_sorting(git2::SORT_TIME);

        // Fill the revwalk with the selected revisions.
        let revspec = try!(self.repo.revparse(&revision_range));
        if revspec.mode().contains(git2::REVPARSE_SINGLE) {
            // A single commit was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            try!(revwalk.push(from.id()));
        } else {
            // A specific commit range was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            let to = try!(revspec.to().ok_or(git2::Error::from_str("Could not set revision range end")));
            try!(revwalk.push(to.id()));
            if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) {
                let base = try!(self.repo.merge_base(from.id(), to.id()));
                let o = try!(self.repo.find_object(base, Some(ObjectType::Commit)));
                try!(revwalk.push(o.id()));
            }
            try!(revwalk.hide(from.id()));
        }

        // Iterate over the git objects and collect them in a vector of tuples
        let mut result: Vec<(String, Vec<String>)> = vec![];
        let mut current_entries: Vec<String> = vec![];
        let today = UTC::today();
        let mut parsed_tags: u32 = 1;
        let mut current_tag = format!("Unreleased ({}-{}-{})",
                                      today.year(),
                                      today.month(),
                                      today.day());
        'revloop: for (index, id) in revwalk.enumerate() {
            let oid = try!(id);
            let commit = try!(self.repo.find_commit(oid));
            for tag in self.tags
                .iter()
                .filter(|tag| tag.0.as_bytes() == oid.as_bytes() && !tag.1.contains(tag_skip_pattern)) {

                // Parsing entries of the last tag done
                if !current_entries.is_empty() {
                    result.push((current_tag.clone(), current_entries.clone()));
                    current_entries.clear();
                }

                // If a single revision is given stop at the first seen tag
                if !all && index > 0 && parsed_tags > *max_tags_count {
                    break 'revloop;
                }

                // Format the tag and set as current
                parsed_tags += 1;
                let date = UTC.timestamp(commit.time().seconds(), 0).date();
                current_tag = format!("{} ({}-{}-{})",
                                      tag.1,
                                      date.year(),
                                      date.month(),
                                      date.day());
            }
            // Add the commit message to the current entries of the tag
            let message = try!(commit.message().ok_or(git2::Error::from_str("Could not parse commit message")));
            match self.parse_commit_message(message) {
                Ok(parsed_message) => current_entries.push(parsed_message),
                Err(e) => println!("Skip commit: {}", e),
            }
        }
        // Add the last processed items as well
        if !current_entries.is_empty() {
            result.push((current_tag, current_entries));
        }

        // Print for testing purposes
        for (tag, mut commits) in result {
            println!("\n{}:", tag);
            commits.sort();
            for commit in commits {
                println!("{}", commit);
            }
        }
        Ok(())
    }

    /// Parses a single commit message and returns a changelog ready form
    fn parse_commit_message(&self, message: &str) -> Result<String, GitJournalError> {
        named!(commit_parser<(&str, &str, Vec<&str>)>,
            chain!(
                separated_pair!(alpha, char!('-'), digit)? ~
                space? ~
                cat: map_res!(
                    alt!(
                        tag!("Added") |
                        tag!("Changed") |
                        tag!("Fixed") |
                        tag!("Improved") |
                        tag!("Removed") |
                        tag!("Changed")),
                str::from_utf8) ~
                sum: map_res!(
                    take_until!("\n"),
                    str::from_utf8
                ) ~
                many1!(newline) ~
                items: many0!(
                    map_res!(
                        chain!(
                            tag!("-") ~
                            space? ~
                            r: take_until!("\n") ~
                            many1!(newline),
                            || r
                        ),
                        str::from_utf8
                    )
                ) ~
                rest,
            || (cat, sum, items))
        );
        match commit_parser(message.as_bytes()) {
             IResult::Done(_, parsed) => {
                 return Ok(format!("- [{}]{}{}", parsed.0, parsed.1, parsed.2.join("\n    - ")));
             },
             _ => {
                 println!("Could not parse:\n{}\n", message.lines().nth(0).unwrap());
                 return Err(GitJournalError::ParserError);
             },
        };
    }
}
<|endoftext|>


<commit_before>#[derive (Debug, PartialEq, Eq)]
pub enum Fix<A> {
    Pro(A),
    Fix(A)
}

impl<A> Fix<A> {
    pub fn map<B, F: FnOnce(A) -> B>(self, f: F) -> Fix<B> {
        match self {
            Fix::Pro(a) => Fix::Pro(f(a)),
            Fix::Fix(a) => Fix::Fix(f(a))
        }
    }
}

pub fn fix<A, F: FnMut(A) -> Fix<A>>(mut a: A, mut f: F) -> A {
    loop {
        match f(a) {
            Fix::Fix(b) => return b,
            Fix::Pro(b) => a = b
        }
    }
}

pub fn fix_result<A, E, F: FnMut(A) -> Result<Fix<A>, E>>(mut a: A, mut f: F) -> Result<A, E> {
    loop {
        match f(a) {
            Result::Err(err) => return Result::Err(err),
            Result::Ok(Fix::Fix(b)) => return Result::Ok(b),
            Result::Ok(Fix::Pro(b)) => a = b
        }
    }
}
<commit_msg>add compose fn<commit_after>#[derive (Debug, PartialEq, Eq)]
pub enum Fix<A> {
    Pro(A),
    Fix(A)
}

impl<A> Fix<A> {
    pub fn map<B, F: FnOnce(A) -> B>(self, f: F) -> Fix<B> {
        match self {
            Fix::Pro(a) => Fix::Pro(f(a)),
            Fix::Fix(a) => Fix::Fix(f(a))
        }
    }
}

pub fn compose<A, F, G>(a: A, mut f: F, mut g: G) -> Fix<A>
    where F: FnMut(A) -> Fix<A>, G: FnMut(A) -> Fix<A> {
    match f(a) {
        Fix::Fix(b) => g(b),
        fix => fix
    }
}

pub fn fix<A, F: FnMut(A) -> Fix<A>>(mut a: A, mut f: F) -> A {
    loop {
        match f(a) {
            Fix::Fix(b) => return b,
            Fix::Pro(b) => a = b
        }
    }
}

pub fn fix_result<A, E, F: FnMut(A) -> Result<Fix<A>, E>>(mut a: A, mut f: F) -> Result<A, E> {
    loop {
        match f(a) {
            Result::Err(err) => return Result::Err(err),
            Result::Ok(Fix::Fix(b)) => return Result::Ok(b),
            Result::Ok(Fix::Pro(b)) => a = b
        }
    }
}
<|endoftext|>


<commit_before>pub trait Interpolate: Clone {
    #[inline]
	fn bilerp(v: [[Self; 2]; 2], x: f64, y: f64) -> Self {
        let v0 = Interpolate::lerp([v[0][0].clone(), v[0][1].clone()], y);
        let v1 = Interpolate::lerp([v[1][0].clone(), v[1][1].clone()], y);
        Interpolate::lerp([v0, v1], x)
    }

	#[inline]
    fn lerp(v: [Self; 2], x: f64) -> Self;
}

impl Interpolate for f64 {
    fn bilerp(v: [[f64; 2]; 2], x: f64, y: f64) -> f64 {
        v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y
    }

    fn lerp(v: [f64; 2], x: f64) -> f64 {
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for f32 {
    fn bilerp(v: [[f32; 2]; 2], x: f64, y: f64) -> f32 {
        let x = x as f32;
        let y = y as f32;
        (v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y)
    }

    fn lerp(v: [f32; 2], x: f64) -> f32 {
        let x = x as f32;
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for u8 {
    fn lerp(v: [u8; 2], x: f64) -> u8 {
        Interpolate::lerp([v[0] as f64, v[1] as f64], x) as u8
    }

    fn bilerp(v: [[u8; 2]; 2], x: f64, y: f64) -> u8 {
        let array = [
            [v[0][0] as f64, v[0][1] as f64],
            [v[1][0] as f64, v[1][1] as f64],
        ];
        Interpolate::bilerp(array, x, y) as u8
    }
}

// TODO: Implement interpolate trait for all types that it is useful for. We might have to do some
// macro magic to do this without too much code duplication.

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

    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    struct Rgb {
    	r: u8,
    	g: u8,
    	b: u8,
    }

    impl Interpolate for Rgb {
    	fn lerp(v: [Rgb; 2], x: f64) -> Rgb {
    		Rgb {
                r: u8::lerp([v[0].r, v[1].r], x),
                g: u8::lerp([v[0].g, v[1].g], x),
                b: u8::lerp([v[0].b, v[1].b], x)
    		}
    	}
    }

    // Test that we get the right result for a basic type
	#[test]
	fn basic_lerp_test() {
        let result = f32::lerp([0.0, 100.0], 0.5);
        assert!(49.9 < result && result < 50.1);
    }

    // Test that an implementation for a custom type works
    #[test]
    fn custom_type_lerp_test() {
		let start = Rgb { r: 0, g: 255, b: 0 };
	    let end = Rgb { r: 100, g: 0, b: 200 };
        assert_eq!(Rgb::lerp([start, end], 0.5), Rgb { r: 50, g: 127, b: 100 });
	}
}<commit_msg>tabs->spaces<commit_after>pub trait Interpolate: Clone {
    #[inline]
    fn bilerp(v: [[Self; 2]; 2], x: f64, y: f64) -> Self {
        let v0 = Interpolate::lerp([v[0][0].clone(), v[0][1].clone()], y);
        let v1 = Interpolate::lerp([v[1][0].clone(), v[1][1].clone()], y);
        Interpolate::lerp([v0, v1], x)
    }

    #[inline]
    fn lerp(v: [Self; 2], x: f64) -> Self;
}

impl Interpolate for f64 {
    fn bilerp(v: [[f64; 2]; 2], x: f64, y: f64) -> f64 {
        v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y
    }

    fn lerp(v: [f64; 2], x: f64) -> f64 {
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for f32 {
    fn bilerp(v: [[f32; 2]; 2], x: f64, y: f64) -> f32 {
        let x = x as f32;
        let y = y as f32;
        (v[0][0]*(1.0-x)*(1.0-y) + v[1][0]*x*(1.0-y) + v[0][1]*(1.0-x)*y + v[1][1]*x*y)
    }

    fn lerp(v: [f32; 2], x: f64) -> f32 {
        let x = x as f32;
        v[0] + x * (v[1] - v[0])
    }
}

impl Interpolate for u8 {
    fn lerp(v: [u8; 2], x: f64) -> u8 {
        Interpolate::lerp([v[0] as f64, v[1] as f64], x) as u8
    }

    fn bilerp(v: [[u8; 2]; 2], x: f64, y: f64) -> u8 {
        let array = [
            [v[0][0] as f64, v[0][1] as f64],
            [v[1][0] as f64, v[1][1] as f64],
        ];
        Interpolate::bilerp(array, x, y) as u8
    }
}

// TODO: Implement interpolate trait for all types that it is useful for. We might have to do some
// macro magic to do this without too much code duplication.

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

    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    struct Rgb {
        r: u8,
        g: u8,
        b: u8,
    }

    impl Interpolate for Rgb {
        fn lerp(v: [Rgb; 2], x: f64) -> Rgb {
            Rgb {
                r: u8::lerp([v[0].r, v[1].r], x),
                g: u8::lerp([v[0].g, v[1].g], x),
                b: u8::lerp([v[0].b, v[1].b], x)
            }
        }
    }

    // Test that we get the right result for a basic type
    #[test]
    fn basic_lerp_test() {
        let result = f32::lerp([0.0, 100.0], 0.5);
        assert!(49.9 < result && result < 50.1);
    }

    // Test that an implementation for a custom type works
    #[test]
    fn custom_type_lerp_test() {
        let start = Rgb { r: 0, g: 255, b: 0 };
        let end = Rgb { r: 100, g: 0, b: 200 };
        assert_eq!(Rgb::lerp([start, end], 0.5), Rgb { r: 50, g: 127, b: 100 });
    }
}<|endoftext|>


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

#![cfg_attr(feature = "unstable", feature(fn_must_use))]
#![cfg_attr(not(test), no_std)]

//! A collection of strongly typed math tools for computer graphics with an inclination
//! towards 2d graphics and layout.
//!
//! All types are generic over the scalar type of their component (`f32`, `i32`, etc.),
//! and tagged with a generic Unit parameter which is useful to prevent mixing
//! values from different spaces. For example it should not be legal to translate
//! a screen-space position by a world-space vector and this can be expressed using
//! the generic Unit parameter.
//!
//! This unit system is not mandatory and all Typed* structures have an alias
//! with the default unit: `UnknownUnit`.
//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
//! Client code typically creates a set of aliases for each type and doesn't need
//! to deal with the specifics of typed units further. For example:
//!
//! ```rust
//! use euclid::*;
//! pub struct ScreenSpace;
//! pub type ScreenPoint = TypedPoint2D<f32, ScreenSpace>;
//! pub type ScreenSize = TypedSize2D<f32, ScreenSpace>;
//! pub struct WorldSpace;
//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! pub type ProjectionMatrix = TypedTransform3D<f32, WorldSpace, ScreenSpace>;
//! // etc...
//! ```
//!
//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
//!
//! Components are accessed in their scalar form by default for convenience, and most
//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers.
//! For example:
//!
//! ```rust
//! # use euclid::*;
//! # pub struct WorldSpace;
//! # pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! let p = WorldPoint::new(0.0, 1.0, 1.0);
//! // p.x is an f32.
//! println!("p.x = {:?} ", p.x);
//! // p.x is a Length<f32, WorldSpace>.
//! println!("p.x_typed() = {:?} ", p.x_typed());
//! // Length::get returns the scalar value (f32).
//! assert_eq!(p.x, p.x_typed().get());
//! ```

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;

#[cfg(feature = "mint")]
pub extern crate mint;
#[macro_use]
extern crate euclid_macros;
extern crate num_traits;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
use std as core;

pub use length::Length;
pub use scale::TypedScale;
pub use transform2d::{Transform2D, TypedTransform2D};
pub use transform3d::{Transform3D, TypedTransform3D};
pub use point::{Point2D, Point3D, TypedPoint2D, TypedPoint3D, point2, point3};
pub use vector::{TypedVector2D, TypedVector3D, Vector2D, Vector3D, vec2, vec3};
pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
pub use homogen::HomogeneousVector;

pub use rect::{rect, Rect, TypedRect};
pub use translation::{TypedTranslation2D, TypedTranslation3D};
pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D};
pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
pub use size::{Size2D, TypedSize2D, size2};
pub use trig::Trig;

#[macro_use]
mod macros;

pub mod approxeq;
mod homogen;
pub mod num;
mod length;
mod point;
mod rect;
mod rotation;
mod scale;
mod side_offsets;
mod size;
mod transform2d;
mod transform3d;
mod translation;
mod trig;
mod vector;

/// The default unit.
#[derive(Clone, Copy)]
pub struct UnknownUnit;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix2D<T> = Transform2D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix2D<T, Src, Dst> = TypedTransform2D<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix4D<T> = Transform3D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type ScaleFactor<T, Src, Dst> = TypedScale<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub use Angle as Radians;
<commit_msg>Derive all the things for UnknownUnit<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(feature = "unstable", feature(fn_must_use))]
#![cfg_attr(not(test), no_std)]

//! A collection of strongly typed math tools for computer graphics with an inclination
//! towards 2d graphics and layout.
//!
//! All types are generic over the scalar type of their component (`f32`, `i32`, etc.),
//! and tagged with a generic Unit parameter which is useful to prevent mixing
//! values from different spaces. For example it should not be legal to translate
//! a screen-space position by a world-space vector and this can be expressed using
//! the generic Unit parameter.
//!
//! This unit system is not mandatory and all Typed* structures have an alias
//! with the default unit: `UnknownUnit`.
//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
//! Client code typically creates a set of aliases for each type and doesn't need
//! to deal with the specifics of typed units further. For example:
//!
//! ```rust
//! use euclid::*;
//! pub struct ScreenSpace;
//! pub type ScreenPoint = TypedPoint2D<f32, ScreenSpace>;
//! pub type ScreenSize = TypedSize2D<f32, ScreenSpace>;
//! pub struct WorldSpace;
//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! pub type ProjectionMatrix = TypedTransform3D<f32, WorldSpace, ScreenSpace>;
//! // etc...
//! ```
//!
//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
//!
//! Components are accessed in their scalar form by default for convenience, and most
//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers.
//! For example:
//!
//! ```rust
//! # use euclid::*;
//! # pub struct WorldSpace;
//! # pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! let p = WorldPoint::new(0.0, 1.0, 1.0);
//! // p.x is an f32.
//! println!("p.x = {:?} ", p.x);
//! // p.x is a Length<f32, WorldSpace>.
//! println!("p.x_typed() = {:?} ", p.x_typed());
//! // Length::get returns the scalar value (f32).
//! assert_eq!(p.x, p.x_typed().get());
//! ```

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;

#[cfg(feature = "mint")]
pub extern crate mint;
#[macro_use]
extern crate euclid_macros;
extern crate num_traits;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
use std as core;

pub use length::Length;
pub use scale::TypedScale;
pub use transform2d::{Transform2D, TypedTransform2D};
pub use transform3d::{Transform3D, TypedTransform3D};
pub use point::{Point2D, Point3D, TypedPoint2D, TypedPoint3D, point2, point3};
pub use vector::{TypedVector2D, TypedVector3D, Vector2D, Vector3D, vec2, vec3};
pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
pub use homogen::HomogeneousVector;

pub use rect::{rect, Rect, TypedRect};
pub use translation::{TypedTranslation2D, TypedTranslation3D};
pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D};
pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
pub use size::{Size2D, TypedSize2D, size2};
pub use trig::Trig;

#[macro_use]
mod macros;

pub mod approxeq;
mod homogen;
pub mod num;
mod length;
mod point;
mod rect;
mod rotation;
mod scale;
mod side_offsets;
mod size;
mod transform2d;
mod transform3d;
mod translation;
mod trig;
mod vector;

/// The default unit.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UnknownUnit;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix2D<T> = Transform2D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix2D<T, Src, Dst> = TypedTransform2D<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix4D<T> = Transform3D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type ScaleFactor<T, Src, Dst> = TypedScale<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub use Angle as Radians;
<|endoftext|>


<commit_before>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.2.2"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! // Can be declared outside of a function if labeled
//! assert_eq_size!(bytes; (u8, u8), u16);
//!
//! // Fails to compile (same label):
//! // assert_eq_size!(bytes; u8, u8);
//!
//! fn main() {
//!     assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//!     // Produces a compilation failure:
//!     // assert_eq_size!(u32, u8);
//! }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! As a [limitation](#limitations), a unique label is required if the macro is
//! used outside of a function.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! const TWO: usize = 2;
//! const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
//!
//! // Fails to compile (same label):
//! // const_assert_eq!(two; TWO, TWO);
//!
//! fn main() {
//!     const NUM: usize = 32;
//!     const_assert_eq!(NUM + NUM, 64);
//! }
//! ```
//!
//! # Assert Object Safety
//!
//! Sometimes changes are made to traits that prevent them from being used in
//! the context of an object. Such a case would be adding a generic method and
//! forgetting to add `where Self: Sized` after it. If left unnoticed, that
//! mistake will end up affecting crate users and break compatibility.
//!
//! [`assert_obj_safe`] is here to save you from those troubles:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_obj_safe!(basic; Send, Sync, AsRef<str>);
//!
//! trait MySafeTrait {}
//!
//! trait MyUnsafeTrait {
//!     fn generic<T>();
//! }
//!
//! fn main() {
//!     assert_obj_safe!(MySafeTrait);
//!
//!     // Produces a compilation failure:
//!     // assert_obj_safe!(MyUnsafeTrait);
//! }
//! ```
//!
//! # Assert Trait `impl`
//!
//! To ensure types implement [`Send`], [`Sync`], and other traits, there's
//! [`assert_impl`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_impl!(str; String, Send, Sync, From<&'static str>);
//! assert_impl!(vec; &'static [u8], Into<Vec<u8>>);
//!
//! fn main() {
//!     // Produces a compilation failure:
//!     // `*const u8` cannot be sent between threads safely
//!     // assert_impl!(*const u8, Send);
//! }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, the following can only be used normally from
//! within the context of a function:
//!
//! - [`assert_eq_size`]
//! - [`assert_obj_safe`]
//! - [`const_assert`]
//! - [`const_assert_eq`]
//!
//! To use these macros in other contexts, a unique label must be provided.
//!
//! If you want to read up about this and provide feedback, see
//! [the related issue on GitHub][issue1].
//!
//! [issue1]: https://github.com/nvzqz/static-assertions-rs/issues/1
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`assert_obj_safe`]: macro.assert_obj_safe.html
//! [`assert_impl`]: macro.assert_impl.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// assert_eq_size!(pair; (u16, u16), [u16; 2], [u8; 4]);
///
/// // Fails to compile (same label):
/// // assert_eq_size!(pair; u8, u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
///
///     // Produces a compilation failure:
///     // assert_eq_size!(Byte, u16);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    };
    ($label:ident; $x:ty, $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($x, $($xs),+) }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Produces a compilation failure:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+) => {
        let _ = [(); 0 - (!($($xs)&&+) as usize)];
    };
    ($label:ident; $($xs:expr),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs),+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+) => {
        const_assert!($label; $($x == $xs),+);
    };
}

/// Asserts at compile-time that the traits are object-safe.
///
/// This is useful for when changes are made to a trait that accidentally
/// prevent it from being used as an object.
#[macro_export]
macro_rules! assert_obj_safe {
    ($($xs:ty),+) => {
        $(let _: Option<&$xs> = None;)+
    };
    ($label:ident; $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_obj_safe!($($xs),+); }
    };
}

/// Asserts at compile-time that the type implements the given traits.
#[macro_export]
macro_rules! assert_impl {
    (
        $x:ty,
        $(
            $y:ident
            $(< $($args:ty),+ $(,)* >)*
        ),+
    ) => {
        $({
            fn assert_impl<T: ?Sized + $y $(< $($args),+ >)* >() {}
            assert_impl::<$x>();
        })+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_impl!($($xs)+); }
    };
}
<commit_msg>Add assert_impl to list of limited macros<commit_after>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.2.2"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! // Can be declared outside of a function if labeled
//! assert_eq_size!(bytes; (u8, u8), u16);
//!
//! // Fails to compile (same label):
//! // assert_eq_size!(bytes; u8, u8);
//!
//! fn main() {
//!     assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//!     // Produces a compilation failure:
//!     // assert_eq_size!(u32, u8);
//! }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! As a [limitation](#limitations), a unique label is required if the macro is
//! used outside of a function.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! const TWO: usize = 2;
//! const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
//!
//! // Fails to compile (same label):
//! // const_assert_eq!(two; TWO, TWO);
//!
//! fn main() {
//!     const NUM: usize = 32;
//!     const_assert_eq!(NUM + NUM, 64);
//! }
//! ```
//!
//! # Assert Object Safety
//!
//! Sometimes changes are made to traits that prevent them from being used in
//! the context of an object. Such a case would be adding a generic method and
//! forgetting to add `where Self: Sized` after it. If left unnoticed, that
//! mistake will end up affecting crate users and break compatibility.
//!
//! [`assert_obj_safe`] is here to save you from those troubles:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_obj_safe!(basic; Send, Sync, AsRef<str>);
//!
//! trait MySafeTrait {}
//!
//! trait MyUnsafeTrait {
//!     fn generic<T>();
//! }
//!
//! fn main() {
//!     assert_obj_safe!(MySafeTrait);
//!
//!     // Produces a compilation failure:
//!     // assert_obj_safe!(MyUnsafeTrait);
//! }
//! ```
//!
//! # Assert Trait `impl`
//!
//! To ensure types implement [`Send`], [`Sync`], and other traits, there's
//! [`assert_impl`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_impl!(str; String, Send, Sync, From<&'static str>);
//! assert_impl!(vec; &'static [u8], Into<Vec<u8>>);
//!
//! fn main() {
//!     // Produces a compilation failure:
//!     // `*const u8` cannot be sent between threads safely
//!     // assert_impl!(*const u8, Send);
//! }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, the following can only be used normally from
//! within the context of a function:
//!
//! - [`assert_eq_size`]
//! - [`assert_obj_safe`]
//! - [`assert_impl`]
//! - [`const_assert`]
//! - [`const_assert_eq`]
//!
//! To use these macros in other contexts, a unique label must be provided.
//!
//! If you want to read up about this and provide feedback, see
//! [the related issue on GitHub][issue1].
//!
//! [issue1]: https://github.com/nvzqz/static-assertions-rs/issues/1
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`assert_obj_safe`]: macro.assert_obj_safe.html
//! [`assert_impl`]: macro.assert_impl.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// assert_eq_size!(pair; (u16, u16), [u16; 2], [u8; 4]);
///
/// // Fails to compile (same label):
/// // assert_eq_size!(pair; u8, u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
///
///     // Produces a compilation failure:
///     // assert_eq_size!(Byte, u16);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    };
    ($label:ident; $x:ty, $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($x, $($xs),+) }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Produces a compilation failure:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+) => {
        let _ = [(); 0 - (!($($xs)&&+) as usize)];
    };
    ($label:ident; $($xs:expr),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs),+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+) => {
        const_assert!($label; $($x == $xs),+);
    };
}

/// Asserts at compile-time that the traits are object-safe.
///
/// This is useful for when changes are made to a trait that accidentally
/// prevent it from being used as an object.
#[macro_export]
macro_rules! assert_obj_safe {
    ($($xs:ty),+) => {
        $(let _: Option<&$xs> = None;)+
    };
    ($label:ident; $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_obj_safe!($($xs),+); }
    };
}

/// Asserts at compile-time that the type implements the given traits.
#[macro_export]
macro_rules! assert_impl {
    (
        $x:ty,
        $(
            $y:ident
            $(< $($args:ty),+ $(,)* >)*
        ),+
    ) => {
        $({
            fn assert_impl<T: ?Sized + $y $(< $($args),+ >)* >() {}
            assert_impl::<$x>();
        })+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_impl!($($xs)+); }
    };
}
<|endoftext|>


<commit_before>/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::new()`.

The `new()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```rust
let server = httpd::Server::new().unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```rust
loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```rust
let server = Arc::new(server);

for _ in range(0u, 4) {
    spawn(proc() {
        loop {
            let rq = server.recv().unwrap();

            ...
        }
    })
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.get_method()` and `request.get_url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```rust
let response = httpd::Response::from_file(Path::new("image.png"));
```

All that remains to do is call `request.respond()`:

```rust
request.respond(response)
```
*/

#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]
#![feature(unsafe_destructor)]

extern crate encoding;
extern crate time;
extern crate url;

use std::io::{Acceptor, IoResult, Listener};
use std::io::net::ip;
use std::io::net::tcp;
use std::comm::Select;
use std::sync::{Arc, Mutex};
use std::sync::atomics::AtomicBool;
use client::ClientConnection;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use response::Response;

mod client;
mod common;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
#[unstable]
pub struct Server {
    // tasks where the client connections are dispatched
    tasks_pool: util::TaskPool,

    // receiver for client connections
    connections_receiver: Mutex<Receiver<IoResult<ClientConnection>>>,

    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // the sender linked to requests_receiver
    // cloned each time a client connection is created
    requests_sender: Mutex<Sender<Request>>,

    // channel to receive requests from
    requests_receiver: Mutex<Receiver<Request>>,

    // result of TcpListener::socket_name()
    listening_addr: ip::SocketAddr,
}

#[unstable]
pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
///  your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can dispatch your requests to
///  worker threads.
///
/// It is possible that multiple requests objects are simultaneously linked to the same client,
///  but don't worry: tiny-http automatically handles synchronization of the answers.
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
///  an empty response with a 500 status code (internal server error) will automatically be
///  sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
///  error" response will automatically be sent during the stack unwinding.
#[unstable]
pub struct Request {
    data_reader: Box<Reader + Send>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<Box<Writer + Send>>,

    remote_addr: ip::SocketAddr,
    method: Method,
    path: url::Path,
    http_version: HTTPVersion,
    headers: Vec<Header>,
    body_length: uint,
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    #[unstable]
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    #[unstable]
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server on a rand port and that listens to all inputs.
    /// Returns the server and the port it was created on.
    /// This function is guaranteed not to fail because of a port already in use,
    ///  and is useful for testing purposes.
    #[unstable]
    pub fn new_with_random_port() -> IoResult<(Server, ip::Port)> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: 0})
            .map(|s| { let port = s.get_server_addr().port; (s, port) })
    }

    /// Builds a new server that listens on the specified address.
    #[unstable]
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpAcceptor
        let (server, local_addr) = {
            let mut listener = try!(tcp::TcpListener::bind(
                format!("{}", addr.ip).as_slice(), addr.port));
            let local_addr = try!(listener.socket_name());
            let server = try!(listener.listen());
            let server = util::ClosableTcpAcceptor::new(server, close_trigger.clone());
            (server, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();

        let inside_close_trigger = close_trigger.clone();
        spawn(proc() {
            let mut server = server;

            loop {
                let new_client = server.accept().map(|sock| {
                    use util::ClosableTcpStream;

                    let read_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), true, false);

                    let write_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), false, true);

                    ClientConnection::new(write_closable, read_closable)
                });

                if tx_incoming.send_opt(new_client).is_err() {
                    break
                }
            }
        });

        //
        let (tx_requests, rx_requests) = channel();

        // result
        Ok(Server {
            tasks_pool: util::TaskPool::new(),
            connections_receiver: Mutex::new(rx_incoming),
            close: close_trigger,
            requests_sender: Mutex::new(tx_requests),
            requests_receiver: Mutex::new(rx_requests),
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[unstable]
    pub fn incoming_requests<'a>(&'a self) -> IncomingRequests<'a> {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[experimental]
    pub fn get_server_addr(&self) -> ip::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    #[stable]
    pub fn get_num_connections(&self) -> uint {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        let connections_receiver = self.connections_receiver.lock();
        let requests_receiver = self.requests_receiver.lock();

        // TODO: the select! macro doesn't seem to be usable without moving
        //       out of self, so we use Select directly

        let select = Select::new();

        let mut request_handle = select.handle(&*requests_receiver);
        unsafe { request_handle.add() };

        let mut connect_handle = select.handle(&*connections_receiver);
        unsafe { connect_handle.add() };

        loop {
            let id = select.wait();

            if id == request_handle.id() {
                let request = request_handle.recv();

                unsafe { request_handle.remove() };
                unsafe { connect_handle.remove() };

                return Ok(request)
            }

            if id == connect_handle.id() {
                let client = connect_handle.recv_opt();

                match client {
                    Ok(Ok(client)) => {
                        self.add_client(client);
                        continue
                    },
                    Ok(Err(err)) => {
                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(err)
                    },
                    Err(_) => {
                        use std::io;

                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(io::standard_error(io::Closed));
                    }
                }
            }

            unreachable!()
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        let mut connections_receiver = self.connections_receiver.lock();
        let mut requests_receiver = self.requests_receiver.lock();

        // processing all new clients
        loop {
            match connections_receiver.try_recv() {
                Ok(client) => self.add_client(try!(client)),
                Err(_) => break
            }
        }

        // reading the next request
        Ok(requests_receiver.try_recv().ok())
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let requests_sender = self.requests_sender.lock().clone();

        self.tasks_pool.spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| requests_sender.send_opt(rq).is_ok());
        });
    }
}

impl Request {
    /// Returns the method requested by the client (eg. `GET`, `POST`, etc.).
    #[stable]
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    #[unstable]
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    #[stable]
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the HTTP version of the request.
    #[unstable]
    pub fn get_http_version<'a>(&'a self) -> &'a HTTPVersion {
        &self.http_version
    }

    /// Returns the length of the body in bytes.
    ///
    /// Returns `None` if the length is unknown.
    #[unstable]
    pub fn get_body_length(&self) -> Option<uint> {
        Some(self.body_length)
    }

    /// Returns the length of the body in bytes.
    #[stable]
    pub fn get_remote_addr<'a>(&'a self) -> &'a ip::SocketAddr {
        &self.remote_addr
    }

    /// Allows to read the body of the request.
    ///
    /// # Example
    ///
    /// ```
    /// let request = server.recv();
    ///
    /// if get_content_type(&request) == "application/json" {
    ///     let json: Json = from_str(request.as_reader().read_to_string()).unwrap();
    /// }
    /// ```
    #[unstable]
    pub fn as_reader<'a>(&'a mut self) -> &'a mut Reader {
        fn passthrough<'a>(r: &'a mut Reader) -> &'a mut Reader { r }
        passthrough(self.data_reader)
    }

    /// Turns the `Request` into a writer.
    ///
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    ///
    /// Note that the destruction of the `Writer` object may trigger
    ///  some events. For exemple if a client has sent multiple requests and the requests
    ///  have been processed in parallel, the destruction of a writer will trigger
    ///  the writing of the next response.
    /// Therefore you should always destroy the `Writer` as soon as possible.
    #[stable]
    pub fn into_writer(mut self) -> Box<Writer + Send> {
        self.into_writer_impl()
    }

    fn into_writer_impl(&mut self) -> Box<Writer + Send> {
        use std::mem;

        assert!(self.response_writer.is_some());

        let mut writer = None;
        mem::swap(&mut self.response_writer, &mut writer);
        writer.unwrap()
    }

    /// Sends a response to this request.
    #[unstable]
    pub fn respond<R: Reader>(mut self, response: Response<R>) {
        self.respond_impl(response)
    }

    fn respond_impl<R: Reader>(&mut self, response: Response<R>) {
        use std::io;

        fn passthrough<'a>(w: &'a mut Writer) -> &'a mut Writer { w }
        let mut writer = self.into_writer_impl();

        let do_not_send_body = self.method.equiv(&"HEAD");

        match response.raw_print(passthrough(writer),
                                self.http_version, self.headers.as_slice(),
                                do_not_send_body)
        {
            Ok(_) => (),
            Err(ref err) if err.kind == io::Closed => (),
            Err(ref err) if err.kind == io::BrokenPipe => (),
            Err(ref err) if err.kind == io::ConnectionAborted => (),
            Err(ref err) if err.kind == io::ConnectionRefused => (),
            Err(ref err) if err.kind == io::ConnectionReset => (),
            Err(ref err) =>
                println!("error while sending answer: {}", err)     // TODO: handle better?
        };

        writer.flush().ok();
    }
}

impl<'a> Iterator<Request> for IncomingRequests<'a> {
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {} from {})",
            self.method, self.path, self.remote_addr.ip)).fmt(formatter)
    }
}

impl Drop for Request {
    fn drop(&mut self) {
        if self.response_writer.is_some() {
            let response = Response::new_empty(StatusCode(500));
            self.respond_impl(response);
        }
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomics::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<commit_msg>Make sure that Server is Share and Request is Send<commit_after>/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::new()`.

The `new()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```rust
let server = httpd::Server::new().unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```rust
loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```rust
let server = Arc::new(server);

for _ in range(0u, 4) {
    spawn(proc() {
        loop {
            let rq = server.recv().unwrap();

            ...
        }
    })
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.get_method()` and `request.get_url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```rust
let response = httpd::Response::from_file(Path::new("image.png"));
```

All that remains to do is call `request.respond()`:

```rust
request.respond(response)
```
*/

#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]
#![feature(unsafe_destructor)]

extern crate encoding;
extern crate time;
extern crate url;

use std::io::{Acceptor, IoResult, Listener};
use std::io::net::ip;
use std::io::net::tcp;
use std::comm::Select;
use std::sync::{Arc, Mutex};
use std::sync::atomics::AtomicBool;
use client::ClientConnection;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use response::Response;

mod client;
mod common;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
#[unstable]
pub struct Server {
    // tasks where the client connections are dispatched
    tasks_pool: util::TaskPool,

    // receiver for client connections
    connections_receiver: Mutex<Receiver<IoResult<ClientConnection>>>,

    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // the sender linked to requests_receiver
    // cloned each time a client connection is created
    requests_sender: Mutex<Sender<Request>>,

    // channel to receive requests from
    requests_receiver: Mutex<Receiver<Request>>,

    // result of TcpListener::socket_name()
    listening_addr: ip::SocketAddr,
}

// this trait is to make sure that Server implements Share and Send
trait MustBeShareDummy : Share + Send {}
impl MustBeShareDummy for Server {}

#[unstable]
pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
///  your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can dispatch your requests to
///  worker threads.
///
/// It is possible that multiple requests objects are simultaneously linked to the same client,
///  but don't worry: tiny-http automatically handles synchronization of the answers.
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
///  an empty response with a 500 status code (internal server error) will automatically be
///  sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
///  error" response will automatically be sent during the stack unwinding.
#[unstable]
pub struct Request {
    data_reader: Box<Reader + Send>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<Box<Writer + Send>>,

    remote_addr: ip::SocketAddr,
    method: Method,
    path: url::Path,
    http_version: HTTPVersion,
    headers: Vec<Header>,
    body_length: uint,
}

// this trait is to make sure that Request implements Send
trait MustBeSendDummy : Send {}
impl MustBeSendDummy for Request {}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    #[unstable]
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    #[unstable]
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server on a rand port and that listens to all inputs.
    /// Returns the server and the port it was created on.
    /// This function is guaranteed not to fail because of a port already in use,
    ///  and is useful for testing purposes.
    #[unstable]
    pub fn new_with_random_port() -> IoResult<(Server, ip::Port)> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: 0})
            .map(|s| { let port = s.get_server_addr().port; (s, port) })
    }

    /// Builds a new server that listens on the specified address.
    #[unstable]
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpAcceptor
        let (server, local_addr) = {
            let mut listener = try!(tcp::TcpListener::bind(
                format!("{}", addr.ip).as_slice(), addr.port));
            let local_addr = try!(listener.socket_name());
            let server = try!(listener.listen());
            let server = util::ClosableTcpAcceptor::new(server, close_trigger.clone());
            (server, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();

        let inside_close_trigger = close_trigger.clone();
        spawn(proc() {
            let mut server = server;

            loop {
                let new_client = server.accept().map(|sock| {
                    use util::ClosableTcpStream;

                    let read_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), true, false);

                    let write_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), false, true);

                    ClientConnection::new(write_closable, read_closable)
                });

                if tx_incoming.send_opt(new_client).is_err() {
                    break
                }
            }
        });

        //
        let (tx_requests, rx_requests) = channel();

        // result
        Ok(Server {
            tasks_pool: util::TaskPool::new(),
            connections_receiver: Mutex::new(rx_incoming),
            close: close_trigger,
            requests_sender: Mutex::new(tx_requests),
            requests_receiver: Mutex::new(rx_requests),
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[unstable]
    pub fn incoming_requests<'a>(&'a self) -> IncomingRequests<'a> {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[experimental]
    pub fn get_server_addr(&self) -> ip::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    #[stable]
    pub fn get_num_connections(&self) -> uint {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        let connections_receiver = self.connections_receiver.lock();
        let requests_receiver = self.requests_receiver.lock();

        // TODO: the select! macro doesn't seem to be usable without moving
        //       out of self, so we use Select directly

        let select = Select::new();

        let mut request_handle = select.handle(&*requests_receiver);
        unsafe { request_handle.add() };

        let mut connect_handle = select.handle(&*connections_receiver);
        unsafe { connect_handle.add() };

        loop {
            let id = select.wait();

            if id == request_handle.id() {
                let request = request_handle.recv();

                unsafe { request_handle.remove() };
                unsafe { connect_handle.remove() };

                return Ok(request)
            }

            if id == connect_handle.id() {
                let client = connect_handle.recv_opt();

                match client {
                    Ok(Ok(client)) => {
                        self.add_client(client);
                        continue
                    },
                    Ok(Err(err)) => {
                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(err)
                    },
                    Err(_) => {
                        use std::io;

                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(io::standard_error(io::Closed));
                    }
                }
            }

            unreachable!()
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        let mut connections_receiver = self.connections_receiver.lock();
        let mut requests_receiver = self.requests_receiver.lock();

        // processing all new clients
        loop {
            match connections_receiver.try_recv() {
                Ok(client) => self.add_client(try!(client)),
                Err(_) => break
            }
        }

        // reading the next request
        Ok(requests_receiver.try_recv().ok())
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let requests_sender = self.requests_sender.lock().clone();

        self.tasks_pool.spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| requests_sender.send_opt(rq).is_ok());
        });
    }
}

impl Request {
    /// Returns the method requested by the client (eg. `GET`, `POST`, etc.).
    #[stable]
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    #[unstable]
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    #[stable]
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the HTTP version of the request.
    #[unstable]
    pub fn get_http_version<'a>(&'a self) -> &'a HTTPVersion {
        &self.http_version
    }

    /// Returns the length of the body in bytes.
    ///
    /// Returns `None` if the length is unknown.
    #[unstable]
    pub fn get_body_length(&self) -> Option<uint> {
        Some(self.body_length)
    }

    /// Returns the length of the body in bytes.
    #[stable]
    pub fn get_remote_addr<'a>(&'a self) -> &'a ip::SocketAddr {
        &self.remote_addr
    }

    /// Allows to read the body of the request.
    ///
    /// # Example
    ///
    /// ```
    /// let request = server.recv();
    ///
    /// if get_content_type(&request) == "application/json" {
    ///     let json: Json = from_str(request.as_reader().read_to_string()).unwrap();
    /// }
    /// ```
    #[unstable]
    pub fn as_reader<'a>(&'a mut self) -> &'a mut Reader {
        fn passthrough<'a>(r: &'a mut Reader) -> &'a mut Reader { r }
        passthrough(self.data_reader)
    }

    /// Turns the `Request` into a writer.
    ///
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    ///
    /// Note that the destruction of the `Writer` object may trigger
    ///  some events. For exemple if a client has sent multiple requests and the requests
    ///  have been processed in parallel, the destruction of a writer will trigger
    ///  the writing of the next response.
    /// Therefore you should always destroy the `Writer` as soon as possible.
    #[stable]
    pub fn into_writer(mut self) -> Box<Writer + Send> {
        self.into_writer_impl()
    }

    fn into_writer_impl(&mut self) -> Box<Writer + Send> {
        use std::mem;

        assert!(self.response_writer.is_some());

        let mut writer = None;
        mem::swap(&mut self.response_writer, &mut writer);
        writer.unwrap()
    }

    /// Sends a response to this request.
    #[unstable]
    pub fn respond<R: Reader>(mut self, response: Response<R>) {
        self.respond_impl(response)
    }

    fn respond_impl<R: Reader>(&mut self, response: Response<R>) {
        use std::io;

        fn passthrough<'a>(w: &'a mut Writer) -> &'a mut Writer { w }
        let mut writer = self.into_writer_impl();

        let do_not_send_body = self.method.equiv(&"HEAD");

        match response.raw_print(passthrough(writer),
                                self.http_version, self.headers.as_slice(),
                                do_not_send_body)
        {
            Ok(_) => (),
            Err(ref err) if err.kind == io::Closed => (),
            Err(ref err) if err.kind == io::BrokenPipe => (),
            Err(ref err) if err.kind == io::ConnectionAborted => (),
            Err(ref err) if err.kind == io::ConnectionRefused => (),
            Err(ref err) if err.kind == io::ConnectionReset => (),
            Err(ref err) =>
                println!("error while sending answer: {}", err)     // TODO: handle better?
        };

        writer.flush().ok();
    }
}

impl<'a> Iterator<Request> for IncomingRequests<'a> {
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {} from {})",
            self.method, self.path, self.remote_addr.ip)).fmt(formatter)
    }
}

impl Drop for Request {
    fn drop(&mut self) {
        if self.response_writer.is_some() {
            let response = Response::new_empty(StatusCode(500));
            self.respond_impl(response);
        }
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomics::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Debug)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

pub fn distance(input: &str) -> u32 {
    let mut chars = input.chars();
    if let (Some(_turn_dir), Some(num_blocks)) = (chars.next(), chars.next()) {
        let num_blocks: u32 = num_blocks.to_string()
                                        .parse()
                                        .expect("Cannot parse");
        return num_blocks
    }
    panic!("oh no!");
}

pub fn turn(initial_direction: Direction, turn_command: char) -> Direction {
    match (turn_command, initial_direction) {
        ('L', Direction::North) => Direction::West,
        ('L', Direction::West) => Direction::South,
        ('L', Direction::South) => Direction::East,
        ('L', Direction::East) => Direction::North,

        ('R', Direction::North) => Direction::East,
        ('R', Direction::East) => Direction::South,
        ('R', Direction::South) => Direction::West,
        ('R', Direction::West) => Direction::North,

        (unknown_turn_command, dir) => panic!("\
            I don't know how to turn {} from {:?}!",
            unknown_turn_command,
            dir
        ),
    }
}

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

    #[test]
    fn right_one_is_one() {
        assert_eq!(distance("R1"), 1);
    }

    #[test]
    fn turn_left() {
        let mut dir = Direction::North;
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::North);
    }

    #[test]
    fn turn_right() {
        let mut dir = Direction::North;
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::North);
    }
}<commit_msg>Keep track of where we are and report final distance as sum of abs of coords<commit_after>#[derive(PartialEq, Debug)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

pub fn distance(input: &str) -> u32 {
    let mut location: (i32, i32) = (0, 0);
    let mut direction = Direction::North;

    for instruction in input.split_whitespace() {
        let mut chars = instruction.chars();
        if let (Some(turn_dir), Some(num_blocks)) = (chars.next(), chars.next()) {
            direction = turn(direction, turn_dir);
            let num_blocks: i32 = num_blocks.to_string()
                                            .parse()
                                            .expect("Cannot parse");
            match direction {
                Direction::North => location.1 += num_blocks,
                Direction::East => location.0 += num_blocks,
                Direction::South => location.1 -= num_blocks,
                Direction::West => location.0 -= num_blocks,
            }

        } else {
            panic!("Could not get instructions out of {}", instruction);
        }

    }
    (location.0.abs() + location.1.abs()) as u32
}

pub fn turn(initial_direction: Direction, turn_command: char) -> Direction {
    match (turn_command, initial_direction) {
        ('L', Direction::North) => Direction::West,
        ('L', Direction::West) => Direction::South,
        ('L', Direction::South) => Direction::East,
        ('L', Direction::East) => Direction::North,

        ('R', Direction::North) => Direction::East,
        ('R', Direction::East) => Direction::South,
        ('R', Direction::South) => Direction::West,
        ('R', Direction::West) => Direction::North,

        (unknown_turn_command, dir) => panic!("\
            I don't know how to turn {} from {:?}!",
            unknown_turn_command,
            dir
        ),
    }
}

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

    #[test]
    fn r1_is_one() {
        assert_eq!(distance("R1"), 1);
    }

    #[test]
    fn r1_r1_is_two() {
        assert_eq!(distance("R1 R1"), 2);
    }

    #[test]
    fn turn_left() {
        let mut dir = Direction::North;
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::North);
    }

    #[test]
    fn turn_right() {
        let mut dir = Direction::North;
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::North);
    }
}<|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>Run `rustfmt`<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 gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
pub extern crate luminance_gl;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate openal;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;

pub mod anim;
pub mod behavior;
pub mod bootstrap;
pub mod camera;
pub mod color;
pub mod device;
pub mod entity;
pub mod model;
pub mod objects;
pub mod projection;
pub mod shader;
pub mod texture;
pub mod transform;
<commit_msg>Added App.<commit_after>extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
pub extern crate luminance_gl;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate openal;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;

pub mod anim;
pub mod app;
pub mod behavior;
pub mod bootstrap;
pub mod camera;
pub mod color;
pub mod device;
pub mod entity;
pub mod model;
pub mod objects;
pub mod projection;
pub mod shader;
pub mod texture;
pub mod transform;
<|endoftext|>