<commit_before>use std::fmt;
use Command;

pub struct Grid {
    width: u32,
    height: u32,
    chars: Vec<char>,
}

pub enum ParseErr {
    PrematureLineEnd(u32, String, u32),
    BadTerminationChar(u32, String, char),
}

impl fmt::Show for ParseErr {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            PrematureLineEnd(h, ref s, width) =>
                write!(w, "line {} content {} ended prematurely; \
                           expected {} characters", h, s, width),
            BadTerminationChar(h, ref s, c) =>
                write!(w, "line {} expected end of input or line \
                           after {}, got {}", h, s, c),
        }
    }
}

impl Grid {
    pub fn new(width: u32, height: u32, background: char) -> Grid {
        let len = width * height;
        let chars = Vec::from_elem(len.to_uint().unwrap(), background);
        Grid { width: width, height: height, chars: chars }
    }

    pub fn to_string(&self) -> String {
        let len = self.height * (self.width + 1);
        let mut s = String::with_capacity(len.to_uint().unwrap());
        for y in range(0, self.height) {
            for x in range(0, self.width) {
                s.push(self.get(x, y));
            }
            s.push('\n');
        }
        s
    }

    pub fn from_str(s: &str) -> Result<Grid, ParseErr> {
        let mut w = 0u32;
        for c in s.chars() {
            if c == '\n' {
                break;
            } else {
                w += 1;
            }
        }

        let mut grid = vec![];
        let mut chars = s.chars();
        let mut h = 0;

        loop {
            h += 1;
            let row_start = grid.len();
            for i in range(0, w) {
                match (i, chars.next()) {
                    (0, None) => break,
                    (_, None) => {
                        let line = grid.slice_from(row_start).to_string();
                        return Err(PrematureLineEnd(h, line, w))
                    }
                    (_, Some(c)) => grid.push(c),
                }
            }
            match chars.next() {
                None => break,
                Some('\n') => continue,
                Some(c) => {
                    let line = grid.slice_from(row_start).to_string();
                    return Err(BadTerminationChar(h, line, c))
                }
            }
        }

        Ok(Grid { width: w, height: h, chars: grid })
    }

    pub fn get(&self, x: u32, y: u32) -> char {
        assert!(x < self.width);
        assert!(y < self.height);
        let idx = y * self.width + x;
        self.chars[idx.to_uint().unwrap()]
    }

    pub fn set(&mut self, x: u32, y: u32, c: char) {
        assert!(x < self.width);
        assert!(y < self.height);
        let idx = y * self.width + x;
        self.chars[idx.to_uint().unwrap()] = c;
    }

    pub fn exec(&mut self, command: &Command) {
        let Command { x, y, w, h, fill } = *command;

        if w == 1 || h == 1 {
            return self.draw_line(command);
        }

        self.set(x, y, '+');
        self.set(x, y+h-1, '+');
        self.set(x+w-1, y, '+');
        self.set(x+w-1, y+h-1, '+');

        for i in range(x + 1, x + w - 1) {
            self.set(i, y, '-');
            self.set(i, y + h - 1, '-');
        }

        for j in range(y + 1, y + h - 1) {
            self.set(x, j, '|');
            self.set(x + w - 1, j, '|');
        }

        for i in range(x+1, x + w - 1) {
            for j in range(y + 1, y + h - 1) {
                self.set(i, j, fill);
            }
        }
    }

    fn draw_line(&mut self, command: &Command) {
        assert!(command.w == 1 || command.h == 1);
        let Command { x, y, w, h, fill } = *command;
        for i in range(x, x+w) {
            for j in range(y, y+h) {
                self.set(i, j, fill);
            }
        }
    }
}
<commit_msg>Add Grid::width and Grid::height methods.<commit_after>use std::fmt;
use Command;

pub struct Grid {
    width: u32,
    height: u32,
    chars: Vec<char>,
}

pub enum ParseErr {
    PrematureLineEnd(u32, String, u32),
    BadTerminationChar(u32, String, char),
}

impl fmt::Show for ParseErr {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            PrematureLineEnd(h, ref s, width) =>
                write!(w, "line {} content {} ended prematurely; \
                           expected {} characters", h, s, width),
            BadTerminationChar(h, ref s, c) =>
                write!(w, "line {} expected end of input or line \
                           after {}, got {}", h, s, c),
        }
    }
}

impl Grid {
    pub fn new(width: u32, height: u32, background: char) -> Grid {
        let len = width * height;
        let chars = Vec::from_elem(len.to_uint().unwrap(), background);
        Grid { width: width, height: height, chars: chars }
    }

    pub fn to_string(&self) -> String {
        let len = self.height * (self.width + 1);
        let mut s = String::with_capacity(len.to_uint().unwrap());
        for y in range(0, self.height) {
            for x in range(0, self.width) {
                s.push(self.get(x, y));
            }
            s.push('\n');
        }
        s
    }

    pub fn from_str(s: &str) -> Result<Grid, ParseErr> {
        let mut w = 0u32;
        for c in s.chars() {
            if c == '\n' {
                break;
            } else {
                w += 1;
            }
        }

        let mut grid = vec![];
        let mut chars = s.chars();
        let mut h = 0;

        loop {
            h += 1;
            let row_start = grid.len();
            for i in range(0, w) {
                match (i, chars.next()) {
                    (0, None) => break,
                    (_, None) => {
                        let line = grid.slice_from(row_start).to_string();
                        return Err(PrematureLineEnd(h, line, w))
                    }
                    (_, Some(c)) => grid.push(c),
                }
            }
            match chars.next() {
                None => break,
                Some('\n') => continue,
                Some(c) => {
                    let line = grid.slice_from(row_start).to_string();
                    return Err(BadTerminationChar(h, line, c))
                }
            }
        }

        Ok(Grid { width: w, height: h, chars: grid })
    }

    pub fn width(&self) -> u32 { self.width }
    pub fn height(&self) -> u32 { self.height }

    pub fn get(&self, x: u32, y: u32) -> char {
        assert!(x < self.width);
        assert!(y < self.height);
        let idx = y * self.width + x;
        self.chars[idx.to_uint().unwrap()]
    }

    pub fn set(&mut self, x: u32, y: u32, c: char) {
        assert!(x < self.width);
        assert!(y < self.height);
        let idx = y * self.width + x;
        self.chars[idx.to_uint().unwrap()] = c;
    }

    pub fn exec(&mut self, command: &Command) {
        let Command { x, y, w, h, fill } = *command;

        if w == 1 || h == 1 {
            return self.draw_line(command);
        }

        self.set(x, y, '+');
        self.set(x, y+h-1, '+');
        self.set(x+w-1, y, '+');
        self.set(x+w-1, y+h-1, '+');

        for i in range(x + 1, x + w - 1) {
            self.set(i, y, '-');
            self.set(i, y + h - 1, '-');
        }

        for j in range(y + 1, y + h - 1) {
            self.set(x, j, '|');
            self.set(x + w - 1, j, '|');
        }

        for i in range(x+1, x + w - 1) {
            for j in range(y + 1, y + h - 1) {
                self.set(i, j, fill);
            }
        }
    }

    fn draw_line(&mut self, command: &Command) {
        assert!(command.w == 1 || command.h == 1);
        let Command { x, y, w, h, fill } = *command;
        for i in range(x, x+w) {
            for j in range(y, y+h) {
                self.set(i, j, fill);
            }
        }
    }
}
<|endoftext|>


<commit_before>use sha2::{HashFunction, MAX_DIGEST_SIZE, Sha384};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;

pub struct Hmac<T> {
    inner_hash_function: T,
    outer_hash_function: T,
}

pub fn hmac_sha384(key: &[u8], message: &[u8]) -> [u8; Sha384::DIGEST_SIZE] {
    let mut digest = [0; Sha384::DIGEST_SIZE];
    let mut hmac = Hmac::<Sha384>::new(key);
    hmac.update(message);
    hmac.write_digest(&mut digest);
    digest
}

impl<T: HashFunction> Hmac<T> {
    pub fn new(key: &[u8]) -> Self {
        let mut hashed_key;
        let new_key;
        if key.len() > T::BLOCK_SIZE {
            hashed_key = [0; MAX_DIGEST_SIZE];
            let mut hash_function = T::default();
            hash_function.update(key);
            hash_function.write_digest(&mut hashed_key[..T::DIGEST_SIZE]);
            new_key = &hashed_key[..T::DIGEST_SIZE];
        } else {
            new_key = key;
        }

        let mut hmac = Self {
            inner_hash_function: T::default(),
            outer_hash_function: T::default(),
        };
        for byte in new_key {
            hmac.inner_hash_function.update(&[byte ^ IPAD]);
            hmac.outer_hash_function.update(&[byte ^ OPAD]);
        }
        for _ in new_key.len()..T::BLOCK_SIZE {
            hmac.inner_hash_function.update(&[IPAD]);
            hmac.outer_hash_function.update(&[OPAD]);
        }
        hmac
    }

    pub fn update(&mut self, input: &[u8]) {
        self.inner_hash_function.update(input);
    }

    pub fn write_digest(mut self, output: &mut [u8]) {
        self.inner_hash_function.write_digest(output);
        self.outer_hash_function.update(output);
        self.outer_hash_function.write_digest(output);
    }
}

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

    fn check(expected: &str, key: &[u8], data: &[u8]) {
        let expected = h2b(expected);
        let mut actual = hmac_sha384(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha384>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());
    }

    #[test]
    fn test_digest() {
        let key = h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
        let data = b"Hi There";
        let mut expected = "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c\
                            faea9ea9076ede7f4af152e8b2fa9cb6";
        check(expected, &key, data);

        let key = b"Jefe";
        let data = b"what do ya want for nothing?";
        expected = "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e\
                    8e2240ca5e69e2c78b3239ecfab21649";
        check(expected, key, data);

        let key = [0xaa; 20];
        let mut data = [0xdd; 50];
        expected = "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b\
                    2a5ab39dc13814b94e3ab6e101a34f27";
        check(expected, &key, &data);

        let key: Vec<_> = (0x01..0x1a).collect();
        data = [0xcd; 50];
        expected = "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e\
                    6801dd23c4a7d679ccf8a386c674cffb";
        check(expected, &key, &data);

        let key = [0xaa; 131];
        let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
        expected = "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6\
                    0c2ef6ab4030fe8296248df163f44952";
        check(expected, &key, data);

        let data =
            b"This is a test using a larger than block-size key and a larger than block-\
              size data. The key needs to be hashed before being used by the HMAC algorithm.";
        expected = "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5\
                    a678cc31e799176d3860e6110c46523e";
        check(expected, &key, data);
    }
}
<commit_msg>hmac: add sha-512<commit_after>use sha2::{HashFunction, MAX_DIGEST_SIZE, Sha384, Sha512};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;

pub struct Hmac<T> {
    inner_hash_function: T,
    outer_hash_function: T,
}

pub fn hmac_sha512(key: &[u8], message: &[u8]) -> [u8; Sha512::DIGEST_SIZE] {
    let mut digest = [0; Sha512::DIGEST_SIZE];
    let mut hmac = Hmac::<Sha512>::new(key);
    hmac.update(message);
    hmac.write_digest(&mut digest);
    digest
}

pub fn hmac_sha384(key: &[u8], message: &[u8]) -> [u8; Sha384::DIGEST_SIZE] {
    let mut digest = [0; Sha384::DIGEST_SIZE];
    let mut hmac = Hmac::<Sha384>::new(key);
    hmac.update(message);
    hmac.write_digest(&mut digest);
    digest
}

impl<T: HashFunction> Hmac<T> {
    pub fn new(key: &[u8]) -> Self {
        let mut hashed_key;
        let new_key;
        if key.len() > T::BLOCK_SIZE {
            hashed_key = [0; MAX_DIGEST_SIZE];
            let mut hash_function = T::default();
            hash_function.update(key);
            hash_function.write_digest(&mut hashed_key[..T::DIGEST_SIZE]);
            new_key = &hashed_key[..T::DIGEST_SIZE];
        } else {
            new_key = key;
        }

        let mut hmac = Self {
            inner_hash_function: T::default(),
            outer_hash_function: T::default(),
        };
        for byte in new_key {
            hmac.inner_hash_function.update(&[byte ^ IPAD]);
            hmac.outer_hash_function.update(&[byte ^ OPAD]);
        }
        for _ in new_key.len()..T::BLOCK_SIZE {
            hmac.inner_hash_function.update(&[IPAD]);
            hmac.outer_hash_function.update(&[OPAD]);
        }
        hmac
    }

    pub fn update(&mut self, input: &[u8]) {
        self.inner_hash_function.update(input);
    }

    pub fn write_digest(mut self, output: &mut [u8]) {
        self.inner_hash_function.write_digest(output);
        self.outer_hash_function.update(output);
        self.outer_hash_function.write_digest(output);
    }
}

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

    fn check(exp512: &str, exp384: &str, key: &[u8], data: &[u8]) {
        let expected = h2b(exp512);
        let mut actual = hmac_sha512(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha512>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());

        let expected = h2b(exp384);
        let mut actual = hmac_sha384(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha384>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());
    }

    #[test]
    fn test_digest() {
        let key = h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
        let data = b"Hi There";
        let exp512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde\
                      daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854";
        let exp384 = "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c\
                      faea9ea9076ede7f4af152e8b2fa9cb6";
        check(exp512, exp384, &key, data);

        let key = b"Jefe";
        let data = b"what do ya want for nothing?";
        let exp512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554\
                      9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
        let exp384 = "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e\
                      8e2240ca5e69e2c78b3239ecfab21649";
        check(exp512, exp384, key, data);

        let key = [0xaa; 20];
        let data = [0xdd; 50];
        let exp512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39\
                      bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb";
        let exp384 = "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b\
                      2a5ab39dc13814b94e3ab6e101a34f27";
        check(exp512, exp384, &key, &data);

        let key: Vec<_> = (0x01..0x1a).collect();
        let data = [0xcd; 50];
        let exp512 = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db\
                      a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
        let exp384 = "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e\
                      6801dd23c4a7d679ccf8a386c674cffb";
        check(exp512, exp384, &key, &data);

        let key = [0xaa; 131];
        let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
        let exp512 = "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352\
                      6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598";
        let exp384 = "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6\
                      0c2ef6ab4030fe8296248df163f44952";
        check(exp512, exp384, &key, data);

        let data =
            b"This is a test using a larger than block-size key and a larger than block-\
              size data. The key needs to be hashed before being used by the HMAC algorithm.";
        let exp512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944\
                      b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58";
        let exp384 = "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5\
                      a678cc31e799176d3860e6110c46523e";
        check(exp512, exp384, &key, data);
    }
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate hyper;
extern crate log;
extern crate serde;
extern crate tokio_core;

use super::config;
use futures::{Future, Stream};
use hyper::{Client, Method, Request, Uri};
use hyper::header::{ContentLength, ContentType};
use std::{mem, str};
use std::io::{Error, ErrorKind};
use tokio_core::reactor::Core;

pub struct Response {
    pub status: u16,
    pub body: String,
}

pub fn request(path: &str, request_body: Option<String>) -> Result<Response, Error> {
    let mut request = Request::new(Method::Post, uri(path));
    match request_body {
        Some(json) => {
            debug!("Request body: {}", json);
            request.headers_mut().set(ContentType::json());
            request.headers_mut().set(ContentLength(json.len() as u64));
            request.set_body(json);
        }
        _ => {
            debug!("Empty request body...");
        }
    }

    let mut status: u16 = 0;
    let mut body = String::new();
    {
        let mut core = Core::new().unwrap();
        let client = Client::new(&core.handle());
        let work = client
            .request(request)
            .and_then(|res| {
                status = res.status().clone().into();
                res.body().for_each(|chunk| {
                    body.push_str(str::from_utf8(&*chunk).unwrap());
                    futures::future::ok(())
                })
            })
            .map_err(|err| Error::new(ErrorKind::Other, err));
        try!(core.run(work));

        // explicit destroy http fuss
        mem::drop(client);
        mem::drop(core);
    }

    debug!("Response status: {}", status);
    debug!("Response body: {}", body);
    Ok(Response { status, body })
}

fn uri(path: &str) -> Uri {
    let addr = config::base_url().clone();
    let uri = format!("{}{}", addr, path).parse().unwrap();
    debug!("Request URL: {}", uri);
    uri
}
<commit_msg>Revert "cleanup http construct"<commit_after>extern crate futures;
extern crate hyper;
extern crate log;
extern crate serde;
extern crate tokio_core;

use super::config;
use futures::{Future, Stream};
use hyper::{Client, Method, Request, Uri};
use hyper::header::{ContentLength, ContentType};
use std::io::{Error, ErrorKind};
use std::str;
use tokio_core::reactor::Core;

pub struct Response {
    pub status: u16,
    pub body: String,
}

pub fn request(path: &str, request_body: Option<String>) -> Result<Response, Error> {
    let mut request = Request::new(Method::Post, uri(path));
    match request_body {
        Some(json) => {
            debug!("Request body: {}", json);
            request.headers_mut().set(ContentType::json());
            request.headers_mut().set(ContentLength(json.len() as u64));
            request.set_body(json);
        }
        _ => {
            debug!("Empty request body...");
        }
    }

    let mut status: u16 = 0;
    let mut body = String::new();
    {
        let mut core = Core::new().unwrap();
        let client = Client::new(&core.handle());
        let work = client
            .request(request)
            .and_then(|res| {
                status = res.status().clone().into();
                res.body().for_each(|chunk| {
                    body.push_str(str::from_utf8(&*chunk).unwrap());
                    futures::future::ok(())
                })
            })
            .map_err(|err| Error::new(ErrorKind::Other, err));
        try!(core.run(work));
    }

    debug!("Response status: {}", status);
    debug!("Response body: {}", body);
    Ok(Response { status, body })
}

fn uri(path: &str) -> Uri {
    let addr = config::base_url().clone();
    let uri = format!("{}{}", addr, path).parse().unwrap();
    debug!("Request URL: {}", uri);
    uri
}
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;

use std::old_io::File;
use std::os;
use git2::{Repository, Oid};
use git2::Error as GitError;
use rustc_serialize::json;

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct Commit {
    hash: String,
    author: String,
    date: i64,
    message: String
}

fn fetch_commits(repo: &Repository, start: &Option<Oid>, query: &str, amount: usize) -> Result<Vec<Commit>, GitError> {
    let mut revs = try!(repo.revwalk());
    match *start {
        Some(commit_id) => try!(revs.push(commit_id)),
        _ => try!(revs.push_head()),
    }

    revs.set_sorting(git2::SORT_TOPOLOGICAL | git2::SORT_TIME);

    let commits = revs
    .filter_map(|commit_id| { repo.find_commit(commit_id).ok() })
    .filter_map(|commit| {
        match commit.message().and_then(|msg| { Some(msg.contains(query)) }) {
            Some(true) => Some(commit),
            _ => None
        }
    })
    .map(|commit| {
        let c = Commit {
            hash: commit.id().to_string(),
            author: commit.author().name()
                .or(commit.author().email())
                .unwrap_or("Some dude").trim().to_string(),
            date: commit.time().seconds(),
            message: commit.message().unwrap_or("").trim().to_string()
        };
        c
    })
    .take(amount)
    .collect();

    Result::Ok(commits)
}

fn main() {
    let args = os::args();
    let start = if args.len() >= 2 { Some(Oid::from_str(&args[1][]).unwrap()) } else { None };

    let cwd = os::getcwd().unwrap();
    let repo = Repository::open(&cwd.join("rust")).unwrap();

    let mut output = File::create(&cwd.join("log.json")).unwrap();

    let commits = fetch_commits(&repo, &start, "[breaking-change]", 100).unwrap();

    match write!(&mut output, "{}", json::as_pretty_json(&commits)) {
        Ok(_) => println!("wrote commits to `log.json`."),
        Err(e) => panic!("failed to write commits to file: {}", e),
    };
}
<commit_msg>Rustup: os -> env<commit_after>#![feature(path, io, env)]

extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;

use std::old_io::File;
use std::env;
use git2::{Repository, Oid};
use git2::Error as GitError;
use rustc_serialize::json;

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct Commit {
    hash: String,
    author: String,
    date: i64,
    message: String
}

fn fetch_commits(repo: &Repository, start: &Option<Oid>, query: &str, amount: usize) -> Result<Vec<Commit>, GitError> {
    let mut revs = try!(repo.revwalk());
    match *start {
        Some(commit_id) => try!(revs.push(commit_id)),
        _ => try!(revs.push_head()),
    }

    revs.set_sorting(git2::SORT_TOPOLOGICAL | git2::SORT_TIME);

    let commits = revs
    .filter_map(|commit_id| { repo.find_commit(commit_id).ok() })
    .filter_map(|commit| {
        match commit.message().and_then(|msg| { Some(msg.contains(query)) }) {
            Some(true) => Some(commit),
            _ => None
        }
    })
    .map(|commit| {
        let c = Commit {
            hash: commit.id().to_string(),
            author: commit.author().name()
                .or(commit.author().email())
                .unwrap_or("Some dude").trim().to_string(),
            date: commit.time().seconds(),
            message: commit.message().unwrap_or("").trim().to_string()
        };
        c
    })
    .take(amount)
    .collect();

    Result::Ok(commits)
}

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let start = if args.len() >= 2 { Some(Oid::from_str(&args[1][]).unwrap()) } else { None };

    let cwd = env::current_dir().unwrap();
    let repo = Repository::open(&cwd.join("rust")).unwrap();

    let mut output = File::create(&cwd.join("log.json")).unwrap();

    let commits = fetch_commits(&repo, &start, "[breaking-change]", 100).unwrap();

    match write!(&mut output, "{}", json::as_pretty_json(&commits)) {
        Ok(_) => println!("wrote commits to `log.json`."),
        Err(e) => panic!("failed to write commits to file: {}", e),
    };
}
<|endoftext|>


<commit_before>extern crate fuse;
extern crate libc;
extern crate time;

use std::path::Path;
use std::env;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyData, ReplyEntry, ReplyDirectory};

struct RedditFileSystem;

impl Filesystem for RedditFileSystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        println!("getattr(ino={})", ino);
        let ts = Timespec::new(0, 0);
        let attr = FileAttr {
            ino: 1,
            size: 0,
            blocks: 0,
            atime: ts,
            mtime: ts,
            ctime: ts,
            crtime: ts,
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 0,
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0
        };
        let ttl = Timespec::new(1, 0);

        if ino == 1 {
            reply.attr(&ttl, &attr);
        } else {
            reply.error(ENOSYS);
        }
    }
}

fn main() {
    let mountpoint = match env::args().nth(1) {
        Some(path) => path,
        None => {
            println!("Usage: {} <Mountpoint>", env::args().nth(0).unwrap());
            return;
        }
    };
    fuse::mount(RedditFileSystem, &mountpoint, &[])
}
<commit_msg>Implement directory listing<commit_after>extern crate fuse;
extern crate libc;
extern crate time;

use std::path::Path;
use std::env;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyData, ReplyEntry, ReplyDirectory};

struct RedditFileSystem;

impl Filesystem for RedditFileSystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        let ts = Timespec::new(0, 0);
        let attr = FileAttr {
            ino: 1,
            size: 0,
            blocks: 0,
            atime: ts,
            mtime: ts,
            ctime: ts,
            crtime: ts,
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 0,
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0
        };
        let ttl = Timespec::new(1, 0);

        if ino == 1 {
            reply.attr(&ttl, &attr);
        } else {
            reply.error(ENOSYS);
        }
    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        if ino == 1 {
            if offset == 0 {
                reply.add(1, 0, FileType::Directory, &Path::new("."));
                reply.add(1, 1, FileType::Directory, &Path::new(".."));
            }

            reply.ok();
        } else {
            reply.error(ENOSYS)
        }
    }
}

fn main() {
    let mountpoint = match env::args().nth(1) {
        Some(path) => path,
        None => {
            println!("Usage: {} <Mountpoint>", env::args().nth(0).unwrap());
            return;
        }
    };
    fuse::mount(RedditFileSystem, &mountpoint, &[])
}
<|endoftext|>


<commit_before>//! I guess these docs will never appear since we re-export the canvas
//! module from graphics...
use std::path;

use gfx::format::{Format, Swizzle};
use gfx::handle::RawRenderTargetView;
use gfx::memory::{Bind, Usage};
use gfx::texture::{AaMode, Kind};
use gfx::Factory;
use glam::Quat;

use crate::context::DebugId;
use crate::error::*;
use crate::graphics::*;
use crate::Context;
use crate::{conf, filesystem};

/// A generic canvas independent of graphics backend. This type should
/// never need to be used directly; use [`graphics::Canvas`](type.Canvas.html)
/// instead.
#[derive(Debug)]
pub struct CanvasGeneric<Spec>
where
    Spec: BackendSpec,
{
    target: RawRenderTargetView<Spec::Resources>,
    image: Image,
    debug_id: DebugId,
}

/// A canvas that can be rendered to instead of the screen (sometimes referred
/// to as "render target" or "render to texture"). Set the canvas with the
/// [`graphics::set_canvas()`](fn.set_canvas.html) function, and then anything you
/// draw will be drawn to the canvas instead of the screen.
///
/// Resume drawing to the screen by calling `graphics::set_canvas(None)`.
///
/// A `Canvas` allows graphics to be rendered to images off-screen
/// in order to do things like saving to an image file or creating cool effects
/// by using shaders that render to an image.
/// If you just want to draw multiple things efficiently, look at
/// [`SpriteBatch`](spritebatch/struct.Spritebatch.html).
///
/// Note that if the canvas is not of the same size as the screen, and you want
/// to render using coordinates relative to the canvas' coordinate system, you
/// need to call [`graphics::set_screen_coordinates`](fn.set_screen_coordinates.html)
/// and pass in a rectangle with position (0, 0) and a size equal to that of the
/// canvas.
///
/// If you draw onto a canvas using BlendMode::Alpha you need to set its blend mode to
/// `BlendMode::Premultiplied` before drawing it to a new surface. This is a side effect
/// of the premultiplication of RGBA values when the canvas was rendered to.
/// This requirement holds for both drawing
/// the `Canvas` directly or converting it to an `Image` first.
/// ```
/// let mut canvas = Canvas::new(width, height, conf::NumSamples::One, get_window_color_format(ctx));
/// graphics::set_canvas(ctx, Some(&canvas));
///
/// // Draw to canvas here...
///
/// graphics::present(ctx);
/// graphics::set_canvas(ctx, None);
/// canvas.set_blend_mode(Some(BlendMode::Premultiplied));
/// ```
pub type Canvas = CanvasGeneric<GlBackendSpec>;

impl<S> CanvasGeneric<S>
where
    S: BackendSpec,
{
    #[allow(clippy::new_ret_no_self)]
    /// Create a new `Canvas` with the given size and number of samples.
    pub fn new(
        ctx: &mut Context,
        width: u16,
        height: u16,
        samples: conf::NumSamples,
        color_format: Format,
    ) -> GameResult<Canvas> {
        let debug_id = DebugId::get(ctx);
        let aa = match samples {
            conf::NumSamples::One => AaMode::Single,
            s => AaMode::Multi(s.into()),
        };
        let kind = Kind::D2(width, height, aa);
        let levels = 1;
        let factory = &mut ctx.gfx_context.factory;
        let texture_create_info = gfx::texture::Info {
            kind,
            levels,
            format: color_format.0,
            bind: Bind::SHADER_RESOURCE | Bind::RENDER_TARGET | Bind::TRANSFER_SRC,
            usage: Usage::Data,
        };
        let tex = factory.create_texture_raw(texture_create_info, Some(color_format.1), None)?;
        let resource_desc = gfx::texture::ResourceDesc {
            channel: color_format.1,
            layer: None,
            min: 0,
            max: levels - 1,
            swizzle: Swizzle::new(),
        };
        let resource = factory.view_texture_as_shader_resource_raw(&tex, resource_desc)?;
        let render_desc = gfx::texture::RenderDesc {
            channel: color_format.1,
            level: 0,
            layer: None,
        };
        let target = factory.view_texture_as_render_target_raw(&tex, render_desc)?;
        Ok(Canvas {
            target,
            image: Image {
                texture: resource,
                texture_handle: tex,
                sampler_info: ctx.gfx_context.default_sampler_info,
                blend_mode: None,
                width,
                height,
                debug_id,
            },
            debug_id,
        })
    }

    /// Create a new `Canvas` with the current window dimensions.
    pub fn with_window_size(ctx: &mut Context) -> GameResult<Canvas> {
        use crate::graphics;
        let (w, h) = graphics::drawable_size(ctx);
        // Default to no multisampling
        Canvas::new(
            ctx,
            w as u16,
            h as u16,
            conf::NumSamples::One,
            get_window_color_format(ctx),
        )
    }

    /// Gets the backend `Image` that is being rendered to. Note that this will be flipped but otherwise the same, use the [`to_image`](#method.to_image) function for the unflipped version.
    pub fn raw_image(&self) -> &Image {
        &self.image
    }

    /// Creates an `Image` with the content of its raw counterpart but transformed to behave like a normal `Image`.
    pub fn to_image(&self, ctx: &mut Context) -> GameResult<Image> {
        let pixel_data = self.to_rgba8(ctx)?;
        Image::from_rgba8(ctx, self.image.width, self.image.height, &pixel_data)
    }

    /// Gets the backend `Target` that is being rendered to.
    pub fn target(&self) -> &RawRenderTargetView<S::Resources> {
        &self.target
    }

    /// Dumps the flipped `Canvas`'s data to a `Vec` of `u8` RBGA8 values.
    pub fn to_rgba8(&self, ctx: &mut Context) -> GameResult<Vec<u8>> {
        // first flush the command buffer to make sure the canvas is up to date before being serialized
        // fixes https://github.com/ggez/ggez/issues/813
        let gfx = &mut ctx.gfx_context;
        gfx.encoder.flush(&mut *gfx.device);

        let mut pixel_data = self.image.to_rgba8(ctx)?;
        flip_pixel_data(
            &mut pixel_data,
            self.image.width as usize,
            self.image.height as usize,
        );
        Ok(pixel_data)
    }

    /// Encode the `Canvas`'s content to the given file format and
    /// write it out to the given path.
    ///
    /// See the [`filesystem`](../filesystem/index.html) module docs for where exactly
    /// the file will end up.
    pub fn encode<P: AsRef<path::Path>>(
        &self,
        ctx: &mut Context,
        format: ImageFormat,
        path: P,
    ) -> GameResult {
        use std::io;
        let data = self.to_rgba8(ctx)?;
        let f = filesystem::create(ctx, path)?;
        let writer = &mut io::BufWriter::new(f);
        let color_format = ::image::ColorType::Rgba8;
        match format {
            ImageFormat::Png => ::image::png::PngEncoder::new(writer)
                .encode(
                    &data,
                    u32::from(self.width()),
                    u32::from(self.height()),
                    color_format,
                )
                .map_err(Into::into),
        }
    }

    /// Return the width of the canvas.
    pub fn width(&self) -> u16 {
        self.image.width
    }

    /// Return the height of the canvas.
    pub fn height(&self) -> u16 {
        self.image.height
    }

    /// Returns the dimensions of the canvas.
    pub fn dimensions(&self) -> Rect {
        Rect::new(0.0, 0.0, f32::from(self.width()), f32::from(self.height()))
    }

    /// Get the filter mode for the canvas.
    pub fn filter(&self) -> FilterMode {
        self.image.filter()
    }

    /// Set the filter mode for the canvas.
    pub fn set_filter(&mut self, mode: FilterMode) {
        self.image.set_filter(mode)
    }
}

impl Drawable for Canvas {
    fn draw(&self, ctx: &mut Context, param: DrawParam) -> GameResult {
        self.debug_id.assert(ctx);

        // We have to mess with the scale to make everything
        // be its-unit-size-in-pixels.
        let scale_x = param.src.w * f32::from(self.width());
        let scale_y = param.src.h * f32::from(self.height());

        let param = param.transform(
            glam::Mat4::from(param.trans.to_bare_matrix())
                * Matrix4::from_scale(glam::vec3(scale_x, scale_y, 1.0)),
        );

        let new_param = flip_draw_param_vertical(param);

        image::draw_image_raw(&self.image, ctx, new_param)
    }
    fn dimensions(&self, _: &mut Context) -> Option<Rect> {
        Some(self.image.dimensions())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.image.blend_mode = mode;
    }
    fn blend_mode(&self) -> Option<BlendMode> {
        self.image.blend_mode
    }
}

fn flip_draw_param_vertical(param: DrawParam) -> DrawParam {
    let param = if let Transform::Matrix(mat) = param.trans {
        param.transform(
            glam::Mat4::from(mat)
                * glam::Mat4::from_scale_rotation_translation(
                    glam::vec3(1.0, -1.0, 1.0),
                    Quat::IDENTITY,
                    glam::vec3(0.0, 1.0, 0.0),
                ),
        )
    } else {
        panic!("Can not be called with a non-matrix DrawParam");
    };
    let new_src = Rect {
        x: param.src.x,
        y: (1.0 - param.src.h) - param.src.y,
        w: param.src.w,
        h: param.src.h,
    };
    param.src(new_src)
}

/// Set the `Canvas` to render to. Specifying `Option::None` will cause all
/// rendering to be done directly to the screen.
pub fn set_canvas(ctx: &mut Context, target: Option<&Canvas>) {
    match target {
        Some(surface) => {
            surface.debug_id.assert(ctx);
            ctx.gfx_context.data.out = surface.target.clone();
        }
        None => {
            ctx.gfx_context.data.out = ctx.gfx_context.screen_render_target.clone();
        }
    };
}
<commit_msg>rustfmt<commit_after>//! I guess these docs will never appear since we re-export the canvas
//! module from graphics...
use std::path;

use gfx::format::{Format, Swizzle};
use gfx::handle::RawRenderTargetView;
use gfx::memory::{Bind, Usage};
use gfx::texture::{AaMode, Kind};
use gfx::Factory;
use glam::Quat;

use crate::context::DebugId;
use crate::error::*;
use crate::graphics::*;
use crate::Context;
use crate::{conf, filesystem};

/// A generic canvas independent of graphics backend. This type should
/// never need to be used directly; use [`graphics::Canvas`](type.Canvas.html)
/// instead.
#[derive(Debug)]
pub struct CanvasGeneric<Spec>
where
    Spec: BackendSpec,
{
    target: RawRenderTargetView<Spec::Resources>,
    image: Image,
    debug_id: DebugId,
}

/// A canvas that can be rendered to instead of the screen (sometimes referred
/// to as "render target" or "render to texture"). Set the canvas with the
/// [`graphics::set_canvas()`](fn.set_canvas.html) function, and then anything you
/// draw will be drawn to the canvas instead of the screen.
///
/// Resume drawing to the screen by calling `graphics::set_canvas(None)`.
///
/// A `Canvas` allows graphics to be rendered to images off-screen
/// in order to do things like saving to an image file or creating cool effects
/// by using shaders that render to an image.
/// If you just want to draw multiple things efficiently, look at
/// [`SpriteBatch`](spritebatch/struct.Spritebatch.html).
///
/// Note that if the canvas is not of the same size as the screen, and you want
/// to render using coordinates relative to the canvas' coordinate system, you
/// need to call [`graphics::set_screen_coordinates`](fn.set_screen_coordinates.html)
/// and pass in a rectangle with position (0, 0) and a size equal to that of the
/// canvas.
///
/// If you draw onto a canvas using BlendMode::Alpha you need to set its blend mode to
/// `BlendMode::Premultiplied` before drawing it to a new surface. This is a side effect
/// of the premultiplication of RGBA values when the canvas was rendered to.
/// This requirement holds for both drawing
/// the `Canvas` directly or converting it to an `Image` first.
/// ```
/// let mut canvas = Canvas::new(width, height, conf::NumSamples::One, get_window_color_format(ctx));
/// graphics::set_canvas(ctx, Some(&canvas));
///
/// // Draw to canvas here...
///
/// graphics::present(ctx);
/// graphics::set_canvas(ctx, None);
/// canvas.set_blend_mode(Some(BlendMode::Premultiplied));
/// ```
pub type Canvas = CanvasGeneric<GlBackendSpec>;

impl<S> CanvasGeneric<S>
where
    S: BackendSpec,
{
    #[allow(clippy::new_ret_no_self)]
    /// Create a new `Canvas` with the given size and number of samples.
    pub fn new(
        ctx: &mut Context,
        width: u16,
        height: u16,
        samples: conf::NumSamples,
        color_format: Format,
    ) -> GameResult<Canvas> {
        let debug_id = DebugId::get(ctx);
        let aa = match samples {
            conf::NumSamples::One => AaMode::Single,
            s => AaMode::Multi(s.into()),
        };
        let kind = Kind::D2(width, height, aa);
        let levels = 1;
        let factory = &mut ctx.gfx_context.factory;
        let texture_create_info = gfx::texture::Info {
            kind,
            levels,
            format: color_format.0,
            bind: Bind::SHADER_RESOURCE | Bind::RENDER_TARGET | Bind::TRANSFER_SRC,
            usage: Usage::Data,
        };
        let tex = factory.create_texture_raw(texture_create_info, Some(color_format.1), None)?;
        let resource_desc = gfx::texture::ResourceDesc {
            channel: color_format.1,
            layer: None,
            min: 0,
            max: levels - 1,
            swizzle: Swizzle::new(),
        };
        let resource = factory.view_texture_as_shader_resource_raw(&tex, resource_desc)?;
        let render_desc = gfx::texture::RenderDesc {
            channel: color_format.1,
            level: 0,
            layer: None,
        };
        let target = factory.view_texture_as_render_target_raw(&tex, render_desc)?;
        Ok(Canvas {
            target,
            image: Image {
                texture: resource,
                texture_handle: tex,
                sampler_info: ctx.gfx_context.default_sampler_info,
                blend_mode: None,
                width,
                height,
                debug_id,
            },
            debug_id,
        })
    }

    /// Create a new `Canvas` with the current window dimensions.
    pub fn with_window_size(ctx: &mut Context) -> GameResult<Canvas> {
        use crate::graphics;
        let (w, h) = graphics::drawable_size(ctx);
        // Default to no multisampling
        Canvas::new(
            ctx,
            w as u16,
            h as u16,
            conf::NumSamples::One,
            get_window_color_format(ctx),
        )
    }

    /// Gets the backend `Image` that is being rendered to. Note that this will be flipped but otherwise the same, use the [`to_image`](#method.to_image) function for the unflipped version.
    pub fn raw_image(&self) -> &Image {
        &self.image
    }

    /// Creates an `Image` with the content of its raw counterpart but transformed to behave like a normal `Image`.
    pub fn to_image(&self, ctx: &mut Context) -> GameResult<Image> {
        let pixel_data = self.to_rgba8(ctx)?;
        Image::from_rgba8(ctx, self.image.width, self.image.height, &pixel_data)
    }

    /// Gets the backend `Target` that is being rendered to.
    pub fn target(&self) -> &RawRenderTargetView<S::Resources> {
        &self.target
    }

    /// Dumps the flipped `Canvas`'s data to a `Vec` of `u8` RBGA8 values.
    pub fn to_rgba8(&self, ctx: &mut Context) -> GameResult<Vec<u8>> {
        // first flush to make sure the canvas is up to date before being serialized
        // fixes https://github.com/ggez/ggez/issues/813
        let gfx = &mut ctx.gfx_context;
        gfx.encoder.flush(&mut *gfx.device);

        let mut pixel_data = self.image.to_rgba8(ctx)?;
        flip_pixel_data(
            &mut pixel_data,
            self.image.width as usize,
            self.image.height as usize,
        );
        Ok(pixel_data)
    }

    /// Encode the `Canvas`'s content to the given file format and
    /// write it out to the given path.
    ///
    /// See the [`filesystem`](../filesystem/index.html) module docs for where exactly
    /// the file will end up.
    pub fn encode<P: AsRef<path::Path>>(
        &self,
        ctx: &mut Context,
        format: ImageFormat,
        path: P,
    ) -> GameResult {
        use std::io;
        let data = self.to_rgba8(ctx)?;
        let f = filesystem::create(ctx, path)?;
        let writer = &mut io::BufWriter::new(f);
        let color_format = ::image::ColorType::Rgba8;
        match format {
            ImageFormat::Png => ::image::png::PngEncoder::new(writer)
                .encode(
                    &data,
                    u32::from(self.width()),
                    u32::from(self.height()),
                    color_format,
                )
                .map_err(Into::into),
        }
    }

    /// Return the width of the canvas.
    pub fn width(&self) -> u16 {
        self.image.width
    }

    /// Return the height of the canvas.
    pub fn height(&self) -> u16 {
        self.image.height
    }

    /// Returns the dimensions of the canvas.
    pub fn dimensions(&self) -> Rect {
        Rect::new(0.0, 0.0, f32::from(self.width()), f32::from(self.height()))
    }

    /// Get the filter mode for the canvas.
    pub fn filter(&self) -> FilterMode {
        self.image.filter()
    }

    /// Set the filter mode for the canvas.
    pub fn set_filter(&mut self, mode: FilterMode) {
        self.image.set_filter(mode)
    }
}

impl Drawable for Canvas {
    fn draw(&self, ctx: &mut Context, param: DrawParam) -> GameResult {
        self.debug_id.assert(ctx);

        // We have to mess with the scale to make everything
        // be its-unit-size-in-pixels.
        let scale_x = param.src.w * f32::from(self.width());
        let scale_y = param.src.h * f32::from(self.height());

        let param = param.transform(
            glam::Mat4::from(param.trans.to_bare_matrix())
                * Matrix4::from_scale(glam::vec3(scale_x, scale_y, 1.0)),
        );

        let new_param = flip_draw_param_vertical(param);

        image::draw_image_raw(&self.image, ctx, new_param)
    }
    fn dimensions(&self, _: &mut Context) -> Option<Rect> {
        Some(self.image.dimensions())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.image.blend_mode = mode;
    }
    fn blend_mode(&self) -> Option<BlendMode> {
        self.image.blend_mode
    }
}

fn flip_draw_param_vertical(param: DrawParam) -> DrawParam {
    let param = if let Transform::Matrix(mat) = param.trans {
        param.transform(
            glam::Mat4::from(mat)
                * glam::Mat4::from_scale_rotation_translation(
                    glam::vec3(1.0, -1.0, 1.0),
                    Quat::IDENTITY,
                    glam::vec3(0.0, 1.0, 0.0),
                ),
        )
    } else {
        panic!("Can not be called with a non-matrix DrawParam");
    };
    let new_src = Rect {
        x: param.src.x,
        y: (1.0 - param.src.h) - param.src.y,
        w: param.src.w,
        h: param.src.h,
    };
    param.src(new_src)
}

/// Set the `Canvas` to render to. Specifying `Option::None` will cause all
/// rendering to be done directly to the screen.
pub fn set_canvas(ctx: &mut Context, target: Option<&Canvas>) {
    match target {
        Some(surface) => {
            surface.debug_id.assert(ctx);
            ctx.gfx_context.data.out = surface.target.clone();
        }
        None => {
            ctx.gfx_context.data.out = ctx.gfx_context.screen_render_target.clone();
        }
    };
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate reroute;

use std::fs::File;
use std::io::{BufReader, Result};
use std::io::prelude::*;
use std::collections::HashSet;
use std::env;

use hyper::Server;
use hyper::server::{Request, Response};
use reroute::{Captures, RouterBuilder};

fn not_found(req: Request, res: Response, _: Captures) {
    let uri = format!("{}", req.uri);
    let msg = format!("No service found behind '{}'.", uri);
    res.send(msg.as_bytes()).unwrap();
}

fn parse_capture(cap: &String) -> HashSet<String> {
    let caps: Vec<&str> = cap.split(|c| c == ',' || c == '/').collect();
    // let mut list: Vec<String> = Vec::new();
    let mut list: HashSet<String> = HashSet::new();
    // &caps[2..] is used to skip `/api/`
    for val in &caps[2..] {
        if val.is_empty() {
            continue;
        }
        list.insert(val.to_string());
    }
    list
}

fn list_handler(_: Request, res: Response, c: Captures) {
    let cap = c.unwrap();
    let caps = parse_capture(&cap[0]);
    let mut re = "; Generated by editorconfig.me\n; EditorConfig helps developers define and maintain consistent\n; coding styles between different editors and IDEs\n; editorconfig.org\n\n".to_string();

    for target in caps {
        let content = match read_file(&get_file_name(&target)) {
            Ok(c) => c,
            Err(e) => {
                println!("Could not process '{}'. {:?}", target, e);
                format!("; Could not process '{}'\n", target)
            }
        };
        re.push_str(&content);
        re.push_str("\n");
    }
    res.send(re.as_bytes()).unwrap();
}

fn get_file_name(name: &String) -> String {
    let mut full_name = "./files/".to_string();
    full_name.push_str(&name);
    full_name.push_str(".editorconfig");
    full_name
}

fn read_file(name: &String) -> Result<String> {
    // let mut full_name = "./files/".to_string();
    // full_name.push_str(&name);
    let file = File::open(name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    Ok(contents)
}

// Look up the server port in PORT for heroku or use 8080 as fallback
fn get_server_port() -> String {
    env::var("PORT").unwrap_or("8080".to_string())
}

fn main() {
    let mut builder = RouterBuilder::new();

    builder.get(r"/api/(,?(\w)+)+", list_handler);

    builder.not_found(not_found);

    let router = builder.finalize().unwrap();

    let mut listen = "0.0.0.0:".to_string();
    listen.push_str(&get_server_port());
    Server::http(&listen).unwrap().handle(router).unwrap();
}

#[test]
fn test_parse_capture() {
    let actual = parse_capture(&"/api/,rust,,markdown,,,rust,".to_string());
    let expected: HashSet<String> = vec!["rust".to_string(), "markdown".to_string()]
        .into_iter()
        .collect();
    assert_eq!(actual, expected);
}

#[test]
fn test_read_file() {
    let actual = read_file(&"test/testfile".to_string()).unwrap();
    let expected = "testtesttest\n".to_string();
    assert_eq!(actual, expected);
}

#[test]
fn test_get_file_name() {
    let actual = get_file_name(&"rust".to_string());
    let expected = "./files/rust.editorconfig".to_string();
    assert_eq!(actual, expected);
}
<commit_msg>Fix request regex<commit_after>extern crate hyper;
extern crate reroute;

use std::fs::File;
use std::io::{BufReader, Result};
use std::io::prelude::*;
use std::collections::HashSet;
use std::env;

use hyper::Server;
use hyper::server::{Request, Response};
use reroute::{Captures, RouterBuilder};

fn not_found(req: Request, res: Response, _: Captures) {
    let uri = format!("{}", req.uri);
    let msg = format!("No service found behind '{}'.", uri);
    res.send(msg.as_bytes()).unwrap();
}

fn parse_capture(cap: &String) -> HashSet<String> {
    let caps: Vec<&str> = cap.split(|c| c == ',' || c == '/').collect();
    // let mut list: Vec<String> = Vec::new();
    let mut list: HashSet<String> = HashSet::new();
    // &caps[2..] is used to skip `/api/`
    for val in &caps[2..] {
        if val.is_empty() {
            continue;
        }
        list.insert(val.to_string());
    }
    list
}

fn list_handler(_: Request, res: Response, c: Captures) {
    let cap = c.unwrap();
    let caps = parse_capture(&cap[0]);
    let mut re = "; Generated by editorconfig.me\n; EditorConfig helps developers define and maintain consistent\n; coding styles between different editors and IDEs\n; editorconfig.org\n\n".to_string();

    for target in caps {
        let content = match read_file(&get_file_name(&target)) {
            Ok(c) => c,
            Err(e) => {
                println!("Could not process '{}'. {:?}", target, e);
                format!("; Could not process '{}'\n", target)
            }
        };
        re.push_str(&content);
        re.push_str("\n");
    }
    res.send(re.as_bytes()).unwrap();
}

fn get_file_name(name: &String) -> String {
    let mut full_name = "./files/".to_string();
    full_name.push_str(&name);
    full_name.push_str(".editorconfig");
    full_name
}

fn read_file(name: &String) -> Result<String> {
    // let mut full_name = "./files/".to_string();
    // full_name.push_str(&name);
    let file = File::open(name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    Ok(contents)
}

// Look up the server port in PORT for heroku or use 8080 as fallback
fn get_server_port() -> String {
    env::var("PORT").unwrap_or("8080".to_string())
}

fn main() {
    let mut builder = RouterBuilder::new();

    builder.get(r"/api/(,?(\w)*)+", list_handler);

    builder.not_found(not_found);

    let router = builder.finalize().unwrap();

    let mut listen = "0.0.0.0:".to_string();
    listen.push_str(&get_server_port());
    Server::http(&listen).unwrap().handle(router).unwrap();
}

#[test]
fn test_parse_capture() {
    let actual = parse_capture(&"/api/,rust,,markdown,,,rust,".to_string());
    let expected: HashSet<String> = vec!["rust".to_string(), "markdown".to_string()]
        .into_iter()
        .collect();
    assert_eq!(actual, expected);
}

#[test]
fn test_read_file() {
    let actual = read_file(&"test/testfile".to_string()).unwrap();
    let expected = "testtesttest\n".to_string();
    assert_eq!(actual, expected);
}

#[test]
fn test_get_file_name() {
    let actual = get_file_name(&"rust".to_string());
    let expected = "./files/rust.editorconfig".to_string();
    assert_eq!(actual, expected);
}
<|endoftext|>


<commit_before>#![allow(unused_imports, unused_must_use, dead_code)]

extern crate bencode;
extern crate rand;
extern crate bittorrent;
extern crate hyper;

use std::{env, str, thread};
use std::io::{Read, Write};
use std::collections::HashMap;
use std::net::{Ipv4Addr, TcpStream, SocketAddrV4};
use bencode::{deserialize, deserialize_file, Bencode, TypedMethods, BencodeVecOption};
use rand::{Rng, thread_rng};
use bittorrent::querystring::QueryString;
use bittorrent::metadata::{MetadataDict, Metadata};
use bittorrent::bt_messages::{decode_message, test};
use hyper::Client;
use hyper::header::Connection;

const PEER_ID_LENGTH:usize = 20;
const PEER_ID_PREFIX:&'static str = "-TR1000-";

#[derive(Debug)]
enum Address {
    TCP(Ipv4Addr, u16)
}

fn gen_rand_peer_id (prefix: &str) -> String {
    let rand_length = PEER_ID_LENGTH - prefix.len();
    let rand = thread_rng().gen_ascii_chars()
                           .take(rand_length)
                           .collect::<String>();

    prefix.to_string() + &rand
}

fn ping_tracker (announce: &String, args: Vec<(&str, String)>) -> Option<HashMap<String, Bencode>> {
    let req_addr = announce.to_string() + "?" + &QueryString::from(args).query_string();
    println!("pinging tracker {}", req_addr);
    let client = Client::new();
    let mut res = client.get(&req_addr)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    deserialize(&body).to_singleton_dict()
}

fn get_peers <T> (tracker_response: &T) -> Vec<Address> where T:TypedMethods {
    let peers = tracker_response.get_owned_string("peers").unwrap_or_else(||panic!("no peers found"));
    //for now keep the bottom unused value, it's for ipv6. which maybe will be addressed
    (0..peers.len()/6).map(|x| {
        let ip_start = x * 6;
        let ip_end = ip_start + 4;
        let ip_bytes = &peers[ip_start..ip_end];
        let ip = Ipv4Addr::new(ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]);
        let port = (peers[ip_end] as u16)*256 + peers[ip_end+1] as u16;
        Address::TCP(ip, port)
    }).collect::<Vec<Address>>()
}

/// The peer handshake message, according to protocol
///
fn to_handshake (pstr:&str, info_hash: &[u8; 20], peer_id: &String) -> Vec<u8> {
    let reserved = [0u8; 8];
    let pstr_bytes = pstr.to_string().into_bytes();
    let a = [pstr_bytes.len() as u8];
    let b = pstr_bytes;
    let c = reserved;
    let d = info_hash.clone();
    let e = peer_id.clone().into_bytes();

    [a.iter(),
     b.iter(),
     c.iter(),
     d.iter(),
     e.iter()].iter().flat_map(|y| {
         y.to_owned().map(|x| *x).collect::<Vec<u8>>()
     }).collect::<Vec<u8>>()
}

fn connect_to_peer (address: Address, metadata: &Metadata, peer_id: &String) -> Result<([u8; 512], usize), String> {
    println!("connecting to {:?}", address);
    let (ip, port) = match address {
        Address::TCP(ip_address, port) => (ip_address, port)
    };

    let mut stream = match TcpStream::connect(SocketAddrV4::new(ip, port)) {
        Ok(tcp_stream) => tcp_stream,
        Err(err) => return Err(format!("unable to connect to peer {:?}", ip))
    };

    println!("connected to {:?}", address);

    let _ = stream.write_all(&to_handshake("BitTorrent protocol", &metadata.info_hash, peer_id));
    let _ = stream.flush();

    //for now enforce a maximum handshake size of 512 bytes
    let mut buffer = [0; 512];
    match stream.read(&mut buffer) {
        Ok(bytes_read) => {
            let something = &buffer[0..bytes_read];

            Ok((buffer, bytes_read))
            //Ok((&buffer[0..bytes_read], buffer))
        },
        Err(err) => Err(format!("unable to read from peer {:?}", ip))
    }
}

fn init (metadata: &Metadata, listen_port: u32, bytes_dled: u32) {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let bytes_left = metadata.get_total_length() - bytes_dled;

    let info_hash_escaped = QueryString::encode_component(&metadata.info_hash);
    let response = ping_tracker(&metadata.announce, vec![
                                ("info_hash", info_hash_escaped),
                                ("peer_id", peer_id.clone()),
                                ("port", listen_port.to_string()),
                                ("uploaded", 0.to_string()),
                                ("downloaded", bytes_dled.to_string()),
                                ("left", bytes_left.to_string()),
                                ("compact", 1.to_string()),
                                ("event", "started".to_string()),
                                ("num_want", "15".to_string())
                                ]);

    let tracker_resp = match response {
        Some(a) => a,
        None => panic!("no valid bencode response from tracker")
    };

    let peers = get_peers(&tracker_resp);
    println!("{} peers", peers.len());
    let handshake_out = to_handshake("BitTorrent protocol", &metadata.info_hash, &peer_id);

    let mut children = vec![];
    for peer in peers {
        //using Arc makes the borrow checker compain. will have to revisit for maximum memory
        //efficiency :)
        let child_meta = metadata.clone();
        let peer_id = peer_id.clone();
        children.push(thread::spawn(move || {
            connect_to_peer(peer, &child_meta, &peer_id)
        }));
    }

    for child in children {
        let _ = child.join();
    }
}

fn start_torrenting () {
    let path = env::args().nth(1)
                          .unwrap_or_else(||panic!("no path to torrent provided"));

    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));

    assert_eq!(content.len(), 1);

    let metadata = match content.first() {
        Some(&Bencode::Dict(ref dict)) => {
            //println!("{:?}", dict);
            dict.to_metadata()
        },
        _ => panic!("no valid information in torrent file")
    }.unwrap();

    init(&metadata, 6887, 0);
}

fn main () {
    start_torrenting();
    //test();
}
<commit_msg>adding null check for handshake - might want to do another read. starting to decode the peer handshake<commit_after>#![allow(unused_imports, unused_must_use, dead_code)]

extern crate bencode;
extern crate rand;
extern crate bittorrent;
extern crate hyper;

use std::{env, str, thread};
use std::io::{Read, Write};
use std::collections::HashMap;
use std::net::{Ipv4Addr, TcpStream, SocketAddrV4};
use bencode::{deserialize, deserialize_file, Bencode, TypedMethods, BencodeVecOption};
use rand::{Rng, thread_rng};
use bittorrent::querystring::QueryString;
use bittorrent::metadata::{MetadataDict, Metadata};
use bittorrent::bt_messages::{decode_message, test};
use hyper::Client;
use hyper::header::Connection;

const PEER_ID_LENGTH:usize = 20;
const PEER_ID_PREFIX:&'static str = "-TR1000-";

#[derive(Debug)]
enum Address {
    TCP(Ipv4Addr, u16)
}

fn gen_rand_peer_id (prefix: &str) -> String {
    let rand_length = PEER_ID_LENGTH - prefix.len();
    let rand = thread_rng().gen_ascii_chars()
                           .take(rand_length)
                           .collect::<String>();

    prefix.to_string() + &rand
}

fn ping_tracker (announce: &String, args: Vec<(&str, String)>) -> Option<HashMap<String, Bencode>> {
    let req_addr = announce.to_string() + "?" + &QueryString::from(args).query_string();
    println!("pinging tracker {}", req_addr);
    let client = Client::new();
    let mut res = client.get(&req_addr)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    deserialize(&body).to_singleton_dict()
}

fn get_peers <T> (tracker_response: &T) -> Vec<Address> where T:TypedMethods {
    let peers = tracker_response.get_owned_string("peers").unwrap_or_else(||panic!("no peers found"));
    //for now keep the bottom unused value, it's for ipv6. which maybe will be addressed
    (0..peers.len()/6).map(|x| {
        let ip_start = x * 6;
        let ip_end = ip_start + 4;
        let ip_bytes = &peers[ip_start..ip_end];
        let ip = Ipv4Addr::new(ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]);
        let port = (peers[ip_end] as u16)*256 + peers[ip_end+1] as u16;
        Address::TCP(ip, port)
    }).collect::<Vec<Address>>()
}

/// The peer handshake message, according to protocol
///
fn to_handshake (pstr:&str, info_hash: &[u8; 20], peer_id: &String) -> Vec<u8> {
    let reserved = [0u8; 8];
    let pstr_bytes = pstr.to_string().into_bytes();
    let a = [pstr_bytes.len() as u8];
    let b = pstr_bytes;
    let c = reserved;
    let d = info_hash.clone();
    let e = peer_id.clone().into_bytes();

    [a.iter(),
     b.iter(),
     c.iter(),
     d.iter(),
     e.iter()].iter().flat_map(|y| {
         y.to_owned().map(|x| *x).collect::<Vec<u8>>()
     }).collect::<Vec<u8>>()
}

fn decode_handshake(resp: &[u8]) {
    println!("len: {}", resp.len());
    let (pstrlen, rest) = {
        let (l, r) = resp.split_at(1);
        (l[0], r)
    };
    //let pstr = resp[1..pstrlen+1];
}

fn connect_to_peer (address: Address, metadata: &Metadata, peer_id: &String) -> Result<String, String> {
    println!("connecting to {:?}", address);
    let (ip, port) = match address {
        Address::TCP(ip_address, port) => (ip_address, port)
    };

    let mut stream = match TcpStream::connect(SocketAddrV4::new(ip, port)) {
        Ok(tcp_stream) => tcp_stream,
        Err(err) => return Err(format!("unable to connect to peer {:?}", ip))
    };

    println!("connected to {:?}", address);

    let _ = stream.write_all(&to_handshake("BitTorrent protocol", &metadata.info_hash, peer_id));
    let _ = stream.flush();

    //for now enforce a maximum handshake size of 512 bytes
    let mut buffer = [0; 512];
    match stream.read(&mut buffer) {
        Ok(0) => Err(format!("invalid handshake from peer")),
        Ok(bytes_read) => {
            let something = &buffer[0..bytes_read];
            decode_handshake(&buffer[0..bytes_read]);
            Ok("id".to_string())
            //Ok((&buffer[0..bytes_read], buffer))
        },
        Err(err) => Err(format!("unable to read from peer {:?}", ip))
    }
}

fn init (metadata: &Metadata, listen_port: u32, bytes_dled: u32) {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let bytes_left = metadata.get_total_length() - bytes_dled;

    let info_hash_escaped = QueryString::encode_component(&metadata.info_hash);
    let response = ping_tracker(&metadata.announce, vec![
                                ("info_hash", info_hash_escaped),
                                ("peer_id", peer_id.clone()),
                                ("port", listen_port.to_string()),
                                ("uploaded", 0.to_string()),
                                ("downloaded", bytes_dled.to_string()),
                                ("left", bytes_left.to_string()),
                                ("compact", 1.to_string()),
                                ("event", "started".to_string()),
                                ("num_want", "15".to_string())
                                ]);

    let tracker_resp = match response {
        Some(a) => a,
        None => panic!("no valid bencode response from tracker")
    };

    let peers = get_peers(&tracker_resp);
    println!("{} peers", peers.len());
    let handshake_out = to_handshake("BitTorrent protocol", &metadata.info_hash, &peer_id);

    let mut children = vec![];
    for peer in peers {
        //using Arc makes the borrow checker compain. will have to revisit for maximum memory
        //efficiency :)
        let child_meta = metadata.clone();
        let peer_id = peer_id.clone();
        children.push(thread::spawn(move || {
            connect_to_peer(peer, &child_meta, &peer_id)
        }));
    }

    for child in children {
        let _ = child.join();
    }
}

fn start_torrenting () {
    let path = env::args().nth(1)
                          .unwrap_or_else(||panic!("no path to torrent provided"));

    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));

    assert_eq!(content.len(), 1);

    let metadata = match content.first() {
        Some(&Bencode::Dict(ref dict)) => {
            //println!("{:?}", dict);
            dict.to_metadata()
        },
        _ => panic!("no valid information in torrent file")
    }.unwrap();

    init(&metadata, 6887, 0);
}

fn main () {
    start_torrenting();
    //test();
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// TODO: TESTS!

#![feature(core, std_misc)]

extern crate rustc_serialize as rustc_serialize;
extern crate time;
extern crate se_rs_ial as serial;
extern crate dxgcap;

use config::parse_led_indices;
use color::{RGB8,
	RgbTransformer,
	Pixel};
use capture::{Capturer, ImageAnalyzer };

use dxgcap::CaptureError;
use std::iter::repeat;
use std::time::Duration;
use std::sync::mpsc::{Sender,
	Receiver,
	channel};
use std::thread;
use std::cmp::{max, partial_max};

pub mod config;
pub mod color;
pub mod capture;

/// A special header is expected by the corresponding LED streaming code running on the Arduino.
/// This only needs to be initialized once since the number of LEDs remains constant.
fn new_pixel_buf_header(n_leds: u16) -> Vec<u8> {
	// In the two below, not sure why the -1 in `(n_leds - 1)` is needed,
	// but that's how LEDstream on the Arduino expects it
	let count_high = ((n_leds - 1) >> 8) as u8;  // LED count high byte
	let count_low = ((n_leds - 1) & 0xff) as u8; // LED count low byte
	vec![
		'A' as u8,
		'd' as u8,
		'a' as u8,
		count_high,
		count_low,
		count_high ^ count_low ^ 0x55, // Checksum
	]
}

/// A timer to track time passed between refreshes. Can for example be used to limit frame rate.
struct FrameTimer {
	before: f64,
	last_frame_dt: f64,
}
impl FrameTimer {
	fn new() -> FrameTimer {
		FrameTimer{ before: time::precise_time_s(), last_frame_dt: 0.0 }
	}

	/// For how long the previous frame lasted
	fn last_frame_dt(&self) -> f64 {
		self.last_frame_dt
	}

	/// Time passed since last tick
	fn dt_to_now(&mut self) -> f64 {
		let now = time::precise_time_s();
		let dt = now - self.before;
		if dt >= 0.0 {
			dt
		} else {
			self.before = now;
			0.0
		}
	}

	/// An update/frame/refresh has occured; take the time.
	fn tick(&mut self) {
		let now = time::precise_time_s();
		self.last_frame_dt = partial_max(now - self.before, 0.0).unwrap_or(0.0);
		self.before = now;
	}
}

/// Initialize a thread for serial writing given a serial port, baud rate, header to write before
/// each data write, and buffer with the actual led color data.
fn init_write_thread(port: &str, baud_rate: u32, header: Vec<u8>, pixel_buf: Vec<RGB8>)
	-> (Sender<Vec<RGB8>>, Receiver<Vec<RGB8>>)
{
	use std::io::Write;

	let mut serial_con = serial::Connection::new(port, baud_rate).unwrap();

	let (from_write_thread_tx, from_write_thread_rx) = channel();
	let (to_write_thread_tx, to_write_thread_rx) = channel::<Vec<RGB8>>();

	thread::spawn(move || loop {
		let pixel_buf = color::rgbs_to_bytes(to_write_thread_rx.recv().unwrap());

		match serial_con.write(header.as_ref()) {
			Ok(hn) if hn == header.len() => match serial_con.write(pixel_buf.as_ref())
			{
				Ok(bn) if bn == pixel_buf.len() => (),
				Ok(_) => println!("Failed to write all bytes of RGB data"),
				Err(e) => println!("Failed to write RGB data, {}", e)
			},
			Ok(_) => println!("Failed to write all bytes in header"),
			Err(e) => println!("Failed to write header, {}", e)
		}

		from_write_thread_tx.send(color::bytes_to_rgbs(pixel_buf)).unwrap();
	});
	to_write_thread_tx.send(pixel_buf).unwrap();

	(to_write_thread_tx, from_write_thread_rx)
}

fn main() {
	let config = config::parse_config();

	let leds: &[_] = config.leds.as_ref();

	let mut led_transformers_list: Vec<_> = repeat(Vec::with_capacity(2)).take(leds.len()).collect();

	// Add color transforms from config to each led in matching vec
	for transform_conf in config.color.transform.iter() {
		let hsv_transformer = if !transform_conf.hsv.is_default() {
			Some(&transform_conf.hsv)
		} else { None };

		let rgb_transformer = if !(transform_conf.red.is_default() &&
			transform_conf.green.is_default() &&
			transform_conf.red.is_default())
		{
			Some(RgbTransformer::new(transform_conf.red.clone(),
				transform_conf.green.clone(),
				transform_conf.blue.clone()))
		} else { None };

		for range in parse_led_indices(transform_conf.leds.as_ref(), leds.len()).iter() {
			for transformers in led_transformers_list[range.clone()].iter_mut() {
				transformers.push((rgb_transformer.clone(), hsv_transformer));
			}
		}
	}

	// Do serial writing on own thread as to not block.
	let (write_thread_tx, write_thread_rx) = {
		// Header to write before led data
		let out_header = new_pixel_buf_header(leds.len() as u16);

		// Skeleton for the output led pixel buffer to write to arduino
		let out_pixels = repeat(RGB8{r: 0, g: 0, b: 0}).take(leds.len()).collect();

		init_write_thread(config.device.output.as_ref(), config.device.rate.clone(),
			out_header, out_pixels)
	};

	let mut capturer = Capturer::new();
	let capture_frame_interval = 1.0 / config.framegrabber.frequency_Hz;
	capturer.set_timeout(Duration::microseconds((1_000_000.0 * capture_frame_interval) as i64));

	let mut frame_analyzer = ImageAnalyzer::new();
	frame_analyzer.set_resize_dimensions(
		(config.framegrabber.width, config.framegrabber.height));

	// Function to use when smoothing led colors
	type SmoothFn = fn(&RGB8, RGB8, f64) -> RGB8;
	let smooth = match config.color.smoothing.type_.as_ref() {
		"linear" => color::linear_smooth as SmoothFn,
		_ => color::no_smooth as SmoothFn,
	};

	// max w/ 1 to avoid future divide by zero
	let smooth_time_const = max(config.color.smoothing.time_ms, 1) as f64 / 1000.0;

	let led_refresh_interval = 1.0 / config.color.smoothing.update_frequency;

	let mut capture_timer = FrameTimer::new();
	let mut led_refresh_timer = FrameTimer::new();
	let mut diag_timer = FrameTimer::new();
	let mut diag_i = 0;
	loop {
		led_refresh_timer.tick();

		// Don't capture new frame if going faster than frame limit,
		// but still proceed to smooth leds
		if capture_timer.dt_to_now() > capture_frame_interval {
			// If something goes wrong, last frame is reused
			match capturer.capture_frame() {
				Ok(frame) => { frame_analyzer.swap_slotted(frame); },
				// Access Denied means we are probably in fullscreen app with
				// restricted access, wait for access
				Err(CaptureError::AccessDenied) => {
					println!("Access Denied");
					thread::sleep_ms(2_000)
				},
				// Should be handled automatically in DXGCap
				Err(CaptureError::AccessLost) =>
					println!("Access to desktop duplication lost"),
				Err(CaptureError::RefreshFailure) => {
					println!("Refresh Failure");
					loop {
						if capturer.acquire_output_duplication().is_ok() {
							break
						} else {
							println!("Refresh Failure");
							thread::sleep_ms(2_000)
						}
					}
				},
				Err(CaptureError::Timeout) => (),
				Err(_) => println!("Unexpected failure when capturing screen"),
			}
			capture_timer.tick();
		}

		let diag_bap = time::precise_time_s();

		let mut out_pixels = write_thread_rx.recv().unwrap();

		let smooth_factor = led_refresh_timer.last_frame_dt() / smooth_time_const;
		for (to_pixel, pixel_in_buf) in leds.iter()
			.map(|led| frame_analyzer.average_color(&led))
			.zip(led_transformers_list.iter())
			.map(|(average_color, color_transformers)|
				color_transformers.iter().fold(Box::new(average_color) as Box<Pixel>,
					|mut acc_color, &(ref opt_rgb_tr, ref opt_hsv_tr)|
				{
					if let Some(rgb_tr) = opt_rgb_tr.as_ref() {
						acc_color = Box::new(acc_color.rgb_transform(rgb_tr))
							as Box<Pixel>;
					}
					if let Some(hsv_tr) = opt_hsv_tr.as_ref() {
						Box::new(acc_color.hsv_transform(hsv_tr)) as Box<Pixel>
					} else {
						acc_color
					}
				})
					.to_rgb())
			.zip(out_pixels.iter_mut())
		{
			*pixel_in_buf = smooth(pixel_in_buf, to_pixel, smooth_factor);
		}

		let diag_aap = time::precise_time_s();

		write_thread_tx.send(out_pixels).unwrap();

		diag_i += 1;
		if diag_i >= 120 {
			diag_timer.tick();
			println!("ap fps: {}", 1.0 / (diag_aap-diag_bap));
			println!("avg fps: {}\n", 1.0 / (diag_timer.last_frame_dt() / 120.0));
			diag_i = 0;
		}

		let time_left = led_refresh_interval - led_refresh_timer.dt_to_now();
		if time_left > 0.0 {
			thread::sleep_ms(if time_left > 0.0 { time_left * 1_000.0 } else { 0.0 } as u32);
		}
	}
}<commit_msg>Don't print avg framerate & Print config on start<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// TODO: TESTS!

#![feature(core, std_misc)]

extern crate rustc_serialize as rustc_serialize;
extern crate time;
extern crate se_rs_ial as serial;
extern crate dxgcap;

use config::parse_led_indices;
use color::{RGB8,
	RgbTransformer,
	Pixel};
use capture::{Capturer, ImageAnalyzer };

use dxgcap::CaptureError;
use std::iter::repeat;
use std::time::Duration;
use std::sync::mpsc::{Sender,
	Receiver,
	channel};
use std::thread;
use std::cmp::{max, partial_max};

pub mod config;
pub mod color;
pub mod capture;

/// A special header is expected by the corresponding LED streaming code running on the Arduino.
/// This only needs to be initialized once since the number of LEDs remains constant.
fn new_pixel_buf_header(n_leds: u16) -> Vec<u8> {
	// In the two below, not sure why the -1 in `(n_leds - 1)` is needed,
	// but that's how LEDstream on the Arduino expects it
	let count_high = ((n_leds - 1) >> 8) as u8;  // LED count high byte
	let count_low = ((n_leds - 1) & 0xff) as u8; // LED count low byte
	vec![
		'A' as u8,
		'd' as u8,
		'a' as u8,
		count_high,
		count_low,
		count_high ^ count_low ^ 0x55, // Checksum
	]
}

/// A timer to track time passed between refreshes. Can for example be used to limit frame rate.
struct FrameTimer {
	before: f64,
	last_frame_dt: f64,
}
impl FrameTimer {
	fn new() -> FrameTimer {
		FrameTimer{ before: time::precise_time_s(), last_frame_dt: 0.0 }
	}

	/// For how long the previous frame lasted
	fn last_frame_dt(&self) -> f64 {
		self.last_frame_dt
	}

	/// Time passed since last tick
	fn dt_to_now(&mut self) -> f64 {
		let now = time::precise_time_s();
		let dt = now - self.before;
		if dt >= 0.0 {
			dt
		} else {
			self.before = now;
			0.0
		}
	}

	/// An update/frame/refresh has occured; take the time.
	fn tick(&mut self) {
		let now = time::precise_time_s();
		self.last_frame_dt = partial_max(now - self.before, 0.0).unwrap_or(0.0);
		self.before = now;
	}
}

/// Initialize a thread for serial writing given a serial port, baud rate, header to write before
/// each data write, and buffer with the actual led color data.
fn init_write_thread(port: &str, baud_rate: u32, header: Vec<u8>, pixel_buf: Vec<RGB8>)
	-> (Sender<Vec<RGB8>>, Receiver<Vec<RGB8>>)
{
	use std::io::Write;

	let mut serial_con = serial::Connection::new(port, baud_rate).unwrap();

	let (from_write_thread_tx, from_write_thread_rx) = channel();
	let (to_write_thread_tx, to_write_thread_rx) = channel::<Vec<RGB8>>();

	thread::spawn(move || loop {
		let pixel_buf = color::rgbs_to_bytes(to_write_thread_rx.recv().unwrap());

		match serial_con.write(header.as_ref()) {
			Ok(hn) if hn == header.len() => match serial_con.write(pixel_buf.as_ref())
			{
				Ok(bn) if bn == pixel_buf.len() => (),
				Ok(_) => println!("Failed to write all bytes of RGB data"),
				Err(e) => println!("Failed to write RGB data, {}", e)
			},
			Ok(_) => println!("Failed to write all bytes in header"),
			Err(e) => println!("Failed to write header, {}", e)
		}

		from_write_thread_tx.send(color::bytes_to_rgbs(pixel_buf)).unwrap();
	});
	to_write_thread_tx.send(pixel_buf).unwrap();

	(to_write_thread_tx, from_write_thread_rx)
}

fn main() {
	let config = config::parse_config();

	let leds: &[_] = config.leds.as_ref();

	let mut led_transformers_list: Vec<_> = repeat(Vec::with_capacity(2)).take(leds.len()).collect();

	// Add color transforms from config to each led in matching vec
	for transform_conf in config.color.transform.iter() {
		let hsv_transformer = if !transform_conf.hsv.is_default() {
			Some(&transform_conf.hsv)
		} else { None };

		let rgb_transformer = if !(transform_conf.red.is_default() &&
			transform_conf.green.is_default() &&
			transform_conf.red.is_default())
		{
			Some(RgbTransformer::new(transform_conf.red.clone(),
				transform_conf.green.clone(),
				transform_conf.blue.clone()))
		} else { None };

		for range in parse_led_indices(transform_conf.leds.as_ref(), leds.len()).iter() {
			for transformers in led_transformers_list[range.clone()].iter_mut() {
				transformers.push((rgb_transformer.clone(), hsv_transformer));
			}
		}
	}

	// Do serial writing on own thread as to not block.
	let (write_thread_tx, write_thread_rx) = {
		// Header to write before led data
		let out_header = new_pixel_buf_header(leds.len() as u16);

		// Skeleton for the output led pixel buffer to write to arduino
		let out_pixels = repeat(RGB8{r: 0, g: 0, b: 0}).take(leds.len()).collect();

		init_write_thread(config.device.output.as_ref(), config.device.rate.clone(),
			out_header, out_pixels)
	};

	let mut capturer = Capturer::new();
	let capture_frame_interval = 1.0 / config.framegrabber.frequency_Hz;
	capturer.set_timeout(Duration::microseconds((1_000_000.0 * capture_frame_interval) as i64));

	let mut frame_analyzer = ImageAnalyzer::new();
	frame_analyzer.set_resize_dimensions(
		(config.framegrabber.width, config.framegrabber.height));

	// Function to use when smoothing led colors
	type SmoothFn = fn(&RGB8, RGB8, f64) -> RGB8;
	let smooth = match config.color.smoothing.type_.as_ref() {
		"linear" => color::linear_smooth as SmoothFn,
		_ => color::no_smooth as SmoothFn,
	};

	// max w/ 1 to avoid future divide by zero
	let smooth_time_const = max(config.color.smoothing.time_ms, 1) as f64 / 1000.0;

	let led_refresh_interval = 1.0 / config.color.smoothing.update_frequency;

	println!("Helion - An LED streamer\n\
		Number of LEDs: {}\n\
		Resize resolution: {} x {}\n\
		Capture rate: {} fps\n\
		LED refresh rate: {} hz\n\
		Serial port: {}",
		leds.len(), config.framegrabber.width, config.framegrabber.height,
		config.framegrabber.frequency_Hz, 1.0 / smooth_time_const, config.device.output);

	let mut capture_timer = FrameTimer::new();
	let mut led_refresh_timer = FrameTimer::new();
	loop {
		led_refresh_timer.tick();

		// Don't capture new frame if going faster than frame limit,
		// but still proceed to smooth leds
		if capture_timer.dt_to_now() > capture_frame_interval {
			// If something goes wrong, last frame is reused
			match capturer.capture_frame() {
				Ok(frame) => { frame_analyzer.swap_slotted(frame); },
				// Access Denied means we are probably in fullscreen app with
				// restricted access, wait for access
				Err(CaptureError::AccessDenied) => {
					println!("Access Denied");
					thread::sleep_ms(2_000)
				},
				// Should be handled automatically in DXGCap
				Err(CaptureError::AccessLost) =>
					println!("Access to desktop duplication lost"),
				Err(CaptureError::RefreshFailure) => {
					println!("Refresh Failure");
					loop {
						if capturer.acquire_output_duplication().is_ok() {
							break
						} else {
							println!("Refresh Failure");
							thread::sleep_ms(2_000)
						}
					}
				},
				Err(CaptureError::Timeout) => (),
				Err(_) => println!("Unexpected failure when capturing screen"),
			}
			capture_timer.tick();
		}

		let mut out_pixels = write_thread_rx.recv().unwrap();

		let smooth_factor = led_refresh_timer.last_frame_dt() / smooth_time_const;
		for (to_pixel, pixel_in_buf) in leds.iter()
			.map(|led| frame_analyzer.average_color(&led))
			.zip(led_transformers_list.iter())
			.map(|(average_color, color_transformers)|
				color_transformers.iter().fold(Box::new(average_color) as Box<Pixel>,
					|mut acc_color, &(ref opt_rgb_tr, ref opt_hsv_tr)|
				{
					if let Some(rgb_tr) = opt_rgb_tr.as_ref() {
						acc_color = Box::new(acc_color.rgb_transform(rgb_tr))
							as Box<Pixel>;
					}
					if let Some(hsv_tr) = opt_hsv_tr.as_ref() {
						Box::new(acc_color.hsv_transform(hsv_tr)) as Box<Pixel>
					} else {
						acc_color
					}
				})
					.to_rgb())
			.zip(out_pixels.iter_mut())
		{
			*pixel_in_buf = smooth(pixel_in_buf, to_pixel, smooth_factor);
		}

		write_thread_tx.send(out_pixels).unwrap();

		let time_left = led_refresh_interval - led_refresh_timer.dt_to_now();
		if time_left > 0.0 {
			thread::sleep_ms(if time_left > 0.0 { time_left * 1_000.0 } else { 0.0 } as u32);
		}
	}
}<|endoftext|>


<commit_before>extern crate iron;
extern crate router;

use std::io::Read;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;

use iron::prelude::*;
use iron::status;
use router::Router;

#[derive(Debug)]
struct Index;

impl Index {
    fn new() -> Index {
        Index
    }
}

fn main() {
    let mut indices = Arc::new(Mutex::new(HashMap::new()));
    indices.lock().unwrap().insert("wagtail", Index::new());

    let mut router = Router::new();

    router.get("/", |_: &mut Request| -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    });

    {
        let indices = indices.clone();

        router.get("/:index/_count", move |req: &mut Request| -> IronResult<Response> {
            let ref index = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            // TODO

            let mut response = Response::with((status::Ok, "{\"count\": 0}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.get("/:index/_search", move |req: &mut Request| -> IronResult<Response> {
            let ref index = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            // TODO

            let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.put("/:index/:mapping/:doc", move |req: &mut Request| -> IronResult<Response> {
            let ref index = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
            let ref mapping = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
            let ref doc = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            // TODO

            let mut response = Response::with((status::Ok, "{}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    Iron::new(router).http("localhost:9200").unwrap();
}
<commit_msg>Return not found response when index is not found<commit_after>extern crate iron;
extern crate router;

use std::io::Read;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;

use iron::prelude::*;
use iron::status;
use router::Router;

#[derive(Debug)]
struct Index;

impl Index {
    fn new() -> Index {
        Index
    }
}

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

fn main() {
    let mut indices = Arc::new(Mutex::new(HashMap::new()));
    indices.lock().unwrap().insert("wagtail", Index::new());

    let mut router = Router::new();

    router.get("/", |_: &mut Request| -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    });

    {
        let indices = indices.clone();

        router.get("/:index/_count", move |req: &mut Request| -> IronResult<Response> {
            let ref index = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
            if !indices.lock().unwrap().contains_key(index) {
                return Ok(index_not_found_response());
            }

            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            // TODO

            let mut response = Response::with((status::Ok, "{\"count\": 0}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.get("/:index/_search", move |req: &mut Request| -> IronResult<Response> {
            let ref index = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
            if !indices.lock().unwrap().contains_key(index) {
                return Ok(index_not_found_response());
            }

            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            // TODO

            let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    {
        let indices = indices.clone();

        router.put("/:index/:mapping/:doc", move |req: &mut Request| -> IronResult<Response> {
            let ref index = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
            if !indices.lock().unwrap().contains_key(index) {
                return Ok(index_not_found_response());
            }

            let ref mapping = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
            let ref doc = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

            let mut payload = String::new();
            req.body.read_to_string(&mut payload).unwrap();

            // TODO

            let mut response = Response::with((status::Ok, "{}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            Ok(response)
        });
    }

    Iron::new(router).http("localhost:9200").unwrap();
}
<|endoftext|>


<commit_before>extern crate xml;

use std::os;

use std::io::{File, BufferedReader};
use std::fmt;

use xml::reader::EventReader;
use xml::reader::events::XmlEvent;

fn main() {
	println!("XGConsole:");
	for arg in parse_command_line(os::args()).iter() {
		println!("  {}", arg);
	}
	sample();
}

fn parse_command_line(args: Vec<String>) -> Vec<String> {
	let mut result: Vec<String> = Vec::new();
	for arg in args.slice(1, args.len()).iter() {
			result.push(arg.clone());
	}
	result
}

enum OptionalString {
Value(String),
Missing,
}

impl fmt::Show for OptionalString {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	match self {
			&OptionalString::Value(ref v) => {
			write!(f, "{}", v)
		}
			&OptionalString::Missing => {
			write!(f, "missing")
		}
		}
}
}

struct XgTask {
id: OptionalString,
title: OptionalString,
tool: OptionalString,
working_dir: OptionalString,
depends_on: Vec<String>,
}

impl fmt::Show for XgTask {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, title={}, tool={}, working_dir={}, depends_on={}", self .id, self .title, self .tool, self .working_dir, self .depends_on)
}
}

struct XgTool {
id: OptionalString,
path: OptionalString,
params: OptionalString,
}

impl fmt::Show for XgTool {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, path={}", self .id, self .path)
}
}

fn sample() {
	let file = File::open(&Path::new("tests/graph-parser.xml")).unwrap();
	let reader = BufferedReader::new(file);

	let mut parser = EventReader::new(reader);
	let mut tasks:Vec<XgTask> = vec![];
	let mut tools:Vec<XgTool> = vec![];
	for e in parser.events() {
		match e {
				XmlEvent::StartElement {name, attributes, namespace} => {
				match name.local_name.as_slice() {
						"Task" =>
						{
								tasks.push(xg_parse_task(&attributes));
						}
						"Tool" =>
						{
								tools.push(xg_parse_tool(&attributes));
						}
						_ => {}
					}
			}
				XmlEvent::EndElement{name} => {
			}
				_ => {
			}
			}
	}
}

fn xg_parse_task (attributes: &Vec<xml::attribute::OwnedAttribute>)->XgTask {
	let mut task = XgTask {
	id: OptionalString::Missing,
	title: OptionalString::Missing,
	tool: OptionalString::Missing,
	working_dir: OptionalString::Missing,
	depends_on: vec![],
	};
	for attr in attributes.iter() {
		match attr.name.local_name.as_slice()
			{
				"Name" =>
				{
						task.id = OptionalString::Value(attr.value.to_string());
				}
				"Caption" =>
				{
						task.title = OptionalString::Value(attr.value.to_string());
				}
				"Tool" =>
				{
						task.tool = OptionalString::Value(attr.value.to_string());
				}
				"WorkingDir" =>
				{
						task.working_dir = OptionalString::Value(attr.value.to_string());
				}
				"DependsOn" =>
				{
					for item in attr.value.split_str(";").collect::<Vec<&str>>().iter() {
							task.depends_on.push(item.to_string());
					}
				}
				_ =>
				{
				}
			}
	}
	task
}
fn xg_parse_tool (attributes: &Vec<xml::attribute::OwnedAttribute>)->XgTool {
	let mut tool = XgTool {
	id: OptionalString::Missing,
	path: OptionalString::Missing,
	params: OptionalString::Missing,
	};
	for attr in attributes.iter() {
		match attr.name.local_name.as_slice()
			{
				"Name" =>
				{
						tool.id = OptionalString::Value(attr.value.to_string());
				}
				"Path" =>
				{
						tool.path = OptionalString::Value(attr.value.to_string());
				}
				"Params" =>
				{
						tool.params = OptionalString::Value(attr.value.to_string());
				}
				_ =>
				{
				}
			}
	}
	tool
}
<commit_msg>More simple code.<commit_after>extern crate xml;

use std::os;

use std::io::{File, BufferedReader};
use std::fmt;

use xml::reader::EventReader;
use xml::reader::events::XmlEvent;

fn main() {
	println!("XGConsole:");
	for arg in parse_command_line(os::args()).iter() {
		println!("  {}", arg);
	}
	sample();
}

fn parse_command_line(args: Vec<String>) -> Vec<String> {
	let mut result: Vec<String> = Vec::new();
	for arg in args.slice(1, args.len()).iter() {
			result.push(arg.clone());
	}
	result
}

struct XgTask {
id: Option<String>,
title: Option<String>,
tool: Option<String>,
working_dir: Option<String>,
depends_on: Vec<String>,
}

impl XgTask {
fn new() -> XgTask {
	XgTask {
	id: None,
	title: None,
	tool: None,
	working_dir: None,
	depends_on: vec![],
	}
}
}

impl fmt::Show for XgTask {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, title={}, tool={}, working_dir={}, depends_on={}", self .id, self .title, self .tool, self .working_dir, self .depends_on)
}
}

struct XgTool {
id: Option<String>,
path: Option<String>,
params: Option<String>,
}

impl XgTool {
fn new() -> XgTool {
	XgTool {
	id: None,
	path: None,
	params: None,
	}
}
}

impl fmt::Show for XgTool {
fn fmt(& self, f: &mut fmt::Formatter) -> fmt::Result {
	write!(f, "id={}, path={}", self .id, self .path)
}
}

fn sample() {
	let file = File::open(&Path::new("tests/graph-parser.xml")).unwrap();
	let reader = BufferedReader::new(file);

	let mut parser = EventReader::new(reader);
	let mut tasks:Vec<XgTask> = vec![];
	let mut tools:Vec<XgTool> = vec![];
	for e in parser.events() {
		match e {
				XmlEvent::StartElement {name, attributes, ..} => {
				match name.local_name.as_slice() {
						"Task" =>
						{
								tasks.push(xg_parse_task(&attributes));
						}
						"Tool" =>
						{
								tools.push(xg_parse_tool(&attributes));
						}
						_ => {}
					}
			}
				XmlEvent::EndElement{..} => {
			}
				_ => {
			}
			}
	}
}

fn xg_parse_task (attributes: &Vec<xml::attribute::OwnedAttribute>)->XgTask {
	let mut task = XgTask::new();
	for attr in attributes.iter() {
		match attr.name.local_name.as_slice()
			{
				"Name" =>
				{
						task.id = Some(attr.value.to_string());
				}
				"Caption" =>
				{
						task.title = Some(attr.value.to_string());
				}
				"Tool" =>
				{
						task.tool = Some(attr.value.to_string());
				}
				"WorkingDir" =>
				{
						task.working_dir = Some(attr.value.to_string());
				}
				"DependsOn" =>
				{
					for item in attr.value.split_str(";").collect::<Vec<&str>>().iter() {
							task.depends_on.push(item.to_string());
					}
				}
				_ =>
				{
				}
			}
	}
	task
}
fn xg_parse_tool (attributes: &Vec<xml::attribute::OwnedAttribute>)->XgTool {
	let mut tool = XgTool::new();
	for attr in attributes.iter() {
		match attr.name.local_name.as_slice()
			{
				"Name" =>
				{
						tool.id = Some(attr.value.to_string());
				}
				"Path" =>
				{
						tool.path = Some(attr.value.to_string());
				}
				"Params" =>
				{
						tool.params = Some(attr.value.to_string());
				}
				_ =>
				{
				}
			}
	}
	tool
}
<|endoftext|>