<commit_before>// Copyright © 2016, Peter Atashian

extern crate googl;
extern crate irc;
#[macro_use] extern crate lazy_static;
extern crate mediawiki;
extern crate rustc_serialize;
extern crate url;

use irc::client::prelude::*;
use mediawiki::{Error as MwError, JsonFun, Mediawiki};
use rustc_serialize::json::{Json, decode};
use std::cmp::{max};
use std::fmt::{Display, Error as FmtError, Formatter};
use std::fs::{File, OpenOptions};
use std::io::{Read, Error as IoError, Write};
use std::sync::{Arc};
use std::sync::mpsc::{Receiver, Sender, channel};
use std::thread::{sleep, spawn};
use std::time::{Duration};
use url::{Url};
use url::form_urlencoded::{serialize};

#[derive(Debug)]
enum Error {
    Mediawiki(MwError),
    Io(IoError),
    Unknown,
}
impl From<MwError> for Error {
    fn from(err: MwError) -> Error {
        Error::Mediawiki(err)
    }
}
impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Error::Io(err)
    }
}
fn main() {
    let (send, recv) = channel();
    spawn(move|| mw_thread(send));
    irc_thread(recv);
}
enum Change {
    New {
        user: String,
        title: String,
        comment: String,
        size: i64,
        link: String,
    },
    Edit {
        user: String,
        title: String,
        comment: String,
        diff: i64,
        link: String,
    },
    Delete {
        user: String,
        title: String,
        comment: String,
    },
    Upload {
        user: String,
        title: String,
        comment: String,
        link: String,
    },
    MarkTranslation {
        user: String,
        title: String,
    },
    ReviewTranslation {
        user: String,
        title: String,
    },
    AddProtection {
        user: String,
        title: String,
        comment: String,
        detail: String,
    },
    RemoveProtection {
        user: String,
        title: String,
        comment: String,
    },
    ModifyProtection {
        user: String,
        title: String,
        comment: String,
        detail: String,
    },
}
impl Display for Change {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        struct Type<'a>(&'a str);
        impl<'a> Display for Type<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                write!(f, "[\x0307{}\x0f]", self.0)
            }
        }
        struct Comment<'a>(&'a str);
        impl<'a> Display for Comment<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                if self.0.is_empty() {
                    write!(f, "")
                } else {
                    write!(f, "(\x1d{}\x0f)", self.0)
                }
            }
        }
        struct User<'a>(&'a str);
        impl<'a> Display for User<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                write!(f, "\x0310{}\x0f", self.0)
            }
        }
        struct Title<'a>(&'a str);
        impl<'a> Display for Title<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                write!(f, "\x02{}\x0f", self.0)
            }
        }
        struct Diff(i64);
        impl Display for Diff {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                if self.0 >= 500 {
                    write!(f, "(\x02\x0303+{}\x0f)", self.0)
                } else if self.0 > 0 {
                    write!(f, "(\x0303+{}\x0f)", self.0)
                } else if self.0 <= -500 {
                    write!(f, "(\x02\x0304{}\x0f)", self.0)
                } else if self.0 < 0 {
                    write!(f, "(\x0304{}\x0f)", self.0)
                } else {
                    write!(f, "(\x0314{}\x0f)", self.0)
                }
            }
        }
        match self {
            &Change::New { ref user, ref title, ref comment, ref size, ref link } => {
                write!(f, "{} {} {} created {} {} {}", Type("new"),
                    Diff(*size), User(user), Title(title), Comment(comment), link)
            },
            &Change::Edit { ref user, ref title, ref comment, ref diff, ref link } => {
                write!(f, "{} {} {} edited {} {} {}", Type("edit"),
                    Diff(*diff), User(user), Title(title), Comment(comment), link)
            },
            &Change::Delete { ref user, ref title, ref comment } => {
                write!(f, "{} {} deleted {} {}", Type("delete"),
                    User(user), Title(title), Comment(comment))
            },
            &Change::Upload { ref user, ref title, ref comment, ref link } => {
                write!(f, "{} {} uploaded {} {} {}", Type("upload"),
                    User(user), Title(title), Comment(comment), link)
            },
            &Change::MarkTranslation { ref user, ref title } => {
                write!(f, "{} {} marked {} for translation", Type("mark"),
                    User(user), Title(title))
            },
            &Change::ReviewTranslation { ref user, ref title } => {
                write!(f, "{} {} reviewed the translation {}", Type("review"),
                    User(user), Title(title))
            },
            &Change::AddProtection { ref user, ref title, ref comment, ref detail } => {
                write!(f, "{} {} added protection to {} {} {}", Type("protect"),
                    User(user), Title(title), detail, Comment(comment))
            },
            &Change::ModifyProtection { ref user, ref title, ref comment, ref detail } => {
                write!(f, "{} {} modified the protection for {} {} {}", Type("protect"),
                    User(user), Title(title), detail, Comment(comment))
            },
            &Change::RemoveProtection { ref user, ref title, ref comment } => {
                write!(f, "{} {} removed the protection on {} {}", Type("protect"),
                    User(user), Title(title), Comment(comment))
            },
        }
    }
}
fn shorten(link: &str) -> String {
    lazy_static! {
        static ref KEY: String = {
            let mut file = File::open("key.txt").unwrap();
            let mut key = String::new();
            file.read_to_string(&mut key).unwrap();
            key
        };
    }
    let shortlink;
    loop {
        match googl::shorten(&KEY, &link) {
            Ok(link) => { shortlink = link; break },
            Err(_) => sleep(Duration::from_secs(5)),
        }
    }
    shortlink
}
fn make_article_link(title: &str) -> String {
    let args = [("title", title)];
    let url = Url::parse(&format!("http://ftb.gamepedia.com/index.php?{}",
        serialize(args.iter().map(|&x| x)))).unwrap().serialize();
    shorten(&url)
}
fn make_revision_link(title: &str, oldid: &str) -> String {
    let args = [("title", title), ("oldid", oldid)];
    let url = Url::parse(&format!("http://ftb.gamepedia.com/index.php?{}",
        serialize(args.iter().map(|&x| x)))).unwrap().serialize();
    shorten(&url)
}
fn make_diff_link(title: &str, oldid: &str) -> String {
    let args = [("title", title), ("diff", "prev"), ("oldid", oldid)];
    let url = Url::parse(&format!("http://ftb.gamepedia.com/index.php?{}",
        serialize(args.iter().map(|&x| x)))).unwrap().serialize();
    shorten(&url)
}
fn process_change(send: &Sender<Change>, change: &Json) -> Result<(), Error> {
    let kind = change.get("type").string().unwrap_or("");
    let user = change.get("user").string().unwrap_or("NO USER").to_owned();
    let title = change.get("title").string().unwrap_or("NO TITLE").to_owned();
    let comment = change.get("comment").string().unwrap_or("").to_owned();
    let oldlen = change.get("oldlen").integer().unwrap_or(0);
    let newlen = change.get("newlen").integer().unwrap_or(0);
    let revid = change.get("revid").integer().unwrap_or(0);
    let logaction = change.get("logaction").string().unwrap_or("");
    let logtype = change.get("logtype").string().unwrap_or("");
    let detail0 = change.get("0").string().unwrap_or("");
    match kind {
        "edit" => send.send(Change::Edit {
            user: user,
            link: make_diff_link(&title, &revid.to_string()),
            title: title,
            comment: comment,
            diff: newlen - oldlen,
        }).unwrap(),
        "new" => send.send(Change::New {
            user: user,
            link: make_revision_link(&title, &revid.to_string()),
            title: title,
            comment: comment,
            size: newlen,
        }).unwrap(),
        "log" => match (logtype, logaction) {
            ("delete", "delete") => send.send(Change::Delete {
                user: user,
                title: title,
                comment: comment,
            }).unwrap(),
            ("upload", "upload") => send.send(Change::Upload {
                user: user,
                link: make_article_link(&title),
                title: title,
                comment: comment,
            }).unwrap(),
            ("pagetranslation", "mark") => send.send(Change::MarkTranslation {
                user: user,
                title: title,
            }).unwrap(),
            ("translationreview", "message") => send.send(Change::ReviewTranslation {
                user: user,
                title: title,
            }).unwrap(),
            ("protect", "protect") => send.send(Change::AddProtection {
                user: user,
                title: title,
                comment: comment,
                detail: detail0.to_owned(),
            }).unwrap(),
            ("protect", "unprotect") => send.send(Change::RemoveProtection {
                user: user,
                title: title,
                comment: comment,
            }).unwrap(),
            ("protect", "modidy") => send.send(Change::ModifyProtection {
                user: user,
                title: title,
                comment: comment,
                detail: detail0.to_owned(),
            }).unwrap(),
            _ => return Err(Error::Unknown),
        },
        _ => return Err(Error::Unknown),
    }
    Ok(())
}
fn mw_thread(send: Sender<Change>) {
    let mut file = File::open("ftb.json").unwrap();
    let mut s = String::new();
    file.read_to_string(&mut s).unwrap();
    let config = decode(&s).unwrap();
    let mw = Mediawiki::login(config).unwrap();
    let mut latest = 0;
    let mut rcfile = OpenOptions::new().write(true).append(true).open("rc.txt").unwrap();
    loop {
        let previous = latest;
        match mw.recent_changes() {
            Ok(rc) => for change in rc {
                match change {
                    Ok(change) => {
                        let id = change.get("rcid").integer().unwrap();
                        latest = max(id, latest);
                        if id <= previous || previous == 0 {
                            break
                        }
                        if let Err(e) = process_change(&send, &change) {
                            writeln!(&mut rcfile, "{}", change.pretty()).unwrap();
                            println!("{:?}", e);
                            break
                        }
                    },
                    Err(e) => {
                        println!("{:?}", e);
                        break
                    },
                }
                sleep(Duration::from_secs(1))
            },
            Err(e) => {
                println!("{:?}", e);
                continue;
            },
        };
        sleep(Duration::from_secs(10))
    }
}
fn irc_print_changes<T, U>(server: &Arc<IrcServer<T, U>>, recv: &Receiver<Change>) -> Result<(), Error>
    where T: IrcRead, U: IrcWrite {
    try!(server.identify());
    for change in recv {
        try!(server.send_privmsg("#FTB-Wiki-recentchanges", &change.to_string()));
    }
    Ok(())
}
fn irc_thread(recv: Receiver<Change>) -> ! {
    let server = Arc::new(IrcServer::new("irc.json").unwrap());
    let server_clone = server.clone();
    spawn(move|| irc_listen_thread(server_clone));
    loop {
        println!("Aw shit {:?}", irc_print_changes(&server, &recv));
        println!("Reconnecting {:?}", server.reconnect());
    }
}
fn irc_listen_thread<T, U>(server: Arc<IrcServer<T, U>>) where T: IrcRead, U: IrcWrite {
    let mut file = File::create("irc.txt").unwrap();
    loop {
        for msg in server.iter() {
            writeln!(&mut file, "{:?}", msg).unwrap();
        }
        println!("Aw dang, loop is over");
    }
}
<commit_msg>Filter out Translations:<commit_after>// Copyright © 2016, Peter Atashian

extern crate googl;
extern crate irc;
#[macro_use] extern crate lazy_static;
extern crate mediawiki;
extern crate rustc_serialize;
extern crate url;

use irc::client::prelude::*;
use mediawiki::{Error as MwError, JsonFun, Mediawiki};
use rustc_serialize::json::{Json, decode};
use std::cmp::{max};
use std::fmt::{Display, Error as FmtError, Formatter};
use std::fs::{File, OpenOptions};
use std::io::{Read, Error as IoError, Write};
use std::sync::{Arc};
use std::sync::mpsc::{Receiver, Sender, channel};
use std::thread::{sleep, spawn};
use std::time::{Duration};
use url::{Url};
use url::form_urlencoded::{serialize};

#[derive(Debug)]
enum Error {
    Mediawiki(MwError),
    Io(IoError),
    Unknown,
}
impl From<MwError> for Error {
    fn from(err: MwError) -> Error {
        Error::Mediawiki(err)
    }
}
impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Error::Io(err)
    }
}
fn main() {
    let (send, recv) = channel();
    spawn(move|| mw_thread(send));
    irc_thread(recv);
}
enum Change {
    New {
        user: String,
        title: String,
        comment: String,
        size: i64,
        link: String,
    },
    Edit {
        user: String,
        title: String,
        comment: String,
        diff: i64,
        link: String,
    },
    Delete {
        user: String,
        title: String,
        comment: String,
    },
    Upload {
        user: String,
        title: String,
        comment: String,
        link: String,
    },
    MarkTranslation {
        user: String,
        title: String,
    },
    ReviewTranslation {
        user: String,
        title: String,
    },
    AddProtection {
        user: String,
        title: String,
        comment: String,
        detail: String,
    },
    RemoveProtection {
        user: String,
        title: String,
        comment: String,
    },
    ModifyProtection {
        user: String,
        title: String,
        comment: String,
        detail: String,
    },
    CreateUser {
        user: String,
    },
}
impl Display for Change {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        struct Type<'a>(&'a str);
        impl<'a> Display for Type<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                write!(f, "[\x0307{}\x0f]", self.0)
            }
        }
        struct Comment<'a>(&'a str);
        impl<'a> Display for Comment<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                if self.0.is_empty() {
                    write!(f, "")
                } else {
                    write!(f, "(\x1d{}\x0f)", self.0)
                }
            }
        }
        struct User<'a>(&'a str);
        impl<'a> Display for User<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                write!(f, "\x0310{}\x0f", self.0)
            }
        }
        struct Title<'a>(&'a str);
        impl<'a> Display for Title<'a> {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                write!(f, "\x02{}\x0f", self.0)
            }
        }
        struct Diff(i64);
        impl Display for Diff {
            fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
                if self.0 >= 500 {
                    write!(f, "(\x02\x0303+{}\x0f)", self.0)
                } else if self.0 > 0 {
                    write!(f, "(\x0303+{}\x0f)", self.0)
                } else if self.0 <= -500 {
                    write!(f, "(\x02\x0304{}\x0f)", self.0)
                } else if self.0 < 0 {
                    write!(f, "(\x0304{}\x0f)", self.0)
                } else {
                    write!(f, "(\x0314{}\x0f)", self.0)
                }
            }
        }
        match self {
            &Change::New { ref user, ref title, ref comment, ref size, ref link } => {
                write!(f, "{} {} {} created {} {} {}", Type("new"),
                    Diff(*size), User(user), Title(title), Comment(comment), link)
            },
            &Change::Edit { ref user, ref title, ref comment, ref diff, ref link } => {
                write!(f, "{} {} {} edited {} {} {}", Type("edit"),
                    Diff(*diff), User(user), Title(title), Comment(comment), link)
            },
            &Change::Delete { ref user, ref title, ref comment } => {
                write!(f, "{} {} deleted {} {}", Type("delete"),
                    User(user), Title(title), Comment(comment))
            },
            &Change::Upload { ref user, ref title, ref comment, ref link } => {
                write!(f, "{} {} uploaded {} {} {}", Type("upload"),
                    User(user), Title(title), Comment(comment), link)
            },
            &Change::MarkTranslation { ref user, ref title } => {
                write!(f, "{} {} marked {} for translation", Type("mark"),
                    User(user), Title(title))
            },
            &Change::ReviewTranslation { ref user, ref title } => {
                write!(f, "{} {} reviewed the translation {}", Type("review"),
                    User(user), Title(title))
            },
            &Change::AddProtection { ref user, ref title, ref comment, ref detail } => {
                write!(f, "{} {} added protection to {} {} {}", Type("protect"),
                    User(user), Title(title), detail, Comment(comment))
            },
            &Change::ModifyProtection { ref user, ref title, ref comment, ref detail } => {
                write!(f, "{} {} modified the protection for {} {} {}", Type("protect"),
                    User(user), Title(title), detail, Comment(comment))
            },
            &Change::RemoveProtection { ref user, ref title, ref comment } => {
                write!(f, "{} {} removed the protection on {} {}", Type("protect"),
                    User(user), Title(title), Comment(comment))
            },
            &Change::CreateUser { ref user } => {
                write!(f, "{} {} created an account", Type("user"),
                    User(user))
            },
        }
    }
}
fn shorten(link: &str) -> String {
    lazy_static! {
        static ref KEY: String = {
            let mut file = File::open("key.txt").unwrap();
            let mut key = String::new();
            file.read_to_string(&mut key).unwrap();
            key
        };
    }
    let shortlink;
    loop {
        match googl::shorten(&KEY, &link) {
            Ok(link) => { shortlink = link; break },
            Err(_) => sleep(Duration::from_secs(5)),
        }
    }
    shortlink
}
fn make_article_link(title: &str) -> String {
    let args = [("title", title)];
    let url = Url::parse(&format!("http://ftb.gamepedia.com/index.php?{}",
        serialize(args.iter().map(|&x| x)))).unwrap().serialize();
    shorten(&url)
}
fn make_revision_link(title: &str, oldid: &str) -> String {
    let args = [("title", title), ("oldid", oldid)];
    let url = Url::parse(&format!("http://ftb.gamepedia.com/index.php?{}",
        serialize(args.iter().map(|&x| x)))).unwrap().serialize();
    shorten(&url)
}
fn make_diff_link(title: &str, oldid: &str) -> String {
    let args = [("title", title), ("diff", "prev"), ("oldid", oldid)];
    let url = Url::parse(&format!("http://ftb.gamepedia.com/index.php?{}",
        serialize(args.iter().map(|&x| x)))).unwrap().serialize();
    shorten(&url)
}
fn process_change(send: &Sender<Change>, change: &Json) -> Result<(), Error> {
    let kind = change.get("type").string().unwrap_or("");
    let user = change.get("user").string().unwrap_or("NO USER").to_owned();
    let title = change.get("title").string().unwrap_or("NO TITLE").to_owned();
    let comment = change.get("comment").string().unwrap_or("").to_owned();
    let oldlen = change.get("oldlen").integer().unwrap_or(0);
    let newlen = change.get("newlen").integer().unwrap_or(0);
    let revid = change.get("revid").integer().unwrap_or(0);
    let logaction = change.get("logaction").string().unwrap_or("");
    let logtype = change.get("logtype").string().unwrap_or("");
    let detail0 = change.get("0").string().unwrap_or("");
    match kind {
        "edit" => send.send(Change::Edit {
            user: user,
            link: make_diff_link(&title, &revid.to_string()),
            title: title,
            comment: comment,
            diff: newlen - oldlen,
        }).unwrap(),
        "new" => send.send(Change::New {
            user: user,
            link: make_revision_link(&title, &revid.to_string()),
            title: title,
            comment: comment,
            size: newlen,
        }).unwrap(),
        "log" => match (logtype, logaction) {
            ("delete", "delete") => send.send(Change::Delete {
                user: user,
                title: title,
                comment: comment,
            }).unwrap(),
            ("upload", "upload") => send.send(Change::Upload {
                user: user,
                link: make_article_link(&title),
                title: title,
                comment: comment,
            }).unwrap(),
            ("pagetranslation", "mark") => send.send(Change::MarkTranslation {
                user: user,
                title: title,
            }).unwrap(),
            ("translationreview", "message") => send.send(Change::ReviewTranslation {
                user: user,
                title: title,
            }).unwrap(),
            ("protect", "protect") => send.send(Change::AddProtection {
                user: user,
                title: title,
                comment: comment,
                detail: detail0.to_owned(),
            }).unwrap(),
            ("protect", "unprotect") => send.send(Change::RemoveProtection {
                user: user,
                title: title,
                comment: comment,
            }).unwrap(),
            ("protect", "modify") => send.send(Change::ModifyProtection {
                user: user,
                title: title,
                comment: comment,
                detail: detail0.to_owned(),
            }).unwrap(),
            ("newusers", "create") => send.send(Change::CreateUser {
                user: user,
            }).unwrap(),
            _ => return Err(Error::Unknown),
        },
        _ => return Err(Error::Unknown),
    }
    Ok(())
}
fn mw_thread(send: Sender<Change>) {
    let mut file = File::open("ftb.json").unwrap();
    let mut s = String::new();
    file.read_to_string(&mut s).unwrap();
    let config = decode(&s).unwrap();
    let mw = Mediawiki::login(config).unwrap();
    let mut latest = 0;
    let mut rcfile = OpenOptions::new().write(true).append(true).open("rc.txt").unwrap();
    loop {
        let previous = latest;
        match mw.recent_changes() {
            Ok(rc) => for change in rc {
                match change {
                    Ok(change) => {
                        let id = change.get("rcid").integer().unwrap();
                        latest = max(id, latest);
                        if id <= previous || previous == 0 {
                            break
                        }
                        if let Err(e) = process_change(&send, &change) {
                            writeln!(&mut rcfile, "{}", change.pretty()).unwrap();
                            println!("{:?}", e);
                            break
                        }
                    },
                    Err(e) => {
                        println!("{:?}", e);
                        break
                    },
                }
                sleep(Duration::from_secs(1))
            },
            Err(e) => {
                println!("{:?}", e);
                continue;
            },
        };
        sleep(Duration::from_secs(10))
    }
}
fn is_translation(change: &Change) -> bool {
    if let &Change::New { ref title, .. } = change {
        title.starts_with("Translations:")
    } else if let &Change::Edit { ref title, .. } = change {
        title.starts_with("Translations:")
    } else { false }
}
fn irc_print_changes<T, U>(server: &Arc<IrcServer<T, U>>, recv: &Receiver<Change>) -> Result<(), Error>
    where T: IrcRead, U: IrcWrite {
    try!(server.identify());
    for change in recv {
        if is_translation(&change) { continue }
        try!(server.send_privmsg("#FTB-Wiki-recentchanges", &change.to_string()));
    }
    Ok(())
}
fn irc_thread(recv: Receiver<Change>) -> ! {
    let server = Arc::new(IrcServer::new("irc.json").unwrap());
    let server_clone = server.clone();
    spawn(move|| irc_listen_thread(server_clone));
    loop {
        println!("Aw shit {:?}", irc_print_changes(&server, &recv));
        println!("Reconnecting {:?}", server.reconnect());
    }
}
fn irc_listen_thread<T, U>(server: Arc<IrcServer<T, U>>) where T: IrcRead, U: IrcWrite {
    let mut file = File::create("irc.txt").unwrap();
    loop {
        for msg in server.iter() {
            writeln!(&mut file, "{:?}", msg).unwrap();
        }
        println!("Aw dang, loop is over");
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate futures;
extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_core;
extern crate tokio_io;
extern crate bytes;

use std::{io, str};
use std::net::ToSocketAddrs;

use futures::{Future, Stream, Poll, Async};
use futures::{Sink, AsyncSink, StartSend};
use futures::future::{self, loop_fn, FutureResult, Loop, LoopFn};
use tokio_proto::TcpClient;
use tokio_proto::pipeline::ClientProto;
use tokio_service::Service;
use tokio_core::reactor::Core;
use tokio_io::codec::{Encoder, Decoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use bytes::BytesMut;

#[derive(Default)]
pub struct LineCodec;

impl Decoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
        println!("Received: {:?}", std::str::from_utf8(buf));
        if let Some(i) = buf.iter().position(|&b| b == b'\n') {
            let line = buf.split_to(i);
            buf.split_to(1);
            match str::from_utf8(&line) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other,
                                             "invalid UTF-8")),
            }
        } else {
            Ok(None)
        }
    }
}

impl Encoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> {
        //println!("Sending: {}", msg);
        buf.extend(msg.as_bytes());
        buf.extend(b"\n");
        Ok(())
    }
}

pub struct PingPong<T> {
    upstream: T,
    response: Option<String>,
    // TODO: stuff like AWAY ?
}

impl<T> PingPong<T> {
    fn new(t: T) -> Self {
        PingPong {
            upstream: t,
            response: None,
        }
    }
}

impl<T> Stream for PingPong<T>
    where T: Stream<Item = String, Error = io::Error>,
          T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type Item = String;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<String>, io::Error> {
        //loop {
        // Poll the upstream transport
        match try_ready!(self.upstream.poll()) {
            Some(ref msg) if msg.starts_with("PING ") => {
                // Intercept pings
                let resp = msg.replacen("PING", "PONG", 1);
                self.response = Some(resp);
                self.poll_complete()?;
                let _poll = try_ready!(self.upstream.poll());
                // Never hit:
                println!("UHHHH `{:?}`", _poll);
                unimplemented!();
                //Ok(Async::Ready(_poll))
            },
            // Final output:
            m => Ok(Async::Ready(m))
                //m => {
            //    self.upstream.foo();
            //},
        }
        //}
    }
}

impl<T> Sink for PingPong<T>
    where T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type SinkItem = String;
    type SinkError = io::Error;

    fn start_send(&mut self, item: String) -> StartSend<String, io::Error> {
        // Only accept the write if there are no pending pongs
        if self.response.is_some() {
            return Ok(AsyncSink::NotReady(item));
        }
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        if let Some(pong) = self.response.take() {
            self.upstream.start_send(pong)?;
        }
        self.upstream.poll_complete()
    }
}

pub struct LineProto;

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for LineProto {
    type Request = String;
    type Response = String;
    type Transport = PingPong<Framed<T, LineCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;
    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(PingPong::new(io.framed(LineCodec)))
    }
}

fn main() {
    //let addr = "0.0.0.0:12345".parse().unwrap();
    //TcpServer::new(IntProto, addr)
    //    .serve(|| Ok(Doubler));
    let cm = "USER qj 0 * qjkx\r\nNICK qjk\r\nJOIN #test\r\n".to_string();

    //let addr = "irc.freenode.org:6697".to_socket_addrs().unwrap().next().unwrap();
    let addr = "0.0.0.0:12345".to_socket_addrs().unwrap().next().unwrap();

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let tc = TcpClient::new(LineProto);
    let response = tc
        .connect(&addr, &handle)
        .and_then(|client| {
            client.call("ONE\r\n".to_string())
                .and_then(move |response| {
                    client.call("TWO".to_string())
                        .and_then(move |response| {
                            client.call("THREE".to_string())
                        })
                })
        });
    //let socket = tc.connect(&addr, &handle);
    //let response = socket.and_then(|x| x.call(cm));
    let data = core.run(response);//.unwrap();
    println!("{:?}", data);

    //let client = tc.and_then(|x| x.call(cm));
    //response.foo();
    //response.and_then(|x| future::ok(x).foo());
                    //client.call("BYE\r\n".to_string())

    //let listen = cli.connect(&addr, &handle).and_then(|r| { });
    //let listen = loop_fn(cli.connect(&addr, &handle), |msg| {
    //let listen = loop_fn(socket.and_then(|s| s.call(cm)), |msg| {

    //let listen: LoopFn<Result<_,io::Error>, _> = loop_fn(conn, |cli| {
        //cli.and_then(|x| cli.call());
        //cli.foo();
        //cli.and_then(|x| future::ok(x).foo())
        //let r = cli.and_then(|x| x.call("HI\r\n"));
        //let r = cli.call("HI\r\n");
        //r.foo();
    //});

    //let mut a = core.run(listen).unwrap();
    //a.poll();
        /*
    let listen: LoopFn<Result<_,io::Error>, _> = loop_fn(response, |x| {
        k
        x.and_then(|y| {
            //y.call("BAD\r\n").and_then(
            if y.contains("fuck") {
                //Ok(Loop::Break(y))
                Ok(Loop::Break(x))
            } else {
                Ok(Loop::Continue(x))
            }
        })
        */
    /*
        if true {
            Ok(Loop::Break(msg))
        } else {
            //Ok(Loop::Continue(msg))
            Ok(Loop::Break(msg))
        }
    });
        */

        /*
    let req = cli.connect(&addr, &handle)
        .and_then(|client| {
            client.call(cm)
                .and_then(move |response| {
                    println!("CLIENT: {:?}", response);
                    client.call("BYE\r\n".to_string())
                })
            .and_then(|response| {
                println!("CLIENT_: {:?}", response);
                Ok(())
            })
        });
        */

    //let response = socket.and_then(|x| x.call(cm));

    //let data = core.run(response);//.unwrap();
    //println!("{:?}", data);
    //let (_socket, data) = core.run(response).unwrap();
    //println!("{}", String::from_utf8_lossy(&data));
}
<commit_msg>loop_fn approach actually works. just need<commit_after>#[macro_use]
extern crate futures;
extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_core;
extern crate tokio_io;
extern crate bytes;

use std::{io, str};
use std::net::ToSocketAddrs;

use futures::{Future, Stream, Poll, Async};
use futures::{Sink, AsyncSink, StartSend};
use futures::future::{self, loop_fn, FutureResult, Loop, LoopFn};
use tokio_proto::TcpClient;
use tokio_proto::pipeline::ClientProto;
use tokio_service::Service;
use tokio_core::reactor::Core;
use tokio_io::codec::{Encoder, Decoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use bytes::BytesMut;

#[derive(Default)]
pub struct LineCodec;

impl Decoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
        println!("Received: {:?}", std::str::from_utf8(buf));
        if let Some(i) = buf.iter().position(|&b| b == b'\n') {
            let line = buf.split_to(i);
            buf.split_to(1);
            match str::from_utf8(&line) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other,
                                             "invalid UTF-8")),
            }
        } else {
            Ok(None)
        }
    }
}

impl Encoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> {
        //println!("Sending: {}", msg);
        buf.extend(msg.as_bytes());
        buf.extend(b"\n");
        Ok(())
    }
}

pub struct PingPong<T> {
    upstream: T,
    response: Option<String>,
    // TODO: stuff like AWAY ?
}

impl<T> PingPong<T> {
    fn new(t: T) -> Self {
        PingPong {
            upstream: t,
            response: None,
        }
    }
}

impl<T> Stream for PingPong<T>
    where T: Stream<Item = String, Error = io::Error>,
          T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type Item = String;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<String>, io::Error> {
        //loop {
        // Poll the upstream transport
        match try_ready!(self.upstream.poll()) {
            Some(ref msg) if msg.starts_with("PING ") => {
                // Intercept pings
                let resp = msg.replacen("PING", "PONG", 1);
                self.response = Some(resp);
                self.poll_complete()?;
                let _poll = try_ready!(self.upstream.poll());
                // Never hit:
                println!("UHHHH `{:?}`", _poll);
                unimplemented!();
                //Ok(Async::Ready(_poll))
            },
            // Final output:
            m => Ok(Async::Ready(m))
                //m => {
            //    self.upstream.foo();
            //},
        }
        //}
    }
}

impl<T> Sink for PingPong<T>
    where T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type SinkItem = String;
    type SinkError = io::Error;

    fn start_send(&mut self, item: String) -> StartSend<String, io::Error> {
        // Only accept the write if there are no pending pongs
        if self.response.is_some() {
            return Ok(AsyncSink::NotReady(item));
        }
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        if let Some(pong) = self.response.take() {
            self.upstream.start_send(pong)?;
        }
        self.upstream.poll_complete()
    }
}

pub struct LineProto;

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for LineProto {
    type Request = String;
    type Response = String;
    type Transport = PingPong<Framed<T, LineCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;
    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(PingPong::new(io.framed(LineCodec)))
    }
}

fn main() {
    //let addr = "0.0.0.0:12345".parse().unwrap();
    //TcpServer::new(IntProto, addr)
    //    .serve(|| Ok(Doubler));
    let cm = "USER qj 0 * qjkx\r\nNICK qjk\r\nJOIN #test\r\n".to_string();

    //let addr = "irc.freenode.org:6697".to_socket_addrs().unwrap().next().unwrap();
    let addr = "0.0.0.0:12345".to_socket_addrs().unwrap().next().unwrap();

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let tc = TcpClient::new(LineProto);
    /*
    let response = tc
        .connect(&addr, &handle)
        .and_then(|client| {
            client.call("ONE".to_string())
                .and_then(move |response| {
                    client.call("TWO".to_string())
                        .and_then(move |response| {
                            client.call("THREE".to_string())
                        })
                })
        });
        */
    let response = tc.connect(&addr, &handle)
        .and_then(|client| {
            client.call(cm)
                .and_then(move |r0| {
                    loop_fn(client, |c| {
                        c.call("ack".to_string())
                            .and_then(|ri| {
                                if ri == "DONE" {
                                    Ok(Loop::Break(c))
                                } else {
                                    Ok(Loop::Continue(c))
                                }
                            })
                    })
                })
        });
    //let socket = tc.connect(&addr, &handle);
    //let response = socket.and_then(|x| x.call(cm));

    let data = core.run(response);//.unwrap();
    //println!("{:?}", data);

    //let client = tc.and_then(|x| x.call(cm));
    //response.foo();
    //response.and_then(|x| future::ok(x).foo());
                    //client.call("BYE\r\n".to_string())

    //let listen = cli.connect(&addr, &handle).and_then(|r| { });
    //let listen = loop_fn(cli.connect(&addr, &handle), |msg| {
    //let listen = loop_fn(socket.and_then(|s| s.call(cm)), |msg| {

    //let listen: LoopFn<Result<_,io::Error>, _> = loop_fn(conn, |cli| {
        //cli.and_then(|x| cli.call());
        //cli.foo();
        //cli.and_then(|x| future::ok(x).foo())
        //let r = cli.and_then(|x| x.call("HI\r\n"));
        //let r = cli.call("HI\r\n");
        //r.foo();
    //});

    //let mut a = core.run(listen).unwrap();
    //a.poll();
        /*
    let listen: LoopFn<Result<_,io::Error>, _> = loop_fn(response, |x| {
        k
        x.and_then(|y| {
            //y.call("BAD\r\n").and_then(
            if y.contains("fuck") {
                //Ok(Loop::Break(y))
                Ok(Loop::Break(x))
            } else {
                Ok(Loop::Continue(x))
            }
        })
        */
    /*
        if true {
            Ok(Loop::Break(msg))
        } else {
            //Ok(Loop::Continue(msg))
            Ok(Loop::Break(msg))
        }
    });
        */

        /*
    let req = cli.connect(&addr, &handle)
        .and_then(|client| {
            client.call(cm)
                .and_then(move |response| {
                    println!("CLIENT: {:?}", response);
                    client.call("BYE\r\n".to_string())
                })
            .and_then(|response| {
                println!("CLIENT_: {:?}", response);
                Ok(())
            })
        });
        */

    //let response = socket.and_then(|x| x.call(cm));

    //let data = core.run(response);//.unwrap();
    //println!("{:?}", data);
    //let (_socket, data) = core.run(response).unwrap();
    //println!("{}", String::from_utf8_lossy(&data));
}
<|endoftext|>


<commit_before>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(plugin, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use std::sync::{Arc,RWLock};
use std::comm::{DuplexStream,Disconnected,Empty};
use std::task::TaskBuilder;
use native::NativeTaskBuilder;

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let args = std::os::args();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").as_slice(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = std::comm::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	TaskBuilder::new().native().spawn(proc() cpuloop(&cpustream, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<commit_msg>Run at (real) full speed when shift is pressed<commit_after>#![crate_id = "rboy"]
#![license = "MIT"]

#![feature(phase)]
#[phase(plugin, link)] extern crate log;

extern crate native;
extern crate getopts;
extern crate time;
extern crate sdl;
#[cfg(test)]
extern crate test;

use cpu::CPU;
use std::sync::{Arc,RWLock};
use std::comm::{DuplexStream,Disconnected,Empty};
use std::task::TaskBuilder;
use native::NativeTaskBuilder;

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;
mod util;

static SCALE: uint = 2;

#[cfg(not(test))]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }

fn main() {
	let args = std::os::args();
	let opts = [ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free.get(0).clone()
	} else {
		println!("{}", getopts::usage(args.get(0).clone().append(" <filename>").as_slice(), opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE as int, 144*SCALE as int, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = std::comm::duplex();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	TaskBuilder::new().native().spawn(proc() cpuloop(&cpustream, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&screen, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	let data = arc.read();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.fill_rect(
				Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
				sdl::video::RGB(data[y*160*3 + x*3 + 0],
				                data[y*160*3 + x*3 + 1],
				                data[y*160*3 + x*3 + 2])
			);
		}
	}
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); return; },
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);
	let mut limit_speed = true;

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				let mut data = arc.write();
				for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				if channel.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match channel.try_recv() {
			Ok(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => limit_speed = false,
				SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<|endoftext|>


<commit_before>extern crate particles;
extern crate rand;

use particles::*;
use rand::{StdRng};

fn main() {
  const NUM_PARTICLES: usize = 10;

  let max_particle = Particle {
    x: Vector((20., 20.)),
    v: Vector((1., 1.)),
    m: 1.,
    r: 1.
  };
  let min_particle = Particle {
    x: Vector((-20., -20.)),
    v: Vector((-1., -1.)),
    m: 1.,
    r: 1.
  };
  let mut rng = StdRng::new().unwrap();

  let mut particles = Vec::with_capacity(NUM_PARTICLES);
  for _ in 0..NUM_PARTICLES {
    let mut new_p: Particle;
    loop {
      new_p = BoundedRand::rand(&mut rng, &min_particle, &max_particle);
      if ! particles.iter().any(|p: &Particle| p.overlaps(&new_p)) { break; }
    }
    particles.push(new_p);
  }

  let mut space = SpaceVec::new(particles);
  let mut i = 0;

  println!("starting: {:?}", space);
  while i < 10 && space.iterate() {
    println!("{}: {:?}", i, space);
    i += 1;
  }
  println!("ending");
}
<commit_msg>[r] modify main to run with SpaceBox<commit_after>extern crate particles;
extern crate rand;

use particles::*;
use rand::{StdRng};

fn main() {
  const NUM_PARTICLES: usize = 10;

  let top_left = Vector((-20., 20.));
  let bottom_right = Vector((20., -20.));

  let max_particle = Particle {
    x: Vector((20., 20.)),
    v: Vector((1., 1.)),
    m: 1.,
    r: 1.
  };
  let min_particle = Particle {
    x: Vector((-20., -20.)),
    v: Vector((-1., -1.)),
    m: 1.,
    r: 1.
  };
  let mut rng = StdRng::new().unwrap();

  let mut particles = Vec::with_capacity(NUM_PARTICLES);
  for _ in 0..NUM_PARTICLES {
    let mut new_p: Particle;
    loop {
      new_p = BoundedRand::rand(&mut rng, &min_particle, &max_particle);
      if ! particles.iter().any(|p: &Particle| p.overlaps(&new_p)) { break; }
    }
    particles.push(new_p);
  }

  let mut space = SpaceBox::new(particles, top_left, bottom_right);
  let mut i = 0;

  println!("starting: {:?}", space);
  while i < 10 && space.iterate() {
    println!("{}: {:?}", i, space);
    i += 1;
  }
  println!("ending");
}
<|endoftext|>


<commit_before>#![feature(time2)]

#![allow(unused)]
#![warn(unused_must_use)]

extern crate fuse;
extern crate time;
extern crate nix;

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

use nix::sys::signal;

use std::sync::{Condvar, Mutex, MutexGuard};

type BlockIndex = u64;

#[derive(Eq,PartialEq)]
struct DelayedWriteback {
    to_be_written_at : Instant,
    block_index : BlockIndex,
}

type BlockCache = std::collections::BTreeMap<BlockIndex, Vec<u64>>;
type Queue = std::collections::BinaryHeap<DelayedWriteback>;

struct State {
    cache: BlockCache,
    queue: Queue,
    attention_of_writeback_thread: Condvar,
}

impl Default for State { fn default() -> Self { State {
        cache: Default::default(),
        queue: Default::default(),
        attention_of_writeback_thread: Condvar::new(), // https://github.com/rust-lang/rust/issues/31865
    } } }

impl Ord for DelayedWriteback {
    fn cmp(&self, peer:&DelayedWriteback) -> ::std::cmp::Ordering {
        use std::cmp::Ordering::{Greater,Less,Equal};
        // flipped ordering for the time
        let o1 = peer.to_be_written_at.cmp(&self.to_be_written_at);
        if o1 != Equal { return o1; }

        // fall-back ordering by index
        return self.block_index.cmp(&peer.block_index);
    }
}
impl PartialOrd for DelayedWriteback {
    fn partial_cmp(&self, other: &DelayedWriteback) -> Option<::std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

extern fn handle_sigint(_:i32) {
    let outstanding_blocks = 0;
    println!("Throwing away {} dirty blocks.", outstanding_blocks);
    ::std::process::exit(0);
}

fn main () {
    let argv = env::args_os();
    if argv.count() != 6 {
        println!("Usage: outoforderfs source_file mountpoint_file blocksize maxtime_ms maxdirtyblocks");
        println!(" outoforderfs 'mirrors' source file to mountpoint_file,");
        println!(" but writes to mountpoint_file get delivered");
        println!(" to source_file after a random delay, in random order.");
        println!(" The reason is to see what happens of some other FS in case of");
        println!(" surprise removal (or sudden shutdown) of the storage.");
        println!("Example session (approximate):");
        println!(" 1$ dd if=/dev/zero bs=4096 count=2560 of=sf.dat");
        println!(" 1$ touch mp.dat");
        println!(" 1$ outoforderfs sf.dat mp.dat 4096 10000 100");
        println!(" 1$ (switch to a new tab)");
        println!(" 2$   mkfs mp.dat");
        println!(" 2$   mount mp.dat -o loop mnt");
        println!(" 2$   start using mnt (filling with logs, creating sqlite, etc)");
        println!(" 1$ ^C");
        println!(" 1$ outoforderfs sf.dat mp.dat 4096 10000 100");
        println!(" 2$   umount mnt");
        println!(" 2$   mount mp.dat -o loop mnt");
        println!(" 2$   inspect mnt for breakage, incomplete/zeroed files, etc");

        ::std::process::exit(1);
    }
    let source_file     = env::args_os().nth(1).unwrap();
    let mountpoint_file = env::args_os().nth(2).unwrap();
    let blocksize       = env::args_os().nth(3).unwrap();
    let maxtime         = env::args_os().nth(4).unwrap();
    let maxblocks       = env::args_os().nth(5).unwrap();
    //fuse::mount(OutoforderFs, &mountpoint, &[]);

    let sig_action = signal::SigAction::new(handle_sigint,
                                          signal::SockFlag::empty(),
                                          signal::SigSet::empty());
    unsafe { signal::sigaction(signal::SIGINT, &sig_action).unwrap(); }

    ::std::thread::sleep(Duration::from_secs(1));
}
<commit_msg>Implement writeback thread<commit_after>#![feature(time2)]

#![allow(unused)]
#![warn(unused_must_use)]

extern crate fuse;
extern crate time;
extern crate nix;

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

use nix::sys::signal;

use std::sync::{Condvar, Mutex, MutexGuard};
use std::sync::Arc;
use std::io::{Write,Read,Seek,SeekFrom};
use std::cell::RefCell;

type BlockIndex = u64;

#[derive(Eq,PartialEq)]
struct DelayedWriteback {
    to_be_written_at : Instant,
    block_index : BlockIndex,
}

type BlockCache = std::collections::BTreeMap<BlockIndex, Vec<u8>>;
type Queue = std::collections::BinaryHeap<DelayedWriteback>;

#[derive(Default)]
struct CacheState {
    cache: BlockCache,
    queue: Queue,
}

struct WritebackThread {
    s : Mutex<CacheState>,
    attention: Condvar,
}

impl Default for WritebackThread { fn default() -> Self { WritebackThread {
        s: Mutex::new(Default::default()),
        attention: Condvar::new(), // https://github.com/rust-lang/rust/issues/31865
    } } }

impl WritebackThread {
    fn run<W>(&self, mut file: W, blocksize: u64) where W : Write + Seek  {

        let mut writeback : Option<(SeekFrom, Vec<u8>)>;

        writeback = None;
        loop {
            if let Some((seekpos, data)) = writeback {
                file.seek(seekpos).expect("seek failed");
                file.write(data.as_ref()).expect("write failed");
                writeback = None;
            }

            let mut g = self.s.lock().unwrap();

            loop {
                let timetowait : Option<Duration>;

                let needwriteback : bool;
                if let Some(p) = g.queue.peek() {
                    let now = Instant::now();

                    if p.to_be_written_at <= now {
                        needwriteback = true;
                        timetowait = None; // actually should not be necessary
                    } else {
                        needwriteback = false;
                        timetowait = Some(p.to_be_written_at.duration_from_earlier(now));
                    }
                } else {
                    needwriteback = false;
                    timetowait = None;
                }

                if needwriteback {
                    let p = g.queue.pop().unwrap();
                    let data = g.cache.remove(&p.block_index).expect("inconsistency detected");
                    writeback = Some((SeekFrom::Start(blocksize * p.block_index), data));
                    break; // release lock and go to outer loop
                }

                if let Some(ttw) = timetowait {
                    let (g2, _) = self.attention.wait_timeout(g, ttw).unwrap();
                    g = g2;
                } else {
                    g = self.attention.wait(g).unwrap();
                }
            }
        }
    }
}

impl Ord for DelayedWriteback {
    fn cmp(&self, peer:&DelayedWriteback) -> ::std::cmp::Ordering {
        use std::cmp::Ordering::{Greater,Less,Equal};
        // flipped ordering for the time
        let o1 = peer.to_be_written_at.cmp(&self.to_be_written_at);
        if o1 != Equal { return o1; }

        // fall-back ordering by index
        return self.block_index.cmp(&peer.block_index);
    }
}
impl PartialOrd for DelayedWriteback {
    fn partial_cmp(&self, other: &DelayedWriteback) -> Option<::std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

extern fn handle_sigint(_:i32) {
    let outstanding_blocks = 0;
    println!("Throwing away {} dirty blocks.", outstanding_blocks);
    ::std::process::exit(0);
}

fn main () {
    let argv = env::args_os();
    if argv.count() != 6 {
        println!("Usage: outoforderfs source_file mountpoint_file blocksize maxtime_ms maxdirtyblocks");
        println!(" outoforderfs 'mirrors' source file to mountpoint_file,");
        println!(" but writes to mountpoint_file get delivered");
        println!(" to source_file after a random delay, in random order.");
        println!(" The reason is to see what happens of some other FS in case of");
        println!(" surprise removal (or sudden shutdown) of the storage.");
        println!("Example session (approximate):");
        println!(" 1$ dd if=/dev/zero bs=4096 count=2560 of=sf.dat");
        println!(" 1$ touch mp.dat");
        println!(" 1$ outoforderfs sf.dat mp.dat 4096 10000 100");
        println!(" 1$ (switch to a new tab)");
        println!(" 2$   mkfs mp.dat");
        println!(" 2$   mount mp.dat -o loop mnt");
        println!(" 2$   start using mnt (filling with logs, creating sqlite, etc)");
        println!(" 1$ ^C");
        println!(" 1$ outoforderfs sf.dat mp.dat 4096 10000 100");
        println!(" 2$   umount mnt");
        println!(" 2$   mount mp.dat -o loop mnt");
        println!(" 2$   inspect mnt for breakage, incomplete/zeroed files, etc");

        ::std::process::exit(1);
    }
    let source_file     = env::args_os().nth(1).unwrap();
    let mountpoint_file = env::args_os().nth(2).unwrap();
    let blocksize       = env::args_os().nth(3).unwrap();
    let maxtime         = env::args_os().nth(4).unwrap();
    let maxblocks       = env::args_os().nth(5).unwrap();
    //fuse::mount(OutoforderFs, &mountpoint, &[]);

    let sig_action = signal::SigAction::new(handle_sigint,
                                          signal::SockFlag::empty(),
                                          signal::SigSet::empty());
    unsafe { signal::sigaction(signal::SIGINT, &sig_action).unwrap(); }

    ::std::thread::sleep(Duration::from_secs(1));
}
<|endoftext|>


<commit_before>
#![feature(io)]

use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::sync::{Arc, Mutex };
use std::sync::mpsc::{ channel, Sender, Receiver };
use std::thread;

// State Function
struct StateFn<E: std::error::Error>(fn(l: &Lex<E>)->Option<StateFn<E>>);

#[derive(Debug)]
struct Pos {
    line: u64,
    col: u64
}

// Position
impl Pos {
    fn new()->Pos {
        Pos {
            line: 0,
            col: 0
        }
    }
}

#[derive(Debug)]
enum TokenType {
    Integer,
    Operator
}

#[derive(Debug)]
struct Token {
    pos: Pos,
    typ: TokenType,
    val: String
}

trait Lex<E: std::error::Error> {
    fn next(&self)->Result<char, E>;
    fn emit(&self);
}

// State Machine
struct Lexer<R: io::Read+Send> {
    pos: Pos,
    buf: Arc<Mutex<io::Chars<R>>>,
    state: StateFn<io::CharsError>,
    send: Option<Sender<Token>>
}

fn start_state<E: std::error::Error>(l: &Lex<E>)->Option<StateFn<E>> {
    l.emit();
    None
}

impl<R: io::Read+Send+'static> Lexer<R> {
    fn new(reader: R)->Lexer<R> {
        Lexer {
            pos: Pos::new(),
            buf: Arc::new(Mutex::new(reader.chars())),
            state: StateFn(start_state),
            send: None
        }
    }

    fn lex(mut self)->(thread::JoinHandle<()>, Receiver<Token>) {
        let (tx, rx) = channel();
        self.send = Some(tx);
        (thread::spawn(move || {
            loop {
                match (self.state.0)(&self) {
                    Some(s) => { self.state = s; }
                    None => { return }
                }
            }
        }), rx)
    }
}

impl<R: io::Read+Send> Lex<io::CharsError> for Lexer<R> {
    fn next(&self)->Result<char, io::CharsError> {
        self.buf.lock().unwrap().next().unwrap()
    }

    fn emit(&self) {
        self.send.as_ref().unwrap().send(Token{
            pos: Pos::new(),
            typ: TokenType::Integer,
            val: "Test".to_string()
        }).unwrap();
    }
}

fn main() {
    let lexer = Lexer::new(BufReader::new(File::open("src.f").unwrap()));
    let (th, rx) = lexer.lex();
    println!("{:?}", rx.recv().unwrap());
    th.join().unwrap();
}
<commit_msg>update<commit_after>
#![feature(io)]

use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::sync::{ Arc, Mutex, MutexGuard };
use std::sync::mpsc::{ channel, Sender, Receiver };
use std::thread;

// State Function
struct StateFn<E: std::error::Error>(fn(l: &mut Lex<E>)->Option<StateFn<E>>);

#[derive(Debug)]
struct Pos {
    pos: u64,
    line: u64,
    col: u64
}

// Position
impl Pos {
    fn new()->Pos {
        Pos {
            pos: 0,
            line: 0,
            col: 0
        }
    }

    fn next(&mut self, c: char) {
        self.pos += 1;
        match c {
            '\n' => {
                self.line += 1;
                self.col = 0;
            },
            _ => self.col += 1
        }
    }

    fn back(&mut self, c: char) {
        self.pos -= 1;
        match c {
            // Don't back over newlines.
            _ => self.col -= 1
        }
    }
}

#[derive(Debug)]
enum TokenType {
    Integer,
    Operator
}

#[derive(Debug)]
struct Token {
    pos: Pos,
    typ: TokenType,
    val: String
}

trait Lex<E: std::error::Error> {
    fn next(&mut self)->Result<char, E>;
    fn back(&mut self);
    fn emit(&mut self);
}

// State Machine
struct Lexer<R: io::Read+Send> {
    // Current position
    pos: Pos,
    // Input character stream
    input: Arc<Mutex<io::Chars<R>>>,
    // Back buffer
    backbuf: Vec<char>,
    // Unemitted buffer
    buf: Vec<char>,
    // State machine position
    state: StateFn<io::CharsError>,
    // Sending handle to token channel
    send: Option<Sender<Token>>,
    // Sending state machine thread handle
    handle: Option<thread::JoinHandle<()>>
}

fn start_state<E: std::error::Error>(l: &mut Lex<E>)->Option<StateFn<E>> {
    l.emit();
    None
}

impl<R: io::Read+Send+'static> Lexer<R> {
    fn new(reader: R)->Lexer<R> {
        let mut l = Lexer {
            pos: Pos::new(),
            input: Arc::new(Mutex::new(reader.chars())),
            buf: Vec::<char>::new(),
            backbuf: Vec::<char>::new(),
            state: StateFn(start_state),
            send: None,
            handle: None,
        };
        l
    }

    fn spawn(mut self)->Receiver<Token> {
        let (tx, rx) = channel();
        self.send = Some(tx);
        self.handle = Some(thread::spawn(move || {
            loop {
                match (self.state.0)(&mut self) {
                    Some(s) => self.state = s,
                    None => return
                }
            }
        }));
        rx
    }
}

impl<R: io::Read+Send> Lex<io::CharsError> for Lexer<R> {
    fn next(&mut self)->Result<char, io::CharsError> {
        let c = if self.backbuf.len() == 0 {
            'h'
            // self.input.lock().unwrap().next().unwrap()
        } else {
            self.backbuf.pop().unwrap()
        };
        self.buf.push(c); // Push to unemitted buffer
        self.pos.next(c); // Update position
        Ok(c)
    }

    fn back(&mut self) {
        self.buf.push(self.backbuf.pop().unwrap())
    }

    fn emit(&mut self) {
        self.send.as_ref().unwrap().send(Token{
            pos: Pos::new(),
            typ: TokenType::Integer,
            val: "Test".to_string()
        }).unwrap();
    }
}

fn main() {
    let lexer = Lexer::new(BufReader::new(File::open("src.f").unwrap()));
    let rx = lexer.spawn();
    println!("{:?}", rx.recv().unwrap());
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate walkdir;

use walkdir::WalkDir;
use rand::{Rng, thread_rng};
use std::env;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use std::io::Error;
use std::cmp;

fn main() {
    let mut recursive: bool = false;
    let mut file: String = String::from("");
    let mut i: i32 = -1;

    for argument in env::args() {
        i += 1;
        if i == 0 {
            continue;
        }

        if argument.to_lowercase() == "--help" || argument.to_lowercase() == "-help" {
            help();
            return;
        } else if argument.to_lowercase() == "--v" || argument.to_lowercase() == "-v" ||
           argument.to_lowercase() == "-version" ||
           argument.to_lowercase() == "--version" {
            version();
            return;
        } else if argument.to_lowercase() == "-r" {
            recursive = true;
        } else {
            file = argument;
            break;
        }
    }
    if file == "" {
        help();
        return;
    }
    file = get_path(&file);

    if recursive {
        for entry in WalkDir::new(file) {
            let entry = entry.unwrap();
            trumpify(entry.path().display().to_string());
        }
    } else {
        trumpify(file)
    }
}

fn get_path2(file: &str) -> Result<String, Error> {
    let path = try!(fs::canonicalize(file));
    return Ok(path.display().to_string());
}

fn get_path(file: &str) -> String {
    return get_path2(file).unwrap_or(file.to_string());
}

fn read_file2(file: &str) -> Result<String, Error> {
    let mut file = try!(File::open(file));
    let mut contents: Vec<u8> = Vec::new();
    try!(file.read_to_end(&mut contents));
    let ret = String::from_utf8(contents).unwrap_or("".to_string());
    return Ok(ret);
}

fn read_file(file: &str) -> String {
    return read_file2(file).unwrap_or("".to_string());
}

fn write_file2(file: &str, content: String) -> Result<bool, Error> {
    let mut f = try!(File::create(file));
    try!(f.write_all(content.as_bytes()));

    try!(f.sync_data());
    return Ok(false);
}

fn write_file(file: &str, content: String) {
    write_file2(file, content).unwrap_or(false);
}

fn version() {
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump-0.1.0");
    println!("\x1b[32mWebsite:");
    println!("\x1b[0m    https://github.com/x13machine/trump/");
    println!("\x1b[32mCreator:");
    println!("\x1b[0m    <Googolplexking/x13machine> https://googolplex.ninja/");
}
fn help() {
    println!("\x1b[32mHelp:");
    println!("\x1b[0m    trump --help");
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump -v");
    println!("\x1b[32mFiles:");
    println!("\x1b[0m    trump <File>");
    println!("\x1b[32mDirectories:");
    println!("\x1b[0m    trump -r <Directory>");
}

fn trumpify(file: String) {
    let dirs: Vec<&str> = file.split("/").collect::<Vec<&str>>();
    let mut name: String = String::from(dirs[dirs.len() - 1]);
    name = format!("{}{}",
                   &name[0..1].to_uppercase(),
                   &name[1..name.len()].to_lowercase());
    // Ansi Color Codes!!!
    println!("\x1b[32mMaking Great Again:\x1b[0m {}", file);

    let text = format!("Make {} Great Again!", name);

    let mut content: String = read_file(&file);
    if content == "" {
        return;
    }

    let loops = cmp::max(content.len() / text.len() / 2, 1);
    let mut rng = thread_rng();
    for i in 0..loops {
        let place: usize = rng.gen_range(0, content.len() as u32) as usize;
        let part1: String = String::from(&content[0..place]);
        let part2: String =
            String::from(&content[cmp::min(place + text.len(), content.len())..content.len()]);
        content = format!("{}{}{}", part1, text, part2);
    }
    write_file(&file, content);
}
<commit_msg>Remove unused variable<commit_after>extern crate rand;
extern crate walkdir;

use walkdir::WalkDir;
use rand::{Rng, thread_rng};
use std::env;
use std::fs::File;
use std::fs;
use std::io::prelude::*;
use std::io::Error;
use std::cmp;

fn main() {
    let mut recursive: bool = false;
    let mut file: String = String::from("");
    let mut i: i32 = -1;

    for argument in env::args() {
        i += 1;
        if i == 0 {
            continue;
        }

        if argument.to_lowercase() == "--help" || argument.to_lowercase() == "-help" {
            help();
            return;
        } else if argument.to_lowercase() == "--v" || argument.to_lowercase() == "-v" ||
           argument.to_lowercase() == "-version" ||
           argument.to_lowercase() == "--version" {
            version();
            return;
        } else if argument.to_lowercase() == "-r" {
            recursive = true;
        } else {
            file = argument;
            break;
        }
    }
    if file == "" {
        help();
        return;
    }
    file = get_path(&file);

    if recursive {
        for entry in WalkDir::new(file) {
            let entry = entry.unwrap();
            trumpify(entry.path().display().to_string());
        }
    } else {
        trumpify(file)
    }
}

fn get_path2(file: &str) -> Result<String, Error> {
    let path = try!(fs::canonicalize(file));
    return Ok(path.display().to_string());
}

fn get_path(file: &str) -> String {
    return get_path2(file).unwrap_or(file.to_string());
}

fn read_file2(file: &str) -> Result<String, Error> {
    let mut file = try!(File::open(file));
    let mut contents: Vec<u8> = Vec::new();
    try!(file.read_to_end(&mut contents));
    let ret = String::from_utf8(contents).unwrap_or("".to_string());
    return Ok(ret);
}

fn read_file(file: &str) -> String {
    return read_file2(file).unwrap_or("".to_string());
}

fn write_file2(file: &str, content: String) -> Result<bool, Error> {
    let mut f = try!(File::create(file));
    try!(f.write_all(content.as_bytes()));

    try!(f.sync_data());
    return Ok(false);
}

fn write_file(file: &str, content: String) {
    write_file2(file, content).unwrap_or(false);
}

fn version() {
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump-0.1.0");
    println!("\x1b[32mWebsite:");
    println!("\x1b[0m    https://github.com/x13machine/trump/");
    println!("\x1b[32mCreator:");
    println!("\x1b[0m    <Googolplexking/x13machine> https://googolplex.ninja/");
}
fn help() {
    println!("\x1b[32mHelp:");
    println!("\x1b[0m    trump --help");
    println!("\x1b[32mVersion:");
    println!("\x1b[0m    trump -v");
    println!("\x1b[32mFiles:");
    println!("\x1b[0m    trump <File>");
    println!("\x1b[32mDirectories:");
    println!("\x1b[0m    trump -r <Directory>");
}

fn trumpify(file: String) {
    let dirs: Vec<&str> = file.split("/").collect::<Vec<&str>>();
    let mut name: String = String::from(dirs[dirs.len() - 1]);
    name = format!("{}{}",
                   &name[0..1].to_uppercase(),
                   &name[1..name.len()].to_lowercase());
    // Ansi Color Codes!!!
    println!("\x1b[32mMaking Great Again:\x1b[0m {}", file);

    let text = format!("Make {} Great Again!", name);

    let mut content: String = read_file(&file);
    if content == "" {
        return;
    }

    let loops = cmp::max(content.len() / text.len() / 2, 1);
    let mut rng = thread_rng();
    for _ in 0..loops {
        let place: usize = rng.gen_range(0, content.len() as u32) as usize;
        let part1: String = String::from(&content[0..place]);
        let part2: String =
            String::from(&content[cmp::min(place + text.len(), content.len())..content.len()]);
        content = format!("{}{}{}", part1, text, part2);
    }
    write_file(&file, content);
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(if_let)]

#[phase(plugin)]
extern crate rustecs_macros;

extern crate rustecs;
extern crate serialize;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;
use std::cell::RefCell;
use std::default::Default;
use std::rc::Rc;
use std::rand;
use std::rand::Rng;
use std::num::abs;

use opengl_graphics::{
    Gl,
    Texture,
};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
};
use piston::graphics::{
    AddBorder,
    AddRectangle,
    AddEllipse,
    AddColor,
    Context,
    Draw,
};
use piston::event::{
    UpdateEvent,
    Event,
    Render,
    Update,
    Input,
};
use piston::input::{
    Focus,
};

use rustecs::{
    Entities,
    Components,
};

fn drawSystem(event: &Event,
              gl: &mut Gl,
              positions: &mut Components<Position>,
              shapes: &mut Components<Shape>) {
    if let &Render(args) = event {
        let w = args.width as f64;
        let h = args.height as f64;
        gl.viewport(0, 0, w as i32, h as i32);
        let c = Context::abs(w, h);
        // Clear background.
        c.rgb(0.0, 0.0, 0.0).draw(gl);

        for (eid, pos) in positions.iter_mut() {
          let mut shape = Point;
          let mut border = None;
          if shapes.contains_key(eid) {
            shape = shapes.get_mut(eid).shape;
            border = shapes.get_mut(eid).border;
          }
          let r = 0.5;
          let g = 0.2;
          let b = 0.8;
          let mut drawing = c.rgb(r, g, b);
          match (shape, border) {
              (Point, None)    => drawing.rect(1.0, 1.0, w, h).draw(gl),
              (Point, Some(b)) => drawing.rect(1.0, 1.0, w, h).border_radius(b).draw(gl),

              (Circle(rad), None)    => drawing.ellipse(pos.x, pos.y, rad, rad).draw(gl),
              (Circle(rad), Some(b)) => drawing.ellipse(pos.x, pos.y, rad, rad).border_radius(b).draw(gl),

              (Square(w,h), None)    => drawing.rect(pos.x, pos.y, w, h).draw(gl),
              (Square(w,h), Some(b)) => drawing.rect(pos.x, pos.y, w, h).border_radius(b).draw(gl),
          };
        }
    }
}

fn moveSystem(event: &Event,
              positions: &mut Components<Position>,
              velocities: &mut Components<Velocity>) {
    if let &Update(args) = event {
        let dt = args.dt;
        for (eid, position) in positions.iter_mut() {
            if !velocities.contains_key(eid) {
                continue;
            }

            // If we have both a position and a velocity, integrate.
            let velocity = velocities.get_mut(eid);
            position.x += velocity.x * dt;
            position.y += velocity.y * dt;
            if position.x > 800.0 || position.x < 0.0 {
                velocity.x *= -1.0;
            }
            if position.y > 600.0 || position.y < 0.0 {
                velocity.y *= -1.0;
            }
        }
    }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Position {
    x: f64,
    y: f64
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { Point }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Shape {
    shape: ShapeVarient,
    border: Option<f64>
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Velocity {
    x: f64,
    y: f64
}

world! {
    World,
    components Position, Shape, Velocity;
}

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Shooter".to_string(),
            size: [800, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);

    let mut world = World::new();

    let num_things: i32 = 300;

    let ref mut rng = rand::task_rng();
    for _ in range(0, num_things) {
        let r = rng.gen_range(10.0, 40.0);
        let shape = if rng.gen() {
            Square(r, r)
        } else {
            Circle(r)
        };
        let border = Some(rng.gen_range(1.0, 3.0));

        let x = (800.0 - r) / 2.0;
        let y = (600.0 - r) / 2.0;

        let e = Entity::new()
            .with_position(
                Position{
                    x: x,
                    y: y
                })
            .with_velocity(
                Velocity {
                    x: rng.gen_range(-80.0, 80.0),
                    y: rng.gen_range(-80.0, 80.0)
                })
            .with_shape(
                Shape {
                    shape: shape,
                    border: border
                });
        world.add(e);
    }
    let event_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    for e in EventIterator::new(&mut window, &event_settings) {
        moveSystem(&e, &mut world.positions, &mut world.velocities);
        drawSystem(&e, &mut gl, &mut world.positions, &mut world.shapes);
    }
}
<commit_msg>Add color and shimmer components<commit_after>#![feature(phase)]
#![feature(if_let)]

#[phase(plugin)]
extern crate rustecs_macros;

extern crate rustecs;
extern crate serialize;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;
use std::cell::RefCell;
use std::default::Default;
use std::rc::Rc;
use std::rand;
use std::rand::Rng;
use std::num::abs;

use opengl_graphics::{
    Gl,
    Texture,
};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
};
use piston::graphics::{
    AddBorder,
    AddRectangle,
    AddEllipse,
    AddColor,
    Context,
    Draw,
};
use piston::event::{
    UpdateEvent,
    Event,
    Render,
    Update,
    Input,
};
use piston::input::{
    Focus,
};

use rustecs::{
    Entities,
    Components,
};

fn drawSystem(event: &Event,
              gl: &mut Gl,
              positions: &mut Components<Position>,
              shapes: &mut Components<Shape>,
              colors: &mut Components<Color>) {
    if let &Render(args) = event {
        let w = args.width as f64;
        let h = args.height as f64;
        gl.viewport(0, 0, w as i32, h as i32);
        let c = Context::abs(w, h);
        // Clear background.
        c.rgb(0.0, 0.0, 0.0).draw(gl);

        for (eid, pos) in positions.iter_mut() {
          let mut shape = Point;
          let mut border = None;
          if shapes.contains_key(eid) {
            shape = shapes.get_mut(eid).shape;
            border = shapes.get_mut(eid).border;
          }
          let (r, g, b) = if colors.contains_key(eid) {
              (colors.get_mut(eid).r, colors.get_mut(eid).g, colors.get_mut(eid).b)
          } else {
              (1.0, 1.0, 1.0)
          };
          let mut drawing = c.rgb(r, g, b);
          match (shape, border) {
              (Point, None)    => drawing.rect(1.0, 1.0, w, h).draw(gl),
              (Point, Some(b)) => drawing.rect(1.0, 1.0, w, h).border_radius(b).draw(gl),

              (Circle(rad), None)    => drawing.ellipse(pos.x, pos.y, rad, rad).draw(gl),
              (Circle(rad), Some(b)) => drawing.ellipse(pos.x, pos.y, rad, rad).border_radius(b).draw(gl),

              (Square(w,h), None)    => drawing.rect(pos.x, pos.y, w, h).draw(gl),
              (Square(w,h), Some(b)) => drawing.rect(pos.x, pos.y, w, h).border_radius(b).draw(gl),
          };
        }
    }
}

fn shimmerSystem(event: &Event,
                 colors: &mut Components<Color>) {
    for (_, color) in colors.iter_mut() {
        let ref mut rng = rand::task_rng();
        color.r = rng.gen_range(0.5, 1.0);
        color.g = rng.gen_range(0.5, 1.0);
        color.b = rng.gen_range(0.5, 1.0);
    }
}

fn moveSystem(event: &Event,
              positions: &mut Components<Position>,
              velocities: &mut Components<Velocity>) {
    if let &Update(args) = event {
        let dt = args.dt;
        for (eid, position) in positions.iter_mut() {
            if !velocities.contains_key(eid) {
                continue;
            }

            // If we have both a position and a velocity, integrate.
            let velocity = velocities.get_mut(eid);
            position.x += velocity.x * dt;
            position.y += velocity.y * dt;
            if position.x > 800.0 || position.x < 0.0 {
                velocity.x *= -1.0;
            }
            if position.y > 600.0 || position.y < 0.0 {
                velocity.y *= -1.0;
            }
        }
    }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Position {
    x: f64,
    y: f64
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { Point }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Shape {
    shape: ShapeVarient,
    border: Option<f64>
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Velocity {
    x: f64,
    y: f64
}

world! {
    World,
    components Position, Shape, Velocity, Color;
}

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Shooter".to_string(),
            size: [800, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);

    let mut world = World::new();

    let num_things: i32 = 300;

    let ref mut rng = rand::task_rng();
    for _ in range(0, num_things) {
        let r = rng.gen_range(10.0, 40.0);
        let shape = if rng.gen() {
            Square(r, r)
        } else {
            Circle(r)
        };
        let border = Some(rng.gen_range(1.0, 3.0));

        let x = (800.0 - r) / 2.0;
        let y = (600.0 - r) / 2.0;

        let e = Entity::new()
            .with_position(
                Position{
                    x: x,
                    y: y
                })
            .with_velocity(
                Velocity {
                    x: rng.gen_range(-80.0, 80.0),
                    y: rng.gen_range(-80.0, 80.0)
                })
            .with_shape(
                Shape {
                    shape: shape,
                    border: border
                })
            .with_color(
                Color{
                    r: 1.0,
                    g: 0.5,
                    b: 0.2
                });
        world.add(e);
    }
    let event_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    for e in EventIterator::new(&mut window, &event_settings) {
        moveSystem(&e, &mut world.positions, &mut world.velocities);
        shimmerSystem(&e, &mut world.colors);
        drawSystem(&e, &mut gl, &mut world.positions, &mut world.shapes, &mut world.colors);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate libc;
extern crate signal;

use clap::ArgMatches;
use std::time::Duration;
use world::World;

#[macro_use]
mod macros;
mod world;

const MAPS_MSG: &'static str = "\
MAPS:
    Maps must be rectangular. Whitespace is ignored.
    '·' is a dead cell. Anything else is a living cell.
";
const TICK_MS: u64 = 50;

fn main() {
    use clap::{App, AppSettings, Arg, SubCommand};

    fn is_number(s: String) -> Result<(), String> {
        if s.chars().all(|c| c.is_digit(10)) { Ok(()) }
        else { Err(format!("in argument \"{}\": expected a number", s)) }
    }

    let app = App::new("rgol")
        .about("Conway's game of life for terminal in Rust")
        .author(crate_authors!())
        .version(crate_version!())
        .after_help(MAPS_MSG)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("genmap")
                    .about("Prints an empty map")
                    .after_help(MAPS_MSG)
                    .arg(Arg::with_name("NROW")
                         .help("Number of rows")
                         .required(true)
                         .validator(is_number))
                    .arg(Arg::with_name("NCOL")
                         .help("Number of columns")
                         .required(true)
                         .validator(is_number))
                    .arg(Arg::with_name("space")
                         .help("Adds spaces to the map")
                         .short("s")
                         .long("space")))
        .subcommand(SubCommand::with_name("play")
                    .about("Plays the game (CTRL-c to exit)")
                    .after_help(MAPS_MSG)
                    .arg(Arg::with_name("FILE")
                         .help("File containing the map")
                         .required(true))
                    .arg(Arg::with_name("TICK_MS")
                         .help("Elapsed time between iterations in ms")
                         .validator(is_number)))
        .get_matches();
    match app.subcommand() {
        ("genmap", Some(args)) => genmap(args),
        ("play",   Some(args)) => play(args),
        _                      => unreachable!(),
    }
}

fn genmap(args: &ArgMatches) {
    use std::io::{Write, stdout};
    use std::iter::repeat;

    let nrow = args.value_of("NROW").expect("NROW has no value").parse().expect("NROW is not a number");
    let ncol = args.value_of("NCOL").expect("NCOL has no value").parse().expect("NCOL is not a number");
    if nrow == 0 || ncol == 0 { return }
    let line = if args.is_present("space") {
        let mut line: String = repeat("· ").take(ncol).collect();
        line.pop();
        line
    }
    else { repeat('·').take(ncol).collect() };
    for _ in 0..nrow { writeln!(&mut stdout(), "{}", line).unwrap(); }
}

fn play(args: &ArgMatches) {
    let filename = args.value_of("FILE").expect("FILE has no value");
    let tick_ms = args.value_of("TICK_MS").map_or(TICK_MS, |tms| tms.parse().expect("TICK_MS is not a number"));
    let tick = Duration::from_millis(tick_ms);
    match World::load(filename) {
        Ok(world) => play_world(world, tick),
        Err(err)  => eprintln!("error: {}", err),
    }
}

fn play_world(mut world: World, tick: Duration) {
    use std::time::Instant;
    use signal::trap::Trap;

    prep_term();
    let sigtrap = Trap::trap(&[libc::SIGINT]);
    let mut deadline = Instant::now();
    loop {
        clear_screen();
        println!("{}", world);
        world.next();
        deadline += tick;
        if sigtrap.wait(deadline).is_some() { break }
    }
    restore_term();
}

fn prep_term() {
    // save screen, cursor position and hide cursor
    print!("{}", concat!("\x1B[?1049h", "\x1B7", "\x1B[?25l"));
}

fn clear_screen() {
    // clear screen and move cursor to home position
    print!("{}", concat!("\x1B[2J", "\x1B[H"));
}

fn restore_term() {
    // restore screen, cursor position and show cursor
    print!("{}", concat!("\x1B[?1049l", "\x1B8", "\x1B[?25h"));
}
<commit_msg>clap: replace builder pattern with macro style<commit_after>#[macro_use]
extern crate clap;
extern crate libc;
extern crate signal;

use clap::ArgMatches;
use std::time::Duration;
use world::World;

#[macro_use]
mod macros;
mod world;

const MAPS_MSG: &'static str = "\
MAPS:
    Maps must be rectangular. Whitespace is ignored.
    '·' is a dead cell. Anything else is a living cell.
";
const TICK_MS: u64 = 50;

fn main() {
    fn is_number(s: String) -> Result<(), String> {
        if s.chars().all(|c| c.is_digit(10)) { Ok(()) }
        else { Err(format!("expected a number, found \"{}\"", s)) }
    }

    let matches = clap_app!( rgol =>
        (about: "Conway's game of life for terminal in Rust")
        (author: crate_authors!())
        (version: crate_version!())
        (after_help: MAPS_MSG)
        (@setting SubcommandRequiredElseHelp)
        (@setting VersionlessSubcommands)
        (@subcommand genmap =>
            (about: "Prints an empty map")
            (after_help: MAPS_MSG)
            (@arg NROW: {is_number} * "Number of rows")
            (@arg NCOL: {is_number} * "Number of columns")
            (@arg space: -s --space "Adds spaces to the map"))
        (@subcommand play =>
            (about: "Plays the game (CTRL-c to exit)")
            (after_help: MAPS_MSG)
            (@arg FILE: * "File containing the map")
            (@arg TICK_MS: {is_number} "Elapsed time between iterations in ms")
        )
    ).get_matches();

    match matches.subcommand() {
        ("genmap", Some(args)) => genmap(args),
        ("play",   Some(args)) => play(args),
        _                      => unreachable!(),
    }
}

fn genmap(args: &ArgMatches) {
    use std::io::{Write, stdout};
    use std::iter::repeat;

    let nrow = args.value_of("NROW").expect("NROW has no value").parse().expect("NROW is not a number");
    let ncol = args.value_of("NCOL").expect("NCOL has no value").parse().expect("NCOL is not a number");
    if nrow == 0 || ncol == 0 { return }
    let line = if args.is_present("space") {
        let mut line: String = repeat("· ").take(ncol).collect();
        line.pop();
        line
    }
    else { repeat('·').take(ncol).collect() };
    for _ in 0..nrow { writeln!(&mut stdout(), "{}", line).unwrap(); }
}

fn play(args: &ArgMatches) {
    let filename = args.value_of("FILE").expect("FILE has no value");
    let tick_ms = args.value_of("TICK_MS").map_or(TICK_MS, |tms| tms.parse().expect("TICK_MS is not a number"));
    let tick = Duration::from_millis(tick_ms);
    match World::load(filename) {
        Ok(world) => play_world(world, tick),
        Err(err)  => eprintln!("error: {}", err),
    }
}

fn play_world(mut world: World, tick: Duration) {
    use std::time::Instant;
    use signal::trap::Trap;

    prep_term();
    let sigtrap = Trap::trap(&[libc::SIGINT]);
    let mut deadline = Instant::now();
    loop {
        clear_screen();
        println!("{}", world);
        world.next();
        deadline += tick;
        if sigtrap.wait(deadline).is_some() { break }
    }
    restore_term();
}

fn prep_term() {
    // save screen, cursor position and hide cursor
    print!("{}", concat!("\x1B[?1049h", "\x1B7", "\x1B[?25l"));
}

fn clear_screen() {
    // clear screen and move cursor to home position
    print!("{}", concat!("\x1B[2J", "\x1B[H"));
}

fn restore_term() {
    // restore screen, cursor position and show cursor
    print!("{}", concat!("\x1B[?1049l", "\x1B8", "\x1B[?25h"));
}
<|endoftext|>