<commit_before>#[macro_use] extern crate nickel;
#[macro_use] extern crate lazy_static;

extern crate rustc_serialize;
extern crate multipart;
extern crate nickel_jwt_session;
extern crate time;

use nickel::{Nickel,
            Request,
            Response,
            MiddlewareResult,
            HttpRouter,
            StaticFilesHandler,
            QueryString,
            MediaType,
            FormBody};
use nickel::status::StatusCode;
use nickel::extensions::Redirect;

use nickel_jwt_session::*;

use std::fs::{File,OpenOptions,remove_file};
use std::path::Path;
use std::io::Read;
use std::thread;

use multipart::server::{Multipart, SaveResult};

use rustc_serialize::json;

mod db;
mod sync;
mod commands;
mod utils;

use db::{Db,VoteImageError};
use utils::save_image;

use std::sync::Mutex;
use std::cell::RefCell;

lazy_static! {
    pub static ref DB : Mutex<Db> = Mutex::new(Db::new());

    /// Использование лежит в utils
    pub static ref OUTF : Mutex<RefCell<File>> = Mutex::new(RefCell::new(OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap()));
}

macro_rules! routes(
    { $serv:ident, $($method:ident $($path:expr),+ => $fun:ident),+ } => {
        {
            $($(
                    $serv.$method($path, $fun);
               )+)+
        }
     };
);

#[derive(RustcEncodable)]
struct UserStatus {
    logined: bool,
    name: Option<String>
}

fn index_n_search<'a, D>(_request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    response.render("src/templates/index.html", &[0]) // Вот тут и ниже так надо, чтобы не пересобирать программу при изменении HTML
}

fn show<'a, D>(_request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    response.render("src/templates/show.html", &[0])
}

fn upload_image<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> {
    if let Some(username) = req.authorized_user() {
        if let Ok(mut multipart) = Multipart::from_request(req) {
            match multipart.save_all() {
                SaveResult::Full(entries) | SaveResult::Partial(entries, _)  => {
                    if let Some(savedfile) = entries.files.get("image") {
                        if let Some(ref filename) = savedfile.filename {
                            if let Some(tags) = entries.fields.get("tags") {
                                let tags = tags.split_whitespace().map(String::from).collect::<Vec<_>>();
                                let mut body = Vec::new();
                                let _ = File::open(&savedfile.path).unwrap().read_to_end(&mut body);
                                let name = DB.lock().unwrap().add_with_tags_name(&tags, filename.split('.').collect::<Vec<_>>()[1], &username).unwrap();

                                save_image(Path::new("assets/images"), &name, &body);

                                res.redirect("/")

                            } else { res.send("No tags found") }
                        } else { res.send("Can't get filename") }
                    } else { res.send("Can't load file") }
                },

                SaveResult::Error(e) =>  res.send(format!("Server could not handle multipart POST! {:?}", e))
            }
        } else {
            res.set(nickel::status::StatusCode::BadRequest);
            res.send("Not a multipart request")
        }
    } else {
        res.error(StatusCode::Forbidden, "Not logged in")
    }
}

fn get_image<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let id = request.param("id").unwrap().parse::<i32>().unwrap();
    response.set(MediaType::Json);
    response.send(json::encode(&DB.lock().unwrap().get_image(id).unwrap()).unwrap())
}

fn more<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let offset = request.query().get("offset").unwrap().parse::<usize>().unwrap();

    let images = match request.query().get("q") {
        Some(x) =>  DB.lock().unwrap().by_tags(25, offset, &x.to_lowercase().split_whitespace().map(String::from).collect::<Vec<_>>()).unwrap(),
        None    =>  DB.lock().unwrap().get_images(25, offset).unwrap()
    };

    response.set(MediaType::Json);
    response.send(json::encode(&images).unwrap())
}

fn adduser<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let body = try_with!(response, request.form_body());
    if let (Some(login), Some(pass), Some(confirm_pass)) = (body.get("login"), body.get("password"),body.get("confirm_password")) {
        if pass == confirm_pass {
            if let Ok(res) = DB.lock().unwrap().add_user(login,pass) {
                if res {
                    response.set_jwt_user(login);
                    response.redirect("/")
                } else {
                    response.send("User already exists")
                }
            } else {
                response.error(StatusCode::InternalServerError, "Internal server error")
            }
        } else {
            response.send("Password and confirmation are not equeal")
        }
    } else {
        response.send("No data")
    }
}

fn login<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let body = try_with!(response, request.form_body());
    if let (Some(login), Some(pass)) = (body.get("login"), body.get("password")) {
        match DB.lock().unwrap().check_user(login, pass) {
            Ok(x) => match x {
                Some(x) => if x {
                    response.set_jwt_user(login);
                    response.redirect("/")
                } else {
                    response.send("Incorrent password")
                },
                _   => response.send("No such user")
            },
            Err(e) =>  panic!(e)
        }
    } else {
        response.send("No login/pass")
    }
}

fn user_status<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    response.set(MediaType::Json);

    let (logined,name) = match request.authorized_user() {
        Some(user)  => (true, Some(user)),
        None        => (false, None)
    };

    response.send(json::encode(&UserStatus{
        logined: logined,
        name: name
    }).unwrap())
}

fn delete<'a, D>(request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let id = request.param("id").unwrap().parse::<i32>().unwrap();
    let name = DB.lock().unwrap().delete_image(id).unwrap();
    remove_file(format!("assets/images/{}", name)).unwrap();
    remove_file(format!("assets/images/preview/{}", name)).unwrap();
    response.redirect("/")
}

fn vote_image<'a, D>(request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let query = request.query() as *const nickel::Query;
    let (id,vote) = unsafe { // Бяка, конечно, но query() почему-то берёт mutable reference и не даёт использовать другим
        let q = &*query;
        (q.get("id"),q.get("vote"))
    };

    if let (Some(id), Some(vote)) = (id,vote) {
        if let Some(name) = request.authorized_user() {
            if let Ok(vote) = vote.parse::<bool>() {
                if let Ok(id) = id.parse::<i32>() {
                    match DB.lock().unwrap().vote_image(&name, id, vote).unwrap() {
                        Ok(newv)                        => response.send(newv.to_string()),
                        Err(VoteImageError::Already)    => response.send("Already voted that"),
                        Err(VoteImageError::NoImage)    => response.send("No such image")
                    }
                } else {
                    response.send("Invalid id")
                }
            } else {
                response.send("Invalid vote")
            }
        } else {
            response.send("Not logged in")
        }
    } else {
        response.send("No data")
    }
}

fn main() {
    let mut server = Nickel::new();

    server.utilize(StaticFilesHandler::new("assets"));
    server.utilize(SessionMiddleware::new(&time::now().to_timespec().sec.to_string()));

    routes!{server,
        get "/","/search" => index_n_search,
        get "/show/:id" => show,
        get "/more" => more,
        get "/get_image/:id" => get_image,
        get "/user_status" => user_status,
        get "/delete/:id" => delete,
        get "/vote_image" => vote_image,

        post "/upload_image" => upload_image,
        post "/login" => login,
        post "/adduser" => adduser
    };

    thread::spawn(commands::main);

    let _server = server.listen("127.0.0.1:3000");
}
<commit_msg>Штуки<commit_after>#[macro_use] extern crate nickel;
#[macro_use] extern crate lazy_static;

extern crate rustc_serialize;
extern crate multipart;
extern crate nickel_jwt_session;
extern crate time;

use nickel::{Nickel,
            Request,
            Response,
            MiddlewareResult,
            HttpRouter,
            StaticFilesHandler,
            QueryString,
            MediaType,
            FormBody};
use nickel::status::StatusCode;
use nickel::extensions::Redirect;

use nickel_jwt_session::*;

use std::fs::{File,OpenOptions,remove_file};
use std::path::Path;
use std::io::Read;
use std::thread;

use multipart::server::{Multipart, SaveResult};

use rustc_serialize::json;

mod db;
mod sync;
mod commands;
mod utils;

use db::{Db,VoteImageError};
use utils::save_image;

use std::sync::Mutex;
use std::cell::RefCell;

lazy_static! {
    pub static ref DB : Mutex<Db> = Mutex::new(Db::new());

    /// Использование лежит в utils
    pub static ref OUTF : Mutex<RefCell<File>> = Mutex::new(RefCell::new(OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap()));
}

macro_rules! routes(
    { $serv:ident, $($method:ident $($path:expr),+ => $fun:ident),+ } => {
        {
            $($(
                    $serv.$method($path, $fun);
               )+)+
        }
     };
);

fn index_n_search<'a, D>(_request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    response.render("src/templates/index.html", &[0]) // Вот тут и ниже так надо, чтобы не пересобирать программу при изменении HTML
}

fn show<'a, D>(_request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    response.render("src/templates/show.html", &[0])
}

fn upload_image<'mw>(req: &mut Request, mut res: Response<'mw>) -> MiddlewareResult<'mw> {
    if let Some(username) = req.authorized_user() {
        if let Ok(mut multipart) = Multipart::from_request(req) {
            match multipart.save_all() {
                SaveResult::Full(entries) | SaveResult::Partial(entries, _)  => {
                    if let Some(savedfile) = entries.files.get("image") {
                        if let Some(ref filename) = savedfile.filename {
                            if let Some(tags) = entries.fields.get("tags") {
                                let tags = tags.split_whitespace().map(String::from).collect::<Vec<_>>();
                                let mut body = Vec::new();
                                let _ = File::open(&savedfile.path).unwrap().read_to_end(&mut body);
                                let name = DB.lock().unwrap().add_with_tags_name(&tags, filename.split('.').collect::<Vec<_>>()[1], &username).unwrap();

                                save_image(Path::new("assets/images"), &name, &body);

                                res.redirect("/")

                            } else { res.send("No tags found") }
                        } else { res.send("Can't get filename") }
                    } else { res.send("Can't load file") }
                },

                SaveResult::Error(e) =>  res.send(format!("Server could not handle multipart POST! {:?}", e))
            }
        } else {
            res.set(nickel::status::StatusCode::BadRequest);
            res.send("Not a multipart request")
        }
    } else {
        res.error(StatusCode::Forbidden, "Not logged in")
    }
}

fn get_image<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let id = request.param("id").unwrap().parse::<i32>().unwrap();
    response.set(MediaType::Json);
    response.send(json::encode(&DB.lock().unwrap().get_image(id).unwrap()).unwrap())
}

fn more<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let offset = request.query().get("offset").unwrap().parse::<usize>().unwrap();

    let images = match request.query().get("q") {
        Some(x) =>  DB.lock().unwrap().by_tags(25, offset, &x.to_lowercase().split_whitespace().map(String::from).collect::<Vec<_>>()).unwrap(),
        None    =>  DB.lock().unwrap().get_images(25, offset).unwrap()
    };

    response.set(MediaType::Json);
    response.send(json::encode(&images).unwrap())
}

fn adduser<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let body = try_with!(response, request.form_body());
    if let (Some(login), Some(pass), Some(confirm_pass)) = (body.get("login"), body.get("password"),body.get("confirm_password")) {
        if pass == confirm_pass {
            if let Ok(res) = DB.lock().unwrap().add_user(login,pass) {
                if res {
                    response.set_jwt_user(login);
                    response.redirect("/")
                } else {
                    response.send("User already exists")
                }
            } else {
                response.error(StatusCode::InternalServerError, "Internal server error")
            }
        } else {
            response.send("Password and confirmation are not equeal")
        }
    } else {
        response.send("No data")
    }
}

fn login<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let body = try_with!(response, request.form_body());
    if let (Some(login), Some(pass)) = (body.get("login"), body.get("password")) {
        match DB.lock().unwrap().check_user(login, pass) {
            Ok(x) => match x {
                Some(x) => if x {
                    response.set_jwt_user(login);
                    response.redirect("/")
                } else {
                    response.send("Incorrent password")
                },
                _   => response.send("No such user")
            },
            Err(e) =>  panic!(e)
        }
    } else {
        response.send("No login/pass")
    }
}

fn user_status<'a, D>(request: &mut Request<D>, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {

    #[derive(RustcEncodable)]
    struct UserStatus {
        logined: bool,
        name: Option<String>
    }

    response.set(MediaType::Json);

    let (logined,name) = match request.authorized_user() {
        Some(user)  => (true, Some(user)),
        None        => (false, None)
    };

    response.send(json::encode(&UserStatus{
        logined: logined,
        name: name
    }).unwrap())
}

fn delete<'a, D>(request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let id = request.param("id").unwrap().parse::<i32>().unwrap();
    let name = DB.lock().unwrap().delete_image(id).unwrap();
    remove_file(format!("assets/images/{}", name)).unwrap();
    remove_file(format!("assets/images/preview/{}", name)).unwrap();
    response.redirect("/")
}

fn vote_image<'a, D>(request: &mut Request<D>, response: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let query = request.query() as *const nickel::Query;
    let (id,vote) = unsafe { // Бяка, конечно, но query() почему-то берёт mutable reference и не даёт использовать другим
        let q = &*query;
        (q.get("id"),q.get("vote"))
    };

    if let (Some(id), Some(vote)) = (id,vote) {
        if let Some(name) = request.authorized_user() {
            if let (Ok(vote),Ok(id)) = (vote.parse::<bool>(),id.parse::<i32>()) {
                match DB.lock().unwrap().vote_image(&name, id, vote).unwrap() {
                    Ok(newv)                        => response.send(newv.to_string()),
                    Err(VoteImageError::Already)    => response.send("Already voted that"),
                    Err(VoteImageError::NoImage)    => response.send("No such image")
                }
            } else {
                response.send("Invalid data")
            }
        } else {
            response.send("Not logged in")
        }
    } else {
        response.send("No data")
    }
}

fn main() {
    let mut server = Nickel::new();

    server.utilize(StaticFilesHandler::new("assets"));
    server.utilize(SessionMiddleware::new(&time::now().to_timespec().sec.to_string()));

    routes!{server,
        get "/","/search" => index_n_search,
        get "/show/:id" => show,
        get "/more" => more,
        get "/get_image/:id" => get_image,
        get "/user_status" => user_status,
        get "/delete/:id" => delete,
        get "/vote_image" => vote_image,

        post "/upload_image" => upload_image,
        post "/login" => login,
        post "/adduser" => adduser
    };

    thread::spawn(commands::main);

    let _server = server.listen("127.0.0.1:3000");
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(docopt_macros)]

#[macro_use]
extern crate docopt;
extern crate env_logger;
extern crate log;
extern crate rustc_serialize;
extern crate website;

use env_logger::LogBuilder;
use log::LogLevelFilter;

use website::persistence::DEFAULT_DATABASE_URI;

const DEFAULT_PORT: u16 = 9000;

docopt!(Args derive Debug, r"
My personal website.

Usage:
    website [options] [<port>]
    website (-h | --help)

Options:
    --db-uri=<URI>      A sqlite database URI to use for the website's backing store. By default,
                        this is a shared, in-memory database.

                        Please note that any existing data in the database pointed at by this URI
                        will be dropped upon server initialization.

                        This option is useful for debugging purposes.
", arg_port: Option<u16>, flag_db_uri: Option<String>);

fn main() {
    LogBuilder::new().filter(None, LogLevelFilter::Info).init().unwrap();

    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    let address = ("localhost", args.arg_port.unwrap_or(DEFAULT_PORT));
    website::listen(address,
                    &args.flag_db_uri.unwrap_or_else(|| String::from(DEFAULT_DATABASE_URI)));
}
<commit_msg>fix(logging): filter out html5ever warnings<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]

#[macro_use]
extern crate docopt;
extern crate env_logger;
extern crate log;
extern crate rustc_serialize;
extern crate website;

use env_logger::LogBuilder;
use log::LogLevelFilter;

use website::persistence::DEFAULT_DATABASE_URI;

const DEFAULT_PORT: u16 = 9000;

docopt!(Args derive Debug, r"
My personal website.

Usage:
    website [options] [<port>]
    website (-h | --help)

Options:
    --db-uri=<URI>      A sqlite database URI to use for the website's backing store. By default,
                        this is a shared, in-memory database.

                        Please note that any existing data in the database pointed at by this URI
                        will be dropped upon server initialization.

                        This option is useful for debugging purposes.
", arg_port: Option<u16>, flag_db_uri: Option<String>);

fn main() {
    LogBuilder::new()
        .filter(None, LogLevelFilter::Info)
        .filter(Some("html5ever"), LogLevelFilter::Error)
        .init()
        .unwrap();

    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    let address = ("localhost", args.arg_port.unwrap_or(DEFAULT_PORT));
    website::listen(address,
                    &args.flag_db_uri.unwrap_or_else(|| String::from(DEFAULT_DATABASE_URI)));
}
<|endoftext|>


<commit_before>extern crate ww;

use ww::map::{Map, MapRoomId};
use ww::room::Room;
use ww::direction::Direction::*;
use ww::command::{PrimaryCommand, CommandProcessor};

#[cfg(target_os = "emscripten")]
use ww::platform::emscripten;

use RoomId::*;

const MAX_ROOMS: usize = 20;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway = 1,
  AudienceChamber = 2,
}

fn build_world(map: &mut Map<RoomId>) {
  map.room(Hallway).describe(
    "Hallway",
    "You are in the hallway. \
     There is a door to the south. \
     Through the windows to the north you can see a secret herb garden."
  );

  map.room(AudienceChamber).describe(
    "Audience Chamber",
    "This is the audience chamber. \
     There is a window to the west. By looking to the right \
     through it you can see the entrance to the castle. \
     Doors leave this room to the north, east, and south."
  );

  map.connect(Hallway, South, AudienceChamber);
}

// Ideally we'd actually just get rid of MapRoomId and add a constraint
// to Map<T> requiring that T be type-castable as usize, but I don't
// know how to do that, so...
impl MapRoomId for RoomId {
  fn room_id(self) -> usize { self as usize }
}

#[derive(Debug, PartialEq, Copy, Clone)]
enum GameMode {
  Primary,
  Finished,
}

struct GameState<'a> {
  map: &'a mut Map<'a, RoomId>,
  pub curr_mode: GameMode,
  curr_room: RoomId,
  show_desc: bool,
}

impl<'a> GameState<'a> {
  pub fn new(map: &'a mut Map<'a, RoomId>) -> Self {
    Self {
      map: map,
      curr_mode: GameMode::Primary,
      curr_room: Hallway,
      show_desc: true,
    }
  }

  pub fn tick(&mut self) {
    match self.curr_mode {
      GameMode::Primary => {
        if self.show_desc {
          println!("{}", self.map.room(self.curr_room).description);
          self.show_desc = false;
        }

        if let Some(cmd) = PrimaryCommand::get() {
          match cmd {
            PrimaryCommand::Go(dir) => {
              if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
                self.curr_room = room;
                self.show_desc = true;
              } else {
                println!("You can't go that way.");
              }
            },
            PrimaryCommand::Look => { self.show_desc = true; }
            PrimaryCommand::Quit => { self.curr_mode = GameMode::Finished; }
          }
        };
      },
      GameMode::Finished => {}
    }
  }
}

fn main() {
  let mut rooms = [Room::new(); MAX_ROOMS];
  let mut map = Map::new(&mut rooms);

  build_world(&mut map);

  let mut state = GameState::new(&mut map);

  println!("Werewolves and Wanderer\n");

  #[cfg(target_os = "emscripten")]
  emscripten::set_main_loop_callback(|| state.tick());

  #[cfg(not(target_os = "emscripten"))]
  while state.curr_mode != GameMode::Finished {
    state.tick();
  }

  println!("Farewell.");
}
<commit_msg>Factor out tick_primary_mode().<commit_after>extern crate ww;

use ww::map::{Map, MapRoomId};
use ww::room::Room;
use ww::direction::Direction::*;
use ww::command::{PrimaryCommand, CommandProcessor};

#[cfg(target_os = "emscripten")]
use ww::platform::emscripten;

use RoomId::*;

const MAX_ROOMS: usize = 20;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway = 1,
  AudienceChamber = 2,
}

fn build_world(map: &mut Map<RoomId>) {
  map.room(Hallway).describe(
    "Hallway",
    "You are in the hallway. \
     There is a door to the south. \
     Through the windows to the north you can see a secret herb garden."
  );

  map.room(AudienceChamber).describe(
    "Audience Chamber",
    "This is the audience chamber. \
     There is a window to the west. By looking to the right \
     through it you can see the entrance to the castle. \
     Doors leave this room to the north, east, and south."
  );

  map.connect(Hallway, South, AudienceChamber);
}

// Ideally we'd actually just get rid of MapRoomId and add a constraint
// to Map<T> requiring that T be type-castable as usize, but I don't
// know how to do that, so...
impl MapRoomId for RoomId {
  fn room_id(self) -> usize { self as usize }
}

#[derive(Debug, PartialEq, Copy, Clone)]
enum GameMode {
  Primary,
  Finished,
}

struct GameState<'a> {
  map: &'a mut Map<'a, RoomId>,
  pub curr_mode: GameMode,
  curr_room: RoomId,
  show_desc: bool,
}

impl<'a> GameState<'a> {
  pub fn new(map: &'a mut Map<'a, RoomId>) -> Self {
    Self {
      map: map,
      curr_mode: GameMode::Primary,
      curr_room: Hallway,
      show_desc: true,
    }
  }

  pub fn tick_primary_mode(&mut self) {
    if self.show_desc {
      println!("{}", self.map.room(self.curr_room).description);
      self.show_desc = false;
    }

    if let Some(cmd) = PrimaryCommand::get() {
      match cmd {
        PrimaryCommand::Go(dir) => {
          if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
            self.curr_room = room;
            self.show_desc = true;
          } else {
            println!("You can't go that way.");
          }
        },
        PrimaryCommand::Look => { self.show_desc = true; }
        PrimaryCommand::Quit => { self.curr_mode = GameMode::Finished; }
      }
    };
  }

  pub fn tick(&mut self) {
    match self.curr_mode {
      GameMode::Primary => { self.tick_primary_mode() },
      GameMode::Finished => {}
    }
  }
}

fn main() {
  let mut rooms = [Room::new(); MAX_ROOMS];
  let mut map = Map::new(&mut rooms);

  build_world(&mut map);

  let mut state = GameState::new(&mut map);

  println!("Werewolves and Wanderer\n");

  #[cfg(target_os = "emscripten")]
  emscripten::set_main_loop_callback(|| state.tick());

  #[cfg(not(target_os = "emscripten"))]
  while state.curr_mode != GameMode::Finished {
    state.tick();
  }

  println!("Farewell.");
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate rustc_serialize;
extern crate gsdmm;

use gsdmm::GSDMM;
use docopt::Docopt;
use std::io::{BufRead,BufReader};
use std::fs::File;
use std::collections::HashSet;
use std::io::Write;

const USAGE: &'static str ="
Gibbs sampling algorithm for a Dirichlet Mixture Model of Yin and Wang 2014.

Usage:
  gsdmm <datafile> <vocabfile> <outprefix> [-k <max_clusters>] [-a <alpha>] [-b <beta>] [-m <maxit>]
  gsdmm (-h | --help)
  gsdmm --version

Options:
  -h --help             Show this screen.
  --version             Show version.
  -k=<K>                Upper bound on the number of possible clusters. [default: 8]
  -a --alpha=<alpha>    Alpha controls the probability that a student will join a table that is currently empty
                        When alpha is 0, no one will join an empty table. [default: 0.1]
  -b --beta=<beta>      Beta controls the student's affinity for other students with similar interests. A low beta means
                        that students desire to sit with students of similar interests. A high beta means they are less
                        concerned with affinity and are more influenced by the popularity of a table. [default: 0.1]
  -m --maxit=<m>        Maximum number of iterations. [default: 30]

";

#[derive(Debug, RustcDecodable)]
struct Args {
    //    flag_mode: isize,
    arg_datafile: String,
    arg_vocabfile: String,
    arg_outprefix: String,
    flag_k: usize,
    flag_alpha: f64,
    flag_beta: f64,
    flag_maxit: isize
}

fn main() {

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    // get the data and vocabulary
    let vocab:HashSet<String> = lines_from_file(&args.arg_vocabfile).into_iter().collect();
    let docs:Vec<Vec<String>> = lines_from_file(&args.arg_datafile).into_iter().map(|line| {
        let mut term_vector = line.to_owned()
            .split_whitespace()
            .map(|s| s.to_owned())
            .filter(|s| (&vocab).contains(s))
            .collect::<Vec<String>>();

        // sort and dedupe: this implementation requires binary term counts
        term_vector.sort();
        term_vector.dedup();
        term_vector
    }).collect::<Vec<Vec<String>>>();

    let mut model = GSDMM::new(args.flag_alpha, args.flag_beta, args.flag_k, args.flag_maxit, vocab, docs);
    model.fit();

    // write the labels
    {
        let fname = (&args.arg_outprefix).clone() + "labels.csv";
        let error_msg = format ! ("Could not write file {}!", fname);
        let mut f = File::create( fname ).expect( & error_msg);
        let mut scored = Vec::<(String,String,String)>::new();

        // zip with the input data so we get clustered, raw input documents in the output set
        for (doc,txt) in (&model.docs).iter().zip(lines_from_file(&args.arg_datafile).iter()) {
            let p = model.score( & doc);
            let mut row = p.iter().enumerate().collect::<Vec<_>>();
            row.sort_by(|a,b| a.1.partial_cmp(b.1).unwrap());
            let line = row.pop().unwrap();
            scored.push((line.0.to_string(), line.1.to_string(), txt.clone()));
        }
        scored.sort();
        for (label, score, txt) in scored {
            f.write((label + "," + &score + "," + &txt + "\n").as_bytes());
        }
    }

    // write the label probabilities
    {
        let fname = (&args.arg_outprefix).clone() + "label_probabilities.csv";
        let error_msg = format ! ("Could not write file {}!", fname);
        let mut f = File::create( fname ).expect( & error_msg);
        for doc in & (model.docs) {
            let p = model.score( & doc);
            let line = p.iter().map( | k | (*k as f32).to_string()).collect::< Vec< String > > ().join(",");
            f.write((line + "\n").as_bytes());
        }
    }

    // write the cluster descriptions
    {
        let fname = (&args.arg_outprefix).clone() + "cluster_descriptions.txt";
        let error_msg = format!("Could not write file {}!", fname);
        let mut f = File::create(fname).expect(&error_msg);
        for k in 0..args.flag_k {
            let ref word_dist = model.cluster_word_distributions[k];
            let mut line = k.to_string() + " ";
            let mut dist_counts:Vec<String> = word_dist.iter().map(|(a,b)| a.clone() + ":" + &b.clone().to_string() ).collect();
            dist_counts.sort();
            line += &dist_counts.join(" ");
            f.write((line+"\n").as_bytes());
        }
    }

    fn lines_from_file(filename: &str) -> Vec<String>
    {
        let error_msg = format!("Could not read file {}!", filename);
        let file = File::open(filename).expect(&error_msg);
        let buf = BufReader::new(file);
        buf.lines().map(|l| l.expect("Could not parse line!")).collect()
    }
}
<commit_msg>Removed label probabilities writer in main<commit_after>extern crate docopt;
extern crate rustc_serialize;
extern crate gsdmm;

use gsdmm::GSDMM;
use docopt::Docopt;
use std::io::{BufRead,BufReader};
use std::fs::File;
use std::collections::HashSet;
use std::io::Write;

const USAGE: &'static str ="
Gibbs sampling algorithm for a Dirichlet Mixture Model of Yin and Wang 2014.

Usage:
  gsdmm <datafile> <vocabfile> <outprefix> [-k <max_clusters>] [-a <alpha>] [-b <beta>] [-m <maxit>]
  gsdmm (-h | --help)
  gsdmm --version

Options:
  -h --help             Show this screen.
  --version             Show version.
  -k=<K>                Upper bound on the number of possible clusters. [default: 8]
  -a --alpha=<alpha>    Alpha controls the probability that a student will join a table that is currently empty
                        When alpha is 0, no one will join an empty table. [default: 0.1]
  -b --beta=<beta>      Beta controls the student's affinity for other students with similar interests. A low beta means
                        that students desire to sit with students of similar interests. A high beta means they are less
                        concerned with affinity and are more influenced by the popularity of a table. [default: 0.1]
  -m --maxit=<m>        Maximum number of iterations. [default: 30]

";

#[derive(Debug, RustcDecodable)]
struct Args {
    //    flag_mode: isize,
    arg_datafile: String,
    arg_vocabfile: String,
    arg_outprefix: String,
    flag_k: usize,
    flag_alpha: f64,
    flag_beta: f64,
    flag_maxit: isize
}

fn main() {

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    // get the data and vocabulary
    let vocab:HashSet<String> = lines_from_file(&args.arg_vocabfile).into_iter().collect();
    let docs:Vec<Vec<String>> = lines_from_file(&args.arg_datafile).into_iter().map(|line| {
        let mut term_vector = line.to_owned()
            .split_whitespace()
            .map(|s| s.to_owned())
            .filter(|s| (&vocab).contains(s))
            .collect::<Vec<String>>();

        // sort and dedupe: this implementation requires binary term counts
        term_vector.sort();
        term_vector.dedup();
        term_vector
    }).collect::<Vec<Vec<String>>>();

    let mut model = GSDMM::new(args.flag_alpha, args.flag_beta, args.flag_k, args.flag_maxit, vocab, docs);
    model.fit();

    // write the labels
    {
        let fname = (&args.arg_outprefix).clone() + "labels.csv";
        let error_msg = format ! ("Could not write file {}!", fname);
        let mut f = File::create( fname ).expect( & error_msg);
        let mut scored = Vec::<(String,String,String)>::new();

        // zip with the input data so we get clustered, raw input documents in the output set
        for (doc,txt) in (&model.docs).iter().zip(lines_from_file(&args.arg_datafile).iter()) {
            let p = model.score( & doc);
            let mut row = p.iter().enumerate().collect::<Vec<_>>();
            row.sort_by(|a,b| a.1.partial_cmp(b.1).unwrap());
            let line = row.pop().unwrap();
            scored.push((line.0.to_string(), line.1.to_string(), txt.clone()));
        }
        scored.sort();
        for (label, score, txt) in scored {
            f.write((label + "," + &score + "," + &txt + "\n").as_bytes());
        }
    }

    // write the cluster descriptions
    {
        let fname = (&args.arg_outprefix).clone() + "cluster_descriptions.txt";
        let error_msg = format!("Could not write file {}!", fname);
        let mut f = File::create(fname).expect(&error_msg);
        for k in 0..args.flag_k {
            let ref word_dist = model.cluster_word_distributions[k];
            let mut line = k.to_string() + " ";
            let mut dist_counts:Vec<String> = word_dist.iter().map(|(a,b)| a.clone() + ":" + &b.clone().to_string() ).collect();
            dist_counts.sort();
            line += &dist_counts.join(" ");
            f.write((line+"\n").as_bytes());
        }
    }

    fn lines_from_file(filename: &str) -> Vec<String>
    {
        let error_msg = format!("Could not read file {}!", filename);
        let file = File::open(filename).expect(&error_msg);
        let buf = BufReader::new(file);
        buf.lines().map(|l| l.expect("Could not parse line!")).collect()
    }
}
<|endoftext|>


<commit_before>#![feature(convert, collections)]
#![allow(unused_variables)]

use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::io;
use std::io::prelude::*;
use std::rc::Rc;
use std::fmt;

type Dictionary = HashMap<String, Rc<Entry>>;
type Statement = Vec<Op>;
type NativeFn = Box<Fn(&mut Vec<Op>, &mut Interpreter)>;

#[derive(Clone, Debug)]
enum Op {
	Number(i32),
	Word(Rc<Entry>),
}

enum Code {
	Native(NativeFn),
	Forth(Statement),
}

#[derive(Clone)]
struct Entry {
	name: String,
	code: Rc<Code>,
}

impl PartialEq for Entry {
	fn eq(&self, other: &Self) -> bool { self.name == other.name }
}

impl Eq for Entry {}

impl Hash for Entry {
	fn hash<H>(&self, state: &mut H) where H: Hasher {
		self.name.hash(state)
	}
}

impl fmt::Debug for Entry {
	fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.name.fmt(fmt)
	}
}

impl Entry {
	fn new(name: &str, code: Code) -> Entry {
		Entry {
			name: String::from_str(name),
			code: Rc::new(code),
		}
	}
}

impl Code {
	fn run(&self, stack: &mut Statement, interp: &mut Interpreter) {
		match self {
			&Code::Native(ref f) => {
				f(stack, interp);
			},
			&Code::Forth(ref statement) => {
				for ref op in statement {
					match *op {
						&Op::Number(ref n) => { break; }
						&Op::Word(ref w) => {
							(*w).code.run(stack, interp);
						},
					}
				}
			},
		}
	}
}

trait StatementExt {
	fn pop_number(&mut self, &mut Interpreter) -> i32;
	fn push_number(&mut self, i32);
	fn run(&mut self, &mut Interpreter) -> Result<i32, Statement>;
}

impl StatementExt for Statement {
	fn pop_number(&mut self, interp: &mut Interpreter) -> i32 {
		loop {
			match self.pop() {
				Some(Op::Number(n)) => { return n; },
				Some(Op::Word(s)) => s.code.run(self, interp),
				None => panic!("Popped empty statement"),
			}
		}
	}

	fn push_number(&mut self, number: i32) {
		self.push(Op::Number(number));
	}

	fn run(&mut self, interp: &mut Interpreter) -> Result<i32, Statement> {
		while self.len() > 0 {
			match self.pop() {
				Some(Op::Number(n)) => {
					if self.len() == 0 {
						return Ok(n)
					} else {
						self.push(Op::Number(n));
						return Err(self.clone())
					}
				},
				Some(Op::Word(w)) => {
					let code = interp.dictionary[w.name.as_str()].code.clone();
					code.run(self, interp);
				},
				None => unreachable!(),
			};
		}
		Ok(0)
	}
}

trait DictionaryExt {
	fn insert_entry(&mut self, Entry);
}

impl DictionaryExt for Dictionary {
	fn insert_entry(&mut self, entry: Entry) {
		self.insert(entry.name.clone(), Rc::new(entry));
	}
}

struct Interpreter {
    dictionary: Dictionary,
}

macro_rules! binary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let b = stack.pop_number(interp);
					let a = stack.pop_number(interp);
					stack.push_number($o(a, b));
				})),
			)
	}
}

macro_rules! unary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let a = stack.pop_number(interp);
					stack.push_number($o(a));
				})),
			)
	}
}

macro_rules! nonary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					Op::Number($o);
				})),
			)
	}
}

impl Interpreter {
	fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		dict.insert_entry(binary_entry!("/", ::std::ops::Div::div));
		dict.insert_entry(binary_entry!("*", ::std::ops::Mul::mul));
		dict.insert_entry(binary_entry!("+", ::std::ops::Add::add));
		dict.insert_entry(binary_entry!("-", ::std::ops::Sub::sub));
		dict.insert_entry(binary_entry!("MOD", ::std::ops::Rem::rem));
		dict.insert_entry(binary_entry!("AND", ::std::ops::BitAnd::bitand));
		dict.insert_entry(binary_entry!("OR", ::std::ops::BitOr::bitor));
		dict.insert_entry(binary_entry!("XOR", ::std::ops::BitXor::bitxor));
		dict.insert_entry(binary_entry!("RSHIFT", ::std::ops::Shr::shr));
		dict.insert_entry(binary_entry!("LSHIFT", ::std::ops::Shl::shl));

		dict.insert_entry(unary_entry!("NEGATE", ::std::ops::Neg::neg));
		dict.insert_entry(unary_entry!("NOT", ::std::ops::Not::not));

		dict.insert_entry(nonary_entry!("bye", ::std::process::exit(0)));

		dict.insert_entry(Entry::new("<",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let y = stack.pop_number(interp);
					let x = stack.pop_number(interp);
					stack.push(if x < y { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new(">",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let y = stack.pop_number(interp);
					let x = stack.pop_number(interp);
					stack.push(if x > y { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("=",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let y = stack.pop_number(interp);
					let x = stack.pop_number(interp);
					stack.push(if x == y { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("0<",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push(if x < 0 { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("0=",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push(if x == 0 { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("0>",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push(if x > 0 { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("1+",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x + 1);
				})),
			));

		dict.insert_entry(Entry::new("1-",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x - 1);
				})),
			));

		dict.insert_entry(Entry::new("2+",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x + 2);
				})),
			));

		dict.insert_entry(Entry::new("2-",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x - 2);
				})),
			));

		dict.insert_entry(Entry::new("2/",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x >> 1); // Per fst83 standard
				})),
			));

		dict.insert_entry(Entry::new("DUP",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x.clone());
					stack.push_number(x);
				})),
			));

		dict.insert_entry(Entry::new("?DUP",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					if x != 0 {
						stack.push_number(x.clone());
						stack.push_number(x);
					} else {
						stack.push_number(x);
					}
				})),
			));

		dict.insert_entry(Entry::new("OVER",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					let y = stack.pop_number(interp);
					stack.push_number(x.clone());
					stack.push_number(y);
					stack.push_number(x);
				})),
			));

		dict.insert_entry(Entry::new("ROT",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					let y = stack.pop_number(interp);
					let z = stack.pop_number(interp);
					stack.push_number(y);
					stack.push_number(x);
					stack.push_number(z);
				})),
			));

		Interpreter {
			dictionary: dict,
		}
	}

	fn lex(&mut self, statement: &str) -> Statement {
		let words = statement.split(' ');
		let mut ret = Statement::new();
		for word in words {
			if let Some(n) = i32::from_str_radix(word, 10).ok() {
				ret.push(Op::Number(n));
			} else {
				ret.push(Op::Word(self.dictionary[word].clone()));
			}
		};
		ret
	}

	fn exec(&mut self, statement: &str) -> Result<i32, Statement> {
		let mut statement = self.lex(statement);
		return statement.run(self);
	}
}

fn main() {
	println!("forth-rs version 0.1.0");
	println!("Type 'bye' to exit");
    let mut interp = Interpreter::new();
    let mut stdin = io::stdin();
    loop {
    	print!("> ");
    	io::stdout().flush().ok().expect("Could not flush stdout");
    	let mut line = String::new();
    	stdin.read_line(&mut line).ok().expect("Unable to read from stdin");
    	match interp.exec(line.trim_right()) {
    		Err(s) => {
    			println!("{:?}", s);
    		},
    		Ok(n) => {
    			println!("{}", n);
    		},
    	}
    }
}
<commit_msg>Add '.' 'dump' 'cr' and no longer echo by default.<commit_after>#![feature(convert, collections, unicode)]
#![allow(unused_variables)]

extern crate rustc_unicode;

use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::io;
use std::io::prelude::*;
use std::rc::Rc;
use std::fmt;
use rustc_unicode::str::UnicodeStr;

type Dictionary = HashMap<String, Rc<Entry>>;
type Statement = Vec<Op>;
type NativeFn = Box<Fn(&mut Vec<Op>, &mut Interpreter)>;

#[derive(Clone, Debug)]
enum Op {
	Number(i32),
	Word(Rc<Entry>),
}

enum Code {
	Native(NativeFn),
	Forth(Statement),
}

#[derive(Clone)]
struct Entry {
	name: String,
	code: Rc<Code>,
}

impl PartialEq for Entry {
	fn eq(&self, other: &Self) -> bool { self.name == other.name }
}

impl Eq for Entry {}

impl Hash for Entry {
	fn hash<H>(&self, state: &mut H) where H: Hasher {
		self.name.hash(state)
	}
}

impl fmt::Debug for Entry {
	fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		self.name.fmt(fmt)
	}
}

impl Entry {
	fn new(name: &str, code: Code) -> Entry {
		Entry {
			name: String::from_str(name),
			code: Rc::new(code),
		}
	}
}

impl Code {
	fn run(&self, stack: &mut Statement, interp: &mut Interpreter) {
		match self {
			&Code::Native(ref f) => {
				f(stack, interp);
			},
			&Code::Forth(ref statement) => {
				for ref op in statement {
					match *op {
						&Op::Number(ref n) => { break; }
						&Op::Word(ref w) => {
							(*w).code.run(stack, interp);
						},
					}
				}
			},
		}
	}
}

trait StatementExt {
	fn pop_number(&mut self, &mut Interpreter) -> i32;
	fn push_number(&mut self, i32);
	fn run(&mut self, &mut Interpreter) -> Result<i32, Statement>;
}

impl StatementExt for Statement {
	fn pop_number(&mut self, interp: &mut Interpreter) -> i32 {
		loop {
			match self.pop() {
				Some(Op::Number(n)) => { return n; },
				Some(Op::Word(s)) => s.code.run(self, interp),
				None => panic!("Popped empty statement"),
			}
		}
	}

	fn push_number(&mut self, number: i32) {
		self.push(Op::Number(number));
	}

	fn run(&mut self, interp: &mut Interpreter) -> Result<i32, Statement> {
		while self.len() > 0 {
			match self.pop() {
				Some(Op::Number(n)) => {
					if self.len() == 0 {
						return Ok(n)
					} else {
						self.push(Op::Number(n));
						return Err(self.clone())
					}
				},
				Some(Op::Word(w)) => {
					let code = interp.dictionary[w.name.as_str()].code.clone();
					code.run(self, interp);
				},
				None => unreachable!(),
			};
		}
		Ok(0)
	}
}

trait DictionaryExt {
	fn insert_entry(&mut self, Entry);
}

impl DictionaryExt for Dictionary {
	fn insert_entry(&mut self, entry: Entry) {
		self.insert(entry.name.clone(), Rc::new(entry));
	}
}

struct Interpreter {
    dictionary: Dictionary,
}

macro_rules! binary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let b = stack.pop_number(interp);
					let a = stack.pop_number(interp);
					stack.push_number($o(a, b));
				})),
			)
	}
}

macro_rules! unary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let a = stack.pop_number(interp);
					stack.push_number($o(a));
				})),
			)
	}
}

macro_rules! nonary_entry {
	($name:expr, $o:expr) => {
		Entry::new($name,
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					Op::Number($o);
				})),
			)
	}
}

impl Interpreter {
	fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		dict.insert_entry(binary_entry!("/", ::std::ops::Div::div));
		dict.insert_entry(binary_entry!("*", ::std::ops::Mul::mul));
		dict.insert_entry(binary_entry!("+", ::std::ops::Add::add));
		dict.insert_entry(binary_entry!("-", ::std::ops::Sub::sub));
		dict.insert_entry(binary_entry!("mod", ::std::ops::Rem::rem));
		dict.insert_entry(binary_entry!("and", ::std::ops::BitAnd::bitand));
		dict.insert_entry(binary_entry!("or", ::std::ops::BitOr::bitor));
		dict.insert_entry(binary_entry!("xor", ::std::ops::BitXor::bitxor));
		dict.insert_entry(binary_entry!("rshift", ::std::ops::Shr::shr));
		dict.insert_entry(binary_entry!("lshift", ::std::ops::Shl::shl));

		dict.insert_entry(unary_entry!("negate", ::std::ops::Neg::neg));
		dict.insert_entry(unary_entry!("not", ::std::ops::Not::not));

		dict.insert_entry(nonary_entry!("bye", ::std::process::exit(0)));

		dict.insert_entry(Entry::new("<",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let y = stack.pop_number(interp);
					let x = stack.pop_number(interp);
					stack.push(if x < y { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new(">",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let y = stack.pop_number(interp);
					let x = stack.pop_number(interp);
					stack.push(if x > y { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("=",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let y = stack.pop_number(interp);
					let x = stack.pop_number(interp);
					stack.push(if x == y { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("0<",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push(if x < 0 { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("0=",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push(if x == 0 { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("0>",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push(if x > 0 { Op::Number(1) } else { Op::Number(0) });
				})),
			));

		dict.insert_entry(Entry::new("1+",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x + 1);
				})),
			));

		dict.insert_entry(Entry::new("1-",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x - 1);
				})),
			));

		dict.insert_entry(Entry::new("2+",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x + 2);
				})),
			));

		dict.insert_entry(Entry::new("2-",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x - 2);
				})),
			));

		dict.insert_entry(Entry::new("2/",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x >> 1); // Per fst83 standard
				})),
			));

		dict.insert_entry(Entry::new("dup",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					stack.push_number(x.clone());
					stack.push_number(x);
				})),
			));

		dict.insert_entry(Entry::new("?dup",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					if x != 0 {
						stack.push_number(x.clone());
						stack.push_number(x);
					} else {
						stack.push_number(x);
					}
				})),
			));

		dict.insert_entry(Entry::new("over",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					let y = stack.pop_number(interp);
					stack.push_number(x.clone());
					stack.push_number(y);
					stack.push_number(x);
				})),
			));

		dict.insert_entry(Entry::new("rot",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop_number(interp);
					let y = stack.pop_number(interp);
					let z = stack.pop_number(interp);
					stack.push_number(y);
					stack.push_number(x);
					stack.push_number(z);
				})),
			));

		dict.insert_entry(Entry::new("dump",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					let x = stack.pop().unwrap();
					print!("{:?} ", x);
					stack.push(x);
				})),
			));

		dict.insert_entry(Entry::new("cr",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					println!("");
				})),
			));

		dict.insert_entry(Entry::new(".",
				Code::Native(Box::new(|stack: &mut Statement, interp: &mut Interpreter| {
					println!("{:?}", stack.pop_number(interp));
				})),
			));

		Interpreter {
			dictionary: dict,
		}
	}

	fn lex(&mut self, statement: &str) -> Statement {
		let words = statement.split(' ');
		let mut ret = Statement::new();
		for word in words {
			if let Some(n) = i32::from_str_radix(word, 10).ok() {
				ret.push(Op::Number(n));
			} else if (*word).is_whitespace() {
				return ret;
			} else {
				ret.push(Op::Word(self.dictionary[word.to_lowercase().as_str()].clone()));
			}
		};
		ret
	}

	fn exec(&mut self, statement: &str) -> Result<i32, Statement> {
		let mut statement = self.lex(statement);
		return statement.run(self);
	}
}

fn main() {
	println!("forth-rs version 0.1.0");
	println!("Type 'bye' to exit");
    let mut interp = Interpreter::new();
    let mut stdin = io::stdin();
    loop {
    	print!("Forth> ");
    	io::stdout().flush().ok().expect("Could not flush stdout");
    	let mut line = String::new();
    	stdin.read_line(&mut line).ok().expect("Unable to read from stdin");
    	let result = interp.exec(line.trim());
    }
}
<|endoftext|>


<commit_before>// Author : Thibault Barbie
//
// A simple evolutionary algorithm written in Rust.
//
//

extern crate rand;

use rand::Rng;
use std::collections::HashMap;

fn main() {
    let target: String = "METHINKS IT IS LIKE A WEASEL".to_string();
    println!("{}", target);

    let mut parent: String = "".to_string();
    generate_first_sentence(&mut parent);
    println!("{}", parent);

    let nb_copy = 400;
    let mutation_rate: f64 = 0.05;
    let mut counter = 0;

    while fitness(&target, &parent) != 0 {
        counter += 1;
        let mut sentences = HashMap::new();
        let mut f_min: u32 = 30;
        for _ in 0..nb_copy {
            let sentence = mutate(&mut parent, mutation_rate);
            let f = fitness(&target, &sentence);
            sentences.insert(f, sentence);

            if f < f_min {
                f_min = f
            }
        }

        if fitness(&target, &parent) > f_min {
            match sentences.get(&f_min) {
                Some(s) => {
                    parent = s.clone();
                    println!("{} : {}", parent, counter);
                }
                None => println!("Error, fitness minimum but no sentence."),
            }
        }
    }
}

fn fitness(target: &String, sentence: &String) -> u32 {
    let mut fitness = 0;
    for (c1, c2) in target.chars().zip(sentence.chars()) {
        if c1 != c2 {
            fitness += 1
        };
    }
    fitness
}

fn mutate(sentence: &mut String, mutation_rate: f64) -> String {
    let mut rng = rand::thread_rng();

    let mut mutation: String = "".to_string();
    for c in sentence.chars() {
        match mutation_rate > rng.gen_range(0f64, 1f64) {
            false => mutation.push(c),               // no mutation
            true => mutation.push(random_char()),   // mutation
        }
    }
    mutation
}

fn generate_first_sentence(parent: &mut String) {
    for _ in 0..28 {
        parent.push(random_char());
    }
}

fn random_char() -> char {
    match rand::thread_rng().gen_range('A' as u8, '\\' as u8) as char {
        '[' => ' ',
        c @ _ => c,
    }
}
<commit_msg>Fix header comment<commit_after>//! A simple evolutionary algorithm written in Rust.

extern crate rand;

use rand::Rng;
use std::collections::HashMap;

fn main() {
    let target: String = "METHINKS IT IS LIKE A WEASEL".to_string();
    println!("{}", target);

    let mut parent: String = "".to_string();
    generate_first_sentence(&mut parent);
    println!("{}", parent);

    let nb_copy = 400;
    let mutation_rate: f64 = 0.05;
    let mut counter = 0;

    while fitness(&target, &parent) != 0 {
        counter += 1;
        let mut sentences = HashMap::new();
        let mut f_min: u32 = 30;
        for _ in 0..nb_copy {
            let sentence = mutate(&mut parent, mutation_rate);
            let f = fitness(&target, &sentence);
            sentences.insert(f, sentence);

            if f < f_min {
                f_min = f
            }
        }

        if fitness(&target, &parent) > f_min {
            match sentences.get(&f_min) {
                Some(s) => {
                    parent = s.clone();
                    println!("{} : {}", parent, counter);
                }
                None => println!("Error, fitness minimum but no sentence."),
            }
        }
    }
}

fn fitness(target: &String, sentence: &String) -> u32 {
    let mut fitness = 0;
    for (c1, c2) in target.chars().zip(sentence.chars()) {
        if c1 != c2 {
            fitness += 1
        };
    }
    fitness
}

fn mutate(sentence: &mut String, mutation_rate: f64) -> String {
    let mut rng = rand::thread_rng();

    let mut mutation: String = "".to_string();
    for c in sentence.chars() {
        match mutation_rate > rng.gen_range(0f64, 1f64) {
            false => mutation.push(c),               // no mutation
            true => mutation.push(random_char()),   // mutation
        }
    }
    mutation
}

fn generate_first_sentence(parent: &mut String) {
    for _ in 0..28 {
        parent.push(random_char());
    }
}

fn random_char() -> char {
    match rand::thread_rng().gen_range('A' as u8, '\\' as u8) as char {
        '[' => ' ',
        c @ _ => c,
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate walkdir;
extern crate twox_hash;

use std::collections::HashMap;
use std::collections::BTreeSet;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::os::linux::fs::MetadataExt;

use clap::{App, Arg, ArgMatches};
use walkdir::WalkDir;
use twox_hash::XxHash;
use std::hash::Hasher;

#[derive(Default)]
struct Stats {
    file_count: u64,
    total_size: u64,
    duplicate_count: u64,
}

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("dupr")
        .version("0.1.0")
        .author("Mike Sampson")
        .about("Duplicate file finder")
        .arg(
            Arg::with_name("DIR")
                .help("Directory to process")
                .required(true),
        )
        .arg(Arg::with_name("sameline").short("1").long("sameline").help(
            "List each set of matches on a single line",
        ))
        .arg(Arg::with_name("noempty").short("n").long("noempty").help(
            "Exclude zero length files",
        ))
        .arg(Arg::with_name("summary").short("s").long("summary").help(
            "Print out summary information after duplicates",
        ))
        .arg(Arg::with_name("size").short("S").long("size").help(
            "Show size of duplicate files",
        ))
        .get_matches()
}

fn collect_paths(path: &str, noempty: bool, stats: &mut Stats) -> HashMap<u64, Vec<PathBuf>> {

    let mut length_paths = HashMap::new();
    let spinner = ["|", "/", "-", "\\"];

    for (idx, entry) in WalkDir::new(path).into_iter().enumerate() {
        eprint!("\rBuilding file list {} ", spinner[idx % spinner.len()]);
        let entry = match entry {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if !entry.file_type().is_file() {
            continue;
        }

        let metadata = match entry.metadata() {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if noempty && metadata.len() == 0 {
            continue;
        }

        stats.file_count += 1;
        stats.total_size += metadata.len();

        let path = entry.path().to_path_buf();

        length_paths
            .entry(metadata.len())
            .or_insert(Vec::new())
            .push(path);
    }
    eprint!("\r{:40}", " ");

    length_paths
}

fn main() {
    let matches = parse_args();

    let mut stats: Stats = Default::default();

    let files = collect_paths(
        matches.value_of("DIR").unwrap(),
        matches.is_present("noempty"),
        &mut stats,
    );

    let mut len_hash_path = HashMap::new();
    let mut paths_completed = 0;

    for (len, paths) in &files {

        eprint!(
            "\rProgress [{}/{}] {:.0}%",
            paths_completed,
            stats.file_count,
            100.0 * paths_completed as f64 / stats.file_count as f64
        );

        if paths.len() < 2 {
            continue;
        }

        paths_completed += paths.len();

        let mut inode_paths = HashMap::new();

        for path in paths {
            let metadata = match path.metadata() {
                Ok(m) => m,
                Err(err) => {
                    eprintln!("dupr: {}", err);
                    continue;
                }
            };

            let dev_inode = (metadata.st_dev(), metadata.st_ino());

            inode_paths.entry(dev_inode).or_insert(Vec::new()).push(
                path,
            );
        }

        if inode_paths.len() > 1 {
            for paths in inode_paths.values() {
                len_hash_path
                    .entry((len, hash_file(paths[0])))
                    .or_insert(BTreeSet::new())
                    .insert(paths[0]);
            }
        }
    }
    eprint!("\r{:40}\r", " ");

    let mut keys:Vec<_> = len_hash_path.iter().filter(|&(_,v)| v.len() > 1).collect();
    keys.sort();
    stats.duplicate_count = keys.len() as u64;

    for (&(len, _), paths) in keys {
        if matches.is_present("size") {
            println!("{} bytes each:", len);
        }

        if matches.is_present("sameline") {
            let p: Vec<_> = paths.iter().map(|x| x.to_string_lossy()).collect();
            println!("{}", p.join("-"));
        } else {
            for path in paths {
                println!("{}", path.display());
            }
            println!();
        }
    }

    if matches.is_present("summary") {
        println!(
            "Processed {} files with a total size of {} bytes. {} duplicates found.",
            stats.file_count,
            stats.total_size,
            stats.duplicate_count
        );
    }
}

fn hash_file<P: AsRef<Path>>(path: P) -> u64 {
    let mut file = File::open(path).unwrap();

    let mut hash = XxHash::with_seed(0);

    let mut buffer = [0; 32 * 1024];

    while let Ok(n) = file.read(&mut buffer) {
        if n == 0 {
            break;
        }
        hash.write(&buffer[0..n]);
    }

    hash.finish()
}
<commit_msg>Style cleanup<commit_after>extern crate clap;
extern crate walkdir;
extern crate twox_hash;

use std::collections::HashMap;
use std::collections::BTreeSet;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::os::linux::fs::MetadataExt;

use clap::{App, Arg, ArgMatches};
use walkdir::WalkDir;
use twox_hash::XxHash;
use std::hash::Hasher;

#[derive(Default)]
struct Stats {
    file_count: u64,
    total_size: u64,
    duplicate_count: u64,
}

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("dupr")
        .version("0.1.0")
        .author("Mike Sampson")
        .about("Duplicate file finder")
        .arg(
            Arg::with_name("DIR")
                .help("Directory to process")
                .required(true),
        )
        .arg(
            Arg::with_name("sameline")
                .short("1")
                .long("sameline")
                .help("List each set of matches on a single line"),
        )
        .arg(Arg::with_name("noempty").short("n").long("noempty").help(
            "Exclude zero length files",
        ))
        .arg(Arg::with_name("summary").short("s").long("summary").help(
            "Print out summary information after duplicates",
        ))
        .arg(Arg::with_name("size").short("S").long("size").help(
            "Show size of duplicate files",
        ))
        .get_matches()
}

fn collect_paths(path: &str, noempty: bool, stats: &mut Stats) -> HashMap<u64, Vec<PathBuf>> {

    let mut length_paths = HashMap::new();
    let spinner = ["|", "/", "-", "\\"];

    for (idx, entry) in WalkDir::new(path).into_iter().enumerate() {
        eprint!("\rBuilding file list {} ", spinner[idx % spinner.len()]);
        let entry = match entry {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if !entry.file_type().is_file() {
            continue;
        }

        let metadata = match entry.metadata() {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if noempty && metadata.len() == 0 {
            continue;
        }

        stats.file_count += 1;
        stats.total_size += metadata.len();

        let path = entry.path().to_path_buf();

        length_paths
            .entry(metadata.len())
            .or_insert(Vec::new())
            .push(path);
    }
    eprint!("\r{:40}", " ");

    length_paths
}

fn main() {
    let matches = parse_args();

    let mut stats: Stats = Default::default();

    let files = collect_paths(
        matches.value_of("DIR").unwrap(),
        matches.is_present("noempty"),
        &mut stats,
    );

    let mut len_hash_path = HashMap::new();
    let mut paths_completed = 0;

    for (len, paths) in &files {

        eprint!(
            "\rProgress [{}/{}] {:.0}%",
            paths_completed,
            stats.file_count,
            100.0 * paths_completed as f64 / stats.file_count as f64
        );

        if paths.len() < 2 {
            continue;
        }

        paths_completed += paths.len();

        let mut inode_paths = HashMap::new();

        for path in paths {
            let metadata = match path.metadata() {
                Ok(m) => m,
                Err(err) => {
                    eprintln!("dupr: {}", err);
                    continue;
                }
            };

            let dev_inode = (metadata.st_dev(), metadata.st_ino());

            inode_paths.entry(dev_inode).or_insert(Vec::new()).push(
                path,
            );
        }

        if inode_paths.len() > 1 {
            for paths in inode_paths.values() {
                len_hash_path
                    .entry((len, hash_file(paths[0])))
                    .or_insert(BTreeSet::new())
                    .insert(paths[0]);
            }
        }
    }
    eprint!("\r{:40}\r", " ");

    let mut keys: Vec<_> = len_hash_path.iter().filter(|&(_, v)| v.len() > 1).collect();
    keys.sort();
    stats.duplicate_count = keys.len() as u64;

    for (&(len, _), paths) in keys {
        if matches.is_present("size") {
            println!("{} bytes each:", len);
        }

        if matches.is_present("sameline") {
            let p: Vec<_> = paths.iter().map(|x| x.to_string_lossy()).collect();
            println!("{}", p.join("-"));
        } else {
            for path in paths {
                println!("{}", path.display());
            }
            println!();
        }
    }

    if matches.is_present("summary") {
        println!(
            "Processed {} files with a total size of {} bytes. {} duplicates found.",
            stats.file_count,
            stats.total_size,
            stats.duplicate_count
        );
    }
}

fn hash_file<P: AsRef<Path>>(path: P) -> u64 {
    let mut file = File::open(path).unwrap();

    let mut hash = XxHash::with_seed(0);

    let mut buffer = [0; 32 * 1024];

    while let Ok(n) = file.read(&mut buffer) {
        if n == 0 {
            break;
        }
        hash.write(&buffer[0..n]);
    }

    hash.finish()
}
<|endoftext|>


<commit_before>use std::ptr::null_mut;
use std::mem;
type Link<T> = Option<Box<Node<T>>>;

#[derive(Debug)]
struct Raw<T> {
    ptr: *const Node<T>,
}
impl<T> Raw<T> {
    fn none() -> Self {
        Raw { ptr: null_mut() }
    }
    fn some(ptr: &mut Node<T>) -> Self {
        Raw { ptr: ptr }
    }
    fn as_mut(&mut self) -> Option<&mut Node<T>> {
        unsafe {
            if self.ptr.is_null() {
                None
            } else {
                Some(&mut *(self.ptr as *mut Node<T>))
            }
        }

    }

    fn take(&mut self) -> Self {
        mem::replace(self, Raw::none())
    }
}

#[derive(Debug)]
struct Node<T> {
    elem: T,
    next: Link<T>,
    prev: Raw<T>,
}
impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Node { elem: elem, next: None, prev: Raw::none() }
    }
    fn link(&mut self, mut next: Box<Self>) {
        next.prev = Raw::some(self);
        self.next = Some(next);
    }
    fn take_next(&mut self) -> Option<Box<Self>> {
        let mut next = self.next.take();
        next.as_mut().map(|node| {
            node.prev = Raw::none();
        });
        next
    }
}
#[derive(Debug)]
struct LinedList<T> {
    head: Link<T>,
    tail: Raw<T>,
    len: usize,
}

impl<T> LinedList<T> {
    fn new() -> Self {
        LinedList { head: None, tail: Raw::none(), len: 0 }
    }

    fn push_back(&mut self, elem: T) {
        self.len += 1;
        let mut node = Box::new(Node::new(elem));
        let mut old_tail = mem::replace(&mut self.tail, Raw::some(&mut *node));

        match old_tail.as_mut() {
            Some(tail) => tail.link(node),
            None => self.head = Some(node),
        }

    }

    fn pop_back(&mut self) -> Option<T> {
        self.tail.take().as_mut().and_then(|tail| {
            self.len -= 1;
            match tail.prev.as_mut() {
                Some(prev) => {
                    self.tail = Raw::some(prev);
                    prev.next.take().map(|node| node.elem)
                },
                None => self.head.take().map(|node| node.elem)
            }
        })
    }

    fn push_front(&mut self, elem: T) {
        self.len += 1;
        let mut new_head = Box::new(Node::new(elem));
        match self.head.take() {
            Some(head) => new_head.link(head),
            None => self.tail = Raw::some(&mut new_head)
        }
        self.head = Some(new_head);
    }

    fn pop_front(&mut self) -> Option<T> {
        self.head.take().and_then(|mut head| {
            // head is Box<Node<T>>
            self.len -= 1;
            head.take_next().map(|mut node| {
                node.prev = Raw::none();
                self.head = Some(node);
            });

            Some(head.elem)

        })
    }

}

/// 三种格式,
/// iter()   // over &T
/// iter_mut()   // over &mut T
/// into_iter()     // over T
///
/// 实现 Iterator
/// 1. 创建一个 struct 保存 iterator 状态
/// 2. 为这个 struct 实现 Iterator traid
fn main() {
    let mut l = LinedList::new();
    l.push_back(30);
    l.pop_front();
}

#[test]
fn push_pop_test() {
    let mut l = LinedList::new();
    l.push_back(30);
    assert_eq!(l.len, 1);
    l.push_back(20);
    assert_eq!(l.len, 2);
    assert_eq!(l.pop_back(), Some(20));
    assert_eq!(l.len, 1);
    assert_eq!(l.pop_back(), Some(30));
    assert_eq!(l.len, 0);
    l.push_back(22);
    assert_eq!(l.len, 1);
    assert_eq!(l.pop_back(), Some(22));
    assert_eq!(l.len, 0);
    assert_eq!(l.pop_back(), None);
    assert_eq!(l.len, 0);
    assert_eq!(l.pop_back(), None);
    assert_eq!(l.len, 0);
}

#[test]
fn push_front_test() {
    let mut list = LinedList::new();
    assert_eq!(list.len, 0);
    list.push_front(30);
    assert_eq!(list.len, 1);
    list.push_front(12);
    assert_eq!(list.len, 2);
    assert_eq!(list.pop_back(), Some(30));
    assert_eq!(list.len, 1);
    assert_eq!(list.pop_back(), Some(12));
    assert_eq!(list.len, 0);
}

#[test]
fn push_front_back_test() {
    let mut list = LinedList::new();
    assert_eq!(list.len, 0);
    list.push_front(30);
    assert_eq!(list.len, 1);
    list.push_front(12);
    assert_eq!(list.len, 2);
    list.push_back(22);
    assert_eq!(list.len, 3);
    assert_eq!(list.pop_back(), Some(22));
    assert_eq!(list.len, 2);
    assert_eq!(list.pop_back(), Some(30));
    assert_eq!(list.len, 1);
    assert_eq!(list.pop_back(), Some(12));
    assert_eq!(list.len, 0);
}

#[test]
fn pop_front_test() {
    let mut list = LinedList::new();
    list.push_front(30);
    list.push_front(12);
    list.push_back(22);
    assert_eq!(list.pop_front(), Some(12));
    assert_eq!(list.pop_front(), Some(30));
    assert_eq!(list.pop_front(), Some(22));
    assert_eq!(list.pop_front(), None);
}

<commit_msg>add pop front<commit_after>use std::ptr::null_mut;
use std::mem;
type Link<T> = Option<Box<Node<T>>>;

#[derive(Debug)]
struct Raw<T> {
    ptr: *const Node<T>,
}
impl<T> Raw<T> {
    fn none() -> Self {
        Raw { ptr: null_mut() }
    }
    fn some(ptr: &mut Node<T>) -> Self {
        Raw { ptr: ptr }
    }
    fn as_mut(&mut self) -> Option<&mut Node<T>> {
        unsafe {
            if self.ptr.is_null() {
                None
            } else {
                Some(&mut *(self.ptr as *mut Node<T>))
            }
        }

    }

    fn take(&mut self) -> Self {
        mem::replace(self, Raw::none())
    }
}

#[derive(Debug)]
struct Node<T> {
    elem: T,
    next: Link<T>,
    prev: Raw<T>,
}
impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Node { elem: elem, next: None, prev: Raw::none() }
    }
    fn link(&mut self, mut next: Box<Self>) {
        next.prev = Raw::some(self);
        self.next = Some(next);
    }
    fn take_next(&mut self) -> Option<Box<Self>> {
        let mut next = self.next.take();
        next.as_mut().map(|node| {
            node.prev = Raw::none();
        });
        next
    }
}
#[derive(Debug)]
struct LinedList<T> {
    head: Link<T>,
    tail: Raw<T>,
    len: usize,
}

impl<T> LinedList<T> {
    fn new() -> Self {
        LinedList { head: None, tail: Raw::none(), len: 0 }
    }

    fn push_back(&mut self, elem: T) {
        self.len += 1;
        let mut node = Box::new(Node::new(elem));
        let mut old_tail = mem::replace(&mut self.tail, Raw::some(&mut *node));

        match old_tail.as_mut() {
            Some(tail) => tail.link(node),
            None => self.head = Some(node),
        }

    }

    fn pop_back(&mut self) -> Option<T> {
        self.tail.take().as_mut().and_then(|tail| {
            self.len -= 1;
            match tail.prev.as_mut() {
                Some(prev) => {
                    self.tail = Raw::some(prev);
                    prev.next.take().map(|node| node.elem)
                },
                None => self.head.take().map(|node| node.elem)
            }
        })
    }

    fn push_front(&mut self, elem: T) {
        self.len += 1;
        let mut new_head = Box::new(Node::new(elem));
        match self.head.take() {
            Some(head) => new_head.link(head),
            None => self.tail = Raw::some(&mut new_head)
        }
        self.head = Some(new_head);
    }

    fn pop_front(&mut self) -> Option<T> {
        self.head.take().and_then(|mut head| {
            // head is Box<Node<T>>
            self.len -= 1;
            head.take_next().map(|mut node| {
                node.prev = Raw::none();
                self.head = Some(node);
            });

            Some(head.elem)

        })
    }

    fn iter(&self) -> Iter<T> {
        Iter {
            head: &self.head,
            tail: &self.tail,
            nelem: self.len,
        }
    }

}

/// 三种格式,
/// iter()   // over &T
/// iter_mut()   // over &mut T
/// into_iter()     // over T
///
/// 实现 Iterator
/// 1. 创建一个 struct 保存 iterator 状态
/// 2. 为这个 struct 实现 Iterator traid

struct Iter<'a, T: 'a> {
    head: &'a Link<T>,
    tail: &'a Raw<T>,
    nelem: usize,

}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        if self.nelem == 0 {
            return None
        }

        self.head.as_ref().and_then(|head| {
            self.nelem -= 1;
            self.head = &head.next;
            Some(&head.elem)
        })
    }
}
fn main() {
    let mut l = LinedList::new();
    for i in 0..30 {
        l.push_back(i);
    }

    for i in l.iter() {
        println!("i = {:#?}", i);
    }
}

#[test]
fn push_pop_test() {
    let mut l = LinedList::new();
    l.push_back(30);
    assert_eq!(l.len, 1);
    l.push_back(20);
    assert_eq!(l.len, 2);
    assert_eq!(l.pop_back(), Some(20));
    assert_eq!(l.len, 1);
    assert_eq!(l.pop_back(), Some(30));
    assert_eq!(l.len, 0);
    l.push_back(22);
    assert_eq!(l.len, 1);
    assert_eq!(l.pop_back(), Some(22));
    assert_eq!(l.len, 0);
    assert_eq!(l.pop_back(), None);
    assert_eq!(l.len, 0);
    assert_eq!(l.pop_back(), None);
    assert_eq!(l.len, 0);
}

#[test]
fn push_front_test() {
    let mut list = LinedList::new();
    assert_eq!(list.len, 0);
    list.push_front(30);
    assert_eq!(list.len, 1);
    list.push_front(12);
    assert_eq!(list.len, 2);
    assert_eq!(list.pop_back(), Some(30));
    assert_eq!(list.len, 1);
    assert_eq!(list.pop_back(), Some(12));
    assert_eq!(list.len, 0);
}

#[test]
fn push_front_back_test() {
    let mut list = LinedList::new();
    assert_eq!(list.len, 0);
    list.push_front(30);
    assert_eq!(list.len, 1);
    list.push_front(12);
    assert_eq!(list.len, 2);
    list.push_back(22);
    assert_eq!(list.len, 3);
    assert_eq!(list.pop_back(), Some(22));
    assert_eq!(list.len, 2);
    assert_eq!(list.pop_back(), Some(30));
    assert_eq!(list.len, 1);
    assert_eq!(list.pop_back(), Some(12));
    assert_eq!(list.len, 0);
}

#[test]
fn pop_front_test() {
    let mut list = LinedList::new();
    list.push_front(30);
    list.push_front(12);
    list.push_back(22);
    assert_eq!(list.pop_front(), Some(12));
    assert_eq!(list.pop_front(), Some(30));
    assert_eq!(list.pop_front(), Some(22));
    assert_eq!(list.pop_front(), None);
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate iron;
extern crate persistent;
extern crate staticfile;
extern crate mount;
extern crate gluon;
extern crate serde_json;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::io::Read;
use std::time::Instant;

use iron::prelude::*;
use iron::status;
use iron::typemap::Key;

use staticfile::Static;

use mount::Mount;

use gluon::vm::thread::{RootedThread, ThreadInternal};
use gluon::vm::Error;
use gluon::vm::api::Generic;
use gluon::vm::api::generic::A;
use gluon::{Compiler, new_vm};

pub struct VMKey;
impl Key for VMKey {
    type Value = RootedThread;
}

fn eval(req: &mut Request) -> IronResult<Response> {
    eval_(req).map(|s| Response::with((status::Ok, ::serde_json::to_string(&s).unwrap())))
}
fn eval_(req: &mut Request) -> IronResult<String> {
    let mut body = String::new();
    itry!(req.body.read_to_string(&mut body));
    info!("Eval: `{}`", body);
    body.push(' ');
    let global_vm = req.get::<persistent::Read<VMKey>>().unwrap();
    let vm = match global_vm.new_thread() {
        Ok(vm) => vm,
        Err(err) => return Ok(format!("{}", err)),
    };

    // Prevent a single thread from allocating to much memory
    vm.set_memory_limit(2_000_000);

    // Prevent infinite loops from running forever
    let start = Instant::now();
    vm.context().set_hook(Some(Box::new(move |_| {
        if start.elapsed().as_secs() < 10 {
            Ok(())
        } else {
            Err(Error::Message("Thread has exceeded the allowed exection time".into()))
        }
    })));

    let (value, typ) = match Compiler::new().run_expr::<Generic<A>>(&vm, "<top>", &body) {
        Ok(value) => value,
        Err(err) => return Ok(format!("{}", err)),
    };
    Ok(format!("{:?} : {}", value, typ))
}

fn main() {
    env_logger::init().unwrap();
    let mut mount = Mount::new();

    mount.mount("/", Static::new("public"));

    let mut middleware = Chain::new(eval);
    let vm = new_vm();
    middleware.link(persistent::Read::<VMKey>::both(vm));
    mount.mount("/eval", middleware);

    let address = "0.0.0.0:8080";
    let _server = Iron::new(mount).http(address).unwrap();
    println!("Server started at `{}`", address);
}
<commit_msg>fix: Prevent evaluated scripts from importing files<commit_after>#[macro_use]
extern crate iron;
extern crate persistent;
extern crate staticfile;
extern crate mount;
extern crate gluon;
extern crate serde_json;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::io::Read;
use std::time::Instant;

use iron::prelude::*;
use iron::status;
use iron::typemap::Key;

use staticfile::Static;

use mount::Mount;

use gluon::vm::thread::{RootedThread, ThreadInternal};
use gluon::vm::Error;
use gluon::vm::api::Generic;
use gluon::vm::api::generic::A;
use gluon::{Compiler, new_vm};
use gluon::import::Import;

pub struct VMKey;
impl Key for VMKey {
    type Value = RootedThread;
}

fn eval(req: &mut Request) -> IronResult<Response> {
    eval_(req).map(|s| Response::with((status::Ok, ::serde_json::to_string(&s).unwrap())))
}
fn eval_(req: &mut Request) -> IronResult<String> {
    let mut body = String::new();
    itry!(req.body.read_to_string(&mut body));
    info!("Eval: `{}`", body);
    body.push(' ');
    let global_vm = req.get::<persistent::Read<VMKey>>().unwrap();
    let vm = match global_vm.new_thread() {
        Ok(vm) => vm,
        Err(err) => return Ok(format!("{}", err)),
    };

    // Prevent a single thread from allocating to much memory
    vm.set_memory_limit(2_000_000);

    // Prevent infinite loops from running forever
    let start = Instant::now();
    vm.context().set_hook(Some(Box::new(move |_| {
        if start.elapsed().as_secs() < 10 {
            Ok(())
        } else {
            Err(Error::Message("Thread has exceeded the allowed exection time".into()))
        }
    })));

    let (value, typ) = match Compiler::new().run_expr::<Generic<A>>(&vm, "<top>", &body) {
        Ok(value) => value,
        Err(err) => return Ok(format!("{}", err)),
    };
    Ok(format!("{:?} : {}", value, typ))
}

fn main() {
    env_logger::init().unwrap();
    let mut mount = Mount::new();

    mount.mount("/", Static::new("public"));

    let mut middleware = Chain::new(eval);
    let vm = new_vm();

    // Ensure the import macro cannot be abused to to open files
    {
        // Ensure the lock to `paths` are released
        let mac = vm.get_macros().get("import").expect("import");
        let mut import = mac.downcast_ref::<Import>()
            .expect("Import macro")
            .paths
            .write()
            .unwrap();
        import.clear();
    }

    middleware.link(persistent::Read::<VMKey>::both(vm));
    mount.mount("/eval", middleware);

    let address = "0.0.0.0:8080";
    let _server = Iron::new(mount).http(address).unwrap();
    println!("Server started at `{}`", address);
}
<|endoftext|>


<commit_before>extern crate gnuplot;
use gnuplot::{Figure, Color};
use gnuplot::PlotOption::LineWidth;

mod genetic;
use genetic::helpers::Range;
use genetic::helpers::{hamming_distance, euclidean_distance_int, euclidean_distance_float};
use genetic::population::{Population};
use genetic::fitness::{max_alternating_bits,
                       max_alternating_even_odd,
                       pattern_recognition,
                       min_dejong,
                       n_queens,
                       path_fitness,
                       deceptive_f3};
use genetic::crossover::{one_point_crossover,
                         uniform_average_crossover,
                         uniform_crossover,
                         partially_matched_crossover};
use genetic::mutation::{bit_flip,
                        swap_position,
                        random_int,
                        delta_mutation,
                        gaussian_mutation};

fn main() {
    let total_generations = 5000;

    let population_size = 30;
    let genome_size = 100;
    let crossover_probability = 0.95;
    let mutation_probability = 0.05;
    let has_elitism = true;
    let fitness_function = deceptive_f3;
    let mutation_function = bit_flip;
    let mut population = Population::<u8>::new(population_size,
                                               genome_size,
                                                crossover_probability,
                                                mutation_probability,
                                               Range::new(0, 1),
                                               has_elitism,
                                               hamming_distance,
                                               fitness_function,
                                               one_point_crossover,
                                                mutation_function);

    println!("Initial population");
    population.print();

    for current_generation in 0..total_generations {
        println!("\nA E S T H E T I C S: {}", current_generation);
        population.iterate_generation(current_generation, total_generations);
        //population.print();
    }

    // let gene = vec![1, 1, 3, 3, 1, 3, 2, 2, 0, 0];
    // println!("{:?}", gene);
    // (fitness_function)(&gene, &Range::new(0, 3));

    population.print_best_individual_diagnostic();

    show_convergence_plot(&population.average_fitness_in_generation,
                          &population.best_fitness_in_generation);

    show_diversity_plot(&population.diversity_in_generation);
}

fn show_convergence_plot(average_fitnesses: &Vec<f32>, best_fitnesses: &Vec<f32>) {
    let generations: Vec<usize> = (0..average_fitnesses.len()).collect();

    let mut fg = Figure::new();
    fg.set_terminal("wxt size 800, 400", "");
    fg.axes2d()
        .lines(&generations,
               average_fitnesses,
               &[Color("#505050"), LineWidth(1.5)])
        .lines(&generations,
               best_fitnesses,
               &[Color("#0072bd"), LineWidth(1.5)]);
    fg.show();
}

fn show_diversity_plot(diversity_in_generations: &Vec<f32>) {
    let generations: Vec<usize> = (0..diversity_in_generations.len()).collect();

    let mut fg = Figure::new();
    fg.set_terminal("wxt size 800, 400", "");
    fg.axes2d()
        .lines(&generations,
               diversity_in_generations,
               &[Color("#505050"), LineWidth(1.5)]);
    fg.show();
}
<commit_msg>Added labels to diversity and convergence plots<commit_after>extern crate gnuplot;
use gnuplot::{AxesCommon, Figure, Color};
use gnuplot::LabelOption::TextColor;
use gnuplot::PlotOption::LineWidth;

mod genetic;
use genetic::helpers::Range;
use genetic::helpers::{hamming_distance, euclidean_distance_int, euclidean_distance_float};
use genetic::population::{Population};
use genetic::fitness::{max_alternating_bits,
                       max_alternating_even_odd,
                       pattern_recognition,
                       min_dejong,
                       n_queens,
                       path_fitness,
                       deceptive_f3,
                       deceptive_f3s,
                       deceptive_4,};
use genetic::crossover::{one_point_crossover,
                         uniform_average_crossover,
                         uniform_crossover,
                         partially_matched_crossover};
use genetic::mutation::{bit_flip,
                        swap_position,
                        random_int,
                        delta_mutation,
                        gaussian_mutation};

fn main() {
    let total_generations = 2000;

    let population_size = 20;
    let genome_size = 64;
    let crossover_probability = 0.95;
    let mutation_probability = 0.05;
    let has_elitism = true;
    let fitness_function = deceptive_4;
    let mutation_function = bit_flip;
    let mut population = Population::<u8>::new(population_size,
                                               genome_size,
                                               crossover_probability,
                                               mutation_probability,
                                               Range::new(0, 1),
                                               has_elitism,
                                               hamming_distance,
                                               fitness_function,
                                               one_point_crossover,
                                               mutation_function);

    println!("Initial population");
    population.print();

    for current_generation in 0..total_generations {
        println!("\nA E S T H E T I C S: {}", current_generation);
        population.iterate_generation(current_generation, total_generations);
        //population.print();
    }

    // let gene = vec![1, 1, 3, 3, 1, 3, 2, 2, 0, 0];
    // println!("{:?}", gene);
    // (fitness_function)(&gene, &Range::new(0, 3));

    population.print_best_individual_diagnostic();

    show_convergence_plot(&population.average_fitness_in_generation,
                          &population.best_fitness_in_generation);

    show_diversity_plot(&population.diversity_in_generation);
}

fn show_convergence_plot(average_fitnesses: &Vec<f32>, best_fitnesses: &Vec<f32>) {
    let generations: Vec<usize> = (0..average_fitnesses.len()).collect();

    let mut fg = Figure::new();
    fg.set_terminal("wxt size 800, 400", "");
    {
        let axes = fg.axes2d()
            .lines(&generations,
                   average_fitnesses,
                   &[Color("#505050"), LineWidth(1.5)])
            .lines(&generations,
                   best_fitnesses,
                   &[Color("#0072bd"), LineWidth(1.5)]);

        let label_options = &[gnuplot::LabelOption::TextColor("black")];
        axes.set_x_label("Gerações", label_options);
        axes.set_y_label("Fitness", label_options);
    }
    fg.show();
}

fn show_diversity_plot(diversity_in_generations: &Vec<f32>) {
    let generations: Vec<usize> = (0..diversity_in_generations.len()).collect();

    let mut fg = Figure::new();
    fg.set_terminal("wxt size 800, 400", "");
    {
        let axes = fg.axes2d()
            .lines(&generations,
                   diversity_in_generations,
                   &[Color("#505050"), LineWidth(1.5)]);

        let label_options = &[gnuplot::LabelOption::TextColor("black")];
        axes.set_x_label("Gerações", label_options);
        axes.set_y_label("Diversidade", label_options);
    }
    fg.show();
}
<|endoftext|>