<commit_before>extern crate num;

use std::borrow::ToOwned;
use core::stack::Stack;
use window_system::Window;
use window_system::Rectangle;
use window_system::WindowSystem;
use window_manager::ScreenDetail;
use config::GeneralConfig;

#[derive(Clone, Copy)]
pub enum LayoutMessage {
    Increase,
    Decrease,
    IncreaseMaster,
    DecreaseMaster,
    IncreaseSlave,
    DecreaseSlave,
    IncreaseGap,
    DecreaseGap,
    Next,
    Prev,
    HorizontalSplit,
    VerticalSplit,
    Hide,
    TreeRotate,
    TreeSwap,
    TreeExpandTowards(Direction),
    TreeShrinkFrom(Direction)
}

pub fn mirror_rect(&Rectangle(x, y, w, h) : &Rectangle) -> Rectangle {
    Rectangle(y, x, h, w)
}

pub fn tile(ratio: f32, screen: ScreenDetail, num_master: u32, num_windows: u32) -> Vec<Rectangle> {
    if num_windows <= num_master || num_master == 0 {
        split_vertically(num_windows, screen)
    } else {
        let (r1, r2) = split_horizontally_by(ratio, screen);
        let v1 = split_vertically(num_master, r1);
        let v2 = split_vertically(num_windows - num_master, r2);
        v1.iter().chain(v2.iter()).map(|&x| x).collect()
    }
}

pub fn split_vertically(num: u32, screen: ScreenDetail) -> Vec<Rectangle> {
    if num < 2 {
        return vec!(screen);
    }

    let Rectangle(sx, sy, sw, sh) = screen;
    let smallh = sh / num;
    (vec!(Rectangle(sx, sy, sw, smallh))).iter()
        .chain(split_vertically(num - 1, Rectangle(sx, sy + smallh as i32, sw, sh - smallh)).iter())
        .map(|&x| x)
        .collect()
}

pub fn split_horizontally_by(ratio: f32, screen: ScreenDetail) -> (Rectangle, Rectangle) {
    let Rectangle(sx, sy, sw, sh) = screen;
    let leftw = (sw as f32 * ratio).floor() as u32;

    (Rectangle(sx, sy, leftw, sh), Rectangle(sx + leftw as i32, sy, sw - leftw, sh))
}

pub trait Layout {
    fn apply_layout(&mut self, window_system: &WindowSystem, screen: Rectangle, config: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)>;
    fn apply_message(&mut self, _: LayoutMessage, _: &WindowSystem,
                         _: &Option<Stack<Window>>, _: &GeneralConfig) -> bool { true }
    fn description(&self) -> String;
    fn copy(&self) -> Box<Layout> { panic!("") }
    fn unhook(&self, _: &WindowSystem, _: &Option<Stack<Window>>, _: &GeneralConfig) { }
}

#[derive(Clone, Copy)]
pub struct TallLayout {
    pub num_master: u32,
    pub increment_ratio: f32,
    pub ratio: f32
}

impl TallLayout {
    pub fn new() -> Box<Layout> {
        Box::new(TallLayout {
            num_master: 1,
            increment_ratio: 0.03,
            ratio: 0.5
        })
    }
}

impl Layout for TallLayout {
    fn apply_layout(&mut self, _: &WindowSystem, screen: Rectangle, _: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)> {
        match stack {
            &Some(ref s) => {
                let ws = s.integrate();
                s.integrate().iter()
                    .zip(tile(self.ratio, screen, self.num_master, ws.len() as u32).iter())
                    .map(|(&x, &y)| (x, y))
                    .collect()
            },
            _ => Vec::new()
        }
    }

    fn apply_message(&mut self, message: LayoutMessage, _: &WindowSystem,
                         _: &Option<Stack<Window>>, _: &GeneralConfig) -> bool {
        match message {
            LayoutMessage::Increase => { self.ratio += 0.05; true }
            LayoutMessage::Decrease => { self.ratio -= 0.05; true }
            LayoutMessage::IncreaseMaster => { self.num_master += 1; true }
            LayoutMessage::DecreaseMaster => {
                if self.num_master > 1 { self.num_master -= 1 } true
            }
            _                       => false
        }
    }

    fn description(&self) -> String {
        "Tall".to_owned()
    }

    fn copy(&self) -> Box<Layout> {
        Box::new(self.clone())
    }
}

#[repr(usize)]
#[derive(Clone, Copy, Ord, Eq, PartialOrd, PartialEq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right
}

impl Direction {
    pub fn opposite(&self) -> Direction {
        match self {
            &Direction::Up    => Direction::Down,
            &Direction::Down  => Direction::Up,
            &Direction::Left  => Direction::Right,
            &Direction::Right => Direction::Left
        }
    }
}

pub struct GapLayout {
    gap: u32,
    layout: Box<Layout>
}

impl GapLayout {
    pub fn new(gap: u32, layout: Box<Layout>) -> Box<Layout> {
        Box::new(GapLayout {
            gap: gap,
            layout: layout.copy()
        })
    }
}

impl Layout for GapLayout {
    fn apply_layout(&mut self, window_system: &WindowSystem, screen: Rectangle, config: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)> {
        let layout = self.layout.apply_layout(window_system, screen, config, stack);

        let g = self.gap;
        layout.iter().map(|&(win, Rectangle(x, y, w, h))| (win, Rectangle(x + g as i32, y + g as i32, w - 2 * g, h - 2 * g))).collect()
    }

    fn apply_message(&mut self, message: LayoutMessage, window_system: &WindowSystem,
                         stack: &Option<Stack<Window>>, config: &GeneralConfig) -> bool {
        match message {
            LayoutMessage::IncreaseGap => { self.gap += 1; true }
            LayoutMessage::DecreaseGap => { if self.gap > 0 { self.gap -= 1; } true }
            _                          => self.layout.apply_message(message, window_system, stack, config)
        }
    }

    fn description(&self) -> String {
        self.layout.description()
    }

    fn copy(&self) -> Box<Layout> {
        Box::new(GapLayout {
            gap: self.gap,
            layout: self.layout.copy()
        })
    }
}

pub struct WithBordersLayout {
    border: u32,
    layout: Box<Layout>
}

impl WithBordersLayout {
    pub fn new(border: u32, layout: Box<Layout>) -> Box<Layout> {
        Box::new(WithBordersLayout {
            border: border,
            layout: layout.copy()
        })
    }
}

impl Layout for WithBordersLayout {
    fn apply_layout(&mut self, window_system: &WindowSystem, screen: Rectangle, config: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)> {
        if let &Some(ref s) = stack {
            for window in s.integrate().into_iter() {
                window_system.set_window_border_width(window, self.border);
            }
        }
        self.layout.apply_layout(window_system, screen, config, stack)
    }

    fn apply_message(&mut self, message: LayoutMessage, window_system: &WindowSystem,
                         stack: &Option<Stack<Window>>, config: &GeneralConfig) -> bool {
        self.layout.apply_message(message, window_system, stack, config)
    }

    fn description(&self) -> String {
        self.layout.description()
    }

    fn copy(&self) -> Box<Layout> {
        Box::new(WithBordersLayout {
            border: self.border,
            layout: self.layout.copy()
        })
    }

    fn unhook(&self, window_system: &WindowSystem, stack: &Option<Stack<Window>>, config: &GeneralConfig) {
        if let &Some(ref s) = stack {
            for window in s.integrate().into_iter() {
                window_system.set_window_border_width(window, config.border_width);
                let Rectangle(_, _, w, h) = window_system.get_geometry(window);
                window_system.resize_window(window, w + 2 * config.border_width, h + 2 * config.border_width);
            }
        }
    }
}

pub struct NoBordersLayout;

impl NoBordersLayout {
    pub fn new(layout: Box<Layout>) -> Box<Layout> {
        WithBordersLayout::new(0, layout)
    }
}

#[derive(Copy, Clone)]
pub struct FullLayout;

impl Layout for FullLayout {
    fn apply_layout(&mut self, _: &WindowSystem, screen: Rectangle, config: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)> {
        match *stack {
            Some(ref st) => {
                let bw = 2 * config.border_width;
                let Rectangle(x, y, sw, sh) = screen;
                vec!((st.focus, Rectangle(x, y, sw + bw, sh + bw)))
            }
            None     => Vec::new()
        }
    }

    fn description(&self) -> String {
        "Full".to_owned()
    }

    fn copy(&self) -> Box<Layout> {
        Box::new(self.clone())
    }
}

pub struct LayoutCollection {
    pub layouts: Vec<Box<Layout>>,
    pub current: usize
}

impl LayoutCollection {
    pub fn new(layouts: Vec<Box<Layout>>) -> Box<Layout> {
        Box::new(LayoutCollection {
            layouts: layouts,
            current: 0
        })
    }
}

impl Layout for LayoutCollection {
    fn apply_layout(&mut self, window_system: &WindowSystem, screen: Rectangle, config: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)> {
        self.layouts[self.current].apply_layout(window_system, screen, config, stack)
    }

    fn apply_message(&mut self, message: LayoutMessage, window_system: &WindowSystem,
                         stack: &Option<Stack<Window>>, config: &GeneralConfig) -> bool {
        match message {
            LayoutMessage::Next => {
                self.layouts[self.current].unhook(window_system, stack, config);
                self.current = (self.current + 1) % self.layouts.len();
                true
            }
            LayoutMessage::Prev => {
                self.layouts[self.current].unhook(window_system, stack, config);
                self.current = (self.current + (self.layouts.len() - 1)) % self.layouts.len();
                true
            }
            _                   => self.layouts[self.current].apply_message(message, window_system, stack, config)
        }
    }

    fn description(&self) -> String {
        self.layouts[self.current].description()
    }

    fn copy(&self) -> Box<Layout> {
        Box::new(LayoutCollection {
            current: self.current,
            layouts: self.layouts.iter().map(|x| x.copy()).collect()
        })
    }
}
<commit_msg>factored out some layouts and moved them to wtftw-contrib<commit_after>extern crate num;

use std::borrow::ToOwned;
use core::stack::Stack;
use window_system::Window;
use window_system::Rectangle;
use window_system::WindowSystem;
use window_manager::ScreenDetail;
use config::GeneralConfig;

#[derive(Clone, Copy)]
pub enum LayoutMessage {
    Increase,
    Decrease,
    IncreaseMaster,
    DecreaseMaster,
    IncreaseSlave,
    DecreaseSlave,
    IncreaseGap,
    DecreaseGap,
    Next,
    Prev,
    HorizontalSplit,
    VerticalSplit,
    Hide,
    TreeRotate,
    TreeSwap,
    TreeExpandTowards(Direction),
    TreeShrinkFrom(Direction)
}

pub fn mirror_rect(&Rectangle(x, y, w, h) : &Rectangle) -> Rectangle {
    Rectangle(y, x, h, w)
}

pub fn tile(ratio: f32, screen: ScreenDetail, num_master: u32, num_windows: u32) -> Vec<Rectangle> {
    if num_windows <= num_master || num_master == 0 {
        split_vertically(num_windows, screen)
    } else {
        let (r1, r2) = split_horizontally_by(ratio, screen);
        let v1 = split_vertically(num_master, r1);
        let v2 = split_vertically(num_windows - num_master, r2);
        v1.iter().chain(v2.iter()).map(|&x| x).collect()
    }
}

pub fn split_vertically(num: u32, screen: ScreenDetail) -> Vec<Rectangle> {
    if num < 2 {
        return vec!(screen);
    }

    let Rectangle(sx, sy, sw, sh) = screen;
    let smallh = sh / num;
    (vec!(Rectangle(sx, sy, sw, smallh))).iter()
        .chain(split_vertically(num - 1, Rectangle(sx, sy + smallh as i32, sw, sh - smallh)).iter())
        .map(|&x| x)
        .collect()
}

pub fn split_horizontally_by(ratio: f32, screen: ScreenDetail) -> (Rectangle, Rectangle) {
    let Rectangle(sx, sy, sw, sh) = screen;
    let leftw = (sw as f32 * ratio).floor() as u32;

    (Rectangle(sx, sy, leftw, sh), Rectangle(sx + leftw as i32, sy, sw - leftw, sh))
}

pub trait Layout {
    fn apply_layout(&mut self, window_system: &WindowSystem, screen: Rectangle, config: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)>;
    fn apply_message(&mut self, _: LayoutMessage, _: &WindowSystem,
                         _: &Option<Stack<Window>>, _: &GeneralConfig) -> bool { true }
    fn description(&self) -> String;
    fn copy(&self) -> Box<Layout> { panic!("") }
    fn unhook(&self, _: &WindowSystem, _: &Option<Stack<Window>>, _: &GeneralConfig) { }
}

#[derive(Clone, Copy)]
pub struct TallLayout {
    pub num_master: u32,
    pub increment_ratio: f32,
    pub ratio: f32
}

impl TallLayout {
    pub fn new() -> Box<Layout> {
        Box::new(TallLayout {
            num_master: 1,
            increment_ratio: 0.03,
            ratio: 0.5
        })
    }
}

impl Layout for TallLayout {
    fn apply_layout(&mut self, _: &WindowSystem, screen: Rectangle, _: &GeneralConfig,
                    stack: &Option<Stack<Window>>) -> Vec<(Window, Rectangle)> {
        match stack {
            &Some(ref s) => {
                let ws = s.integrate();
                s.integrate().iter()
                    .zip(tile(self.ratio, screen, self.num_master, ws.len() as u32).iter())
                    .map(|(&x, &y)| (x, y))
                    .collect()
            },
            _ => Vec::new()
        }
    }

    fn apply_message(&mut self, message: LayoutMessage, _: &WindowSystem,
                         _: &Option<Stack<Window>>, _: &GeneralConfig) -> bool {
        match message {
            LayoutMessage::Increase => { self.ratio += 0.05; true }
            LayoutMessage::Decrease => { self.ratio -= 0.05; true }
            LayoutMessage::IncreaseMaster => { self.num_master += 1; true }
            LayoutMessage::DecreaseMaster => {
                if self.num_master > 1 { self.num_master -= 1 } true
            }
            _                       => false
        }
    }

    fn description(&self) -> String {
        "Tall".to_owned()
    }

    fn copy(&self) -> Box<Layout> {
        Box::new(self.clone())
    }
}

#[repr(usize)]
#[derive(Clone, Copy, Ord, Eq, PartialOrd, PartialEq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right
}

impl Direction {
    pub fn opposite(&self) -> Direction {
        match self {
            &Direction::Up    => Direction::Down,
            &Direction::Down  => Direction::Up,
            &Direction::Left  => Direction::Right,
            &Direction::Right => Direction::Left
        }
    }
}
<|endoftext|>


<commit_before>use crypto::digest::Digest;

use tree::{ Tree };
use hashable::{ Hashable };
use merkledigest::{ MerkleDigest };

/// The Merkle tree
pub struct MerkleTree<D, T> {
    digest: D,
    tree: Tree<T>,
    pub height: usize,
    pub count: usize
}

impl <D, T> MerkleTree<D, T> where D: Digest, T: Hashable {
    /// Constructs a Merkle Tree from a vector of data blocks.
    pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
        if values.is_empty() {
            panic!("Cannot build a Merkle tree from an empty vector.");
        }

        let count      = values.len();
        let mut height = 0;

        let mut cur = Vec::with_capacity(count);

        for v in values.into_iter().rev() {
            let leaf = Tree::make_leaf(&mut digest, v);
            cur.push(leaf);
        }

        cur.reverse();

        while cur.len() > 1 {
            let mut next = Vec::new();
            while cur.len() > 0 {
                if cur.len() == 1 {
                    next.push(cur.remove(0));
                }
                else {
                    let left  = cur.remove(0);
                    let right = cur.remove(0);

                    let combined_hash = digest.combine_hashes(
                        left.get_hash(),
                        right.get_hash()
                    );

                    let node = Tree::Node {
                       hash: combined_hash,
                       left: Box::new(left),
                       right: Box::new(right)
                    };

                    next.push(node);
                }
            }

            height += 1;

            cur = next;
        }

        assert!(cur.len() == 1);

        let tree = cur.remove(0);

        MerkleTree {
            digest: digest,
            tree: tree,
            height: height,
            count: count
        }
    }

    /// Returns the tree's root hash.
    pub fn root_hash(&self) -> &Vec<u8> {
        self.tree.get_hash()
    }

}
<commit_msg>revert double reversing<commit_after>use crypto::digest::Digest;

use tree::{ Tree };
use hashable::{ Hashable };
use merkledigest::{ MerkleDigest };

/// The Merkle tree
pub struct MerkleTree<D, T> {
    #[allow(dead_code)]
    digest: D,
    tree: Tree<T>,
    pub height: usize,
    pub count: usize
}

impl <D, T> MerkleTree<D, T> where D: Digest, T: Hashable {
    /// Constructs a Merkle Tree from a vector of data blocks.
    pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
        if values.is_empty() {
            panic!("Cannot build a Merkle tree from an empty vector.");
        }

        let count      = values.len();
        let mut height = 0;

        let mut cur = Vec::with_capacity(count);

        for v in values.into_iter() {
            let leaf = Tree::make_leaf(&mut digest, v);
            cur.push(leaf);
        }

        while cur.len() > 1 {
            let mut next = Vec::new();
            while cur.len() > 0 {
                if cur.len() == 1 {
                    next.push(cur.remove(0));
                }
                else {
                    let left  = cur.remove(0);
                    let right = cur.remove(0);

                    let combined_hash = digest.combine_hashes(
                        left.get_hash(),
                        right.get_hash()
                    );

                    let node = Tree::Node {
                       hash: combined_hash,
                       left: Box::new(left),
                       right: Box::new(right)
                    };

                    next.push(node);
                }
            }

            height += 1;

            cur = next;
        }

        assert!(cur.len() == 1);

        let tree = cur.remove(0);

        MerkleTree {
            digest: digest,
            tree: tree,
            height: height,
            count: count
        }
    }

    /// Returns the tree's root hash.
    pub fn root_hash(&self) -> &Vec<u8> {
        self.tree.get_hash()
    }

}
<|endoftext|>


<commit_before>#![feature(proc_macro_hygiene)]
#![feature(decl_macro)]
#![feature(rustc_private)]
#[macro_use] extern crate rocket;
#[macro_use] extern crate diesel;
extern crate serde_json;
extern crate serde;
extern crate dotenv;

use rocket::request::{Outcome, FromRequest};
use rocket::Outcome::Success;
use rocket::Request;

use rocket::Data;
use rocket::data::{self, FromDataSimple};
use rocket::http::Status;
use rocket::Outcome::Failure;
use serde::{Deserialize, Serialize};

use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;

pub mod schema;
use schema::posts;

use std::rc::Rc;

#[derive(Debug)]
#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub publihed: bool,
}

#[derive(Serialize, Deserialize)]
#[derive(Insertable)]
#[derive(Clone)]
#[derive(Debug)]
#[table_name="posts"]
pub struct NewPost{
    pub title: String,
    pub body: String,
}

impl FromDataSimple for NewPost {
    type Error = String;

    #[allow(unused_variables)]
    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
        let reader = data.open();
        match serde_json::from_reader(reader).map(|val| val) {
            Ok(value) => Success(value),
            Err(e) => Failure((Status::BadRequest, e.to_string())),
        }
    }
}

// DB classes
pub struct DBPost {}

impl DBPost {
    // DATABASE classes
        pub fn establish_connection(self) -> PgConnection {
            dotenv().ok();
            let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
            PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
        }

        pub fn create(self, post: NewPost) -> Post {
            let conn = self.establish_connection();
            diesel::insert_into(posts::table).values(&post).get_result(&conn).expect("Error saving!")
        }
        pub fn read(self) -> Vec<Post> {
            let conn = self.establish_connection();
            posts::table.load::<Post>(&conn).unwrap()
      }
}

impl<'a, 'r> FromRequest<'a, 'r> for DBPost {
    type Error = ();
    fn from_request(_request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        Success(DBPost{})
    }
}

// Entities classes
pub trait UseCase {
    fn run(&self) -> &'static str;
}

struct HelloWorldCase {
    db: Rc<Option<DBPost>>
}

impl HelloWorldCase {
    pub fn new() -> HelloWorldCase {
        HelloWorldCase{db: Rc::new(None)}
    }
}

impl UseCase for HelloWorldCase {
    fn run(&self) -> &'static str {
        //unwrap shared reference
        let values = Rc::try_unwrap(Rc::clone(&self.db));
        let result = match values.unwrap_or(None)  {
            Some(unwrapped_db) => unwrapped_db.read(),
            None => Vec::new(),
        };
        println!("{:?}",result);
        "Hello world"
    }
}

struct AddNewPostCase {
    db: Rc<Option<DBPost>>,
    post: NewPost
}
impl AddNewPostCase  {
    pub fn new(post: NewPost) -> AddNewPostCase {
        AddNewPostCase{db: Rc::new(None), post: post}
    }
}

impl UseCase for AddNewPostCase {
    fn run(&self) -> &'static str {
        //unwrap shared reference
        let unwrap_db = Rc::try_unwrap(Rc::clone(&self.db));
        let created_post = match unwrap_db {
            Ok(v) => Some(v.unwrap().create(self.post.clone())),
            Err(e) => {println!("It was not possible ost the result"); None},
        };
        "Hello world"
    }
}

impl<'a, 'r> FromRequest<'a, 'r> for HelloWorldCase {
    type Error = ();
    fn from_request(_request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        Success(HelloWorldCase::new())
    }
}

#[get("/")]
fn get(db: DBPost) -> &'static str {
    HelloWorldCase{db: Rc::new(Some(db))}.run()
}
#[post("/", format="application/json", data="<post>")]
fn post(db: DBPost, post: NewPost) -> &'static str {
    "post"
}

fn main() {
    rocket::ignite().mount("/", routes![get]).launch();
}

#[test]
fn test1() {
    use rocket::local::Client;
//    let use_case = HelloWorldCase{};
    let db = DBPost{};
    let rocket = rocket::ignite().manage(db).mount("/", routes![get]);
    let client = Client::new(rocket).unwrap();
    let mut response = client.get("/").dispatch();
    assert_eq!(response.body_string(), Some("Hello world".into()));
}
<commit_msg>added test for post message<commit_after>#![feature(proc_macro_hygiene)]
#![feature(decl_macro)]
#![feature(rustc_private)]
#[macro_use] extern crate rocket;
#[macro_use] extern crate diesel;
extern crate serde_json;
extern crate serde;
extern crate dotenv;

use rocket::request::{Outcome, FromRequest};
use rocket::Outcome::Success;
use rocket::Request;

use rocket::Data;
use rocket::data::{self, FromDataSimple};
use rocket::http::Status;
use rocket::Outcome::Failure;
use serde::{Deserialize, Serialize};

use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;

use rocket::http::ContentType;

pub mod schema;
use schema::posts;

use std::rc::Rc;

#[derive(Debug)]
#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub publihed: bool,
}

#[derive(Serialize, Deserialize)]
#[derive(Insertable)]
#[derive(Clone)]
#[derive(Debug)]
#[table_name="posts"]
pub struct NewPost{
    pub title: String,
    pub body: String,
}

impl FromDataSimple for NewPost {
    type Error = String;

    #[allow(unused_variables)]
    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
        let reader = data.open();
        match serde_json::from_reader(reader).map(|val| val) {
            Ok(value) => Success(value),
            Err(e) => Failure((Status::BadRequest, e.to_string())),
        }
    }
}

// DB classes
pub struct DBPost {}

impl DBPost {
    // DATABASE classes
        pub fn establish_connection(self) -> PgConnection {
            dotenv().ok();
            let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
            PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
        }

        pub fn create(self, post: NewPost) -> Post {
            let conn = self.establish_connection();
            diesel::insert_into(posts::table).values(&post).get_result(&conn).expect("Error saving!")
        }
        pub fn read(self) -> Vec<Post> {
            let conn = self.establish_connection();
            posts::table.load::<Post>(&conn).unwrap()
      }
}

impl<'a, 'r> FromRequest<'a, 'r> for DBPost {
    type Error = ();
    fn from_request(_request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        Success(DBPost{})
    }
}

// Entities classes
pub trait UseCase {
    fn run(&self) -> &'static str;
}

struct HelloWorldCase {
    db: Rc<Option<DBPost>>
}

impl HelloWorldCase {
    pub fn new() -> HelloWorldCase {
        HelloWorldCase{db: Rc::new(None)}
    }
}

impl UseCase for HelloWorldCase {
    fn run(&self) -> &'static str {
        //unwrap shared reference
        let values = Rc::try_unwrap(Rc::clone(&self.db));
        let result = match values.unwrap_or(None)  {
            Some(unwrapped_db) => unwrapped_db.read(),
            None => Vec::new(),
        };
        println!("{:?}",result);
        "Hello world"
    }
}

struct AddNewPostCase {
    db: Rc<Option<DBPost>>,
    post: NewPost
}
impl AddNewPostCase  {
    pub fn new(post: NewPost) -> AddNewPostCase {
        AddNewPostCase{db: Rc::new(None), post: post}
    }
}

impl UseCase for AddNewPostCase {
    fn run(&self) -> &'static str {
        //unwrap shared reference
        let unwrap_db = Rc::try_unwrap(Rc::clone(&self.db));
        let created_post = match unwrap_db {
            Ok(v) => Some(v.unwrap().create(self.post.clone())),
            Err(_) => {println!("It was not possible ost the result"); None},
        };
        "Hello world"
    }
}

impl<'a, 'r> FromRequest<'a, 'r> for HelloWorldCase {
    type Error = ();
    fn from_request(_request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        Success(HelloWorldCase::new())
    }
}

#[get("/")]
fn get(db: DBPost) -> &'static str {
    HelloWorldCase{db: Rc::new(Some(db))}.run()
}
#[post("/", format="application/json", data="<post>")]
fn post(db: DBPost, post: NewPost) -> &'static str {
    println!("{:?}", post);
    AddNewPostCase{db: Rc::new(Some(db)), post:post}.run()
}

fn main() {
    let db = DBPost{};
    rocket::ignite().manage(db).mount("/", routes![get, post]).launch();
}

#[test]
fn test1() {
    use rocket::local::Client;
//    let use_case = HelloWorldCase{};
    let db = DBPost{};
    let rocket = rocket::ignite().manage(db).mount("/", routes![get, post]);
    let client = Client::new(rocket).unwrap();
    let mut response = client.get("/").dispatch();
    assert_eq!(response.body_string(), Some("Hello world".into()));
}

#[test]
fn test2() {
    use rocket::local::Client;
//    let use_case = HelloWorldCase{};
    let db = DBPost{};
    let rocket = rocket::ignite().manage(db).mount("/", routes![get, post]);
    let client = Client::new(rocket).unwrap();
    let mut response = client.post("/").header(ContentType::JSON).body("{\"title\": \"mytitle1\", \"body\": \"mybody1\"}").dispatch();
    assert_eq!(response.body_string(), Some("Hello world".into()));
}
<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::result::Result;
use std::collections::HashMap;

use clap::{App, ArgMatches};

use storage::backend::{StorageBackend, StorageBackendError};

pub mod bm;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    pub fn new(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub struct CommandEnv<'a> {
    pub rt:         &'a Runtime<'a>,
    pub bk:         &'a StorageBackend,
    pub matches:    &'a ArgMatches<'a, 'a>,
}

pub type ModuleResult = Result<(), ModuleError>;
pub type CommandResult  = ModuleResult;
pub type CommandMap<'a> = HashMap<&'a str, fn(&Module, CommandEnv) -> CommandResult>;

pub trait Module {

    fn callnames(&self) -> &'static [&'static str];
    fn name(&self) -> &'static str;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn get_commands(&self, rt: &Runtime) -> CommandMap;

}

<commit_msg>ModuleError needs a cause as well<commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::result::Result;
use std::collections::HashMap;

use clap::{App, ArgMatches};

use storage::backend::{StorageBackend, StorageBackendError};

pub mod bm;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
    caused_by: Option<Box<Error>>,
}

impl ModuleError {
    pub fn new(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
            caused_by: None,
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        unimplemented!()
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub struct CommandEnv<'a> {
    pub rt:         &'a Runtime<'a>,
    pub bk:         &'a StorageBackend,
    pub matches:    &'a ArgMatches<'a, 'a>,
}

pub type ModuleResult = Result<(), ModuleError>;
pub type CommandResult  = ModuleResult;
pub type CommandMap<'a> = HashMap<&'a str, fn(&Module, CommandEnv) -> CommandResult>;

pub trait Module {

    fn callnames(&self) -> &'static [&'static str];
    fn name(&self) -> &'static str;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn get_commands(&self, rt: &Runtime) -> CommandMap;

}

<|endoftext|>


<commit_before>use wpilib::wpilib_hal::*;
use wpilib::hal_call::HalResult;
use std::mem;

#[repr(u32)]
#[derive(Copy, Clone, Debug)]
pub enum AnalogTriggerType {
    InWindow = 0,
    State = 1,
    RisingPulse = 2,
    FallingPulse = 3,
}

pub fn setup_source_edge(interrupt: HAL_InterruptHandle,
                         rising: bool,
                         falling: bool)
                         -> HalResult<()> {
    if interrupt == 0 {
        Err(0)
    } else {
        hal_call!(HAL_SetInterruptUpSourceEdge(interrupt, rising as i32, falling as i32))
    }
}

pub fn allocate_interrupts(watcher: bool) -> HalResult<HAL_InterruptHandle> {
    hal_call!(HAL_InitializeInterrupts(watcher as i32))
}

pub fn request_interrupts_async(handler: HAL_InterruptHandlerFunction,
                                param: *mut (),
                                port_handle: HAL_Handle,
                                analog_trigger_type: AnalogTriggerType)
                                -> HalResult<HAL_InterruptHandle> {
    let handle = allocate_interrupts(false)?;
    hal_call!(HAL_RequestInterrupts(handle, port_handle, mem::transmute(analog_trigger_type)))?;
    Ok(handle)
}

pub fn request_interrupts_sync(port_handle: HAL_Handle,
                               analog_trigger_type: AnalogTriggerType)
                               -> HalResult<HAL_InterruptHandle> {
    let handle = allocate_interrupts(true)?;
    hal_call!(HAL_RequestInterrupts(handle, port_handle, mem::transmute(analog_trigger_type)))?;
    setup_source_edge(handle, true, false);
    Ok(handle)
}

pub fn cancel_interrupts(interrupt: HAL_InterruptHandle) -> HalResult<()> {
    if interrupt == 0 {
        Err(0)
    } else {
        hal_call!(HAL_CleanInterrupts(interrupt))
    }
}
<commit_msg>Finish implementing interrupts request async function<commit_after>use wpilib::wpilib_hal::*;
use wpilib::hal_call::HalResult;
use std::{mem, os};

#[repr(u32)]
#[derive(Copy, Clone, Debug)]
pub enum AnalogTriggerType {
    InWindow = 0,
    State = 1,
    RisingPulse = 2,
    FallingPulse = 3,
}

pub fn setup_source_edge(interrupt: HAL_InterruptHandle,
                         rising: bool,
                         falling: bool)
                         -> HalResult<()> {
    if interrupt == 0 {
        Err(0)
    } else {
        hal_call!(HAL_SetInterruptUpSourceEdge(interrupt, rising as i32, falling as i32))
    }
}

pub fn allocate_interrupts(watcher: bool) -> HalResult<HAL_InterruptHandle> {
    hal_call!(HAL_InitializeInterrupts(watcher as i32))
}

pub fn request_interrupts_async(handler: HAL_InterruptHandlerFunction,
                                param: *mut os::raw::c_void,
                                port_handle: HAL_Handle,
                                analog_trigger_type: AnalogTriggerType)
                                -> HalResult<HAL_InterruptHandle> {
    let handle = allocate_interrupts(false)?;
    hal_call!(HAL_RequestInterrupts(handle, port_handle, mem::transmute(analog_trigger_type)))?;
    setup_source_edge(port_handle, true, false);
    hal_call!(HAL_AttachInterruptHandler(handle, handler, param))?;
    Ok(handle)
}

pub fn request_interrupts_sync(port_handle: HAL_Handle,
                               analog_trigger_type: AnalogTriggerType)
                               -> HalResult<HAL_InterruptHandle> {
    let handle = allocate_interrupts(true)?;
    hal_call!(HAL_RequestInterrupts(handle, port_handle, mem::transmute(analog_trigger_type)))?;
    setup_source_edge(handle, true, false);
    Ok(handle)
}

pub fn cancel_interrupts(interrupt: HAL_InterruptHandle) -> HalResult<()> {
    if interrupt == 0 {
        Err(0)
    } else {
        hal_call!(HAL_CleanInterrupts(interrupt))
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use bytecode_verifier::{
    verifier::{verify_module_dependencies, VerifiedProgram},
    VerifiedModule,
};
use compiler::{util, Compiler};
use serde_json;
use std::{convert::TryFrom, fs, io::Write, path::PathBuf};
use stdlib::stdlib_modules;
use structopt::StructOpt;
use types::{account_address::AccountAddress, transaction::Program};
use vm::{errors::VerificationError, file_format::CompiledModule};

#[derive(Debug, StructOpt)]
#[structopt(
    name = "IR Compiler",
    author = "Libra",
    about = "Move IR to bytecode compiler."
)]
struct Args {
    /// Serialize and write the compiled output to this file
    #[structopt(short = "o", long = "output")]
    pub output_path: Option<String>,
    /// Treat input file as a module (default is to treat file as a program)
    #[structopt(short = "m", long = "module")]
    pub module_input: bool,
    /// Account address used for publishing
    #[structopt(short = "a", long = "address")]
    pub address: Option<String>,
    /// Do not automatically compile stdlib dependencies
    #[structopt(long = "no-stdlib")]
    pub no_stdlib: bool,
    /// Do not automatically run the bytecode verifier
    #[structopt(long = "no-verify")]
    pub no_verify: bool,
    /// Path to the Move IR source to compile
    #[structopt(parse(from_os_str))]
    pub source_path: PathBuf,
}

fn print_errors_and_exit(verification_errors: &[VerificationError]) -> ! {
    println!("Verification failed. Errors below:");
    for e in verification_errors {
        println!("{:?}", e);
    }
    std::process::exit(1);
}

fn do_verify_module(module: CompiledModule, dependencies: &[VerifiedModule]) -> VerifiedModule {
    let verified_module = match VerifiedModule::new(module) {
        Ok(module) => module,
        Err((_, errors)) => print_errors_and_exit(&errors),
    };
    let (verified_module, errors) = verify_module_dependencies(verified_module, dependencies);
    if !errors.is_empty() {
        print_errors_and_exit(&errors);
    }
    verified_module
}

fn write_output(path: &str, buf: &[u8]) {
    let mut f = fs::File::create(path)
        .unwrap_or_else(|err| panic!("Unable to open output file {}: {}", path, err));
    f.write_all(&buf)
        .unwrap_or_else(|err| panic!("Unable to write to output file {}: {}", path, err));
}

fn main() {
    let args = Args::from_args();

    let address = args
        .address
        .map(|a| AccountAddress::try_from(a).unwrap())
        .unwrap_or_else(AccountAddress::default);

    if !args.module_input {
        let source = fs::read_to_string(args.source_path).expect("Unable to read file");
        let compiler = Compiler {
            address,
            code: &source,
            skip_stdlib_deps: args.no_stdlib,
            ..Compiler::default()
        };
        let (compiled_program, dependencies) = compiler
            .into_compiled_program_and_deps()
            .expect("Failed to compile program");

        let compiled_program = if !args.no_verify {
            let verified_program = VerifiedProgram::new(compiled_program, &dependencies)
                .expect("Failed to verify program");
            verified_program.into_inner()
        } else {
            compiled_program
        };

        match args.output_path {
            Some(path) => {
                let mut script = vec![];
                compiled_program
                    .script
                    .serialize(&mut script)
                    .expect("Unable to serialize script");
                let mut modules = vec![];
                for m in compiled_program.modules.iter() {
                    let mut buf = vec![];
                    m.serialize(&mut buf).expect("Unable to serialize module");
                    modules.push(buf);
                }
                let program = Program::new(script, modules, vec![]);
                let program_bytes =
                    serde_json::to_vec(&program).expect("Unable to serialize program");
                write_output(&path, &program_bytes);
            }
            None => {
                println!("{}", compiled_program);
            }
        }
    } else {
        let dependencies = if args.no_stdlib {
            vec![]
        } else {
            stdlib_modules().to_vec()
        };
        let compiled_module = util::do_compile_module(&args.source_path, &address, &dependencies);
        let compiled_module = if !args.no_verify {
            let verified_module = do_verify_module(compiled_module, &dependencies);
            verified_module.into_inner()
        } else {
            compiled_module
        };
        match args.output_path {
            Some(path) => {
                let mut out = vec![];
                compiled_module
                    .serialize(&mut out)
                    .expect("Unable to serialize module");
                write_output(&path, &out);
            }
            None => {
                println!("{}", compiled_module);
            }
        }
    }
}
<commit_msg>[compiler] Implement a command line option to fetch the dependency list of a module<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use bytecode_verifier::{
    verifier::{verify_module_dependencies, VerifiedProgram},
    VerifiedModule,
};
use compiler::{util, Compiler};
use ir_to_bytecode::parser::{parse_module, parse_script};
use serde_json;
use std::{convert::TryFrom, fs, io::Write, path::PathBuf};
use stdlib::stdlib_modules;
use structopt::StructOpt;
use types::{access_path::AccessPath, account_address::AccountAddress, transaction::Program};
use vm::{errors::VerificationError, file_format::CompiledModule};

#[derive(Debug, StructOpt)]
#[structopt(
    name = "IR Compiler",
    author = "Libra",
    about = "Move IR to bytecode compiler."
)]
struct Args {
    /// Serialize and write the compiled output to this file
    #[structopt(short = "o", long = "output")]
    pub output_path: Option<String>,
    /// Treat input file as a module (default is to treat file as a program)
    #[structopt(short = "m", long = "module")]
    pub module_input: bool,
    /// Account address used for publishing
    #[structopt(short = "a", long = "address")]
    pub address: Option<String>,
    /// Do not automatically compile stdlib dependencies
    #[structopt(long = "no-stdlib")]
    pub no_stdlib: bool,
    /// Do not automatically run the bytecode verifier
    #[structopt(long = "no-verify")]
    pub no_verify: bool,
    /// Path to the Move IR source to compile
    #[structopt(parse(from_os_str))]
    pub source_path: PathBuf,
    /// Instead of compiling the source, emit a dependency list of the compiled source
    #[structopt(short = "-l", long = "list_dependencies")]
    pub list_dependencies: bool,
}

fn print_errors_and_exit(verification_errors: &[VerificationError]) -> ! {
    println!("Verification failed. Errors below:");
    for e in verification_errors {
        println!("{:?}", e);
    }
    std::process::exit(1);
}

fn do_verify_module(module: CompiledModule, dependencies: &[VerifiedModule]) -> VerifiedModule {
    let verified_module = match VerifiedModule::new(module) {
        Ok(module) => module,
        Err((_, errors)) => print_errors_and_exit(&errors),
    };
    let (verified_module, errors) = verify_module_dependencies(verified_module, dependencies);
    if !errors.is_empty() {
        print_errors_and_exit(&errors);
    }
    verified_module
}

fn write_output(path: &str, buf: &[u8]) {
    let mut f = fs::File::create(path)
        .unwrap_or_else(|err| panic!("Unable to open output file {}: {}", path, err));
    f.write_all(&buf)
        .unwrap_or_else(|err| panic!("Unable to write to output file {}: {}", path, err));
}

fn main() {
    let args = Args::from_args();

    let address = args
        .address
        .map(|a| AccountAddress::try_from(a).unwrap())
        .unwrap_or_else(AccountAddress::default);

    if args.list_dependencies {
        let source = fs::read_to_string(args.source_path).expect("Unable to read file");
        let dependency_list: Vec<AccessPath> = if args.module_input {
            let module = parse_module(&source).expect("Unable to parse module");
            module.get_external_deps()
        } else {
            let script = parse_script(&source).expect("Unable to parse module");
            script.get_external_deps()
        }
        .into_iter()
        .map(|m| AccessPath::code_access_path(&m))
        .collect();
        match args.output_path {
            Some(path) => {
                let deps_bytes =
                    serde_json::to_vec(&dependency_list).expect("Unable to serialize dependencies");
                write_output(&path, &deps_bytes);
            }
            None => println!(
                "{}",
                serde_json::to_string(&dependency_list).expect("Unable to serialize dependencies")
            ),
        }
        return;
    }

    if !args.module_input {
        let source = fs::read_to_string(args.source_path).expect("Unable to read file");
        let compiler = Compiler {
            address,
            code: &source,
            skip_stdlib_deps: args.no_stdlib,
            ..Compiler::default()
        };
        let (compiled_program, dependencies) = compiler
            .into_compiled_program_and_deps()
            .expect("Failed to compile program");

        let compiled_program = if !args.no_verify {
            let verified_program = VerifiedProgram::new(compiled_program, &dependencies)
                .expect("Failed to verify program");
            verified_program.into_inner()
        } else {
            compiled_program
        };

        match args.output_path {
            Some(path) => {
                let mut script = vec![];
                compiled_program
                    .script
                    .serialize(&mut script)
                    .expect("Unable to serialize script");
                let mut modules = vec![];
                for m in compiled_program.modules.iter() {
                    let mut buf = vec![];
                    m.serialize(&mut buf).expect("Unable to serialize module");
                    modules.push(buf);
                }
                let program = Program::new(script, modules, vec![]);
                let program_bytes =
                    serde_json::to_vec(&program).expect("Unable to serialize program");
                write_output(&path, &program_bytes);
            }
            None => {
                println!("{}", compiled_program);
            }
        }
    } else {
        let dependencies = if args.no_stdlib {
            vec![]
        } else {
            stdlib_modules().to_vec()
        };
        let compiled_module = util::do_compile_module(&args.source_path, &address, &dependencies);
        let compiled_module = if !args.no_verify {
            let verified_module = do_verify_module(compiled_module, &dependencies);
            verified_module.into_inner()
        } else {
            compiled_module
        };
        match args.output_path {
            Some(path) => {
                let mut out = vec![];
                compiled_module
                    .serialize(&mut out)
                    .expect("Unable to serialize module");
                write_output(&path, &out);
            }
            None => {
                println!("{}", compiled_module);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::hash_set::HashSet;
use std::rc::Rc;

use uuid::Uuid;

use alloc::AllocBox;
use js_types::js_type::JsPtrEnum;

pub struct Scope {
    pub parent: Option<Rc<Scope>>,
    alloc_box: Rc<RefCell<AllocBox>>,
    // TODO add stack-alloc'd data
    pub get_roots: Box<Fn() -> HashSet<Uuid>>,
}

impl Scope {
    pub fn new<F>(alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: None,
            alloc_box: alloc_box.clone(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn as_child<F>(parent: &Rc<Scope>, alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: Some(parent.clone()),
            alloc_box: alloc_box.clone(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn set_parent(&mut self, parent: &Rc<Scope>) {
        self.parent = Some(parent.clone());
    }

    pub fn alloc(&mut self, uuid: Uuid, ptr: JsPtrEnum) -> Uuid {
        self.alloc_box.borrow_mut().alloc(uuid, ptr)
    }

    pub fn dealloc(&mut self, uuid: &Uuid) -> bool {
        self.alloc_box.borrow_mut().dealloc(uuid)
    }

    pub fn get_ptr_copy(&self, uuid: &Uuid) -> Option<JsPtrEnum> {
        self.alloc_box.borrow().find_id(uuid).map(|var| var.borrow().clone())
    }

    pub fn update_ptr(&mut self, uuid: &Uuid, ptr: JsPtrEnum) -> bool {
        self.alloc_box.borrow_mut().update_var(uuid, ptr)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    use std::collections::hash_set::HashSet;
    use std::rc::{Rc, Weak};
    use uuid::Uuid;

    use alloc::{Alloc, AllocBox};
    use js_types::js_type::{JsVar, JsType, JsPtrEnum, JsKey, JsKeyEnum};
    use js_types::js_obj::JsObjStruct;
    use js_types::js_str::JsStrStruct;

    fn dummy_get_roots() -> HashSet<Uuid> {
        HashSet::new()
    }

    fn make_alloc_box() -> Rc<RefCell<AllocBox>> {
        Rc::new(RefCell::new(AllocBox::new()))
    }

    fn make_num(i: f64) -> JsVar {
        JsVar::new(JsType::JsNum(i))
    }

    fn make_obj(alloc_box: Rc<RefCell<AllocBox>>, kvs: Vec<(JsKey, JsVar)>) -> JsVar {
        let var = JsVar::new(JsType::JsPtr);
        alloc_box.borrow_mut()
            .alloc(var.uuid, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs)));
        var
    }

    #[test]
    fn test_new_scope() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
    }

    #[test]
    fn test_as_child_scope() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::as_child(&parent_scope, &alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_set_parent() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
        test_scope.set_parent(&parent_scope);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_alloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsSym(String::from("test")));
        assert_eq!(test_id, test_var.uuid);
    }

    #[test]
    fn test_dealloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsSym(String::from("test")));
        let bad_uuid = Uuid::new_v4();
        assert!(test_scope.dealloc(&test_id));
        assert!(!test_scope.dealloc(&bad_uuid));
    }

    #[test]
    fn test_get_ptr_copy() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsSym(String::from("test")));
        let bad_uuid = Uuid::new_v4();

        let ptr_copy = test_scope.get_ptr_copy(&test_id);
        assert!(ptr_copy.is_some());

        let bad_copy = test_scope.get_ptr_copy(&bad_uuid);
        assert!(bad_copy.is_none());
    }

    #[test]
    fn test_update_ptr() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsSym(String::from("test")));
        let mut update = test_scope.get_ptr_copy(&test_id).unwrap();
        update = JsPtrEnum::JsStr(JsStrStruct::new("test"));
        assert!(test_scope.update_ptr(&test_id, update));

        let update = test_scope.get_ptr_copy(&test_id).unwrap();
        match update {
            JsPtrEnum::JsStr(JsStrStruct{text: ref s}) => assert_eq!(s, "test"),
            _ => ()
        }
        test_scope.dealloc(&test_id);
        assert!(!test_scope.update_ptr(&test_id, update));
    }
}
<commit_msg>Add stack to each scope to track locals. Still need a way to look up parent's vars and push live-out vars to parent when the scope dies<commit_after>use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_set::HashSet;
use std::rc::Rc;

use uuid::Uuid;

use alloc::AllocBox;
use js_types::js_type::{JsPtrEnum, JsType, JsVar};

pub struct Scope {
    pub parent: Option<Rc<Scope>>,
    alloc_box: Rc<RefCell<AllocBox>>,
    // TODO how should we save stack variables that are live-out from this scope
    // frame? Push them up to our parent? There's also the problem of this scope
    // needing access to its parent's variables that are on the stack, but right
    // now the way that'd work is by traversing the scope tree upwards until you
    // find what you're looking for, which is not the best solution. Also, how
    // granular is a scope? Is an `if` block a new scope, or are new scopes only
    // introduced by function calls (things that would actually introduce a new
    // stack frame)?
    //
    // Perhaps a better way to think about it is like this: every scope owns some
    // "stack allocator" object which contains *everything* allocated on the stack
    // up until that point, including things allocated by the parent scope. When
    // a new scope gets pushed, ownership of this object gets transferred to the
    // new scope, which then returns ownership when it exits, deleting the set of
    // things it allocated. This could even just be a list of arenas (where `list`
    // is an ambiguous term; it might be an actual stack or a hash map or something),
    // such that a scope can just drop its arena when it exits. Is that okay? What
    // problems could that cause? Lookup is a bit harder, I suppose, since you'd
    // have to search all arenas in the worst case. Maybe look into simonsapin's
    // ArenaTree implementation? There's also still the problem of live-out references,
    // as well as deleting things that get GC'd by making them `undefined`. Arenas
    // might be too coarse-grained to solve either of those problems.
    //
    // How can we handle live-out references? They're taken care of under the
    // hood in alloc_box, i.e. they don't get deleted. From the frontend, though,
    // all stack allocations will get deleted from the current scope unless they
    // get saved somewhere due to being live-out. POD values can be deleted safely,
    // since they contain no references. Non-POD must be moved into ownership by
    // the parent scope until they are GC'd, at which point the GC should tell
    // this scope that those references are now `undef`. How do you reconsile
    // the fact that a dead-out reference might not be considered as such until
    // after the scope exits? Obviously, you can consider everything live-out
    // unless the GC tells you it's not, but these pointers could in theory be
    // used by a different scope, even if they die. I guess that's not really a
    // problem, though, since usage makes you not dead anymore.
    //
    // So there we go. Delete all POD values when the scope exits, and pass all
    // references to the parent to await GC (unless this scope invokes the GC,
    // in which case they get marked as `undef` and die due to being POD.
    stack: HashMap<Uuid, JsVar>,
    pub get_roots: Box<Fn() -> HashSet<Uuid>>,
}

impl Scope {
    pub fn new<F>(alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: None,
            alloc_box: alloc_box.clone(),
            stack: HashMap::new(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn as_child<F>(parent: &Rc<Scope>, alloc_box: &Rc<RefCell<AllocBox>>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: Some(parent.clone()),
            alloc_box: alloc_box.clone(),
            stack: HashMap::new(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn set_parent(&mut self, parent: &Rc<Scope>) {
        self.parent = Some(parent.clone());
    }

    fn alloc(&mut self, uuid: Uuid, ptr: JsPtrEnum) -> Uuid {
        self.alloc_box.borrow_mut().alloc(uuid, ptr)
    }

    fn dealloc(&mut self, uuid: &Uuid) -> bool {
        self.alloc_box.borrow_mut().dealloc(uuid)
    }

    pub fn push(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Uuid {
        let uuid = match &var.t {
            &JsType::JsPtr => self.alloc(var.uuid, ptr.unwrap()),
                //.expect("ERR: Attempted allocation of heap pointer, but pointer contents were invalid!"));
            _ => var.uuid,
        };
        self.stack.insert(var.uuid, var);
        uuid
    }

    pub fn get_var_copy(&self, uuid: &Uuid) -> (Option<JsVar>, Option<JsPtrEnum>) {
        if let Some(var) = self.stack.get(uuid) {
            match var.t {
                JsType::JsPtr => {
                    if let Some(alloc) = self.alloc_box.borrow().find_id(uuid) {
                        (Some(var.clone()), Some(alloc.borrow().clone()))
                    } else {
                        // This case should be impossible unless you have an
                        // invalid ptr, which should also be impossible.
                        (None, None)
                    }
                },
                _ => (Some(var.clone()), None),
            }
        } else { (None, None) }
    }

    // TODO is there a better way to encode ptr than as an option that is only
    // ever used when it is `Some`? Default argument?
    pub fn update_var(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> bool {
        match var.t {
            JsType::JsPtr => self.alloc_box.borrow_mut().update_ptr(&var.uuid, ptr.unwrap()),
            _ => {
                // TODO might be simpler to do this with `insert`, but I can't remember what it returns
                if let Entry::Occupied(mut view) = self.stack.entry(var.uuid) {
                    *view.get_mut() = var;
                    true
                } else { false }
            },
        }
    }
}

impl Drop for Scope {
    // TODO get the sig for this
    fn drop(&mut self) {
        for (uuid, var) in self.stack.drain() {
            // push to parent
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    use std::collections::hash_set::HashSet;
    use std::rc::{Rc, Weak};
    use uuid::Uuid;

    use alloc::{Alloc, AllocBox};
    use js_types::js_type::{JsVar, JsType, JsPtrEnum, JsKey, JsKeyEnum};
    use js_types::js_obj::JsObjStruct;
    use js_types::js_str::JsStrStruct;

    fn dummy_get_roots() -> HashSet<Uuid> {
        HashSet::new()
    }

    fn make_alloc_box() -> Rc<RefCell<AllocBox>> {
        Rc::new(RefCell::new(AllocBox::new()))
    }

    fn make_num(i: f64) -> JsVar {
        JsVar::new(JsType::JsNum(i))
    }

    fn make_obj(alloc_box: Rc<RefCell<AllocBox>>, kvs: Vec<(JsKey, JsVar)>) -> JsVar {
        let var = JsVar::new(JsType::JsPtr);
        alloc_box.borrow_mut()
            .alloc(var.uuid, JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs)));
        var
    }

    #[test]
    fn test_new_scope() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
    }

    #[test]
    fn test_as_child_scope() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::as_child(&parent_scope, &alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_set_parent() {
        let alloc_box = make_alloc_box();
        let parent_scope = Rc::new(Scope::new(&alloc_box, dummy_get_roots));
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        assert!(test_scope.parent.is_none());
        test_scope.set_parent(&parent_scope);
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_alloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsSym(String::from("test")));
        assert_eq!(test_id, test_var.uuid);
    }

    #[test]
    fn test_dealloc() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.alloc(test_var.uuid, JsPtrEnum::JsSym(String::from("test")));
        let bad_uuid = Uuid::new_v4();
        assert!(test_scope.dealloc(&test_id));
        assert!(!test_scope.dealloc(&bad_uuid));
    }

    #[test]
    fn test_get_var_copy() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.push(test_var, Some(JsPtrEnum::JsSym(String::from("test"))));
        let bad_uuid = Uuid::new_v4();

        let (var_copy, ptr_copy) = test_scope.get_var_copy(&test_id);
        assert!(var_copy.is_some());
        assert!(ptr_copy.is_some());

        let (bad_copy, ptr_copy) = test_scope.get_var_copy(&bad_uuid);
        assert!(bad_copy.is_none());
        assert!(ptr_copy.is_none());
    }

    #[test]
    fn test_update_var() {
        let alloc_box = make_alloc_box();
        let mut test_scope = Scope::new(&alloc_box, dummy_get_roots);
        let test_var = JsVar::new(JsType::JsPtr);
        let test_id = test_scope.push(test_var, Some(JsPtrEnum::JsSym(String::from("test"))));
        let (update, mut update_ptr) = test_scope.get_var_copy(&test_id);
        update_ptr = Some(JsPtrEnum::JsStr(JsStrStruct::new("test")));
        assert!(test_scope.update_var(update.unwrap(), update_ptr));

        let (update, update_ptr) = test_scope.get_var_copy(&test_id);
        match update_ptr.clone().unwrap() {
            JsPtrEnum::JsStr(JsStrStruct{text: ref s}) => assert_eq!(s, "test"),
            _ => ()
        }
        test_scope.dealloc(&test_id);
        assert!(update.is_some());
        assert!(!test_scope.update_var(update.unwrap(), update_ptr));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use czmq::{ZMsg, ZSock};
use error::{Error, Result};
use inapi::{Command, Host};
use zdaemon::ZMsgExtended;

pub struct CommandApi;

impl CommandApi {
    pub fn exec(sock: &mut ZSock, host: &mut Host, router_id: &[u8]) -> Result<()> {
        let request = ZMsg::expect_recv(sock, 2, Some(2), false)?;
        let cmd = Command::new(&request.popstr().unwrap().or(Err(Error::MessageUtf8))?);
        let result = cmd.exec(host)?;

        let msg = ZMsg::new_ok()?;
        msg.pushstr("")?;
        msg.pushbytes(router_id)?;
        msg.send_multi(sock, &[
            &result.exit_code.to_string(),
            &result.stdout,
            &result.stderr
        ])?;

        Ok(())
    }
}
<commit_msg>Expect only one frame for Command API calls<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use czmq::{ZMsg, ZSock};
use error::{Error, Result};
use inapi::{Command, Host};
use zdaemon::ZMsgExtended;

pub struct CommandApi;

impl CommandApi {
    pub fn exec(sock: &mut ZSock, host: &mut Host, router_id: &[u8]) -> Result<()> {
        let request = ZMsg::expect_recv(sock, 1, Some(1), false)?;
        let cmd = Command::new(&request.popstr().unwrap().or(Err(Error::MessageUtf8))?);
        let result = cmd.exec(host)?;

        let msg = ZMsg::new_ok()?;
        msg.pushstr("")?;
        msg.pushbytes(router_id)?;
        msg.send_multi(sock, &[
            &result.exit_code.to_string(),
            &result.stdout,
            &result.stderr
        ])?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Implements a simple parser and extractor for a Unix Archive.
//!
//! There are two "common" formats: BSD and SysV
//!
//! This crate currently only implements the SysV version, which essentially postfixes all
//! names in the archive with a / as a sigil for the end of the name, and uses a special symbol
//! index for looking up symbols faster.

use byteorder::{BigEndian, ReadBytesExt};

use elf::strtab;

use std::io::{self, Read, Seek, Cursor};
use std::io::SeekFrom::{Start, Current};
use std::usize;
use std::collections::HashMap;

pub const SIZEOF_MAGIC: usize = 8;
/// The magic number of a Unix Archive
pub const MAGIC: &'static [u8; SIZEOF_MAGIC] = b"!<arch>\x0A";

const SIZEOF_FILE_IDENTIFER: usize = 16;

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
/// A Unix Archive File Header - meta data for the file/byte blob/whatever that follows exactly after.
/// All data is right-padded with spaces ASCII `0x20`. The Binary layout is as follows:
///
/// |Offset|Length|Name                       |Format |
/// |:-----|:-----|:--------------------------|:------|
/// |0     |16    |File identifier            |ASCII  |
/// |16    |12    |File modification timestamp|Decimal|
/// |28    |6     |Owner ID                   |Decimal|
/// |34    |6     |Group ID                   |Decimal|
/// |40    |8     |File mode                  |Octal  |
/// |48    |10    |Filesize in bytes          |Decimal|
/// |58    |2     |Ending characters          |`0x60 0x0A`|
///
/// Byte alignment is according to the following:
/// > Each archive file member begins on an even byte boundary; a newline is inserted between files
/// > if necessary. Nevertheless, the size given reflects the actual size of the file exclusive
/// > of padding.
// TODO: serialize more values here
pub struct FileHeader {
    /// The identifier, or name for this file.
    pub identifier: String,
    /// The timestamp for when this file was last modified. Base 10 number
    pub timestamp: [u8; 12],
    /// The file's owner's id. Base 10 string number
    pub owner_id: [u8; 6],
    /// The file's group id. Base 10 string number
    pub group_id: [u8; 6],
    /// The file's permissions mode. Base 8 number number
    pub mode: [u8; 8],
    /// The size of this file. Base 10 string number
    pub size: usize,
    /// The file header's terminator, always `0x60 0x0A`
    pub terminator: [u8; 2],
}

const SIZEOF_FILE_SIZE: usize = 10;
pub const SIZEOF_FILEHEADER: usize = SIZEOF_FILE_IDENTIFER + 12 + 6 + 6 + 8 + SIZEOF_FILE_SIZE + 2;

impl FileHeader {
    pub fn parse<R: Read + Seek>(cursor: &mut R) -> io::Result<FileHeader> {
        let mut file_identifier = vec![0u8; SIZEOF_FILE_IDENTIFER];
        try!(cursor.read_exact(&mut file_identifier));
        let file_identifier = unsafe { String::from_utf8_unchecked(file_identifier) };
        let mut file_modification_timestamp = [0u8; 12];
        try!(cursor.read(&mut file_modification_timestamp));
        let mut owner_id = [0u8; 6];
        try!(cursor.read(&mut owner_id));
        let mut group_id = [0u8; 6];
        try!(cursor.read(&mut group_id));
        let mut file_mode = [0u8; 8];
        try!(cursor.read(&mut file_mode));
        let mut file_size = [0u8; SIZEOF_FILE_SIZE];
        try!(cursor.read(&mut file_size));
        let mut terminator = [0u8; 2];
        try!(cursor.read(&mut terminator));
        let string = unsafe { ::std::str::from_utf8_unchecked(&file_size) };
        let file_size = match usize::from_str_radix(string.trim_right(), 10) {
            Ok(file_size) => file_size,
            Err(err) => return io_error!("Err: {:?} Bad file_size {:?}", err, &file_size),
        };
        Ok(FileHeader {
            identifier: file_identifier,
            timestamp: file_modification_timestamp.clone(),
            owner_id: owner_id.clone(),
            group_id: group_id.clone(),
            mode: file_mode.clone(),
            size: file_size,
            terminator: terminator,
        })
    }
}

#[derive(Debug, Clone, PartialEq)]
/// Represents a single file entry in the archive
pub struct File {
    /// The parsed file header
    header: FileHeader,
    /// File offset from the start of the archive to where the file begins
    pub offset: u64,
}

impl File {
    /// Tries to parse the header in `R`, as well as the offset in `R.
    /// **NOTE** the Seek will be pointing at the first byte of whatever the file is, skipping padding.
    pub fn parse<R: Read + Seek>(cursor: &mut R) -> io::Result<File> {
        let header = try!(FileHeader::parse(cursor));
        let data_offset = try!(cursor.seek(Current(0)));
        Ok(File {
            header: header,
            offset: data_offset,
        })
    }

    /// The size of the File's content, in bytes. Does **not** include padding, nor the size of the
    /// file header.
    pub fn size(&self) -> usize {
        self.header.size
    }

    pub fn name(&self) -> &str {
        &self.header.identifier
    }

}

#[derive(Debug, Default)]
/// The special index member signified by the name `"/"`.
/// The data element contains a list of symbol indexes and symbol names, giving their offsets
/// into the archive for a given name.
// TODO: make this into a hashmap from string -> (file_name, offset) indexes?
pub struct Index {
    /// Big Endian number of symbol_indexes and strings
    pub size: usize,
    /// Big Endian u32 index into the archive for this symbol (index in array is the index into the string table)
    pub symbol_indexes: Vec<u32>,
    /// Set of zero-terminated strings indexed by above. Number of strings = `self.size`
    pub strtab: strtab::Strtab<'static>,
}

/// SysV Archive Variant Symbol Lookup Table "Magic" Name
pub const SYMBOL_LOOKUP_MAGIC: &'static [u8; SIZEOF_FILE_IDENTIFER] = b"/               ";
pub const SYMBOL_LOOKUP_NAME: &'static str = "/               ";

impl Index {
    pub fn parse<'c, R: Read + Seek>(cursor: &'c mut R, size: usize) -> io::Result<Index> {
        let sizeof_table = try!(cursor.read_u32::<BigEndian>()) as usize;
        let mut indexes = Vec::with_capacity(sizeof_table);
        for _ in 0..sizeof_table {
            indexes.push(try!(cursor.read_u32::<BigEndian>()));
        }
        let sizeof_strtab = size - ((sizeof_table * 4) + 4);
        let offset = try!(cursor.seek(Current(0)));
        let strtab = try!(strtab::Strtab::parse(cursor, offset as usize, sizeof_strtab));
        Ok (Index {
            size: sizeof_table,
            symbol_indexes: indexes,
            strtab: strtab,
        })
    }
}

#[derive(Debug)]
pub struct Archive {
    pub index: Index,
    files: HashMap<String, File>,
}

impl Archive {
    pub fn parse<R: Read + Seek>(mut cursor: &mut R, size: usize) -> io::Result<Archive> {
        try!(cursor.seek(Start(0)));
        let mut magic = [0; SIZEOF_MAGIC];
        try!(cursor.read_exact(&mut magic));
        if &magic != MAGIC {
            return io_error!("Invalid Archive magic number: {:?}", &magic);
        }
        let mut files = HashMap::new();
        let size = size as u64;
        let mut pos = 0u64;
        loop {
            if pos >= size { break }
            let file = try!(File::parse(&mut cursor));
            let size = file.size() as i64;
            files.insert(file.name().to_owned(), file);
            // we move the cursor past the file blob
            pos = try!(cursor.seek(Current(size)));
        }

        let mut index = Index::default();
        if let Some(file) = files.get(SYMBOL_LOOKUP_NAME) {
            let mut data = vec![0u8; file.size()];
            try!(cursor.seek(Start(file.offset)));
            try!(cursor.read_exact(&mut data));
            let mut data = Cursor::new(&data);
            index = try!(Index::parse(&mut data, file.size()));
        }
        let archive = Archive {
            index: index,
            files: files,
        };
        Ok(archive)
    }

    pub fn get (&self, member: &str) -> Option<&File> {
        self.files.get(member)
    }

    pub fn extract<R: Read + Seek> (&self, member: &str, cursor: &mut R) -> io::Result<Vec<u8>> {
        if let Some(file) = self.get(member) {
            let mut bytes = vec![0u8; file.size()];
            try!(cursor.seek(Start(file.offset)));
            try!(cursor.read_exact(&mut bytes));
            Ok(bytes)
        } else {
            return io_error!(format!("Error: cannot extract member {}, not found", member));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    #[test]
    fn parse_file_header() {
        let file_header: [u8; SIZEOF_FILEHEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                                    0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38,
                                                    0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x60, 0x0a];
        let mut cursor = Cursor::new(&file_header[..]);
        match FileHeader::parse(&mut cursor) {
            Err(_) => assert!(false),
            Ok(file_header2) => {
                let file_header = FileHeader { identifier: "/               ".to_owned(),
                    timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
                    owner_id: [48, 32, 32, 32, 32, 32],
                    group_id: [48, 32, 32, 32, 32, 32],
                    mode: [48, 32, 32, 32, 32, 32, 32, 32],
                    size: 8244, terminator:
                    [96, 10] };
                assert_eq!(file_header, file_header2)
            }
        }
    }

    #[test]
    fn parse_archive() {
        let crt1a: Vec<u8> = include!("../../crt1a.rs");
        let mut cursor = Cursor::new(&crt1a);
        match Archive::parse(&mut cursor, crt1a.len()) {
            Ok(archive) => {
                if let Some(file) = archive.get("crt1.o/         ") {
                    assert_eq!(file.offset, 194);
                    assert_eq!(file.size(), 1928)
                } else {
                    assert!(false)
                }
            },
            Err(_) => assert!(false),
        };
    }
}
<commit_msg>archive: skip newline in File parse<commit_after>//! Implements a simple parser and extractor for a Unix Archive.
//!
//! There are two "common" formats: BSD and SysV
//!
//! This crate currently only implements the SysV version, which essentially postfixes all
//! names in the archive with a / as a sigil for the end of the name, and uses a special symbol
//! index for looking up symbols faster.

use byteorder::{BigEndian, ReadBytesExt};

use elf::strtab;

use std::io::{self, Read, Seek, Cursor};
use std::io::SeekFrom::{Start, Current};
use std::usize;
use std::collections::HashMap;

pub const SIZEOF_MAGIC: usize = 8;
/// The magic number of a Unix Archive
pub const MAGIC: &'static [u8; SIZEOF_MAGIC] = b"!<arch>\x0A";

const SIZEOF_FILE_IDENTIFER: usize = 16;

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
/// A Unix Archive File Header - meta data for the file/byte blob/whatever that follows exactly after.
/// All data is right-padded with spaces ASCII `0x20`. The Binary layout is as follows:
///
/// |Offset|Length|Name                       |Format |
/// |:-----|:-----|:--------------------------|:------|
/// |0     |16    |File identifier            |ASCII  |
/// |16    |12    |File modification timestamp|Decimal|
/// |28    |6     |Owner ID                   |Decimal|
/// |34    |6     |Group ID                   |Decimal|
/// |40    |8     |File mode                  |Octal  |
/// |48    |10    |Filesize in bytes          |Decimal|
/// |58    |2     |Ending characters          |`0x60 0x0A`|
///
/// Byte alignment is according to the following:
/// > Each archive file member begins on an even byte boundary; a newline is inserted between files
/// > if necessary. Nevertheless, the size given reflects the actual size of the file exclusive
/// > of padding.
// TODO: serialize more values here
pub struct FileHeader {
    /// The identifier, or name for this file.
    pub identifier: String,
    /// The timestamp for when this file was last modified. Base 10 number
    pub timestamp: [u8; 12],
    /// The file's owner's id. Base 10 string number
    pub owner_id: [u8; 6],
    /// The file's group id. Base 10 string number
    pub group_id: [u8; 6],
    /// The file's permissions mode. Base 8 number number
    pub mode: [u8; 8],
    /// The size of this file. Base 10 string number
    pub size: usize,
    /// The file header's terminator, always `0x60 0x0A`
    pub terminator: [u8; 2],
}

const SIZEOF_FILE_SIZE: usize = 10;
pub const SIZEOF_FILEHEADER: usize = SIZEOF_FILE_IDENTIFER + 12 + 6 + 6 + 8 + SIZEOF_FILE_SIZE + 2;

impl FileHeader {
    pub fn parse<R: Read + Seek>(cursor: &mut R) -> io::Result<FileHeader> {
        let mut file_identifier = vec![0u8; SIZEOF_FILE_IDENTIFER];
        try!(cursor.read_exact(&mut file_identifier));
        let file_identifier = unsafe { String::from_utf8_unchecked(file_identifier) };
        let mut file_modification_timestamp = [0u8; 12];
        try!(cursor.read(&mut file_modification_timestamp));
        let mut owner_id = [0u8; 6];
        try!(cursor.read(&mut owner_id));
        let mut group_id = [0u8; 6];
        try!(cursor.read(&mut group_id));
        let mut file_mode = [0u8; 8];
        try!(cursor.read(&mut file_mode));
        let mut file_size = [0u8; SIZEOF_FILE_SIZE];
        try!(cursor.read(&mut file_size));
        let mut terminator = [0u8; 2];
        try!(cursor.read(&mut terminator));
        let string = unsafe { ::std::str::from_utf8_unchecked(&file_size) };
        let file_size = match usize::from_str_radix(string.trim_right(), 10) {
            Ok(file_size) => file_size,
            Err(err) => return io_error!("Err: {:?} Bad file_size {:?}", err, &file_size),
        };
        Ok(FileHeader {
            identifier: file_identifier,
            timestamp: file_modification_timestamp.clone(),
            owner_id: owner_id.clone(),
            group_id: group_id.clone(),
            mode: file_mode.clone(),
            size: file_size,
            terminator: terminator,
        })
    }
}

#[derive(Debug, Clone, PartialEq)]
/// Represents a single file entry in the archive
pub struct File {
    /// The parsed file header
    header: FileHeader,
    /// File offset from the start of the archive to where the file begins
    pub offset: u64,
}

impl File {
    /// Tries to parse the header in `R`, as well as the offset in `R.
    /// **NOTE** the Seek will be pointing at the first byte of whatever the file is, skipping padding.
    pub fn parse<R: Read + Seek>(cursor: &mut R) -> io::Result<File> {
        let header = try!(FileHeader::parse(cursor));
        let mut offset = try!(cursor.seek(Current(0)));
        // skip newline padding if we're on an uneven byte boundary
        if offset & 1 == 1 {
            offset = try!(cursor.seek(Current(1)));
        }
        Ok(File {
            header: header,
            offset: offset,
        })
    }

    /// The size of the File's content, in bytes. Does **not** include padding, nor the size of the
    /// file header.
    pub fn size(&self) -> usize {
        self.header.size
    }

    pub fn name(&self) -> &str {
        &self.header.identifier
    }

}

#[derive(Debug, Default)]
/// The special index member signified by the name `"/"`.
/// The data element contains a list of symbol indexes and symbol names, giving their offsets
/// into the archive for a given name.
// TODO: make this into a hashmap from string -> (file_name, offset) indexes?
pub struct Index {
    /// Big Endian number of symbol_indexes and strings
    pub size: usize,
    /// Big Endian u32 index into the archive for this symbol (index in array is the index into the string table)
    pub symbol_indexes: Vec<u32>,
    /// Set of zero-terminated strings indexed by above. Number of strings = `self.size`
    pub strtab: strtab::Strtab<'static>,
}

/// SysV Archive Variant Symbol Lookup Table "Magic" Name
pub const SYMBOL_LOOKUP_MAGIC: &'static [u8; SIZEOF_FILE_IDENTIFER] = b"/               ";
pub const SYMBOL_LOOKUP_NAME: &'static str = "/               ";

impl Index {
    pub fn parse<'c, R: Read + Seek>(cursor: &'c mut R, size: usize) -> io::Result<Index> {
        let sizeof_table = try!(cursor.read_u32::<BigEndian>()) as usize;
        let mut indexes = Vec::with_capacity(sizeof_table);
        for _ in 0..sizeof_table {
            indexes.push(try!(cursor.read_u32::<BigEndian>()));
        }
        let sizeof_strtab = size - ((sizeof_table * 4) + 4);
        let offset = try!(cursor.seek(Current(0)));
        let strtab = try!(strtab::Strtab::parse(cursor, offset as usize, sizeof_strtab));
        Ok (Index {
            size: sizeof_table,
            symbol_indexes: indexes,
            strtab: strtab,
        })
    }
}

#[derive(Debug)]
pub struct Archive {
    pub index: Index,
    files: HashMap<String, File>,
}

impl Archive {
    pub fn parse<R: Read + Seek>(mut cursor: &mut R, size: usize) -> io::Result<Archive> {
        try!(cursor.seek(Start(0)));
        let mut magic = [0; SIZEOF_MAGIC];
        try!(cursor.read_exact(&mut magic));
        if &magic != MAGIC {
            return io_error!("Invalid Archive magic number: {:?}", &magic);
        }
        let mut files = HashMap::new();
        let size = size as u64;
        let mut pos = 0u64;
        loop {
            if pos >= size { break }
            let file = try!(File::parse(&mut cursor));
            let size = file.size() as i64;
            files.insert(file.name().to_owned(), file);
            // we move the cursor past the file blob
            pos = try!(cursor.seek(Current(size)));
        }

        let mut index = Index::default();
        if let Some(file) = files.get(SYMBOL_LOOKUP_NAME) {
            let mut data = vec![0u8; file.size()];
            try!(cursor.seek(Start(file.offset)));
            try!(cursor.read_exact(&mut data));
            let mut data = Cursor::new(&data);
            index = try!(Index::parse(&mut data, file.size()));
        }
        let archive = Archive {
            index: index,
            files: files,
        };
        Ok(archive)
    }

    pub fn get (&self, member: &str) -> Option<&File> {
        self.files.get(member)
    }

    pub fn extract<R: Read + Seek> (&self, member: &str, cursor: &mut R) -> io::Result<Vec<u8>> {
        if let Some(file) = self.get(member) {
            let mut bytes = vec![0u8; file.size()];
            try!(cursor.seek(Start(file.offset)));
            try!(cursor.read_exact(&mut bytes));
            Ok(bytes)
        } else {
            return io_error!(format!("Error: cannot extract member {}, not found", member));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    #[test]
    fn parse_file_header() {
        let file_header: [u8; SIZEOF_FILEHEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                                    0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
                                                    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38,
                                                    0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20,
                                                    0x20, 0x20, 0x60, 0x0a];
        let mut cursor = Cursor::new(&file_header[..]);
        match FileHeader::parse(&mut cursor) {
            Err(_) => assert!(false),
            Ok(file_header2) => {
                let file_header = FileHeader { identifier: "/               ".to_owned(),
                    timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
                    owner_id: [48, 32, 32, 32, 32, 32],
                    group_id: [48, 32, 32, 32, 32, 32],
                    mode: [48, 32, 32, 32, 32, 32, 32, 32],
                    size: 8244, terminator:
                    [96, 10] };
                assert_eq!(file_header, file_header2)
            }
        }
    }

    #[test]
    fn parse_archive() {
        let crt1a: Vec<u8> = include!("../../crt1a.rs");
        let mut cursor = Cursor::new(&crt1a);
        match Archive::parse(&mut cursor, crt1a.len()) {
            Ok(archive) => {
                if let Some(file) = archive.get("crt1.o/         ") {
                    assert_eq!(file.offset, 194);
                    assert_eq!(file.size(), 1928)
                } else {
                    assert!(false)
                }
            },
            Err(_) => assert!(false),
        };
    }
}
<|endoftext|>


<commit_before><commit_msg>corect endianness for unsigned 16 bit<commit_after><|endoftext|>


<commit_before>#[cfg(feature = "getopts")] extern crate getopts;
#[cfg(feature = "getopts")] extern crate markov;

#[cfg(all(feature = "getopts", not(test)))] use std::env::args;
#[cfg(feature = "getopts")] use std::path::Path;
#[cfg(feature = "getopts")] use getopts::Options;
#[cfg(feature = "getopts")] use markov::Chain;

#[cfg(all(feature = "getopts", not(test)))]
fn main() {
    markov_gen(args().collect()).iter().map(|s| println!("{}", s)).count();
}

#[cfg(all(not(feature = "getopts"), not(test)))]
fn main() {
    println!("markgen must be compiled with getopts enabled.")
}

/// Generates a number of strings using a markov chain on specified inputs. This is designed
/// primarily for command-line usage. The arguments are expected to be paths to files to be fed
/// into the chain. Additionally, the argument `-n #` is supported to specify the number of phrases
/// to be generated. This number must be a positive, non-zero integer. `-o #` is also supported to
/// specify the order of Markov chain to be used. Note `-o` must be specified before any file
/// names and must also be a positive, non-zero integer.
///
/// Some valid usages of this function:
/// `markov_gen(vec!["test".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned(), "test".to_owned()])`
/// `markov_gen(vec!["-o".to_owned(), "2".to_owned(), "test".to_owned()])`
///
/// Some invalid usages of this function:
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "0".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "test".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-o".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["-o".to_owned(), "0".to_owned()], "test".to_owned())`
#[cfg(feature = "getopts")]
fn markov_gen(args: Vec<String>) -> Vec<String>{
    let mut opts = Options::new();
    opts.optopt("n", "count", "set the number of phrases to generate", "COUNT");
    opts.optopt("o", "order", "set the order of the Markov chain", "ORDER");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => panic!(e.to_string()),
    };
    if matches.opt_present("h") {
        let brief = format!("Usage: {} FILE1 [FILE2 FILE3 ...] [options]", args[0]);
        print!("{}", opts.usage(&brief));
        Vec::new()
    } else {
        let mut chain: Chain<String> = Chain::new();
        let count = match matches.opt_str("n") {
            Some(arg) => match arg.parse() {
                Ok(n) if n > 0 => n,
                _ => panic!("Expected positive integer argument to -n, found {}.", &arg),
            },
            None => 1
        };
        if let Some(arg) = matches.opt_str("o") {
            match arg.parse() {
                Ok(n) if n > 0 => { chain.order(n); },
                _ => panic!("Expected positive integer argument to -n, found {}.", &arg),
            }
        }
        for path in matches.free.iter() {
            chain.feed_file(Path::new(&path));
        }
        if chain.is_empty() { panic!("No files were fed into the chain.") }
        chain.str_iter_for(count).collect()
    }
}

#[cfg(all(feature = "getopts", test))]
mod test {
    use super::markov_gen;
    use std::borrow::ToOwned;

    #[test]
    fn gen_default() {
        assert_eq!(markov_gen(vec!["prog".to_owned(), "test".to_owned()]).len(), 1)
    }

    #[test]
    fn gen_number_after() {
        assert_eq!(markov_gen(
            vec!["markgen".to_owned(), "test".to_owned(), "-n".to_owned(), "3".to_owned()]
        ).len(), 3)
    }

    #[test]
    fn gen_before_number() {
        assert_eq!(markov_gen(
            vec!["markgen".to_owned(), "-n".to_owned(), "3".to_owned(), "test".to_owned()]
        ).len(), 3)
    }

    #[test]
    #[should_panic(expected = "No files were fed into the chain.")]
    fn gen_invalid_no_files() {
        markov_gen(vec!["prog".to_owned(), "-n".to_owned(), "3".to_owned()]);
    }

    #[test]
    #[should_panic(expected = "Expected positive integer argument to -n, found 0.")]
    fn gen_invalid_n_arg_zero() {
        markov_gen(vec!["prog".to_owned(), "test".to_owned(), "-n".to_owned(), "0".to_owned()]);
    }

    #[test]
    #[should_panic(expected = "Expected positive integer argument to -n, found test.")]
    fn gen_invalid_n_arg_string() {
        markov_gen(vec!["prog".to_owned(), "test".to_owned(), "-n".to_owned(), "test".to_owned()]);
    }
}
<commit_msg>Fixed compilation of markgen.<commit_after>#[cfg(feature = "getopts")] extern crate getopts;
#[cfg(feature = "getopts")] extern crate markov;

#[cfg(all(feature = "getopts", not(test)))] use std::env::args;
#[cfg(feature = "getopts")] use std::path::Path;
#[cfg(feature = "getopts")] use getopts::Options;
#[cfg(feature = "getopts")] use markov::Chain;

#[cfg(all(feature = "getopts", not(test)))]
fn main() {
    markov_gen(args().collect()).iter().map(|s| println!("{}", s)).count();
}

#[cfg(all(not(feature = "getopts"), not(test)))]
fn main() {
    println!("markgen must be compiled with getopts enabled.")
}

/// Generates a number of strings using a markov chain on specified inputs. This is designed
/// primarily for command-line usage. The arguments are expected to be paths to files to be fed
/// into the chain. Additionally, the argument `-n #` is supported to specify the number of phrases
/// to be generated. This number must be a positive, non-zero integer. `-o #` is also supported to
/// specify the order of Markov chain to be used. Note `-o` must be specified before any file
/// names and must also be a positive, non-zero integer.
///
/// Some valid usages of this function:
/// `markov_gen(vec!["test".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned(), "test".to_owned()])`
/// `markov_gen(vec!["-o".to_owned(), "2".to_owned(), "test".to_owned()])`
///
/// Some invalid usages of this function:
/// `markov_gen(vec!["-n".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "0".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-n".to_owned(), "test".to_owned()])`
/// `markov_gen(vec!["test".to_owned(), "-o".to_owned(), "3".to_owned()])`
/// `markov_gen(vec!["-o".to_owned(), "0".to_owned()], "test".to_owned())`
#[cfg(feature = "getopts")]
fn markov_gen(args: Vec<String>) -> Vec<String>{
    let mut opts = Options::new();
    opts.optopt("n", "count", "set the number of phrases to generate", "COUNT");
    opts.optopt("o", "order", "set the order of the Markov chain", "ORDER");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => panic!(e.to_string()),
    };
    if matches.opt_present("h") {
        let brief = format!("Usage: {} FILE1 [FILE2 FILE3 ...] [options]", args[0]);
        print!("{}", opts.usage(&brief));
        Vec::new()
    } else {
        let count = match matches.opt_str("n") {
            Some(arg) => match arg.parse() {
                Ok(n) if n > 0 => n,
                _ => panic!("Expected positive integer argument to -n, found {}.", &arg),
            },
            None => 1
        };
        let mut chain = match matches.opt_str("o").map(|arg| arg.parse()) {
            Some(Ok(n)) if n > 0 => Chain::new_with_order(n),
            None => Chain::new(),
            Some(_) => panic!(
                "Expected positive integer argument to -n, found {}.", matches.opt_str("o").unwrap()
            ),
        };
        for path in matches.free.iter() {
            chain.feed_file(Path::new(&path));
        }
        if chain.is_empty() { panic!("No files were fed into the chain.") }
        chain.str_iter_for(count).collect()
    }
}

#[cfg(all(feature = "getopts", test))]
mod test {
    use super::markov_gen;
    use std::borrow::ToOwned;

    #[test]
    fn gen_default() {
        assert_eq!(markov_gen(vec!["prog".to_owned(), "test".to_owned()]).len(), 1)
    }

    #[test]
    fn gen_number_after() {
        assert_eq!(markov_gen(
            vec!["markgen".to_owned(), "test".to_owned(), "-n".to_owned(), "3".to_owned()]
        ).len(), 3)
    }

    #[test]
    fn gen_before_number() {
        assert_eq!(markov_gen(
            vec!["markgen".to_owned(), "-n".to_owned(), "3".to_owned(), "test".to_owned()]
        ).len(), 3)
    }

    #[test]
    #[should_panic(expected = "No files were fed into the chain.")]
    fn gen_invalid_no_files() {
        markov_gen(vec!["prog".to_owned(), "-n".to_owned(), "3".to_owned()]);
    }

    #[test]
    #[should_panic(expected = "Expected positive integer argument to -n, found 0.")]
    fn gen_invalid_n_arg_zero() {
        markov_gen(vec!["prog".to_owned(), "test".to_owned(), "-n".to_owned(), "0".to_owned()]);
    }

    #[test]
    #[should_panic(expected = "Expected positive integer argument to -n, found test.")]
    fn gen_invalid_n_arg_string() {
        markov_gen(vec!["prog".to_owned(), "test".to_owned(), "-n".to_owned(), "test".to_owned()]);
    }
}
<|endoftext|>


<commit_before>extern crate nes_emulator;

use nes_emulator::rom::Rom;

use std::path::Path;
use std::env;
use std::fs;
use std::fs::*;
use std::io;
use std::collections::HashSet;

fn visit_dirs(dir: &Path, cb: &mut FnMut(&DirEntry)) -> io::Result<()> {
    if try!(fs::metadata(dir)).is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            if try!(fs::metadata(entry.path())).is_dir() {
                try!(visit_dirs(&entry.path(), cb));
            } else {
                cb(&entry);
            }
        }
    }
    Ok(())
}

fn scan_dirs() -> io::Result<()> {
    let args = env::args();
    let path_str = args.skip(1).next().unwrap();
    let path = Path::new( &path_str );
    let mut mappers : HashSet<u8> = HashSet::new();
    let result = visit_dirs( path, &mut |file: &DirEntry| {
        let path = file.path();
        match path.extension().and_then( |ext| ext.to_str() ) {
            Some("NES") | Some( "nes" ) => {
                println!( "{}", path.to_str().unwrap() );
                match Rom::read( &path ) {
                    Ok(ref rom) => {
                        println!( "PRG Size: {}, CHR Size: {}, PRG_RAM Size:{}, trainer size: {}", rom.prg_rom().len(), rom.chr_rom().len(), rom.prg_ram.len(), rom.trainer.len() );
                        println!( "SRAM:{}, Screen Mode: {:?}, PC10: {}, VS: {}, Mapper: {}", rom.sram(), rom.screen_mode(), rom.pc10(), rom.vs(), rom.mapper() );
                        mappers.insert( rom.mapper() );
                    }
                    Err(ref err) => println!( "{}", err )
                };
                println!("");
            }
            _ => ()
        };
    });
    let mut mappers : Vec<u8> = mappers.iter().cloned().collect();
    mappers.sort();
    println!("Mappers: {:?}", mappers);
    result
}

fn main() {
    scan_dirs().ok().unwrap();
}
<commit_msg>Fix compile errors in scanner.<commit_after>extern crate nes_emulator;

use nes_emulator::rom::Rom;

use std::path::Path;
use std::env;
use std::fs;
use std::fs::*;
use std::io;
use std::collections::HashSet;

fn visit_dirs(dir: &Path, cb: &mut FnMut(&DirEntry)) -> io::Result<()> {
    if try!(fs::metadata(dir)).is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            if try!(fs::metadata(entry.path())).is_dir() {
                try!(visit_dirs(&entry.path(), cb));
            } else {
                cb(&entry);
            }
        }
    }
    Ok(())
}

fn scan_dirs() -> io::Result<()> {
    let args = env::args();
    let path_str = args.skip(1).next().unwrap();
    let path = Path::new( &path_str );
    let mut mappers : HashSet<u8> = HashSet::new();
    let result = visit_dirs( path, &mut |file: &DirEntry| {
        let path = file.path();
        match path.extension().and_then( |ext| ext.to_str() ) {
            Some("NES") | Some( "nes" ) => {
                println!( "{}", path.to_str().unwrap() );
                match Rom::read( &path ) {
                    Ok(ref rom) => {
                        println!( "PRG Size: {}, CHR Size: {}, PRG_RAM Size:{}, trainer size: {}", rom.prg_rom.len(), rom.chr_rom.len(), rom.prg_ram.len(), rom.trainer.len() );
                        println!( "SRAM:{}, Screen Mode: {:?}, PC10: {}, VS: {}, Mapper: {}", rom.sram(), rom.screen_mode(), rom.pc10(), rom.vs(), rom.mapper() );
                        mappers.insert( rom.mapper() );
                    }
                    Err(ref err) => println!( "{}", err )
                };
                println!("");
            }
            _ => ()
        };
    });
    let mut mappers : Vec<u8> = mappers.iter().cloned().collect();
    mappers.sort();
    println!("Mappers: {:?}", mappers);
    result
}

fn main() {
    scan_dirs().ok().unwrap();
}
<|endoftext|>


<commit_before><commit_msg>refactor(builder): Group related build functions<commit_after><|endoftext|>