<commit_before>//! The package provides a parser for the
//! [TGFF](http://ziyang.eecs.umich.edu/~dickrp/tgff/) (Task Graphs For Free)
//! format, which is a format for storing task graphs and accompanying data
//! used in scheduling and allocation research.

#![feature(macro_rules, if_let)]

use std::collections::HashMap;
use std::iter::Peekable;
use std::str::CharOffsets;

pub use content::Content;
pub use content::{Graph, Task, Arc, Deadline};
pub use content::{Table, Column};

mod content;

static READ_CAPACITY: uint = 20;

pub type Result<T> = std::result::Result<T, Error>;

pub struct Error {
    line: uint,
    message: String,
}

impl std::fmt::Show for Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "{} on line {}", self.message, self.line)
    }
}

pub struct Parser<'a> {
    line: uint,
    cursor: Peekable<(uint, char), CharOffsets<'a>>,
    content: Content,
}

macro_rules! raise(
    ($parser:expr, $($arg:tt)*) => (
        return Err(Error { line: $parser.line, message: format!($($arg)*) });
    );
)

macro_rules! some(
    ($parser:expr, $result:expr, $($arg:tt)*) => (
        match $result {
            Some(result) => result,
            None => raise!($parser, $($arg)*),
        }
    );
)

impl<'a> Parser<'a> {
    /// Create a new `Parser` for processing the content of a TGFF file
    /// generated by the `tgff` command-line utility and given in `input`.
    pub fn new(input: &'a str) -> Parser<'a> {
        Parser {
            line: 1,
            cursor: input.char_indices().peekable(),
            content: Content::new(),
        }
    }

    /// Perform parsing of the data passed to `new`.
    pub fn process<'a>(&'a mut self) -> Result<&'a Content> {
        loop {
            match self.peek() {
                Some('@') => try!(self.process_at()),
                Some(_) => raise!(self, "found an unknown statement"),
                None => return Ok(&self.content),
            }
        }
    }

    fn process_at(&mut self) -> Result<()> {
        self.next(); // @

        let name = try!(self.get_token());
        let number = try!(self.get_natural());

        if let Some('{') = self.peek() {
            self.process_block(name, number)
        } else {
            self.content.attributes.insert(name, number);
            Ok(())
        }
    }

    fn process_block(&mut self, name: String, id: uint) -> Result<()> {
        self.next(); // {
        self.skip_void();

        if let Some('#') = self.peek() {
            try!(self.process_table(name, id));
        } else {
            try!(self.process_graph(name, id));
        }

        if let Some('}') = self.peek() {
            self.next();
            return Ok(());
        }

        raise!(self, "cannot find the end of a block");
    }

    fn process_graph(&mut self, name: String, id: uint) -> Result<()> {
        let mut graph = Graph::new(name, id);

        loop {
            match self.read_token() {
                Some(ref token) => match token.as_slice() {
                    "TASK" => {
                        let id = try!(self.get_id());
                        try!(self.skip_str("TYPE"));
                        let kind = try!(self.get_natural());

                        graph.tasks.push(Task::new(id, kind));
                    },
                    "ARC" => {
                        let id = try!(self.get_id());
                        try!(self.skip_str("FROM"));
                        let from = try!(self.get_id());
                        try!(self.skip_str("TO"));
                        let to = try!(self.get_id());
                        try!(self.skip_str("TYPE"));
                        let kind = try!(self.get_natural());

                        graph.arcs.push(Arc::new(id, from, to, kind));
                    },
                    "HARD_DEADLINE" => {
                        let id = try!(self.get_id());
                        try!(self.skip_str("ON"));
                        let on = try!(self.get_id());
                        try!(self.skip_str("AT"));
                        let at = try!(self.get_natural());

                        graph.deadlines.push(Deadline::new(id, on, at));
                    },
                    _ => {
                        let value = try!(self.get_natural());

                        graph.attributes.insert(token.clone(), value);
                    },
                },
                None => break,
            }
        }

        self.content.graphs.push(graph);
        Ok(())
    }

    fn process_table(&mut self, name: String, id: uint) -> Result<()> {
        let mut table = Table::new(name, id);

        self.content.tables.push(table);
        Ok(())
    }

    fn skip(&mut self, accept: |uint, char| -> bool) -> uint {
        let mut count = 0;

        loop {
            match self.peek() {
                Some(c) => {
                    if !accept(count, c) { break; }
                    self.next();
                    count += 1;
                },
                None => break,
            }
        }

        count
    }

    #[inline]
    fn skip_void(&mut self) {
        self.skip(|_, c| c == ' ' || c == '\t' || c == '\n');
    }

    fn skip_str(&mut self, chars: &str) -> Result<()> {
        let len = chars.len();
        if self.skip(|i, c| i < len && c == chars.char_at(i)) != len {
            raise!(self, "expected `{}`", chars);
        }
        self.skip_void();
        Ok(())
    }

    fn read(&mut self, accept: |uint, char| -> bool) -> Option<String> {
        let mut result = std::string::String::with_capacity(READ_CAPACITY);
        let mut count = 0;

        loop {
            match self.peek() {
                Some(c) => {
                    if !accept(count, c) { break; }
                    result.push(c);
                    self.next();
                    count += 1;
                },
                None => break,
            }
        }

        if count == 0 {
            None
        } else {
            Some(result)
        }
    }

    fn read_token(&mut self) -> Option<String> {
        let result = self.read(|i, c| {
            match c {
                'A'...'Z' | 'a'...'z' if i == 0 => true,
                'A'...'Z' | 'a'...'z' | '_' | '0'...'9' if i > 0 => true,
                _ => false,
            }
        });
        self.skip_void();
        result
    }

    fn read_natural(&mut self) -> Option<uint> {
        let result = match self.read(|_, c| c >= '0' && c <= '9') {
            Some(ref number) => std::num::from_str_radix(number.as_slice(), 10),
            None => None,
        };
        self.skip_void();
        result
    }

    fn read_id(&mut self) -> Option<uint> {
        match self.read_token() {
            Some(ref token) => match token.as_slice().split('_').nth(1) {
                Some(id) => std::num::from_str_radix(id, 10),
                None => None,
            },
            None => None,
        }
    }

    fn get_token(&mut self) -> Result<String> {
        match self.read_token() {
            Some(token) => Ok(token),
            None => raise!(self, "expected a token"),
        }
    }

    fn get_natural(&mut self) -> Result<uint> {
        match self.read_natural() {
            Some(number) => Ok(number),
            None => raise!(self, "expected a natural number"),
        }
    }

    fn get_id(&mut self) -> Result<uint> {
        match self.read_id() {
            Some(id) => Ok(id),
            None => raise!(self, "expected an id"),
        }
    }

    #[inline]
    fn peek(&mut self) -> Option<char> {
        match self.cursor.peek() {
            Some(&(_, c)) => Some(c),
            None => None,
        }
    }
}

impl<'a> std::iter::Iterator<char> for Parser<'a> {
    fn next(&mut self) -> Option<char> {
        match self.cursor.next() {
            Some((_, '\n')) => {
                self.line += 1;
                Some('\n')
            },
            Some((_, c)) => Some(c),
            None => None,
        }
    }
}

#[cfg(test)]
mod tests {
    macro_rules! assert_ok(
        ($result: expr) => (
            if let Err(err) = $result {
                assert!(false, "{}", err);
            }
        );
    )

    macro_rules! assert_error(
        ($result: expr) => (
            if let Ok(_) = $result {
                assert!(false, "expected an error");
            }
        );
    )

    macro_rules! parser(
        ($input:expr) => (super::Parser::new($input));
    )

    #[test]
    fn process_at() {
        assert_ok!(parser!("@abc 12").process_at());
        assert_error!(parser!("@ ").process_at());
        assert_error!(parser!("@abc").process_at());
    }

    #[test]
    fn process_block() {
        assert_ok!(parser!("{}").process_block(String::from_str("life"), 42));
    }

    #[test]
    fn process_graph() {
        let mut parser = parser!("TASK t0_0\tTYPE 2   ");
        parser.process_graph(String::new(), 0);
        {
            let ref task = parser.content.graphs[0].tasks[0];
            assert_eq!(task.id, 0);
            assert_eq!(task.kind, 2);
        }

        parser = parser!("ARC a0_42 \tFROM t0_0  TO  t0_1 TYPE 35   ");
        parser.process_graph(String::new(), 0);
        {
            let ref arc = parser.content.graphs[0].arcs[0];
            assert_eq!(arc.id, 42);
            assert_eq!(arc.from, 0);
            assert_eq!(arc.to, 1);
            assert_eq!(arc.kind, 35);
        }

        parser = parser!("HARD_DEADLINE d0_9 ON t0_12 AT 1000   ");
        parser.process_graph(String::new(), 0);
        {
            let ref deadline = parser.content.graphs[0].deadlines[0];
            assert_eq!(deadline.id, 9);
            assert_eq!(deadline.on, 12);
            assert_eq!(deadline.at, 1000);
        }
    }

    #[test]
    fn process_table() {
    }

    #[test]
    fn skip_void() {
        let mut parser = parser!("  \t  abc");
        parser.skip_void();
        assert_eq!(parser.next().unwrap(), 'a');
    }

    #[test]
    fn get_token() {
        macro_rules! test(
            ($input:expr, $output:expr) => (
                assert_eq!(parser!($input).get_token().unwrap(),
                           String::from_str($output));
            );
        )

        test!("AZ xyz", "AZ");
        test!("az xyz", "az");
        test!("AZ_az_09 xyz", "AZ_az_09");
    }

    #[test]
    fn get_natural() {
        assert_eq!(parser!("09").get_natural().unwrap(), 9);
    }

    #[test]
    fn get_id() {
        assert_eq!(parser!("t0_42").get_id().unwrap(), 42);
    }
}
<commit_msg>Introduced skip_char<commit_after>//! The package provides a parser for the
//! [TGFF](http://ziyang.eecs.umich.edu/~dickrp/tgff/) (Task Graphs For Free)
//! format, which is a format for storing task graphs and accompanying data
//! used in scheduling and allocation research.

#![feature(macro_rules, if_let)]

use std::collections::HashMap;
use std::iter::Peekable;
use std::str::CharOffsets;

pub use content::Content;
pub use content::{Graph, Task, Arc, Deadline};
pub use content::{Table, Column};

mod content;

static READ_CAPACITY: uint = 20;

pub type Result<T> = std::result::Result<T, Error>;

pub struct Error {
    line: uint,
    message: String,
}

impl std::fmt::Show for Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "{} on line {}", self.message, self.line)
    }
}

pub struct Parser<'a> {
    line: uint,
    cursor: Peekable<(uint, char), CharOffsets<'a>>,
    content: Content,
}

macro_rules! raise(
    ($parser:expr, $($arg:tt)*) => (
        return Err(Error { line: $parser.line, message: format!($($arg)*) });
    );
)

macro_rules! some(
    ($parser:expr, $result:expr, $($arg:tt)*) => (
        match $result {
            Some(result) => result,
            None => raise!($parser, $($arg)*),
        }
    );
)

impl<'a> Parser<'a> {
    /// Create a new `Parser` for processing the content of a TGFF file
    /// generated by the `tgff` command-line utility and given in `input`.
    pub fn new(input: &'a str) -> Parser<'a> {
        Parser {
            line: 1,
            cursor: input.char_indices().peekable(),
            content: Content::new(),
        }
    }

    /// Perform parsing of the data passed to `new`.
    pub fn process<'a>(&'a mut self) -> Result<&'a Content> {
        loop {
            match self.peek() {
                Some('@') => try!(self.process_at()),
                Some(_) => raise!(self, "found an unknown statement"),
                None => return Ok(&self.content),
            }
        }
    }

    fn process_at(&mut self) -> Result<()> {
        try!(self.skip_char('@'));

        let name = try!(self.get_token());
        let number = try!(self.get_natural());

        if let Some('{') = self.peek() {
            self.process_block(name, number)
        } else {
            self.content.attributes.insert(name, number);
            Ok(())
        }
    }

    fn process_block(&mut self, name: String, id: uint) -> Result<()> {
        try!(self.skip_char('{'));

        if let Some('#') = self.peek() {
            try!(self.process_table(name, id));
        } else {
            try!(self.process_graph(name, id));
        }

        if let Some('}') = self.peek() {
            self.next();
            return Ok(());
        }

        raise!(self, "cannot find the end of a block");
    }

    fn process_graph(&mut self, name: String, id: uint) -> Result<()> {
        let mut graph = Graph::new(name, id);

        loop {
            match self.read_token() {
                Some(ref token) => match token.as_slice() {
                    "TASK" => {
                        let id = try!(self.get_id());
                        try!(self.skip_str("TYPE"));
                        let kind = try!(self.get_natural());
                        graph.tasks.push(Task::new(id, kind));
                    },
                    "ARC" => {
                        let id = try!(self.get_id());
                        try!(self.skip_str("FROM"));
                        let from = try!(self.get_id());
                        try!(self.skip_str("TO"));
                        let to = try!(self.get_id());
                        try!(self.skip_str("TYPE"));
                        let kind = try!(self.get_natural());
                        graph.arcs.push(Arc::new(id, from, to, kind));
                    },
                    "HARD_DEADLINE" => {
                        let id = try!(self.get_id());
                        try!(self.skip_str("ON"));
                        let on = try!(self.get_id());
                        try!(self.skip_str("AT"));
                        let at = try!(self.get_natural());
                        graph.deadlines.push(Deadline::new(id, on, at));
                    },
                    _ => {
                        let value = try!(self.get_natural());
                        graph.attributes.insert(token.clone(), value);
                    },
                },
                None => break,
            }
        }

        self.content.graphs.push(graph);
        Ok(())
    }

    fn process_table(&mut self, name: String, id: uint) -> Result<()> {
        let mut table = Table::new(name, id);

        self.content.tables.push(table);
        Ok(())
    }

    fn skip(&mut self, accept: |uint, char| -> bool) -> uint {
        let mut count = 0;

        loop {
            match self.peek() {
                Some(c) => {
                    if !accept(count, c) { break; }
                    self.next();
                    count += 1;
                },
                None => break,
            }
        }

        count
    }

    fn skip_char(&mut self, expected: char) -> Result<()> {
        match self.next() {
            Some(c) => {
                if c == expected {
                    self.skip_void();
                    return Ok(());
                }
            },
            None => {},
        }
        raise!(self, "expected `{}`", expected);
    }

    fn skip_str(&mut self, expected: &str) -> Result<()> {
        let len = expected.len();
        if self.skip(|i, c| i < len && c == expected.char_at(i)) != len {
            raise!(self, "expected `{}`", expected);
        }
        self.skip_void();
        Ok(())
    }

    #[inline]
    fn skip_void(&mut self) {
        self.skip(|_, c| c == ' ' || c == '\t' || c == '\n');
    }

    fn read(&mut self, accept: |uint, char| -> bool) -> Option<String> {
        let mut result = std::string::String::with_capacity(READ_CAPACITY);
        let mut count = 0;

        loop {
            match self.peek() {
                Some(c) => {
                    if !accept(count, c) { break; }
                    result.push(c);
                    self.next();
                    count += 1;
                },
                None => break,
            }
        }

        if count == 0 {
            None
        } else {
            Some(result)
        }
    }

    fn read_token(&mut self) -> Option<String> {
        let result = self.read(|i, c| {
            match c {
                'A'...'Z' | 'a'...'z' if i == 0 => true,
                'A'...'Z' | 'a'...'z' | '_' | '0'...'9' if i > 0 => true,
                _ => false,
            }
        });
        self.skip_void();
        result
    }

    fn read_natural(&mut self) -> Option<uint> {
        let result = match self.read(|_, c| c >= '0' && c <= '9') {
            Some(ref number) => std::num::from_str_radix(number.as_slice(), 10),
            None => None,
        };
        self.skip_void();
        result
    }

    fn read_id(&mut self) -> Option<uint> {
        match self.read_token() {
            Some(ref token) => match token.as_slice().split('_').nth(1) {
                Some(id) => std::num::from_str_radix(id, 10),
                None => None,
            },
            None => None,
        }
    }

    fn get_token(&mut self) -> Result<String> {
        match self.read_token() {
            Some(token) => Ok(token),
            None => raise!(self, "expected a token"),
        }
    }

    fn get_natural(&mut self) -> Result<uint> {
        match self.read_natural() {
            Some(number) => Ok(number),
            None => raise!(self, "expected a natural number"),
        }
    }

    fn get_id(&mut self) -> Result<uint> {
        match self.read_id() {
            Some(id) => Ok(id),
            None => raise!(self, "expected an id"),
        }
    }

    #[inline]
    fn peek(&mut self) -> Option<char> {
        match self.cursor.peek() {
            Some(&(_, c)) => Some(c),
            None => None,
        }
    }
}

impl<'a> std::iter::Iterator<char> for Parser<'a> {
    fn next(&mut self) -> Option<char> {
        match self.cursor.next() {
            Some((_, '\n')) => {
                self.line += 1;
                Some('\n')
            },
            Some((_, c)) => Some(c),
            None => None,
        }
    }
}

#[cfg(test)]
mod tests {
    macro_rules! assert_ok(
        ($result: expr) => (
            if let Err(err) = $result {
                assert!(false, "{}", err);
            }
        );
    )

    macro_rules! assert_error(
        ($result: expr) => (
            if let Ok(_) = $result {
                assert!(false, "expected an error");
            }
        );
    )

    macro_rules! parser(
        ($input:expr) => (super::Parser::new($input));
    )

    #[test]
    fn process_at() {
        assert_ok!(parser!("@abc 12").process_at());
        assert_error!(parser!("@ ").process_at());
        assert_error!(parser!("@abc").process_at());
    }

    #[test]
    fn process_block() {
        assert_ok!(parser!("{}").process_block(String::new(), 0));
    }

    #[test]
    fn process_graph() {
        let mut parser = parser!("TASK t0_0\tTYPE 2   ");
        parser.process_graph(String::new(), 0);
        {
            let ref task = parser.content.graphs[0].tasks[0];
            assert_eq!(task.id, 0);
            assert_eq!(task.kind, 2);
        }

        parser = parser!("ARC a0_42 \tFROM t0_0  TO  t0_1 TYPE 35   ");
        parser.process_graph(String::new(), 0);
        {
            let ref arc = parser.content.graphs[0].arcs[0];
            assert_eq!(arc.id, 42);
            assert_eq!(arc.from, 0);
            assert_eq!(arc.to, 1);
            assert_eq!(arc.kind, 35);
        }

        parser = parser!("HARD_DEADLINE d0_9 ON t0_12 AT 1000   ");
        parser.process_graph(String::new(), 0);
        {
            let ref deadline = parser.content.graphs[0].deadlines[0];
            assert_eq!(deadline.id, 9);
            assert_eq!(deadline.on, 12);
            assert_eq!(deadline.at, 1000);
        }
    }

    #[test]
    fn process_table() {
        let mut parser = parser!("#        price\n       70.1121");
        parser.process_table(String::new(), 0);
        {
            let ref table = parser.content.tables[0];
            assert_eq!(table.attributes["price".to_string()], 70.1121);
        }
    }

    #[test]
    fn skip_char() {
        let mut parser = parser!("#  \t\n  abc");
        assert_ok!(parser.skip_char('#'));
        assert_eq!(parser.next().unwrap(), 'a');
    }

    #[test]
    fn skip_str() {
        let mut parser = parser!("abc  \t\n  xyz");
        assert_ok!(parser.skip_str("abc"));
        assert_eq!(parser.next().unwrap(), 'x');
    }

    #[test]
    fn skip_void() {
        let mut parser = parser!("  \t  abc");
        parser.skip_void();
        assert_eq!(parser.next().unwrap(), 'a');
    }

    #[test]
    fn get_token() {
        macro_rules! test(
            ($input:expr, $output:expr) => (
                assert_eq!(parser!($input).get_token().unwrap(),
                           String::from_str($output));
            );
        )

        test!("AZ xyz", "AZ");
        test!("az xyz", "az");
        test!("AZ_az_09 xyz", "AZ_az_09");
    }

    #[test]
    fn get_natural() {
        assert_eq!(parser!("09").get_natural().unwrap(), 9);
    }

    #[test]
    fn get_id() {
        assert_eq!(parser!("t0_42").get_id().unwrap(), 42);
    }
}
<|endoftext|>


<commit_before>/*! The main Fastnet module.

This is the low-level API.  If your goal is extremely high-performance usage, this is the API you want.  See the blocking module for a simpler API which is less annoying for common use cases.*/
#![allow(warnings)]

extern crate byteorder;
extern crate mio;
extern crate crc;

mod packets;
mod server;
mod status_translator;

use std::{result, io, net};

///Represents a Fastnet error.
#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
enum Error {
    TimedOut,
    HostNotFound,
    PeerNotFound,
    MessageTooLarge,
}

type Result<T> = result::Result<T, Error>;

/**A Fastnet server.

Fastnet does not distinguish between clients and servers.  This is used both for connecting to other peers and listening for incoming connections.*/
struct Server<H: Handler> {
    handler: H,
}

impl<H: Handler> Server<H> {
    pub fn new(addr: net::SocketAddr, handler: H)->Result<Server<H>> {
        Ok(Server {
            handler: handler,
        })
    }
}

/**An event handler.

The methods in this trait are called in a thread which is running in the background, not on the main thread.  None of them should ever block.*/
pub trait Handler {
    fn connected(&mut self, id: u64, request_id: Option<u64>);
    fn disconnected(&mut self, id: u64, request_id: Option<u64>);
    fn message(&mut self, id: u64, channel: u16, payload: &[u8]);
}
<commit_msg>More public API.<commit_after>/*! The main Fastnet module.

This is the low-level API.  If your goal is extremely high-performance usage, this is the API you want.  See the blocking module for a simpler API which is less annoying for common use cases.*/
#![allow(warnings)]

extern crate byteorder;
extern crate mio;
extern crate crc;

mod packets;
mod server;
mod status_translator;

use std::{result, io, net};

///Represents a Fastnet error.
#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub enum Error {
    TimedOut,
    HostNotFound,
    PeerNotFound,
    MessageTooLarge,
}

pub type Result<T> = result::Result<T, Error>;

/**A Fastnet server.

Fastnet does not distinguish between clients and servers.  This is used both for connecting to other peers and listening for incoming connections.*/
#[derive(Default)]
pub struct Server;

impl Server {
    pub fn new<H: Handler>(addr: net::SocketAddr, handler: H)->Result<Server> {
        Ok(Server::default())
    }
}

/**An event handler.

The methods in this trait are called in a thread which is running in the background, not on the main thread.  None of them should ever block.*/
pub trait Handler {
    fn connected(&mut self, id: u64, request_id: Option<u64>);
    fn disconnected(&mut self, id: u64, request_id: Option<u64>);
    fn message(&mut self, id: u64, channel: u16, payload: &[u8]);
    fn request_failed(&mut self, request_id: u64, error: Error);
}
<|endoftext|>


<commit_before><commit_msg>an empy message<commit_after><|endoftext|>


<commit_before><commit_msg> removed filter for testing<commit_after><|endoftext|>


<commit_before>use layout::{AnonymousBlock, BlockNode, InlineNode, LayoutBox, Rect};
use css::{ColorValue, Color};
use std::iter::range;
use std::cmp::{max, min};

/// Paint a tree of LayoutBoxes to an array of pixels.
pub fn paint(layout_root: &LayoutBox, bounds: Rect) -> Canvas {
    let display_list = build_display_list(layout_root);
    let mut canvas = Canvas::new(bounds.width as uint, bounds.height as uint);
    for item in display_list.iter() {
        canvas.paint_item(item);
    }
    return canvas;
}

#[deriving(Show)]
enum DisplayItem {
    SolidColor(Color, Rect),
}

type DisplayList = Vec<DisplayItem>;

pub fn build_display_list(layout_root: &LayoutBox) -> DisplayList {
    let mut list = Vec::new();
    render_layout_box(&mut list, layout_root);
    return list;
}

fn render_layout_box(list: &mut DisplayList, layout_box: &LayoutBox) {
    render_background(list, layout_box);
    render_borders(list, layout_box);
    for child in layout_box.children.iter() {
        render_layout_box(list, child);
    }
}

fn render_background(list: &mut DisplayList, layout_box: &LayoutBox) {
    get_color(layout_box, "background").map(|color|
        list.push(SolidColor(color, layout_box.dimensions.padding_box())));
}

fn render_borders(list: &mut DisplayList, layout_box: &LayoutBox) {
    let color = match get_color(layout_box, "border-color") {
        Some(color) => color,
        _ => return
    };

    let d = &layout_box.dimensions;
    let border_box = d.border_box();

    // Left border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: d.border.left,
        height: border_box.height,
    }));

    // Right border
    list.push(SolidColor(color, Rect {
        x: border_box.x + border_box.width - d.border.right,
        y: border_box.y,
        width: d.border.right,
        height: border_box.height,
    }));

    // Top border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: border_box.width,
        height: d.border.top,
    }));

    // Bottom border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y + border_box.height - d.border.bottom,
        width: border_box.width,
        height: d.border.bottom,
    }));
}

fn get_color(layout_box: &LayoutBox, name: &str) -> Option<Color> {
    match layout_box.box_type {
        BlockNode(style) | InlineNode(style) => match style.value(name) {
            Some(ColorValue(color)) => Some(color),
            _ => None
        },
        AnonymousBlock => None
    }
}

pub struct Canvas {
    pub pixels: Vec<Color>,
    pub width: uint,
    pub height: uint,
}

impl Canvas {
    fn new(width: uint, height: uint) -> Canvas {
        let white = Color { r: 255, g: 255, b: 255, a: 255 };
        return Canvas {
            pixels: Vec::from_elem(width * height, white),
            width: width,
            height: height,
        }
    }

    fn paint_item(&mut self, item: &DisplayItem) {
        match item {
            &SolidColor(color, rect) => {
                let x0 = max(0, rect.x as uint);
                let y0 = max(0, rect.y as uint);
                let x1 = min(self.width, (rect.x + rect.width) as uint);
                let y1 = min(self.height, (rect.y + rect.height) as uint);

                for x in range(x0, x1) {
                    for y in range(y0, y1) {
                        // TODO: alpha compositing with existing pixel
                        self.pixels[x + y * self.width] = color;
                    }
                }
            }
        }
    }
}
<commit_msg>Fix clipping calculation<commit_after>use layout::{AnonymousBlock, BlockNode, InlineNode, LayoutBox, Rect};
use css::{ColorValue, Color};
use std::iter::range;

/// Paint a tree of LayoutBoxes to an array of pixels.
pub fn paint(layout_root: &LayoutBox, bounds: Rect) -> Canvas {
    let display_list = build_display_list(layout_root);
    let mut canvas = Canvas::new(bounds.width as uint, bounds.height as uint);
    for item in display_list.iter() {
        canvas.paint_item(item);
    }
    return canvas;
}

#[deriving(Show)]
enum DisplayItem {
    SolidColor(Color, Rect),
}

type DisplayList = Vec<DisplayItem>;

pub fn build_display_list(layout_root: &LayoutBox) -> DisplayList {
    let mut list = Vec::new();
    render_layout_box(&mut list, layout_root);
    return list;
}

fn render_layout_box(list: &mut DisplayList, layout_box: &LayoutBox) {
    render_background(list, layout_box);
    render_borders(list, layout_box);
    for child in layout_box.children.iter() {
        render_layout_box(list, child);
    }
}

fn render_background(list: &mut DisplayList, layout_box: &LayoutBox) {
    get_color(layout_box, "background").map(|color|
        list.push(SolidColor(color, layout_box.dimensions.padding_box())));
}

fn render_borders(list: &mut DisplayList, layout_box: &LayoutBox) {
    let color = match get_color(layout_box, "border-color") {
        Some(color) => color,
        _ => return
    };

    let d = &layout_box.dimensions;
    let border_box = d.border_box();

    // Left border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: d.border.left,
        height: border_box.height,
    }));

    // Right border
    list.push(SolidColor(color, Rect {
        x: border_box.x + border_box.width - d.border.right,
        y: border_box.y,
        width: d.border.right,
        height: border_box.height,
    }));

    // Top border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: border_box.width,
        height: d.border.top,
    }));

    // Bottom border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y + border_box.height - d.border.bottom,
        width: border_box.width,
        height: d.border.bottom,
    }));
}

fn get_color(layout_box: &LayoutBox, name: &str) -> Option<Color> {
    match layout_box.box_type {
        BlockNode(style) | InlineNode(style) => match style.value(name) {
            Some(ColorValue(color)) => Some(color),
            _ => None
        },
        AnonymousBlock => None
    }
}

pub struct Canvas {
    pub pixels: Vec<Color>,
    pub width: uint,
    pub height: uint,
}

impl Canvas {
    fn new(width: uint, height: uint) -> Canvas {
        let white = Color { r: 255, g: 255, b: 255, a: 255 };
        return Canvas {
            pixels: Vec::from_elem(width * height, white),
            width: width,
            height: height,
        }
    }

    fn paint_item(&mut self, item: &DisplayItem) {
        match item {
            &SolidColor(color, rect) => {
                // Clip the rectangle to the canvas boundaries.
                let x0 = rect.x.max(0.0) as uint;
                let y0 = rect.y.max(0.0) as uint;
                let x1 = (rect.x + rect.width).min(self.width as f32) as uint;
                let y1 = (rect.y + rect.height).min(self.height as f32) as uint;

                for x in range(x0, x1) {
                    for y in range(y0, y1) {
                        // TODO: alpha compositing with existing pixel
                        self.pixels[x + y * self.width] = color;
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Empty argument slice now results in empty command (#335)<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed a fix<commit_after><|endoftext|>


<commit_before>use std::io::{IoResult, File};
use std::io::util::copy;
use std::path::BytesContainer;
use http;
use time;
use mimes::get_media_type;

///A container for the response
pub struct Response<'a, 'b> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

impl<'a, 'b> Response<'a, 'b> {

    pub fn from_internal<'c, 'd>(response: &'c mut http::server::ResponseWriter<'d>) -> Response<'c, 'd> {
        Response {
            origin: response
        }
    }

    /// Writes a response
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.send("hello world");
    /// ```
    pub fn send<T: BytesContainer> (&mut self, text: T) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.container_as_bytes());
    }

    /// sets the content type by it's short form.
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.set_content_type("html");
    /// ```
    pub fn set_content_type(&mut self, text: &str) {
        // TODO: make this a chaining API. (Fight the lifetime hell!)
        self.origin.headers.content_type = get_media_type(text);
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        response_writer.headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        response_writer.headers.content_length = None;
        response_writer.headers.content_type = response_writer.headers.content_type
                                                                      .clone()
                                                                      .or(get_media_type("txt"));

        response_writer.headers.server = Some(String::from_str("Nickel"));
    }

    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str().and_then(get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<commit_msg>fix(response): adjust to new lifetime rules<commit_after>use std::io::{IoResult, File};
use std::io::util::copy;
use std::path::BytesContainer;
use http;
use time;
use mimes::get_media_type;

///A container for the response
pub struct Response<'a, 'b: 'a> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

impl<'a, 'b> Response<'a, 'b> {

    pub fn from_internal<'c, 'd>(response: &'c mut http::server::ResponseWriter<'d>) -> Response<'c, 'd> {
        Response {
            origin: response
        }
    }

    /// Writes a response
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.send("hello world");
    /// ```
    pub fn send<T: BytesContainer> (&mut self, text: T) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.container_as_bytes());
    }

    /// sets the content type by it's short form.
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.set_content_type("html");
    /// ```
    pub fn set_content_type(&mut self, text: &str) {
        // TODO: make this a chaining API. (Fight the lifetime hell!)
        self.origin.headers.content_type = get_media_type(text);
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        response_writer.headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        response_writer.headers.content_length = None;
        response_writer.headers.content_type = response_writer.headers.content_type
                                                                      .clone()
                                                                      .or(get_media_type("txt"));

        response_writer.headers.server = Some(String::from_str("Nickel"));
    }

    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str().and_then(get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "alloc_system"]
#![crate_type = "rlib"]
#![staged_api]
#![no_std]
#![cfg_attr(not(stage0), allocator)]
#![unstable(feature = "alloc_system",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![feature(allocator)]
#![feature(libc)]
#![feature(no_std)]
#![feature(staged_api)]

extern crate libc;

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(all(any(target_arch = "arm",
              target_arch = "mips",
              target_arch = "mipsel",
              target_arch = "powerpc")))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "aarch64")))]
const MIN_ALIGN: usize = 16;

#[no_mangle]
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
    unsafe { imp::allocate(size, align) }
}

#[no_mangle]
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
    unsafe { imp::deallocate(ptr, old_size, align) }
}

#[no_mangle]
pub extern "C" fn __rust_reallocate(ptr: *mut u8,
                                    old_size: usize,
                                    size: usize,
                                    align: usize)
                                    -> *mut u8 {
    unsafe { imp::reallocate(ptr, old_size, size, align) }
}

#[no_mangle]
pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
                                            old_size: usize,
                                            size: usize,
                                            align: usize)
                                            -> usize {
    unsafe { imp::reallocate_inplace(ptr, old_size, size, align) }
}

#[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
    imp::usable_size(size, align)
}

#[cfg(unix)]
mod imp {
    use core::cmp;
    use core::ptr;
    use libc;
    use MIN_ALIGN;

    extern {
        // Apparently android doesn't have posix_memalign
        #[cfg(target_os = "android")]
        fn memalign(align: libc::size_t, size: libc::size_t) -> *mut libc::c_void;

        #[cfg(not(target_os = "android"))]
        fn posix_memalign(memptr: *mut *mut libc::c_void,
                          align: libc::size_t,
                          size: libc::size_t)
                          -> libc::c_int;
    }

    pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::malloc(size as libc::size_t) as *mut u8
        } else {
            #[cfg(target_os = "android")]
            unsafe fn more_aligned_malloc(size: usize, align: usize) -> *mut u8 {
                memalign(align as libc::size_t, size as libc::size_t) as *mut u8
            }
            #[cfg(not(target_os = "android"))]
            unsafe fn more_aligned_malloc(size: usize, align: usize) -> *mut u8 {
                let mut out = ptr::null_mut();
                let ret = posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
                if ret != 0 {
                    ptr::null_mut()
                } else {
                    out as *mut u8
                }
            }
            more_aligned_malloc(size, align)
        }
    }

    pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
        if align <= MIN_ALIGN {
            libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
        } else {
            let new_ptr = allocate(size, align);
            ptr::copy(ptr, new_ptr, cmp::min(size, old_size));
            deallocate(ptr, old_size, align);
            new_ptr
        }
    }

    pub unsafe fn reallocate_inplace(_ptr: *mut u8,
                                     old_size: usize,
                                     _size: usize,
                                     _align: usize)
                                     -> usize {
        old_size
    }

    pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
        libc::free(ptr as *mut libc::c_void)
    }

    pub fn usable_size(size: usize, _align: usize) -> usize {
        size
    }
}

#[cfg(windows)]
mod imp {
    use libc::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T};
    use MIN_ALIGN;

    extern "system" {
        fn GetProcessHeap() -> HANDLE;
        fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
        fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
        fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
    }

    #[repr(C)]
    struct Header(*mut u8);

    const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;

    unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
        &mut *(ptr as *mut Header).offset(-1)
    }

    unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
        let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize);
        *get_header(aligned) = Header(ptr);
        aligned
    }

    pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
        if align <= MIN_ALIGN {
            HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
        } else {
            let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
            if ptr.is_null() {
                return ptr
            }
            align_ptr(ptr, align)
        }
    }

    pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
        if align <= MIN_ALIGN {
            HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8
        } else {
            let header = get_header(ptr);
            let new = HeapReAlloc(GetProcessHeap(),
                                  0,
                                  header.0 as LPVOID,
                                  (size + align) as SIZE_T) as *mut u8;
            if new.is_null() {
                return new
            }
            align_ptr(new, align)
        }
    }

    pub unsafe fn reallocate_inplace(ptr: *mut u8,
                                     old_size: usize,
                                     size: usize,
                                     align: usize)
                                     -> usize {
        if align <= MIN_ALIGN {
            let new = HeapReAlloc(GetProcessHeap(),
                                  HEAP_REALLOC_IN_PLACE_ONLY,
                                  ptr as LPVOID,
                                  size as SIZE_T) as *mut u8;
            if new.is_null() {
                old_size
            } else {
                size
            }
        } else {
            old_size
        }
    }

    pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) {
        if align <= MIN_ALIGN {
            let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
            debug_assert!(err != 0);
        } else {
            let header = get_header(ptr);
            let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
            debug_assert!(err != 0);
        }
    }

    pub fn usable_size(size: usize, _align: usize) -> usize {
        size
    }
}
<commit_msg>Patch liballoc system<commit_after>// Copyright 2015 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.

#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "alloc_system"]
#![crate_type = "rlib"]
#![staged_api]
#![no_std]
#![cfg_attr(not(stage0), allocator)]
#![unstable(feature = "alloc_system",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![feature(allocator)]
#![feature(asm)]
#![feature(libc)]
#![feature(no_std)]
#![feature(staged_api)]

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
// constant at the call site and the branch will be optimized out.
#[cfg(all(any(target_arch = "arm",
              target_arch = "mips",
              target_arch = "mipsel",
              target_arch = "powerpc")))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "aarch64")))]
const MIN_ALIGN: usize = 16;

extern {
    fn memmove(dst: *mut u8, src: *const u8, size: usize);
    fn __rust_allocate(size: usize, align: usize) -> *mut u8;
    fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
    fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
    fn __rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> usize;
    fn __rust_usable_size(size: usize, align: usize) -> usize;
 }

<|endoftext|>


<commit_before><commit_msg>Added rust.<commit_after>
// Calculate the n^th Fibonacci number.
fn fib(n: u32) -> u32 {
  if n < 2 {
    return n;
  } else {
    return fib(n - 1) + fib(n - 2);
  }
}

fn main() {
  let res = fib(20);
  println!("{}", res);
}
<|endoftext|>


<commit_before><commit_msg>More progress on second variant of zerosub<commit_after><|endoftext|>


<commit_before><commit_msg>tuple indexing added<commit_after><|endoftext|>


<commit_before><commit_msg>add gerrit-query example binary<commit_after>use std::path::PathBuf;

use futures::Future as _;
use log::error;
use structopt::StructOpt;
use tokio;

use gerritbot_gerrit as gerrit;

#[derive(StructOpt, Debug)]
struct Args {
    /// Gerrit username
    #[structopt(short = "u")]
    username: String,
    /// Gerrit hostname
    hostname: String,
    /// Gerrit SSH port
    #[structopt(short = "p", default_value = "29418")]
    port: u32,
    /// Path to SSH private key
    #[structopt(short = "i", parse(from_os_str))]
    private_key_path: PathBuf,
    /// Enable verbose output
    #[structopt(short = "v")]
    verbose: bool,
    query: String,
}

fn main() {
    let args = Args::from_args();
    stderrlog::new()
        .module(module_path!())
        .timestamp(stderrlog::Timestamp::Second)
        .verbosity(if args.verbose { 5 } else { 2 })
        .init()
        .unwrap();

    let connection = gerrit::GerritConnection::connect(
        format!("{}:{}", args.hostname, args.port),
        args.username,
        args.private_key_path,
    )
    .unwrap_or_else(|e| {
        error!("connection to gerrit failed: {}", e);
        std::process::exit(1);
    });

    let mut command_runner = gerrit::CommandRunner::new(connection).unwrap_or_else(|e| {
        error!("failed to create command runner: {}", e);
        std::process::exit(1);
    });

    tokio::run(
        command_runner
            .run_command(format!("gerrit query {}", args.query))
            .map_err(|e| error!("error running query: {}", e))
            .map(|output| println!("{}", output)),
    );
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

//
// Utilities.
//

// returns an infinite iterator of repeated applications of f to x,
// i.e. [x, f(x), f(f(x)), ...], as haskell iterate function.
fn iterate<'a, T>(x: T, f: |&T|: 'a -> T) -> Iterate<'a, T> {
    Iterate {f: f, next: x}
}
struct Iterate<'a, T> {
    f: |&T|: 'a -> T,
    next: T
}
impl<'a, T> Iterator<T> for Iterate<'a, T> {
    fn next(&mut self) -> Option<T> {
        let mut res = (self.f)(&self.next);
        std::mem::swap(&mut res, &mut self.next);
        Some(res)
    }
}

// a linked list using borrowed next.
enum List<'a, T> {
    Nil,
    Cons(T, &'a List<'a, T>)
}
struct ListIterator<'a, T> {
    cur: &'a List<'a, T>
}
impl<'a, T> List<'a, T> {
    fn iter(&'a self) -> ListIterator<'a, T> {
        ListIterator{cur: self}
    }
}
impl<'a, T> Iterator<&'a T> for ListIterator<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        match *self.cur {
            Nil => None,
            Cons(ref elt, next) => {
                self.cur = next;
                Some(elt)
            }
        }
    }
}

//
// preprocess
//

// Takes a pieces p on the form [(y1, x1), (y2, x2), ...] and returns
// every possible transformations (the 6 rotations with their
// corresponding mirrored piece), with, as minimum coordinates, (0,
// 0).  If all is false, only generate half of the possibilities (used
// to break the symetry of the board).
fn transform(piece: Vec<(int, int)> , all: bool) -> Vec<Vec<(int, int)>> {
    let mut res: Vec<Vec<(int, int)>> =
        // rotations
        iterate(piece, |rot| rot.iter().map(|&(y, x)| (x + y, -y)).collect())
        .take(if all {6} else {3})
        // mirror
        .flat_map(|cur_piece| {
            iterate(cur_piece, |mir| mir.iter().map(|&(y, x)| (x, y)).collect())
            .take(2)
        }).collect();

    // translating to (0, 0) as minimum coordinates.
    for cur_piece in res.mut_iter() {
        let (dy, dx) = *cur_piece.iter().min_by(|e| *e).unwrap();
        for &(ref mut y, ref mut x) in cur_piece.mut_iter() {
            *y -= dy; *x -= dx;
        }
    }

    res
}

// A mask is a piece somewere on the board.  It is represented as a
// u64: for i in the first 50 bits, m[i] = 1 if the cell at (i/5, i%5)
// is occuped.  m[50 + id] = 1 if the identifier of the piece is id.

// Takes a piece with minimum coordinate (0, 0) (as generated by
// transform).  Returns the corresponding mask if p translated by (dy,
// dx) is on the board.
fn mask(dy: int, dx: int, id: uint, p: &[(int, int)]) -> Option<u64> {
    let mut m = 1 << (50 + id);
    for &(y, x) in p.iter() {
        let x = x + dx + (y + (dy % 2)) / 2;
        if x < 0 || x > 4 {return None;}
        let y = y + dy;
        if y < 0 || y > 9 {return None;}
        m |= 1 << (y * 5 + x);
    }
    Some(m)
}

// Makes every possible masks.  masks[id][i] correspond to every
// possible masks for piece with identifier id with minimum coordinate
// (i/5, i%5).
fn make_masks() -> Vec<Vec<Vec<u64> > > {
    let pieces = vec!(
        vec!((0,0),(0,1),(0,2),(0,3),(1,3)),
        vec!((0,0),(0,2),(0,3),(1,0),(1,1)),
        vec!((0,0),(0,1),(0,2),(1,2),(2,1)),
        vec!((0,0),(0,1),(0,2),(1,1),(2,1)),
        vec!((0,0),(0,2),(1,0),(1,1),(2,1)),
        vec!((0,0),(0,1),(0,2),(1,1),(1,2)),
        vec!((0,0),(0,1),(1,1),(1,2),(2,1)),
        vec!((0,0),(0,1),(0,2),(1,0),(1,2)),
        vec!((0,0),(0,1),(0,2),(1,2),(1,3)),
        vec!((0,0),(0,1),(0,2),(0,3),(1,2)));
    let mut res = Vec::new();
    for (id, p) in pieces.move_iter().enumerate() {
        // To break the central symetry of the problem, every
        // transformation must be taken except for one piece (piece 3
        // here).
        let trans = transform(p, id != 3);
        let mut cur_piece = Vec::new();
        for dy in range(0, 10) {
            for dx in range(0, 5) {
                let masks =
                    trans.iter()
                    .filter_map(|t| mask(dy, dx, id, t.as_slice()))
                    .collect();
                cur_piece.push(masks);
            }
        }
        res.push(cur_piece);
    }
    res
}

// Check if all coordinates can be covered by an unused piece and that
// all unused piece can be placed on the board.
fn is_board_unfeasible(board: u64, masks: &[Vec<Vec<u64> > ]) -> bool {
    let mut coverable = board;
    for i in range(0, 50).filter(|&i| board & 1 << i == 0) {
        for (cur_id, pos_masks) in masks.iter().enumerate() {
            if board & 1 << (50 + cur_id) != 0 {continue;}
            for &cur_m in pos_masks.get(i as uint).iter() {
                if cur_m & board == 0 {coverable |= cur_m;}
            }
        }
        if coverable & (1 << i) == 0 {return true;}
    }
    // check if every coordinates can be covered and every piece can
    // be used.
    coverable != (1 << 60) - 1
}

// Filter the masks that we can prove to result to unfeasible board.
fn filter_masks(masks: &[Vec<Vec<u64> > ]) -> Vec<Vec<Vec<u64> > > {
    masks.iter().map(
        |p| p.iter().map(
            |p| p.iter()
                .map(|&m| m)
                .filter(|&m| !is_board_unfeasible(m, masks))
                .collect())
            .collect())
        .collect()
}

// Gets the identifier of a mask.
fn get_id(m: u64) -> u8 {
    for id in range(0, 10) {
        if m & (1 << (id + 50)) != 0 {return id as u8;}
    }
    fail!("{:016x} does not have a valid identifier", m);
}

// Converts a list of mask to a ~str.
fn to_utf8(raw_sol: &List<u64>) -> ~str {
    let mut sol: Vec<u8> = Vec::from_elem(50, '.' as u8);
    for &m in raw_sol.iter() {
        let id = get_id(m);
        for i in range(0, 50) {
            if m & 1 << i != 0 {
                *sol.get_mut(i as uint) = '0' as u8 + id;
            }
        }
    }
    std::str::from_utf8(sol.as_slice()).unwrap().to_owned()
}

// Prints a solution in ~str form.
fn print_sol(sol: &str) {
    for (i, c) in sol.chars().enumerate() {
        if (i) % 5 == 0 { println!(""); }
        if (i + 5) % 10 == 0 { print!(" "); }
        print!("{} ", c);
    }
    println!("");
}

// The data managed during the search
struct Data {
    // If more than stop_after is found, stop the search.
    stop_after: int,
    // Number of solution found.
    nb: int,
    // Lexicographically minimal solution found.
    min: ~str,
    // Lexicographically maximal solution found.
    max: ~str
}

// Records a new found solution.  Returns false if the search must be
// stopped.
fn handle_sol(raw_sol: &List<u64>, data: &mut Data) -> bool {
    // because we break the symetry, 2 solutions correspond to a call
    // to this method: the normal solution, and the same solution in
    // reverse order, i.e. the board rotated by half a turn.
    data.nb += 2;
    let sol1 = to_utf8(raw_sol);
    let sol2: ~str = sol1.chars().rev().collect();

    if data.nb == 2 {
        data.min = sol1.clone();
        data.max = sol1.clone();
    }

    if sol1 < data.min {data.min = sol1.clone();}
    if sol2 < data.min {data.min = sol2.clone();}
    if sol1 > data.max {data.max = sol1;}
    if sol2 > data.max {data.max = sol2;}
    data.nb < data.stop_after
}

// Search for every solutions.  Returns false if the search was
// stopped before the end.
fn search(
    masks: &[Vec<Vec<u64> > ],
    board: u64,
    mut i: int,
    cur: List<u64>,
    data: &mut Data)
    -> bool
{
    // Search for the lesser empty coordinate.
    while board & (1 << i)  != 0 && i < 50 {i += 1;}
    // the board is full: a solution is found.
    if i >= 50 {return handle_sol(&cur, data);}

    // for every unused piece
    for id in range(0, 10).filter(|id| board & (1 << (id + 50)) == 0) {
        // for each mask that fits on the board
        for &m in masks[id as uint].get(i as uint)
                                   .iter()
                                   .filter(|&m| board & *m == 0) {
            // This check is too costy.
            //if is_board_unfeasible(board | m, masks) {continue;}
            if !search(masks, board | m, i + 1, Cons(m, &cur), data) {
                return false;
            }
        }
    }
    return true;
}

fn main () {
    let args = std::os::args();
    let args = args.as_slice();
    let stop_after = if args.len() <= 1 {
        2098
    } else {
        from_str(args[1]).unwrap()
    };
    let masks = make_masks();
    let masks = filter_masks(masks.as_slice());
    let mut data = Data {stop_after: stop_after, nb: 0, min: "".to_owned(), max: "".to_owned()};
    search(masks.as_slice(), 0, 0, Nil, &mut data);
    println!("{} solutions found", data.nb);
    print_sol(data.min);
    print_sol(data.max);
    println!("");
}
<commit_msg>auto merge of #14063 : TeXitoi/rust/shootout-meteor-improvement, r=pcwalton<commit_after>// Copyright 2013-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.

#![feature(phase)]
#[phase(syntax)] extern crate green;
extern crate sync;

use sync::Arc;

green_start!(main)

//
// Utilities.
//

// returns an infinite iterator of repeated applications of f to x,
// i.e. [x, f(x), f(f(x)), ...], as haskell iterate function.
fn iterate<'a, T>(x: T, f: |&T|: 'a -> T) -> Iterate<'a, T> {
    Iterate {f: f, next: x}
}
struct Iterate<'a, T> {
    f: |&T|: 'a -> T,
    next: T
}
impl<'a, T> Iterator<T> for Iterate<'a, T> {
    fn next(&mut self) -> Option<T> {
        let mut res = (self.f)(&self.next);
        std::mem::swap(&mut res, &mut self.next);
        Some(res)
    }
}

// a linked list using borrowed next.
enum List<'a, T> {
    Nil,
    Cons(T, &'a List<'a, T>)
}
struct ListIterator<'a, T> {
    cur: &'a List<'a, T>
}
impl<'a, T> List<'a, T> {
    fn iter(&'a self) -> ListIterator<'a, T> {
        ListIterator{cur: self}
    }
}
impl<'a, T> Iterator<&'a T> for ListIterator<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        match *self.cur {
            Nil => None,
            Cons(ref elt, next) => {
                self.cur = next;
                Some(elt)
            }
        }
    }
}

//
// preprocess
//

// Takes a pieces p on the form [(y1, x1), (y2, x2), ...] and returns
// every possible transformations (the 6 rotations with their
// corresponding mirrored piece), with, as minimum coordinates, (0,
// 0).  If all is false, only generate half of the possibilities (used
// to break the symetry of the board).
fn transform(piece: Vec<(int, int)> , all: bool) -> Vec<Vec<(int, int)>> {
    let mut res: Vec<Vec<(int, int)>> =
        // rotations
        iterate(piece, |rot| rot.iter().map(|&(y, x)| (x + y, -y)).collect())
        .take(if all {6} else {3})
        // mirror
        .flat_map(|cur_piece| {
            iterate(cur_piece, |mir| mir.iter().map(|&(y, x)| (x, y)).collect())
            .take(2)
        }).collect();

    // translating to (0, 0) as minimum coordinates.
    for cur_piece in res.mut_iter() {
        let (dy, dx) = *cur_piece.iter().min_by(|e| *e).unwrap();
        for &(ref mut y, ref mut x) in cur_piece.mut_iter() {
            *y -= dy; *x -= dx;
        }
    }

    res
}

// A mask is a piece somewere on the board.  It is represented as a
// u64: for i in the first 50 bits, m[i] = 1 if the cell at (i/5, i%5)
// is occuped.  m[50 + id] = 1 if the identifier of the piece is id.

// Takes a piece with minimum coordinate (0, 0) (as generated by
// transform).  Returns the corresponding mask if p translated by (dy,
// dx) is on the board.
fn mask(dy: int, dx: int, id: uint, p: &Vec<(int, int)>) -> Option<u64> {
    let mut m = 1 << (50 + id);
    for &(y, x) in p.iter() {
        let x = x + dx + (y + (dy % 2)) / 2;
        if x < 0 || x > 4 {return None;}
        let y = y + dy;
        if y < 0 || y > 9 {return None;}
        m |= 1 << (y * 5 + x);
    }
    Some(m)
}

// Makes every possible masks.  masks[i][id] correspond to every
// possible masks for piece with identifier id with minimum coordinate
// (i/5, i%5).
fn make_masks() -> Vec<Vec<Vec<u64> > > {
    let pieces = vec!(
        vec!((0,0),(0,1),(0,2),(0,3),(1,3)),
        vec!((0,0),(0,2),(0,3),(1,0),(1,1)),
        vec!((0,0),(0,1),(0,2),(1,2),(2,1)),
        vec!((0,0),(0,1),(0,2),(1,1),(2,1)),
        vec!((0,0),(0,2),(1,0),(1,1),(2,1)),
        vec!((0,0),(0,1),(0,2),(1,1),(1,2)),
        vec!((0,0),(0,1),(1,1),(1,2),(2,1)),
        vec!((0,0),(0,1),(0,2),(1,0),(1,2)),
        vec!((0,0),(0,1),(0,2),(1,2),(1,3)),
        vec!((0,0),(0,1),(0,2),(0,3),(1,2)));

    // To break the central symetry of the problem, every
    // transformation must be taken except for one piece (piece 3
    // here).
    let transforms: Vec<Vec<Vec<(int, int)>>> =
        pieces.move_iter().enumerate()
        .map(|(id, p)| transform(p, id != 3))
        .collect();

    range(0, 50).map(|yx| {
        transforms.iter().enumerate().map(|(id, t)| {
            t.iter().filter_map(|p| mask(yx / 5, yx % 5, id, p)).collect()
        }).collect()
    }).collect()
}

// Check if all coordinates can be covered by an unused piece and that
// all unused piece can be placed on the board.
fn is_board_unfeasible(board: u64, masks: &Vec<Vec<Vec<u64>>>) -> bool {
    let mut coverable = board;
    for (i, masks_at) in masks.iter().enumerate() {
        if board & 1 << i != 0 { continue; }
        for (cur_id, pos_masks) in masks_at.iter().enumerate() {
            if board & 1 << (50 + cur_id) != 0 { continue; }
            for &cur_m in pos_masks.iter() {
                if cur_m & board != 0 { continue; }
                coverable |= cur_m;
                // if every coordinates can be covered and every
                // piece can be used.
                if coverable == (1 << 60) - 1 { return false; }
            }
        }
        if coverable & 1 << i == 0 { return true; }
    }
    true
}

// Filter the masks that we can prove to result to unfeasible board.
fn filter_masks(masks: &mut Vec<Vec<Vec<u64>>>) {
    for i in range(0, masks.len()) {
        for j in range(0, masks.get(i).len()) {
            *masks.get_mut(i).get_mut(j) =
                masks.get(i).get(j).iter().map(|&m| m)
                .filter(|&m| !is_board_unfeasible(m, masks))
                .collect();
        }
    }
}

// Gets the identifier of a mask.
fn get_id(m: u64) -> u8 {
    for id in range(0u8, 10) {
        if m & (1 << (id + 50)) != 0 {return id;}
    }
    fail!("{:016x} does not have a valid identifier", m);
}

// Converts a list of mask to a ~str.
fn to_vec(raw_sol: &List<u64>) -> Vec<u8> {
    let mut sol = Vec::from_elem(50, '.' as u8);
    for &m in raw_sol.iter() {
        let id = '0' as u8 + get_id(m);
        for i in range(0u, 50) {
            if m & 1 << i != 0 {
                *sol.get_mut(i) = id;
            }
        }
    }
    sol
}

// Prints a solution in ~str form.
fn print_sol(sol: &Vec<u8>) {
    for (i, c) in sol.iter().enumerate() {
        if (i) % 5 == 0 { println!(""); }
        if (i + 5) % 10 == 0 { print!(" "); }
        print!("{} ", *c as char);
    }
    println!("");
}

// The data managed during the search
struct Data {
    // Number of solution found.
    nb: int,
    // Lexicographically minimal solution found.
    min: Vec<u8>,
    // Lexicographically maximal solution found.
    max: Vec<u8>
}
impl Data {
    fn new() -> Data {
        Data {nb: 0, min: vec!(), max: vec!()}
    }
    fn reduce_from(&mut self, other: Data) {
        self.nb += other.nb;
        let Data { min: min, max: max, ..} = other;
        if min < self.min { self.min = min; }
        if max > self.max { self.max = max; }
    }
}

// Records a new found solution.  Returns false if the search must be
// stopped.
fn handle_sol(raw_sol: &List<u64>, data: &mut Data) {
    // because we break the symetry, 2 solutions correspond to a call
    // to this method: the normal solution, and the same solution in
    // reverse order, i.e. the board rotated by half a turn.
    data.nb += 2;
    let sol1 = to_vec(raw_sol);
    let sol2: Vec<u8> = sol1.iter().rev().map(|x| *x).collect();

    if data.nb == 2 {
        data.min = sol1.clone();
        data.max = sol1.clone();
    }

    if sol1 < data.min {data.min = sol1;}
    else if sol1 > data.max {data.max = sol1;}
    if sol2 < data.min {data.min = sol2;}
    else if sol2 > data.max {data.max = sol2;}
}

fn search(
    masks: &Vec<Vec<Vec<u64>>>,
    board: u64,
    mut i: uint,
    cur: List<u64>,
    data: &mut Data)
{
    // Search for the lesser empty coordinate.
    while board & (1 << i)  != 0 && i < 50 {i += 1;}
    // the board is full: a solution is found.
    if i >= 50 {return handle_sol(&cur, data);}
    let masks_at = masks.get(i);

    // for every unused piece
    for id in range(0u, 10).filter(|id| board & (1 << (id + 50)) == 0) {
        // for each mask that fits on the board
        for &m in masks_at.get(id).iter().filter(|&m| board & *m == 0) {
            // This check is too costy.
            //if is_board_unfeasible(board | m, masks) {continue;}
            search(masks, board | m, i + 1, Cons(m, &cur), data);
        }
    }
}

fn par_search(masks: Vec<Vec<Vec<u64>>>) -> Data {
    let masks = Arc::new(masks);
    let (tx, rx) = channel();

    // launching the search in parallel on every masks at minimum
    // coordinate (0,0)
    for &m in masks.get(0).iter().flat_map(|masks_pos| masks_pos.iter()) {
        let masks = masks.clone();
        let tx = tx.clone();
        spawn(proc() {
            let mut data = Data::new();
            search(&*masks, m, 1, Cons(m, &Nil), &mut data);
            tx.send(data);
        });
    }

    // collecting the results
    drop(tx);
    let mut data = rx.recv();
    for d in rx.iter() { data.reduce_from(d); }
    data
}

fn main () {
    let mut masks = make_masks();
    filter_masks(&mut masks);
    let data = par_search(masks);
    println!("{} solutions found", data.nb);
    print_sol(&data.min);
    print_sol(&data.max);
    println!("");
}
<|endoftext|>