<commit_before>use simplepattern::ParameterDictionary;
use simplepattern::SimplePattern;
use simplepattern::PatternMatcher;

pub struct HttpContext{
    request: Request,
    response: Response,
}

impl HttpContext{
}

pub struct Request {
    path: ~str,
    querystring: ~str
}

pub struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    pub fn new() -> Response{
        Response{contenttype: ~"text/html", body: ~""}
    }
}

pub struct Route {
    matcher: ~PatternMatcher,
    handler: ~fn(&mut ControllerContext)
}

pub struct Router{
    routes: ~[Route],
}

impl Router{
    pub fn new() -> Router{
        Router{routes: ~[]}
    }
    pub fn add(&mut self, r: ~Route){
        self.routes.push(*r);
    }
    pub fn execute(&mut self, c: &mut HttpContext) {
        for route in self.routes.iter(){
            let res=route.matcher.matches(c.request.path);

            if(res.is_match){
                (route.handler)(&mut ControllerContext{http: c, router: self, route_params: res.params});
                return;
            }
        }
        default_handler(&mut ControllerContext{http: c, router: self, route_params: ParameterDictionary::new()});
    }
    pub fn controller<'r,T>(&'r mut self, creator: ~fn(&mut ControllerContext) -> T) -> ControllerBox<'r,T>
    {
        ControllerBox{
            router: self,
            path: ~"",
            creator: Some(creator)
        }
    }
}

pub struct ControllerContext<'self>
{
    http: &'self mut HttpContext,
    router: &'self Router,
    route_params: ParameterDictionary
}

pub trait HttpController{

}

pub struct ControllerBox<'self,T>{
    router: &'self mut Router,
    path: ~str,
    creator: Option<~fn(&mut ControllerContext) -> T>
}

impl<'self,T> ControllerBox<'self,T>{
    pub fn handles(&'self mut self, path: ~str) -> &'self mut ControllerBox<'self,T>{
        self.path=path;
        self
    }
    pub fn with(&'self mut self, invoker: ~fn(&mut T, &mut ControllerContext)) -> &'self mut ControllerBox<'self,T>{
        let tmp=self.creator.take();

        self.router.add(~Route{matcher: ~SimplePattern::new(self.path) as ~PatternMatcher, handler:
         |c| {
            match tmp {
                None => (),
                Some(ref t) => {
                    let mut ctrl=(*t)(c);
                    invoker(&mut ctrl, c);
                }
            };
        }});
        self
    }
}
/*
struct Meh{
    biz: ~fn(int) -> int
}

impl Meh{
    fn foo(@mut self
}
*/
/*
struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}
*/

fn default_handler(context: &mut ControllerContext){
    context.http.response.body.push_str("404 not found");
}
/*
fn main() {
    let mut context=HttpContext::create();
    let mut router=Router::new();
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/test").with(|c,ctx| c.index(ctx));
    }
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
    }

    router.execute(&mut context);

    println(context.response.contenttype);
    println("");
    println(context.response.body);
}
*/<commit_msg>Change lambda signatures to Send+Freeze.<commit_after>use simplepattern::ParameterDictionary;
use simplepattern::SimplePattern;
use simplepattern::PatternMatcher;

pub struct HttpContext{
    request: Request,
    response: Response,
}

impl HttpContext{
}

pub struct Request {
    path: ~str,
    querystring: ~str
}

pub struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    pub fn new() -> Response{
        Response{contenttype: ~"text/html", body: ~""}
    }
}

pub struct Route {
    matcher: ~PatternMatcher,
    handler: ~fn:Send+Freeze(&mut ControllerContext)
}

pub struct Router{
    routes: ~[Route],
}

impl Router{
    pub fn new() -> Router{
        Router{routes: ~[]}
    }
    pub fn add(&mut self, r: ~Route){
        self.routes.push(*r);
    }
    pub fn execute(&mut self, c: &mut HttpContext) {
        for route in self.routes.iter(){
            let res=route.matcher.matches(c.request.path);

            if(res.is_match){
                (route.handler)(&mut ControllerContext{http: c, router: self, route_params: res.params});
                return;
            }
        }
        default_handler(&mut ControllerContext{http: c, router: self, route_params: ParameterDictionary::new()});
    }
    pub fn controller<'r,T>(&'r mut self, creator: ~fn:Send+Freeze(&mut ControllerContext) -> T) -> ControllerBox<'r,T>
    {
        ControllerBox{
            router: self,
            path: ~"",
            creator: Some(creator)
        }
    }
}

pub struct ControllerContext<'self>
{
    http: &'self mut HttpContext,
    router: &'self Router,
    route_params: ParameterDictionary
}

pub trait HttpController{

}

pub struct ControllerBox<'self,T>{
    router: &'self mut Router,
    path: ~str,
    creator: Option<~fn:Send+Freeze(&mut ControllerContext) -> T>
}

impl<'self,T> ControllerBox<'self,T>{
    pub fn handles(&'self mut self, path: ~str) -> &'self mut ControllerBox<'self,T>{
        self.path=path;
        self
    }
    pub fn with(&'self mut self, invoker: ~fn:Send+Freeze(&mut T, &mut ControllerContext)) -> &'self mut ControllerBox<'self,T>{
        let tmp=self.creator.take();

        self.router.add(~Route{matcher: ~SimplePattern::new(self.path) as ~PatternMatcher, handler: |c| {
            match tmp {
                None => (),
                Some(ref t) => {
                    let mut ctrl=(*t)(c);
                    invoker(&mut ctrl, c);
                }
            };
        }});
        self
    }
}
/*
struct Meh{
    biz: ~fn(int) -> int
}

impl Meh{
    fn foo(@mut self
}
*/
/*
struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}
*/

fn default_handler(context: &mut ControllerContext){
    context.http.response.body.push_str("404 not found");
}
/*
fn main() {
    let mut context=HttpContext::create();
    let mut router=Router::new();
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/test").with(|c,ctx| c.index(ctx));
    }
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
    }

    router.execute(&mut context);

    println(context.response.contenttype);
    println("");
    println(context.response.body);
}
*/
<|endoftext|>


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

//! The Rust Prelude
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particuarly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! into the crate root of every crate, and
//!
//! ```ignore
//! use std::prelude::v1::*;
//! ```
//!
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and reexports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
//!   traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destuctors and overloading `()`.
//! * [`std::mem`]::[`drop`], a convenience function for explicitly dropping a
//!   value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned()`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`],
//!   the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//!   reasons, but shouldn't have to exist. It provides a few useful methods on
//!   slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone
//! [`drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/closures.html
//! [book-dtor]: ../../book/drop.html
//! [book-enums]: ../../book/enums.html
//! [book-iter]: ../../book/iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<commit_msg>Rollup merge of #31513 - scottrobertwhittaker:fix-typo, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust Prelude
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! into the crate root of every crate, and
//!
//! ```ignore
//! use std::prelude::v1::*;
//! ```
//!
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and reexports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
//!   traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destuctors and overloading `()`.
//! * [`std::mem`]::[`drop`], a convenience function for explicitly dropping a
//!   value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned()`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`],
//!   the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//!   reasons, but shouldn't have to exist. It provides a few useful methods on
//!   slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone
//! [`drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/closures.html
//! [book-dtor]: ../../book/drop.html
//! [book-enums]: ../../book/enums.html
//! [book-iter]: ../../book/iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<|endoftext|>


<commit_before>#![allow(dead_code)]
/// The XML structure for a cobatura report is roughly as follows:
///
/// <coverage lines-valid="5" lines-covered="0" line-rate="0.0" branches-valid="0"
/// branches-covered="0" branch-rate="0.0" version="1.9" timestamp="...">
///   <sources>
///     <source>PATH</source>
///     ...
///   </sources>
///
///   <packages>
///     <package name=".."  line-rate="0.0" branch-rate="0.0" complexity="0.0">
///       <classes>
///         <class name="Main" filename="main.rs" line-rate="0.0" branch-rate="0.0" complexity="0.0">
///           <methods>
///             <method name="main" signature="()" line-rate="0.0" branch-rate="0.0">
///               <lines>
///                 <line number="1" hits="5" branch="false"/>
///                 <line number="3" hits="2" branch="true">
///                   <conditions>
///                     <condition number="0" type="jump" coverage="50%"/>
///                     ...
///                   </conditions>
///                 </line>
///               </lines>
///             </method>
///             ...
///           </methods>
///
///           <lines>
///             <line number="10" hits="4" branch="false"/>
///           </lines>
///         </class>
///         ...
///       </classes>
///     </package>
///     ...
///   </packages>
/// </coverage>

use std::error;
use std::fmt;
use std::fs::File;
use std::io::{Cursor, Write};
use std::time::{SystemTime, UNIX_EPOCH};
use std::path::{Path, PathBuf};

use quick_xml::{Writer, events::{BytesDecl, BytesEnd, BytesStart, Event}};

use chrono::offset::Utc;

use crate::config::{Config};
use crate::traces::{CoverageStat, Trace, TraceMap};

pub fn report(traces: &TraceMap, config: &Config) -> Result<(), Error> {
    let result = Report::render(config, traces)?;
    result.export(config)
}

#[derive(Debug)]
pub enum Error {
    Unknown,
    ExportError(quick_xml::Error),
}

impl error::Error for Error {

    #[inline]
    fn description(&self) -> &str {
        match self {
            Error::ExportError(_) => "Error exporting xml file",
            Error::Unknown => "Unknown Error",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl fmt::Display for Error {

    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::ExportError(ref e) => write!(f, "Export Error {}", e),
            Error::Unknown => write!(f, "Unknown Error"),
        }
    }
}

#[derive(Debug)]
pub struct Report {
    timestamp: i64,
    lines_covered: usize,
    lines_valid: usize,
    line_rate: f64,
    branches_covered:usize,
    branches_valid: usize,
    branch_rate: f64,
    sources: Vec<PathBuf>,
    packages: Vec<Package>,
}

impl Report {

    pub fn render(config: &Config, traces: &TraceMap) -> Result<Self, Error> {
        let timestamp   = Utc::now().timestamp();
        let sources     = render_sources(config);
        let packages    = render_packages(config, traces);
        let mut line_rate   = 0.0;
        let mut branch_rate = 0.0;

        if packages.len() > 0 {
            line_rate   = packages.iter()
                .map(|x| x.line_rate).sum::<f64>() / packages.len() as f64;
            branch_rate = packages.iter()
                .map(|x| x.branch_rate).sum::<f64>() / packages.len() as f64;
        }

        Ok(Report {
            timestamp:      timestamp,
            lines_covered: traces.total_covered(),
            lines_valid: traces.total_coverable(),
            line_rate:      line_rate,
            branches_covered: 0,
            branches_valid: 0,
            branch_rate:    branch_rate,
            sources:        sources,
            packages:       packages,
        })
    }

    pub fn export(&self, _config: &Config) -> Result<(), Error> {
        let mut file = File::create("cobertura.xml")
            .map_err(|e| Error::ExportError(quick_xml::Error::Io(e)))?;

        let mut writer = Writer::new(Cursor::new(vec![]));
        writer.write_event(Event::Decl(BytesDecl::new(b"1.0", None, None)))
            .map_err(|e| Error::ExportError(e))?;

        let cov_tag = b"coverage";
        let mut cov = BytesStart::borrowed(cov_tag, cov_tag.len());
        cov.push_attribute(("lines-covered", self.lines_covered.to_string().as_ref()));
        cov.push_attribute(("lines-valid", self.lines_valid.to_string().as_ref()));
        cov.push_attribute(("line-rate", self.line_rate.to_string().as_ref()));
        cov.push_attribute(("branches-covered", self.branches_covered.to_string().as_ref()));
        cov.push_attribute(("branches-valid", self.branches_valid.to_string().as_ref()));
        cov.push_attribute(("branch-rate", self.branch_rate.to_string().as_ref()));
        cov.push_attribute(("complexity", "0"));
        cov.push_attribute(("version", "1.9"));

        let secs = match SystemTime::now().duration_since(UNIX_EPOCH) {
            Ok(s) => s.as_secs().to_string(),
            Err(_) => String::from("0"),
        };
        cov.push_attribute(("timestamp", secs.as_ref()));

        writer.write_event(Event::Start(cov))
            .map_err(|e| Error::ExportError(e))?;

        self.export_header(&mut writer)
            .map_err(|e| Error::ExportError(e))?;

        self.export_packages(&mut writer)
            .map_err(|e| Error::ExportError(e))?;

        writer.write_event(Event::End(BytesEnd::borrowed(cov_tag)))
            .map_err(|e| Error::ExportError(e))?;

        let result = writer.into_inner().into_inner();
        file.write_all(&result)
            .map_err(|e| Error::ExportError(quick_xml::Error::Io(e)))
    }

    fn export_header<T: Write>(&self, writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let sources_tag = b"sources";
        let source_tag = b"source";
        writer.write_event(Event::Start(BytesStart::borrowed(sources_tag, sources_tag.len())))?;
        for source in self.sources.iter() {
            if let Some(ref path) = source.to_str() {
                writer.write_event(Event::Start(BytesStart::borrowed(source_tag, source_tag.len())))?;
                writer.write(path.as_bytes())?;
                writer.write_event(Event::End(BytesEnd::borrowed(source_tag)))?;
            }
        }
        writer.write_event(Event::End(BytesEnd::borrowed(sources_tag)))
            .map(|_| ())
    }

    fn export_packages<T: Write>(&self, writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let packages_tag = b"packages";
        let pack_tag = b"package";

        writer.write_event(Event::Start(BytesStart::borrowed(packages_tag, packages_tag.len())))?;
        // Export the package
        for package in &self.packages {
            let mut pack = BytesStart::borrowed(pack_tag, pack_tag.len());
            pack.push_attribute(("line-rate", package.line_rate.to_string().as_ref()));
            pack.push_attribute(("branch-rate", package.branch_rate.to_string().as_ref()));
            pack.push_attribute(("complexity", package.complexity.to_string().as_ref()));

            writer.write_event(Event::Start(pack))?;
            self.export_classes(&package.classes, writer)?;
            writer.write_event(Event::End(BytesEnd::borrowed(pack_tag)))?;
        }

        writer.write_event(Event::End(BytesEnd::borrowed(packages_tag)))
            .map(|_| ())
    }

    fn export_classes<T: Write>(&self, classes: &[Class], writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let classes_tag = b"classes";
        let class_tag = b"class";
        let methods_tag = b"methods";

        writer.write_event(Event::Start(BytesStart::borrowed(classes_tag, classes_tag.len())))?;
        for class in classes {
            let mut c = BytesStart::borrowed(class_tag, class_tag.len());
            c.push_attribute(("name", class.name.as_ref()));
            c.push_attribute(("filename", class.file_name.as_ref()));
            c.push_attribute(("line-rate", class.line_rate.to_string().as_ref()));
            c.push_attribute(("branch-rate", class.branch_rate.to_string().as_ref()));
            c.push_attribute(("complexity", class.complexity.to_string().as_ref()));

            writer.write_event(Event::Start(c))?;
            writer.write_event(Event::Empty(BytesStart::borrowed(methods_tag, methods_tag.len())))?;
            self.export_lines(&class.lines, writer)?;
            writer.write_event(Event::End(BytesEnd::borrowed(class_tag)))?;
        }
        writer.write_event(Event::End(BytesEnd::borrowed(classes_tag)))
            .map(|_| ())
    }

    fn export_lines<T: Write>(&self, lines: &[Line], writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let lines_tag = b"lines";
        let line_tag = b"line";

        writer.write_event(Event::Start(BytesStart::borrowed(lines_tag, lines_tag.len())))?;
        for line in lines {
            let mut l = BytesStart::borrowed(line_tag, line_tag.len());
            match line {
                Line::Plain{ref number, ref hits} => {
                    l.push_attribute(("number", number.to_string().as_ref()));
                    l.push_attribute(("hits", hits.to_string().as_ref()));
                },
                Line::Branch{..} => {},
            }
            writer.write_event(Event::Empty(l))?;
        }
        writer.write_event(Event::End(BytesEnd::borrowed(lines_tag)))
            .map(|_| ())
    }
}

fn render_sources(config: &Config) -> Vec<PathBuf> {
    let render_source = |&x| Path::to_path_buf(x);

    config.manifest.parent().iter().map(render_source).collect()
}

#[derive(Debug)]
struct Package {
    name:           String,
    line_rate:      f64,
    branch_rate:    f64,
    complexity:     f64,
    classes:        Vec<Class>,
}

fn render_packages(config: &Config, traces: &TraceMap) -> Vec<Package> {
    let mut dirs: Vec<&Path> = traces.files().into_iter()
        .filter_map(|x| x.parent())
        .collect();

    dirs.dedup();

    dirs.into_iter()
        .map(|x| render_package(config, traces, x))
        .collect()
}

fn render_package(config: &Config, traces: &TraceMap, pkg: &Path) -> Package {
    let root = config.manifest.parent().unwrap_or(&config.manifest);
    let name = pkg.strip_prefix(root)
        .map(|x| Path::to_str(x))
        .unwrap_or_default()
        .unwrap_or_default();

    let line_cover = traces.covered_in_path(pkg) as f64;
    let line_rate = line_cover / (traces.coverable_in_path(pkg) as f64);

    Package {
        name:           name.to_string(),
        line_rate:      line_rate,
        branch_rate:    0.0,
        complexity:     0.0,
        classes:        render_classes(config, traces, pkg)
    }
}

#[derive(Debug)]
struct Class {
    name:           String,
    file_name:      String,
    line_rate:      f64,
    branch_rate:    f64,
    complexity:     f64,
    lines:          Vec<Line>,
    methods:        Vec<Method>,
}

fn render_classes(config: &Config, traces: &TraceMap, pkg: &Path) -> Vec<Class> {
    traces.files().iter()
        .filter(|x| x.parent() == Some(pkg))
        .map(|x| render_class(config, traces, x))
        .collect()
}

// TODO: Cobertura distinguishes between lines outside methods, and methods
// (which also contain lines). As there is currently no way to get traces from
// a particular function only, all traces are put into lines, and the vector
// of methods is empty.
//
// Until this is fixed, the render_method function will panic if called, as it
// cannot be properly implemented.
//
fn render_class(config: &Config, traces: &TraceMap, file: &Path) -> Class {
    let root = config.manifest.parent().unwrap_or(&config.manifest);
    let name = file.file_stem()
        .map(|x| x.to_str().unwrap())
        .unwrap_or_default()
        .to_string();

    let file_name = file.strip_prefix(root)
        .unwrap_or(file)
        .to_str()
        .unwrap()
        .to_string();

    let covered = traces.covered_in_path(file) as f64;
    let line_rate = covered / traces.coverable_in_path(file) as f64;
    let lines = traces.get_child_traces(file).iter()
        .map(|x| render_line(x))
        .collect();

    Class {
        name:           name,
        file_name:      file_name,
        line_rate:      line_rate,
        branch_rate:    0.0,
        complexity:     0.0,
        lines:          lines,
        methods:        vec![]
    }
}

#[derive(Debug)]
struct Method {
    name:           String,
    signature:      String,
    line_rate:      f64,
    branch_rate:    f64,
    lines:          Vec<Line>,
}

fn render_methods() -> Vec<Method> {
    unimplemented!()
}

fn render_method() -> Method {
    unimplemented!()
}

#[derive(Debug)]
enum Line {
    Plain {
        number:     usize,
        hits:       usize,
    },

    Branch {
        number:     usize,
        hits:       usize,
        conditions: Vec<Condition>,
    }
}

fn render_line(trace: &Trace) -> Line {
    match &trace.stats {
        CoverageStat::Line(hits) => Line::Plain {
            number: trace.line as usize,
            hits:   *hits as usize
        },

        // TODO: Branches in cobertura are given a fresh number as a label,
        // which would require having some form of context when rendering.
        //
        _ => panic!("Not currently supported")
    }
}

#[derive(Debug)]
struct Condition {
    number:         usize,
    cond_type:      ConditionType,
    coverage:       f64,
}

// Condition types
#[derive(Debug)]
enum ConditionType {
    Jump,
}

<commit_msg>Put xml in markdown block to avoid doctest failure<commit_after>#![allow(dead_code)]
/// The XML structure for a cobatura report is roughly as follows:
/// ```xml
/// <coverage lines-valid="5" lines-covered="0" line-rate="0.0" branches-valid="0"
/// branches-covered="0" branch-rate="0.0" version="1.9" timestamp="...">
///   <sources>
///     <source>PATH</source>
///     ...
///   </sources>
///
///   <packages>
///     <package name=".."  line-rate="0.0" branch-rate="0.0" complexity="0.0">
///       <classes>
///         <class name="Main" filename="main.rs" line-rate="0.0" branch-rate="0.0" complexity="0.0">
///           <methods>
///             <method name="main" signature="()" line-rate="0.0" branch-rate="0.0">
///               <lines>
///                 <line number="1" hits="5" branch="false"/>
///                 <line number="3" hits="2" branch="true">
///                   <conditions>
///                     <condition number="0" type="jump" coverage="50%"/>
///                     ...
///                   </conditions>
///                 </line>
///               </lines>
///             </method>
///             ...
///           </methods>
///
///           <lines>
///             <line number="10" hits="4" branch="false"/>
///           </lines>
///         </class>
///         ...
///       </classes>
///     </package>
///     ...
///   </packages>
/// </coverage>
/// ```

use std::error;
use std::fmt;
use std::fs::File;
use std::io::{Cursor, Write};
use std::time::{SystemTime, UNIX_EPOCH};
use std::path::{Path, PathBuf};

use quick_xml::{Writer, events::{BytesDecl, BytesEnd, BytesStart, Event}};

use chrono::offset::Utc;

use crate::config::{Config};
use crate::traces::{CoverageStat, Trace, TraceMap};

pub fn report(traces: &TraceMap, config: &Config) -> Result<(), Error> {
    let result = Report::render(config, traces)?;
    result.export(config)
}

#[derive(Debug)]
pub enum Error {
    Unknown,
    ExportError(quick_xml::Error),
}

impl error::Error for Error {

    #[inline]
    fn description(&self) -> &str {
        match self {
            Error::ExportError(_) => "Error exporting xml file",
            Error::Unknown => "Unknown Error",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl fmt::Display for Error {

    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::ExportError(ref e) => write!(f, "Export Error {}", e),
            Error::Unknown => write!(f, "Unknown Error"),
        }
    }
}

#[derive(Debug)]
pub struct Report {
    timestamp: i64,
    lines_covered: usize,
    lines_valid: usize,
    line_rate: f64,
    branches_covered:usize,
    branches_valid: usize,
    branch_rate: f64,
    sources: Vec<PathBuf>,
    packages: Vec<Package>,
}

impl Report {

    pub fn render(config: &Config, traces: &TraceMap) -> Result<Self, Error> {
        let timestamp   = Utc::now().timestamp();
        let sources     = render_sources(config);
        let packages    = render_packages(config, traces);
        let mut line_rate   = 0.0;
        let mut branch_rate = 0.0;

        if packages.len() > 0 {
            line_rate   = packages.iter()
                .map(|x| x.line_rate).sum::<f64>() / packages.len() as f64;
            branch_rate = packages.iter()
                .map(|x| x.branch_rate).sum::<f64>() / packages.len() as f64;
        }

        Ok(Report {
            timestamp:      timestamp,
            lines_covered: traces.total_covered(),
            lines_valid: traces.total_coverable(),
            line_rate:      line_rate,
            branches_covered: 0,
            branches_valid: 0,
            branch_rate:    branch_rate,
            sources:        sources,
            packages:       packages,
        })
    }

    pub fn export(&self, _config: &Config) -> Result<(), Error> {
        let mut file = File::create("cobertura.xml")
            .map_err(|e| Error::ExportError(quick_xml::Error::Io(e)))?;

        let mut writer = Writer::new(Cursor::new(vec![]));
        writer.write_event(Event::Decl(BytesDecl::new(b"1.0", None, None)))
            .map_err(|e| Error::ExportError(e))?;

        let cov_tag = b"coverage";
        let mut cov = BytesStart::borrowed(cov_tag, cov_tag.len());
        cov.push_attribute(("lines-covered", self.lines_covered.to_string().as_ref()));
        cov.push_attribute(("lines-valid", self.lines_valid.to_string().as_ref()));
        cov.push_attribute(("line-rate", self.line_rate.to_string().as_ref()));
        cov.push_attribute(("branches-covered", self.branches_covered.to_string().as_ref()));
        cov.push_attribute(("branches-valid", self.branches_valid.to_string().as_ref()));
        cov.push_attribute(("branch-rate", self.branch_rate.to_string().as_ref()));
        cov.push_attribute(("complexity", "0"));
        cov.push_attribute(("version", "1.9"));

        let secs = match SystemTime::now().duration_since(UNIX_EPOCH) {
            Ok(s) => s.as_secs().to_string(),
            Err(_) => String::from("0"),
        };
        cov.push_attribute(("timestamp", secs.as_ref()));

        writer.write_event(Event::Start(cov))
            .map_err(|e| Error::ExportError(e))?;

        self.export_header(&mut writer)
            .map_err(|e| Error::ExportError(e))?;

        self.export_packages(&mut writer)
            .map_err(|e| Error::ExportError(e))?;

        writer.write_event(Event::End(BytesEnd::borrowed(cov_tag)))
            .map_err(|e| Error::ExportError(e))?;

        let result = writer.into_inner().into_inner();
        file.write_all(&result)
            .map_err(|e| Error::ExportError(quick_xml::Error::Io(e)))
    }

    fn export_header<T: Write>(&self, writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let sources_tag = b"sources";
        let source_tag = b"source";
        writer.write_event(Event::Start(BytesStart::borrowed(sources_tag, sources_tag.len())))?;
        for source in self.sources.iter() {
            if let Some(ref path) = source.to_str() {
                writer.write_event(Event::Start(BytesStart::borrowed(source_tag, source_tag.len())))?;
                writer.write(path.as_bytes())?;
                writer.write_event(Event::End(BytesEnd::borrowed(source_tag)))?;
            }
        }
        writer.write_event(Event::End(BytesEnd::borrowed(sources_tag)))
            .map(|_| ())
    }

    fn export_packages<T: Write>(&self, writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let packages_tag = b"packages";
        let pack_tag = b"package";

        writer.write_event(Event::Start(BytesStart::borrowed(packages_tag, packages_tag.len())))?;
        // Export the package
        for package in &self.packages {
            let mut pack = BytesStart::borrowed(pack_tag, pack_tag.len());
            pack.push_attribute(("line-rate", package.line_rate.to_string().as_ref()));
            pack.push_attribute(("branch-rate", package.branch_rate.to_string().as_ref()));
            pack.push_attribute(("complexity", package.complexity.to_string().as_ref()));

            writer.write_event(Event::Start(pack))?;
            self.export_classes(&package.classes, writer)?;
            writer.write_event(Event::End(BytesEnd::borrowed(pack_tag)))?;
        }

        writer.write_event(Event::End(BytesEnd::borrowed(packages_tag)))
            .map(|_| ())
    }

    fn export_classes<T: Write>(&self, classes: &[Class], writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let classes_tag = b"classes";
        let class_tag = b"class";
        let methods_tag = b"methods";

        writer.write_event(Event::Start(BytesStart::borrowed(classes_tag, classes_tag.len())))?;
        for class in classes {
            let mut c = BytesStart::borrowed(class_tag, class_tag.len());
            c.push_attribute(("name", class.name.as_ref()));
            c.push_attribute(("filename", class.file_name.as_ref()));
            c.push_attribute(("line-rate", class.line_rate.to_string().as_ref()));
            c.push_attribute(("branch-rate", class.branch_rate.to_string().as_ref()));
            c.push_attribute(("complexity", class.complexity.to_string().as_ref()));

            writer.write_event(Event::Start(c))?;
            writer.write_event(Event::Empty(BytesStart::borrowed(methods_tag, methods_tag.len())))?;
            self.export_lines(&class.lines, writer)?;
            writer.write_event(Event::End(BytesEnd::borrowed(class_tag)))?;
        }
        writer.write_event(Event::End(BytesEnd::borrowed(classes_tag)))
            .map(|_| ())
    }

    fn export_lines<T: Write>(&self, lines: &[Line], writer: &mut Writer<T>) -> Result<(), quick_xml::Error> {
        let lines_tag = b"lines";
        let line_tag = b"line";

        writer.write_event(Event::Start(BytesStart::borrowed(lines_tag, lines_tag.len())))?;
        for line in lines {
            let mut l = BytesStart::borrowed(line_tag, line_tag.len());
            match line {
                Line::Plain{ref number, ref hits} => {
                    l.push_attribute(("number", number.to_string().as_ref()));
                    l.push_attribute(("hits", hits.to_string().as_ref()));
                },
                Line::Branch{..} => {},
            }
            writer.write_event(Event::Empty(l))?;
        }
        writer.write_event(Event::End(BytesEnd::borrowed(lines_tag)))
            .map(|_| ())
    }
}

fn render_sources(config: &Config) -> Vec<PathBuf> {
    let render_source = |&x| Path::to_path_buf(x);

    config.manifest.parent().iter().map(render_source).collect()
}

#[derive(Debug)]
struct Package {
    name:           String,
    line_rate:      f64,
    branch_rate:    f64,
    complexity:     f64,
    classes:        Vec<Class>,
}

fn render_packages(config: &Config, traces: &TraceMap) -> Vec<Package> {
    let mut dirs: Vec<&Path> = traces.files().into_iter()
        .filter_map(|x| x.parent())
        .collect();

    dirs.dedup();

    dirs.into_iter()
        .map(|x| render_package(config, traces, x))
        .collect()
}

fn render_package(config: &Config, traces: &TraceMap, pkg: &Path) -> Package {
    let root = config.manifest.parent().unwrap_or(&config.manifest);
    let name = pkg.strip_prefix(root)
        .map(|x| Path::to_str(x))
        .unwrap_or_default()
        .unwrap_or_default();

    let line_cover = traces.covered_in_path(pkg) as f64;
    let line_rate = line_cover / (traces.coverable_in_path(pkg) as f64);

    Package {
        name:           name.to_string(),
        line_rate:      line_rate,
        branch_rate:    0.0,
        complexity:     0.0,
        classes:        render_classes(config, traces, pkg)
    }
}

#[derive(Debug)]
struct Class {
    name:           String,
    file_name:      String,
    line_rate:      f64,
    branch_rate:    f64,
    complexity:     f64,
    lines:          Vec<Line>,
    methods:        Vec<Method>,
}

fn render_classes(config: &Config, traces: &TraceMap, pkg: &Path) -> Vec<Class> {
    traces.files().iter()
        .filter(|x| x.parent() == Some(pkg))
        .map(|x| render_class(config, traces, x))
        .collect()
}

// TODO: Cobertura distinguishes between lines outside methods, and methods
// (which also contain lines). As there is currently no way to get traces from
// a particular function only, all traces are put into lines, and the vector
// of methods is empty.
//
// Until this is fixed, the render_method function will panic if called, as it
// cannot be properly implemented.
//
fn render_class(config: &Config, traces: &TraceMap, file: &Path) -> Class {
    let root = config.manifest.parent().unwrap_or(&config.manifest);
    let name = file.file_stem()
        .map(|x| x.to_str().unwrap())
        .unwrap_or_default()
        .to_string();

    let file_name = file.strip_prefix(root)
        .unwrap_or(file)
        .to_str()
        .unwrap()
        .to_string();

    let covered = traces.covered_in_path(file) as f64;
    let line_rate = covered / traces.coverable_in_path(file) as f64;
    let lines = traces.get_child_traces(file).iter()
        .map(|x| render_line(x))
        .collect();

    Class {
        name:           name,
        file_name:      file_name,
        line_rate:      line_rate,
        branch_rate:    0.0,
        complexity:     0.0,
        lines:          lines,
        methods:        vec![]
    }
}

#[derive(Debug)]
struct Method {
    name:           String,
    signature:      String,
    line_rate:      f64,
    branch_rate:    f64,
    lines:          Vec<Line>,
}

fn render_methods() -> Vec<Method> {
    unimplemented!()
}

fn render_method() -> Method {
    unimplemented!()
}

#[derive(Debug)]
enum Line {
    Plain {
        number:     usize,
        hits:       usize,
    },

    Branch {
        number:     usize,
        hits:       usize,
        conditions: Vec<Condition>,
    }
}

fn render_line(trace: &Trace) -> Line {
    match &trace.stats {
        CoverageStat::Line(hits) => Line::Plain {
            number: trace.line as usize,
            hits:   *hits as usize
        },

        // TODO: Branches in cobertura are given a fresh number as a label,
        // which would require having some form of context when rendering.
        //
        _ => panic!("Not currently supported")
    }
}

#[derive(Debug)]
struct Condition {
    number:         usize,
    cond_type:      ConditionType,
    coverage:       f64,
}

// Condition types
#[derive(Debug)]
enum ConditionType {
    Jump,
}

<|endoftext|>


<commit_before><commit_msg>Make sure everything from local variable table that needs to be deallocated is dealloc'd in all cases<commit_after><|endoftext|>


<commit_before>#[macro_use] extern crate quote;

extern crate proc_macro;
extern crate syn;

mod ast;
mod generator;
mod parser;
mod scanner;
mod token;

use proc_macro::TokenStream;

use ast::Ast;
use std::fs::File;
use std::io::prelude::*;

fn find_attr<'a>(attrs: &'a Vec<syn::Attribute>, name: &str) -> Option<&'a str> {
    attrs.iter()
        .find(|&x| x.name() == name)
        .and_then(|ref attr| match &attr.value {
            &syn::MetaItem::NameValue(_, syn::Lit::Str(ref template, _)) => Some(template),
            _ => None
        })
        .map(|x| x.as_ref())
}

fn buf_file(filename: &str) -> String {
    let mut f = File::open(filename)
        .expect("Unable to open file for reading");
    let mut buf = String::new();
    f.read_to_string(&mut buf)
        .expect("Unable to read file");

    buf
}

fn parse_str(input: &str) -> Result<Ast, parser::Error> {
    parser::parse(scanner::sequence(input).unwrap())
}

#[proc_macro_derive(BartDisplay, attributes(template, template_string, template_root))]
pub fn bart_display(input: TokenStream) -> TokenStream {
    use std::env;

    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();

    let user_crate_root = env::current_dir().expect("Unable to get current directory");

    let mut dependencies = Vec::<String>::new();

    let filename_opt = find_attr(&ast.attrs, "template");

    let template =
        filename_opt.map(buf_file)
            .or_else(||
                find_attr(&ast.attrs, "template_string").map(|x| x.to_owned())
            )
        .expect("#[derive(BartDisplay)] requires #[template = \"(filename)\"] or  #[template_string = \"...\"]");

    if let Some(filename) = filename_opt {
        dependencies.push(user_crate_root.join(filename).to_str().unwrap().to_owned());
    }

    let template_root = syn::Ident::new(find_attr(&ast.attrs, "template_root")
        .map(|x| scanner::segmented_name(&x).expect("Syntax error in template_root"))
        .map(|x| format!("self.{}", x.join(".")))
        .unwrap_or("self".to_owned()));

    let parsed = parse_str(&template).unwrap();
    let generated = generator::generate(parsed, 1);

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    let dummy_const = syn::Ident::new(format!("_IMPL_BART_DISPLAY_FOR_{}", &name));

    let gen = quote! {
        #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
        const #dummy_const: () = {
            extern crate bart as _bart;

            #[automatically_derived]
            impl #impl_generics ::std::fmt::Display for #name #ty_generics #where_clause {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    #(
                        let _ = include_bytes!(#dependencies);
                    )*

                    let ref _s0 = #template_root;

                    #generated

                    Ok(())
                }
            }
        };
    };

    gen.parse().unwrap()
}
<commit_msg>Cleanup<commit_after>#[macro_use] extern crate quote;

extern crate proc_macro;
extern crate syn;

mod ast;
mod generator;
mod parser;
mod scanner;
mod token;

use ast::Ast;
use proc_macro::TokenStream;
use std::fs::File;
use std::io::prelude::*;

fn find_attr<'a>(attrs: &'a Vec<syn::Attribute>, name: &str) -> Option<&'a str> {
    attrs.iter()
        .find(|&x| x.name() == name)
        .and_then(|ref attr| match &attr.value {
            &syn::MetaItem::NameValue(_, syn::Lit::Str(ref template, _)) => Some(template),
            _ => None
        })
        .map(|x| x.as_ref())
}

fn buf_file(filename: &str) -> String {
    let mut f = File::open(filename)
        .expect("Unable to open file for reading");
    let mut buf = String::new();
    f.read_to_string(&mut buf)
        .expect("Unable to read file");

    buf
}

fn parse_str(input: &str) -> Result<Ast, parser::Error> {
    parser::parse(scanner::sequence(input).unwrap())
}

#[proc_macro_derive(BartDisplay, attributes(template, template_string, template_root))]
pub fn bart_display(input: TokenStream) -> TokenStream {
    use std::env;

    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();

    let user_crate_root = env::current_dir().expect("Unable to get current directory");

    let mut dependencies = Vec::<String>::new();

    let filename_opt = find_attr(&ast.attrs, "template");

    let template =
        filename_opt.map(buf_file)
            .or_else(||
                find_attr(&ast.attrs, "template_string").map(|x| x.to_owned())
            )
        .expect("#[derive(BartDisplay)] requires #[template = \"(filename)\"] or  #[template_string = \"...\"]");

    if let Some(filename) = filename_opt {
        dependencies.push(user_crate_root.join(filename).to_str().unwrap().to_owned());
    }

    let template_root = syn::Ident::new(find_attr(&ast.attrs, "template_root")
        .map(|x| scanner::segmented_name(&x).expect("Syntax error in template_root"))
        .map(|x| format!("self.{}", x.join(".")))
        .unwrap_or("self".to_owned()));

    let parsed = parse_str(&template).unwrap();
    let generated = generator::generate(parsed, 1);

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    let dummy_const = syn::Ident::new(format!("_IMPL_BART_DISPLAY_FOR_{}", &name));

    let gen = quote! {
        #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
        const #dummy_const: () = {
            extern crate bart as _bart;

            #[automatically_derived]
            impl #impl_generics ::std::fmt::Display for #name #ty_generics #where_clause {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    #(
                        let _ = include_bytes!(#dependencies);
                    )*

                    let ref _s0 = #template_root;

                    #generated

                    Ok(())
                }
            }
        };
    };

    gen.parse().unwrap()
}
<|endoftext|>


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

#![feature(ascii_ctype)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(const_ptr_null)]
#![feature(const_ptr_null_mut)]
#![feature(core_intrinsics)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(plugin)]
#![feature(proc_macro)]
#![feature(try_from)]
#![feature(untagged_unions)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(script_plugins)]

extern crate angle;
extern crate app_units;
extern crate audio_video_metadata;
extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use] extern crate cssparser;
#[macro_use] extern crate deny_public_fields;
extern crate devtools_traits;
extern crate dom_struct;
#[macro_use]
extern crate domobject_derive;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate half;
#[macro_use] extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
#[macro_use] extern crate html5ever;
#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
extern crate ipc_channel;
#[macro_use]
extern crate js;
#[macro_use]
extern crate jstraceable_derive;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate metrics;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate mitochondria;
extern crate msg;
extern crate net_traits;
extern crate num_traits;
extern crate offscreen_gl_context;
extern crate open;
extern crate parking_lot;
extern crate phf;
#[macro_use]
extern crate profile_traits;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;
extern crate serde;
extern crate servo_arc;
#[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_rand;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate swapper;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicode_segmentation;
extern crate url;
extern crate utf8;
extern crate uuid;
extern crate webrender_api;
extern crate webvr_traits;
extern crate xml5ever;

#[macro_use]
mod task;

mod body;
pub mod clipboard_provider;
mod devtools;
pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
mod layout_image;
mod mem;
mod microtask;
mod network_listener;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
mod serviceworker_manager;
mod serviceworkerjob;
mod stylesheet_loader;
mod task_source;
pub mod test;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

/// A module with everything layout can use from script.
///
/// Try to keep this small!
///
/// TODO(emilio): A few of the FooHelpers can go away, presumably...
pub mod layout_exports {
    pub use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
    pub use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
    pub use dom::bindings::js::LayoutJS;
    pub use dom::characterdata::LayoutCharacterDataHelpers;
    pub use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
    pub use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
    pub use dom::node::{CAN_BE_FRAGMENTED, HAS_DIRTY_DESCENDANTS, IS_IN_DOC};
    pub use dom::node::{HANDLED_SNAPSHOT, HAS_SNAPSHOT};
    pub use dom::node::{LayoutNodeHelpers, Node};
    pub use dom::text::Text;
}

use dom::bindings::codegen::RegisterBindings;
use dom::bindings::proxyhandler;
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

pub fn init_service_workers(sw_senders: SWManagerSenders) {
    // Spawn the service worker manager passing the constellation sender
    ServiceWorkerManager::spawn_manager(sw_senders);
}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        proxyhandler::init();

        // Create the global vtables used by the (generated) DOM
        // bindings to implement JS proxies.
        RegisterBindings::RegisterProxyHandlers();
    }

    perform_platform_specific_initialization();
}
<commit_msg>Auto merge of #18601 - mbrubeck:features, r=KiChjang<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(ascii_ctype)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(const_ptr_null)]
#![feature(const_ptr_null_mut)]
#![feature(core_intrinsics)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(plugin)]
#![feature(proc_macro)]
#![feature(try_from)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(script_plugins)]

extern crate angle;
extern crate app_units;
extern crate audio_video_metadata;
extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use] extern crate cssparser;
#[macro_use] extern crate deny_public_fields;
extern crate devtools_traits;
extern crate dom_struct;
#[macro_use]
extern crate domobject_derive;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate half;
#[macro_use] extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
#[macro_use] extern crate html5ever;
#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
extern crate ipc_channel;
#[macro_use]
extern crate js;
#[macro_use]
extern crate jstraceable_derive;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate metrics;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate mitochondria;
extern crate msg;
extern crate net_traits;
extern crate num_traits;
extern crate offscreen_gl_context;
extern crate open;
extern crate parking_lot;
extern crate phf;
#[macro_use]
extern crate profile_traits;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;
extern crate serde;
extern crate servo_arc;
#[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_rand;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate swapper;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicode_segmentation;
extern crate url;
extern crate utf8;
extern crate uuid;
extern crate webrender_api;
extern crate webvr_traits;
extern crate xml5ever;

#[macro_use]
mod task;

mod body;
pub mod clipboard_provider;
mod devtools;
pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
mod layout_image;
mod mem;
mod microtask;
mod network_listener;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
mod serviceworker_manager;
mod serviceworkerjob;
mod stylesheet_loader;
mod task_source;
pub mod test;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

/// A module with everything layout can use from script.
///
/// Try to keep this small!
///
/// TODO(emilio): A few of the FooHelpers can go away, presumably...
pub mod layout_exports {
    pub use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
    pub use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
    pub use dom::bindings::js::LayoutJS;
    pub use dom::characterdata::LayoutCharacterDataHelpers;
    pub use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
    pub use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
    pub use dom::node::{CAN_BE_FRAGMENTED, HAS_DIRTY_DESCENDANTS, IS_IN_DOC};
    pub use dom::node::{HANDLED_SNAPSHOT, HAS_SNAPSHOT};
    pub use dom::node::{LayoutNodeHelpers, Node};
    pub use dom::text::Text;
}

use dom::bindings::codegen::RegisterBindings;
use dom::bindings::proxyhandler;
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

pub fn init_service_workers(sw_senders: SWManagerSenders) {
    // Spawn the service worker manager passing the constellation sender
    ServiceWorkerManager::spawn_manager(sw_senders);
}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        proxyhandler::init();

        // Create the global vtables used by the (generated) DOM
        // bindings to implement JS proxies.
        RegisterBindings::RegisterProxyHandlers();
    }

    perform_platform_specific_initialization();
}
<|endoftext|>


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

#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(field_init_shorthand)]
#![feature(more_struct_aliases)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![feature(try_from)]
#![feature(untagged_unions)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(plugins)]

extern crate angle;
extern crate app_units;
extern crate atomic_refcell;
extern crate audio_video_metadata;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use]
extern crate cssparser;
extern crate devtools_traits;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gfx_traits;
extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
extern crate html5ever;
#[macro_use] extern crate html5ever_atoms;
#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
extern crate ipc_channel;
#[macro_use]
extern crate js;
#[macro_use]
extern crate jstraceable_derive;
extern crate libc;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate msg;
extern crate net_traits;
extern crate num_traits;
extern crate offscreen_gl_context;
extern crate open;
extern crate parking_lot;
extern crate phf;
#[macro_use]
extern crate profile_traits;
extern crate range;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate rustc_serialize;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;
extern crate serde;
#[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_rand;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate url;
extern crate uuid;
extern crate webrender_traits;
extern crate websocket;
extern crate webvr_traits;
extern crate xml5ever;

mod body;
pub mod clipboard_provider;
mod devtools;
pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
pub mod layout_wrapper;
mod mem;
mod microtask;
mod network_listener;
pub mod origin;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
mod serviceworker_manager;
mod serviceworkerjob;
mod stylesheet_loader;
mod task_source;
pub mod test;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

use dom::bindings::codegen::RegisterBindings;
use dom::bindings::proxyhandler;
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

pub fn init_service_workers(sw_senders: SWManagerSenders) {
    // Spawn the service worker manager passing the constellation sender
    ServiceWorkerManager::spawn_manager(sw_senders);
}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        proxyhandler::init();

        // Create the global vtables used by the (generated) DOM
        // bindings to implement JS proxies.
        RegisterBindings::RegisterProxyHandlers();
    }

    perform_platform_specific_initialization();
}
<commit_msg>Auto merge of #15403 - servo:warnings, r=SimonSapin<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(field_init_shorthand)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![feature(try_from)]
#![feature(untagged_unions)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(plugins)]

extern crate angle;
extern crate app_units;
extern crate atomic_refcell;
extern crate audio_video_metadata;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use]
extern crate cssparser;
extern crate devtools_traits;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gfx_traits;
extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
extern crate html5ever;
#[macro_use] extern crate html5ever_atoms;
#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
extern crate ipc_channel;
#[macro_use]
extern crate js;
#[macro_use]
extern crate jstraceable_derive;
extern crate libc;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate msg;
extern crate net_traits;
extern crate num_traits;
extern crate offscreen_gl_context;
extern crate open;
extern crate parking_lot;
extern crate phf;
#[macro_use]
extern crate profile_traits;
extern crate range;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate rustc_serialize;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;
extern crate serde;
#[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_rand;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate url;
extern crate uuid;
extern crate webrender_traits;
extern crate websocket;
extern crate webvr_traits;
extern crate xml5ever;

mod body;
pub mod clipboard_provider;
mod devtools;
pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
pub mod layout_wrapper;
mod mem;
mod microtask;
mod network_listener;
pub mod origin;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
mod serviceworker_manager;
mod serviceworkerjob;
mod stylesheet_loader;
mod task_source;
pub mod test;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

use dom::bindings::codegen::RegisterBindings;
use dom::bindings::proxyhandler;
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

pub fn init_service_workers(sw_senders: SWManagerSenders) {
    // Spawn the service worker manager passing the constellation sender
    ServiceWorkerManager::spawn_manager(sw_senders);
}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        proxyhandler::init();

        // Create the global vtables used by the (generated) DOM
        // bindings to implement JS proxies.
        RegisterBindings::RegisterProxyHandlers();
    }

    perform_platform_specific_initialization();
}
<|endoftext|>


<commit_before>use super::token::TokenType;
use super::token::Token;

struct Lexer {
    input: String,
    // Current position in input.
    position: usize,
    // Current reading position.
    read_position: usize,
    // Current char under examination.
    ch: char,
}

impl Lexer {
    fn new(input: String) -> Self {
        let mut l = Lexer {
            input: input,
            position: 0,
            read_position: 0,
            ch: '\\',
        };
        l.read_char();
        l
    }

    fn read_char(&mut self) {
        if self.read_position >= self.input.len() {
            self.ch = '\\';
        } else {
            self.ch = self.input.chars().nth(self.read_position).unwrap();
        }
        self.position = self.read_position;
        self.read_position += 1;
    }

    fn next_token(&mut self) -> Token {
        let tt = match self.ch {
            '=' => TokenType::Assign,
            ';' => TokenType::Semicolon,
            '(' => TokenType::LeftParen,
            ')' => TokenType::RightParen,
            ',' => TokenType::Comma,
            '+' => TokenType::Plus,
            '{' => TokenType::LeftBrace,
            '}' => TokenType::RightBrace,
            '\\' => TokenType::EOF,
            _ => TokenType::Illegal,
        };
        let tok = Token::new(tt, self.ch.to_string());

        self.read_char();

        tok
    }
}

#[test]
fn test_next_token() {
    let input = String::from("let five = 5;
        let ten = 10;
        let add = fn(x, y) {
            x + y;
        };
        let result = add(five, ten);
    ");
    let mut lexer = Lexer::new(input);

    let tests = vec![(TokenType::Let, "let"),
                     (TokenType::Ident, "five"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "ten"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "10"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "add"),
                     (TokenType::Assign, "="),
                     (TokenType::Function, "fn"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "x"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "y"),
                     (TokenType::RightParen, ")"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Ident, "x"),
                     (TokenType::Plus, "+"),
                     (TokenType::Ident, "y"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "result"),
                     (TokenType::Assign, "="),
                     (TokenType::Ident, "add"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "five"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "ten"),
                     (TokenType::RightParen, ")"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::EOF, "")];

    for (expected_type, expected_literal) in tests {
        let tok = lexer.next_token();

        assert!(tok.token_type == expected_type,
                "Wrong TokenType. Expected - {:?}, got - {:?}.",
                expected_type,
                tok.token_type);

        assert!(tok.literal == expected_literal,
                "Wrong literal. Expected - {:?}, got - {:?}.",
                expected_literal,
                tok.literal);
    }
}
<commit_msg>Lexer is looking for keywords, idents, numbers + fixed bugs.<commit_after>use super::token::TokenType;
use super::token::Token;

struct Lexer {
    input: String,
    // Current position in input.
    position: usize,
    // Current reading position.
    read_position: usize,
    // Current char under examination.
    ch: char,
}

impl Lexer {
    fn new(input: String) -> Self {
        let mut l = Lexer {
            input: input,
            position: 0,
            read_position: 0,
            ch: '\0',
        };
        l.read_char();
        l
    }

    fn read_char(&mut self) {
        if self.read_position >= self.input.len() {
            self.ch = '\0';
        } else {
            self.ch = self.input.chars().nth(self.read_position).unwrap();
        }
        self.position = self.read_position;
        self.read_position += 1;
    }

    fn is_letter(&self, ch: char) -> bool {
        ch.is_alphabetic() || ch == '_' || ch == '?'
    }

    fn read_ident(&mut self) -> String {
        let position = self.position;
        while self.is_letter(self.ch) {
            self.read_char();
        }

        self.input[position..self.position].to_string()
    }

    fn read_number(&mut self) -> String {
        let position = self.position;
        while self.ch.is_digit(10) {
            self.read_char();
        }

        self.input[position..self.position].to_string()
    }

    fn next_token(&mut self) -> Token {
        while self.ch.is_whitespace() {
            self.read_char();
        }

        let tok = match self.ch {
            '=' => Token::new(TokenType::Assign, self.ch.to_string()),
            ';' => Token::new(TokenType::Semicolon, self.ch.to_string()),
            '(' => Token::new(TokenType::LeftParen, self.ch.to_string()),
            ')' => Token::new(TokenType::RightParen, self.ch.to_string()),
            ',' => Token::new(TokenType::Comma, self.ch.to_string()),
            '+' => Token::new(TokenType::Plus, self.ch.to_string()),
            '{' => Token::new(TokenType::LeftBrace, self.ch.to_string()),
            '}' => Token::new(TokenType::RightBrace, self.ch.to_string()),
            '\0' => Token::new(TokenType::EOF, "".to_string()),
            ch @ _ if self.is_letter(ch) => {
                let ident = self.read_ident();
                let tt = TokenType::lookup_ident(&ident);
                return Token::new(tt, ident);
            }
            ch @ _ if ch.is_digit(10) => {
                let literal = self.read_number();
                return Token::new(TokenType::Int, literal);
            }
            _ => Token::new(TokenType::Illegal, self.ch.to_string()),
        };

        self.read_char();
        tok
    }
}

#[test]
fn test_next_token() {
    let input = String::from("let five = 5;
        let ten = 10;
        let add = fn(x, y) {
            x + y;
        };
        let result = add(five, ten);
    ");
    let mut lexer = Lexer::new(input);

    let tests = vec![(TokenType::Let, "let"),
                     (TokenType::Ident, "five"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "ten"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "10"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "add"),
                     (TokenType::Assign, "="),
                     (TokenType::Function, "fn"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "x"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "y"),
                     (TokenType::RightParen, ")"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Ident, "x"),
                     (TokenType::Plus, "+"),
                     (TokenType::Ident, "y"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "result"),
                     (TokenType::Assign, "="),
                     (TokenType::Ident, "add"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "five"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "ten"),
                     (TokenType::RightParen, ")"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::EOF, "")];

    for (i, &(ref expected_type, ref expected_literal)) in tests.iter().enumerate() {
        let tok = lexer.next_token();

        assert!(tok.token_type == *expected_type,
                "Wrong TokenType [{}]. Expected - {:?}, got - {:?}.",
                i,
                expected_type,
                tok.token_type);

        assert!(tok.literal == *expected_literal,
                "Wrong literal [{}]. Expected - {:?}, got - {:?}.",
                i,
                expected_literal,
                tok.literal);
    }
}
<|endoftext|>


<commit_before>/*
 * Implemenation of a bitfield as a vec. Only
 * supports bytes (Vec<u8>) as the underlying
 * storage.
 *
 * A future implementation should be more efficient,
 * this is just to get the job done for now.
 */
extern crate rlp;
use self::rlp::{ RlpStream, Encodable };

pub struct BooleanBitfield{
    vec: Vec<u8>
}

impl BooleanBitfield {
    pub fn new() -> Self {
        Self {
            vec: vec![]
        }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            vec: Vec::with_capacity(capacity)
        }
    }

    // Output the bitfield as a big-endian vec of u8
    pub fn to_be_vec(&self) -> Vec<u8> {
        let mut o = self.vec.clone();
        o.reverse();
        o
    }

    pub fn get_bit(&self, i: &usize) -> bool {
        self.get_bit_on_byte(*i % 8, *i / 8)
    }

    fn get_bit_on_byte(&self, bit: usize, byte: usize) -> bool {
        assert!(bit < 8);
        if byte >= self.vec.len() {
            false
        } else {
             self.vec[byte] & (1 << (bit as u8)) != 0
        }
    }

    pub fn set_bit(&mut self, bit: &usize, to: &bool) {
        self.set_bit_on_byte(*bit % 8, *bit / 8, to);
    }

    fn set_bit_on_byte(&mut self, bit: usize, byte: usize, val: &bool) {
        assert!(bit < 8);
        if byte >= self.vec.len() {
            self.vec.resize(byte + 1, 0);
        }
        match val {
            true =>  self.vec[byte] = self.vec[byte] |  (1 << (bit as u8)),
            false => self.vec[byte] = self.vec[byte] & !(1 << (bit as u8))
        }
    }
}

impl Encodable for BooleanBitfield {
    // TODO: ensure this is a sensible method of encoding
    // the bitfield. Currently, it is treated as a list of
    // bytes not as a string. I do not have any guidance as
    // to which method is correct -- don't follow my lead
    // without seeking authoritative advice.
    fn rlp_append(&self, s: &mut RlpStream) {
        s.append(&self.to_be_vec());
    }
}

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

    #[test]
    fn test_bitfield_set() {
        let mut b = BooleanBitfield::new();
        b.set_bit(&0, &false);
        assert_eq!(b.to_be_vec(), [0]);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        assert_eq!(b.to_be_vec(), [128]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [0]);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        b.set_bit(&0, &true);
        assert_eq!(b.to_be_vec(), [129]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [1]);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        assert_eq!(b.to_be_vec(), [1, 0]);
        b.set_bit(&8, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);

        b = BooleanBitfield::new();
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [128, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [129, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [1, 0]);
    }

    #[test]
    fn test_bitfield_get() {
        let mut b = BooleanBitfield::new();
        let test_nums = vec![0, 8, 15, 42, 1337];
        for i in test_nums {
            b = BooleanBitfield::new();
            assert_eq!(b.get_bit(&0), false);
            b.set_bit(&0, &true);
            assert_eq!(b.get_bit(&0), true);
            b.set_bit(&0, &true);
        }
    }

    #[test]
    fn test_bitfield_rlp_serialization() {
        let mut b = BooleanBitfield::new();
        b.set_bit(&15, &true);
        let e = rlp::encode(&b);
        assert_eq!(e[0], 130);
        assert_eq!(e[1], 128);
        assert_eq!(e[2], 0);
    }
}
<commit_msg>Update bool_bitfield tests<commit_after>/*
 * Implemenation of a bitfield as a vec. Only
 * supports bytes (Vec<u8>) as the underlying
 * storage.
 *
 * A future implementation should be more efficient,
 * this is just to get the job done for now.
 */
extern crate rlp;
use self::rlp::{ RlpStream, Encodable };

pub struct BooleanBitfield{
    vec: Vec<u8>
}

impl BooleanBitfield {
    pub fn new() -> Self {
        Self {
            vec: vec![]
        }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            vec: Vec::with_capacity(capacity)
        }
    }

    // Output the bitfield as a big-endian vec of u8
    pub fn to_be_vec(&self) -> Vec<u8> {
        let mut o = self.vec.clone();
        o.reverse();
        o
    }

    pub fn get_bit(&self, i: &usize) -> bool {
        self.get_bit_on_byte(*i % 8, *i / 8)
    }

    fn get_bit_on_byte(&self, bit: usize, byte: usize) -> bool {
        assert!(bit < 8);
        if byte >= self.vec.len() {
            false
        } else {
             self.vec[byte] & (1 << (bit as u8)) != 0
        }
    }

    pub fn set_bit(&mut self, bit: &usize, to: &bool) {
        self.set_bit_on_byte(*bit % 8, *bit / 8, to);
    }

    fn set_bit_on_byte(&mut self, bit: usize, byte: usize, val: &bool) {
        assert!(bit < 8);
        if byte >= self.vec.len() {
            self.vec.resize(byte + 1, 0);
        }
        match val {
            true =>  self.vec[byte] = self.vec[byte] |  (1 << (bit as u8)),
            false => self.vec[byte] = self.vec[byte] & !(1 << (bit as u8))
        }
    }
}

impl Encodable for BooleanBitfield {
    // TODO: ensure this is a sensible method of encoding
    // the bitfield. Currently, it is treated as a list of
    // bytes not as a string. I do not have any guidance as
    // to which method is correct -- don't follow my lead
    // without seeking authoritative advice.
    fn rlp_append(&self, s: &mut RlpStream) {
        s.append(&self.to_be_vec());
    }
}

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

    #[test]
    fn test_bitfield_set() {
        let mut b = BooleanBitfield::new();
        b.set_bit(&0, &false);
        assert_eq!(b.to_be_vec(), [0]);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        assert_eq!(b.to_be_vec(), [128]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [0]);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        b.set_bit(&0, &true);
        assert_eq!(b.to_be_vec(), [129]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [1]);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        assert_eq!(b.to_be_vec(), [1, 0]);
        b.set_bit(&8, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);

        b = BooleanBitfield::new();
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [128, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [129, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [1, 0]);
    }

    #[test]
    fn test_bitfield_get() {
        let test_nums = vec![0, 8, 15, 42, 1337];
        for i in test_nums {
            let mut b = BooleanBitfield::new();
            assert_eq!(b.get_bit(&i), false);
            b.set_bit(&i, &true);
            assert_eq!(b.get_bit(&i), true);
            b.set_bit(&i, &true);
        }
    }

    #[test]
    fn test_bitfield_rlp_serialization() {
        let mut b = BooleanBitfield::new();
        b.set_bit(&15, &true);
        let e = rlp::encode(&b);
        assert_eq!(e[0], 130);
        assert_eq!(e[1], 128);
        assert_eq!(e[2], 0);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::{stderr, Write};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

extern crate clap;
use clap::{App, Arg};

extern crate mio;
use mio::{EventLoop, EventSet, Handler, Token};
use mio::tcp::{TcpListener, TcpStream};

extern crate time;

const SERVER: Token = Token(0);

struct EchoHandler {
    connections: BTreeMap<usize, TcpStream>,
    listener: TcpListener,
    next_token: usize,
}

impl EchoHandler {
    fn new(l: TcpListener) -> EchoHandler {
        EchoHandler {
            connections: BTreeMap::new(),
            listener: l,
            next_token: 1
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
        {
            let conn = self.connections.get_mut(&token.as_usize()).unwrap();
            match write!(conn, "{}", time::now_utc().rfc822()) {
                Ok(_) => {
                    event_loop.deregister(conn).unwrap();
                    let addr = conn.peer_addr().unwrap();
                    write!(stderr(), "Sent the time to {} succesfully\n", addr);
                },
                Err(e) => {
                    write!(stderr(), "Error while writing: {}\n", e);
                }
            }
        }
        self.connections.remove(&token.as_usize()).unwrap();
    }
}

impl Handler for EchoHandler {
    type Message = ();
    type Timeout = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            SERVER => {
                let client = match self.listener.accept() {
                    // As per documentation, Ok(None) means WOULDBLOCK.
                    Ok(None) => return,
                    Ok(Some(c)) => {
                        let addr = c.peer_addr().unwrap();
                        write!(stderr(), "Succesful connection from {}\n", addr);
                        c
                    }
                    Err(e) => {
                        write!(stderr(), "Error while accepting: {}\n", e);
                        return;
                    }
                };

                event_loop.register(&client, Token(self.next_token));
                self.connections.insert(self.next_token, client);
                self.next_token += 1;
            }
            _  => {
                if events.is_writable() {
                    self.writable(event_loop, token);
                }
            }
        }
    }
}

fn main() {
    let matches = App::new("qotd")
        .author("Justinas Stankevicius")
        .arg(Arg::with_name("port").short("p").takes_value(true))
        .get_matches();

    let port = matches.value_of("port").unwrap_or("7")
        .parse::<u16>().ok().unwrap_or_else(|| {
            write!(stderr(), "An invalid port number supplied, defaulting to 7.\n");
            7
        });

    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let addr = SocketAddrV4::new(ip, port);
    let listener = TcpListener::bind(&SocketAddr::V4(addr)).unwrap();

    let mut event_loop = EventLoop::new().unwrap();
    event_loop.register(&listener, SERVER).unwrap();
    event_loop.run(&mut EchoHandler::new(listener)).unwrap();
}
<commit_msg>[daytime] Fix the name<commit_after>use std::collections::BTreeMap;
use std::io::{stderr, Write};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

extern crate clap;
use clap::{App, Arg};

extern crate mio;
use mio::{EventLoop, EventSet, Handler, Token};
use mio::tcp::{TcpListener, TcpStream};

extern crate time;

const SERVER: Token = Token(0);

struct EchoHandler {
    connections: BTreeMap<usize, TcpStream>,
    listener: TcpListener,
    next_token: usize,
}

impl EchoHandler {
    fn new(l: TcpListener) -> EchoHandler {
        EchoHandler {
            connections: BTreeMap::new(),
            listener: l,
            next_token: 1
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
        {
            let conn = self.connections.get_mut(&token.as_usize()).unwrap();
            match write!(conn, "{}", time::now_utc().rfc822()) {
                Ok(_) => {
                    event_loop.deregister(conn).unwrap();
                    let addr = conn.peer_addr().unwrap();
                    write!(stderr(), "Sent the time to {} succesfully\n", addr);
                },
                Err(e) => {
                    write!(stderr(), "Error while writing: {}\n", e);
                }
            }
        }
        self.connections.remove(&token.as_usize()).unwrap();
    }
}

impl Handler for EchoHandler {
    type Message = ();
    type Timeout = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            SERVER => {
                let client = match self.listener.accept() {
                    // As per documentation, Ok(None) means WOULDBLOCK.
                    Ok(None) => return,
                    Ok(Some(c)) => {
                        let addr = c.peer_addr().unwrap();
                        write!(stderr(), "Succesful connection from {}\n", addr);
                        c
                    }
                    Err(e) => {
                        write!(stderr(), "Error while accepting: {}\n", e);
                        return;
                    }
                };

                event_loop.register(&client, Token(self.next_token));
                self.connections.insert(self.next_token, client);
                self.next_token += 1;
            }
            _  => {
                if events.is_writable() {
                    self.writable(event_loop, token);
                }
            }
        }
    }
}

fn main() {
    let matches = App::new("daytime")
        .author("Justinas Stankevicius")
        .arg(Arg::with_name("port").short("p").takes_value(true))
        .get_matches();

    let port = matches.value_of("port").unwrap_or("7")
        .parse::<u16>().ok().unwrap_or_else(|| {
            write!(stderr(), "An invalid port number supplied, defaulting to 7.\n");
            7
        });

    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let addr = SocketAddrV4::new(ip, port);
    let listener = TcpListener::bind(&SocketAddr::V4(addr)).unwrap();

    let mut event_loop = EventLoop::new().unwrap();
    event_loop.register(&listener, SERVER).unwrap();
    event_loop.run(&mut EchoHandler::new(listener)).unwrap();
}
<|endoftext|>