<commit_before>/* automatically generated by rust-bindgen */

use bindgen::{glutCreateWindow, glutDestroyWindow, glutDisplayFunc, glutGetWindow, glutInit};
use bindgen::{glutInitDisplayMode, glutPostRedisplay, glutReshapeFunc, glutReshapeWindow};
use bindgen::{glutSetWindow, glutSwapBuffers, glutTimerFunc};
use libc::*;
use dvec::DVec;
use ptr::{addr_of, null};
use str::to_bytes;
use task::{local_data_get, local_data_set};
use unsafe::reinterpret_cast;
use vec::raw::to_ptr;

/* FIXME: global variable glutStrokeRoman */

/* FIXME: global variable glutStrokeMonoRoman */

/* FIXME: global variable glutBitmap9By15 */

/* FIXME: global variable glutBitmap8By13 */

/* FIXME: global variable glutBitmapTimesRoman10 */

/* FIXME: global variable glutBitmapTimesRoman24 */

/* FIXME: global variable glutBitmapHelvetica10 */

/* FIXME: global variable glutBitmapHelvetica12 */

/* FIXME: global variable glutBitmapHelvetica18 */

type GLenum = i32;
type GLint = i32;
type GLfloat = f32;
type GLdouble = f64;

enum Window = c_int;

const DOUBLE: c_uint = 2 as c_uint;

fn destroy<T>(-_value: ~[T]) {
    // let it drop
}

fn init() unsafe {
    let argc = 0 as c_int;
    let command = to_bytes(~"glut");
    let argv: (*u8, *u8) = (to_ptr(command), null());
    let argv_p = reinterpret_cast(&addr_of(argv));

    glutInit(addr_of(argc), argv_p);

    destroy(command);
}

fn create_window(name: ~str) -> Window unsafe {
    let bytes = to_bytes(name);
    return Window(glutCreateWindow(to_ptr(bytes) as *c_char));
}

fn destroy_window(window: Window) unsafe {
    glutDestroyWindow(*window);
}

fn reshape_window(window: Window, width: c_int, height: c_int) unsafe {
    let current_window = glutGetWindow();
    glutSetWindow(*window);
    glutReshapeWindow(width, height);
    glutSetWindow(current_window);
}

fn display_callback_tls_key(+_callback: @fn@()) {
    // Empty.
}

extern fn display_callback() unsafe {
    let callback = local_data_get(display_callback_tls_key).get();
    (*callback)();
}

fn display_func(callback: fn@()) unsafe {
    local_data_set(display_callback_tls_key, @callback);
    glutDisplayFunc(display_callback);
}

fn timer_callback_tls_key(+_callback: @DVec<fn@()>) {
    // Empty.
}

extern fn timer_callback(index: int) unsafe {
    let callbacks = local_data_get(timer_callback_tls_key).get();
    ((*callbacks)[index as uint])();
}

fn timer_func(msecs: u32, callback: fn@()) unsafe {
    let callbacks;
    match local_data_get(timer_callback_tls_key) {
        None => {
            callbacks = @DVec();
            local_data_set(timer_callback_tls_key, copy callbacks);
        }
        Some(existing_callbacks) => {
            callbacks = existing_callbacks;
        }
    }

    callbacks.push(callback);
    let index = (callbacks.len() - 1) as c_int;
    glutTimerFunc(msecs, timer_callback, index);
}

fn reshape_callback_tls_key(+_callback: @fn@(++c_int, ++c_int)) {
    // Empty.
}

extern fn reshape_callback(++width: c_int, ++height: c_int) unsafe {
    let callback = local_data_get(reshape_callback_tls_key).get();
    (*callback)(width, height);
}

fn reshape_func(_window: Window, callback: fn@(++c_int, ++c_int)) unsafe {
    local_data_set(reshape_callback_tls_key, @callback);
    glutReshapeFunc(reshape_callback);
}

#[cfg(target_os="macos")]
fn check_loop() unsafe {
    ext::glutCheckLoop();
}

#[cfg(target_os="linux")]
fn check_loop() unsafe {
    ext::glutMainLoopEvent();
}

fn init_display_mode(mode: c_uint) unsafe {
    glutInitDisplayMode(mode);
}

fn swap_buffers() unsafe {
    glutSwapBuffers();
}

fn post_redisplay() unsafe {
    glutPostRedisplay();
}

#[cfg(target_os="macos")]
#[nolink]
#[link_args="-framework GLUT"]
extern mod dummy {
}

#[cfg(target_os="linux")]
#[link_name="glut"]
extern mod dummy {
}

#[cfg(target_os="macos")]
#[nolink]
extern mod ext {
    // Mac GLUT extension.
    fn glutCheckLoop();
}

#[cfg(target_os="linux")]
#[nolink]
extern mod ext {
    // freeglut extension.
    fn glutMainLoopEvent();
}

#[nolink]
extern mod bindgen {

fn glutInit(++argcp: *c_int, ++argv: **c_char);

fn glutInitDisplayMode(++mode: c_uint);

fn glutInitDisplayString(++string: *c_char);

fn glutInitWindowPosition(++x: c_int, ++y: c_int);

fn glutInitWindowSize(++width: c_int, ++height: c_int);

fn glutMainLoop();

fn glutCreateWindow(++title: *c_char) -> c_int;

fn glutCreateSubWindow(++win: c_int, ++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int) -> c_int;

fn glutDestroyWindow(++win: c_int);

fn glutPostRedisplay();

fn glutPostWindowRedisplay(++win: c_int);

fn glutSwapBuffers();

fn glutGetWindow() -> c_int;

fn glutSetWindow(++win: c_int);

fn glutSetWindowTitle(++title: *c_char);

fn glutSetIconTitle(++title: *c_char);

fn glutPositionWindow(++x: c_int, ++y: c_int);

fn glutReshapeWindow(++width: c_int, ++height: c_int);

fn glutPopWindow();

fn glutPushWindow();

fn glutIconifyWindow();

fn glutShowWindow();

fn glutHideWindow();

fn glutFullScreen();

fn glutSetCursor(++cursor: c_int);

fn glutWarpPointer(++x: c_int, ++y: c_int);

fn glutEstablishOverlay();

fn glutRemoveOverlay();

fn glutUseLayer(++layer: GLenum);

fn glutPostOverlayRedisplay();

fn glutPostWindowOverlayRedisplay(++win: c_int);

fn glutShowOverlay();

fn glutHideOverlay();

fn glutCreateMenu(++arg1: *u8) -> c_int;

fn glutDestroyMenu(++menu: c_int);

fn glutGetMenu() -> c_int;

fn glutSetMenu(++menu: c_int);

fn glutAddMenuEntry(++label: *c_char, ++value: c_int);

fn glutAddSubMenu(++label: *c_char, ++submenu: c_int);

fn glutChangeToMenuEntry(++item: c_int, ++label: *c_char, ++value: c_int);

fn glutChangeToSubMenu(++item: c_int, ++label: *c_char, ++submenu: c_int);

fn glutRemoveMenuItem(++item: c_int);

fn glutAttachMenu(++button: c_int);

fn glutDetachMenu(++button: c_int);

fn glutDisplayFunc(++func: *u8);

fn glutReshapeFunc(++func: *u8);

fn glutKeyboardFunc(++func: *u8);

fn glutMouseFunc(++func: *u8);

fn glutMotionFunc(++func: *u8);

fn glutPassiveMotionFunc(++func: *u8);

fn glutEntryFunc(++func: *u8);

fn glutVisibilityFunc(++func: *u8);

fn glutIdleFunc(++func: *u8);

fn glutTimerFunc(++millis: c_uint, ++func: *u8, ++value: c_int);

fn glutMenuStateFunc(++func: *u8);

fn glutSpecialFunc(++func: *u8);

fn glutSpaceballMotionFunc(++func: *u8);

fn glutSpaceballRotateFunc(++func: *u8);

fn glutSpaceballButtonFunc(++func: *u8);

fn glutButtonBoxFunc(++func: *u8);

fn glutDialsFunc(++func: *u8);

fn glutTabletMotionFunc(++func: *u8);

fn glutTabletButtonFunc(++func: *u8);

fn glutMenuStatusFunc(++func: *u8);

fn glutOverlayDisplayFunc(++func: *u8);

fn glutWindowStatusFunc(++func: *u8);

fn glutKeyboardUpFunc(++func: *u8);

fn glutSpecialUpFunc(++func: *u8);

fn glutJoystickFunc(++func: *u8, ++pollInterval: c_int);

fn glutSetColor(++arg1: c_int, ++red: GLfloat, ++green: GLfloat, ++blue: GLfloat);

fn glutGetColor(++ndx: c_int, ++component: c_int) -> GLfloat;

fn glutCopyColormap(++win: c_int);

fn glutGet(++_type: GLenum) -> c_int;

fn glutDeviceGet(++_type: GLenum) -> c_int;

fn glutExtensionSupported(++name: *c_char) -> c_int;

fn glutGetModifiers() -> c_int;

fn glutLayerGet(++_type: GLenum) -> c_int;

fn glutGetProcAddress(++procName: *c_char) -> *c_void;

fn glutBitmapCharacter(++font: *c_void, ++character: c_int);

fn glutBitmapWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutStrokeCharacter(++font: *c_void, ++character: c_int);

fn glutStrokeWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutBitmapLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutStrokeLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutWireSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCube(++size: GLdouble);

fn glutSolidCube(++size: GLdouble);

fn glutWireTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutSolidTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutWireDodecahedron();

fn glutSolidDodecahedron();

fn glutWireTeapot(++size: GLdouble);

fn glutSolidTeapot(++size: GLdouble);

fn glutWireOctahedron();

fn glutSolidOctahedron();

fn glutWireTetrahedron();

fn glutSolidTetrahedron();

fn glutWireIcosahedron();

fn glutSolidIcosahedron();

fn glutVideoResizeGet(++param: GLenum) -> c_int;

fn glutSetupVideoResizing();

fn glutStopVideoResizing();

fn glutVideoResize(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutVideoPan(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutReportErrors();

fn glutIgnoreKeyRepeat(++ignore: c_int);

fn glutSetKeyRepeat(++repeatMode: c_int);

fn glutForceJoystickFunc();

fn glutGameModeString(++string: *c_char);

fn glutEnterGameMode() -> c_int;

fn glutLeaveGameMode();

fn glutGameModeGet(++mode: GLenum) -> c_int;

}
<commit_msg>build fix<commit_after>/* automatically generated by rust-bindgen */

use bindgen::{glutCreateWindow, glutDestroyWindow, glutDisplayFunc, glutGetWindow, glutInit};
use bindgen::{glutInitDisplayMode, glutPostRedisplay, glutReshapeFunc, glutReshapeWindow};
use bindgen::{glutSetWindow, glutSwapBuffers, glutTimerFunc};
use libc::*;
use dvec::DVec;
use ptr::{addr_of, null};
use str::to_bytes;
use task::local_data::{local_data_get, local_data_set};
use cast::reinterpret_cast;
use vec::raw::to_ptr;

/* FIXME: global variable glutStrokeRoman */

/* FIXME: global variable glutStrokeMonoRoman */

/* FIXME: global variable glutBitmap9By15 */

/* FIXME: global variable glutBitmap8By13 */

/* FIXME: global variable glutBitmapTimesRoman10 */

/* FIXME: global variable glutBitmapTimesRoman24 */

/* FIXME: global variable glutBitmapHelvetica10 */

/* FIXME: global variable glutBitmapHelvetica12 */

/* FIXME: global variable glutBitmapHelvetica18 */

type GLenum = i32;
type GLint = i32;
type GLfloat = f32;
type GLdouble = f64;

enum Window = c_int;

const DOUBLE: c_uint = 2 as c_uint;

fn destroy<T>(-_value: ~[T]) {
    // let it drop
}

fn init() unsafe {
    let argc = 0 as c_int;
    let command = to_bytes(~"glut");
    let argv: (*u8, *u8) = (to_ptr(command), null());
    let argv_p = reinterpret_cast(&addr_of(argv));

    glutInit(addr_of(argc), argv_p);

    destroy(command);
}

fn create_window(name: ~str) -> Window unsafe {
    let bytes = to_bytes(name);
    return Window(glutCreateWindow(to_ptr(bytes) as *c_char));
}

fn destroy_window(window: Window) unsafe {
    glutDestroyWindow(*window);
}

fn reshape_window(window: Window, width: c_int, height: c_int) unsafe {
    let current_window = glutGetWindow();
    glutSetWindow(*window);
    glutReshapeWindow(width, height);
    glutSetWindow(current_window);
}

fn display_callback_tls_key(+_callback: @fn@()) {
    // Empty.
}

extern fn display_callback() unsafe {
    let callback = local_data_get(display_callback_tls_key).get();
    (*callback)();
}

fn display_func(callback: fn@()) unsafe {
    local_data_set(display_callback_tls_key, @callback);
    glutDisplayFunc(display_callback);
}

fn timer_callback_tls_key(+_callback: @DVec<fn@()>) {
    // Empty.
}

extern fn timer_callback(index: int) unsafe {
    let callbacks = local_data_get(timer_callback_tls_key).get();
    ((*callbacks)[index as uint])();
}

fn timer_func(msecs: u32, callback: fn@()) unsafe {
    let callbacks;
    match local_data_get(timer_callback_tls_key) {
        None => {
            callbacks = @DVec();
            local_data_set(timer_callback_tls_key, copy callbacks);
        }
        Some(existing_callbacks) => {
            callbacks = existing_callbacks;
        }
    }

    callbacks.push(callback);
    let index = (callbacks.len() - 1) as c_int;
    glutTimerFunc(msecs, timer_callback, index);
}

fn reshape_callback_tls_key(+_callback: @fn@(++c_int, ++c_int)) {
    // Empty.
}

extern fn reshape_callback(++width: c_int, ++height: c_int) unsafe {
    let callback = local_data_get(reshape_callback_tls_key).get();
    (*callback)(width, height);
}

fn reshape_func(_window: Window, callback: fn@(++c_int, ++c_int)) unsafe {
    local_data_set(reshape_callback_tls_key, @callback);
    glutReshapeFunc(reshape_callback);
}

#[cfg(target_os="macos")]
fn check_loop() unsafe {
    ext::glutCheckLoop();
}

#[cfg(target_os="linux")]
fn check_loop() unsafe {
    ext::glutMainLoopEvent();
}

fn init_display_mode(mode: c_uint) unsafe {
    glutInitDisplayMode(mode);
}

fn swap_buffers() unsafe {
    glutSwapBuffers();
}

fn post_redisplay() unsafe {
    glutPostRedisplay();
}

#[cfg(target_os="macos")]
#[nolink]
#[link_args="-framework GLUT"]
extern mod dummy {
}

#[cfg(target_os="linux")]
#[link_name="glut"]
extern mod dummy {
}

#[cfg(target_os="macos")]
#[nolink]
extern mod ext {
    // Mac GLUT extension.
    fn glutCheckLoop();
}

#[cfg(target_os="linux")]
#[nolink]
extern mod ext {
    // freeglut extension.
    fn glutMainLoopEvent();
}

#[nolink]
extern mod bindgen {

fn glutInit(++argcp: *c_int, ++argv: **c_char);

fn glutInitDisplayMode(++mode: c_uint);

fn glutInitDisplayString(++string: *c_char);

fn glutInitWindowPosition(++x: c_int, ++y: c_int);

fn glutInitWindowSize(++width: c_int, ++height: c_int);

fn glutMainLoop();

fn glutCreateWindow(++title: *c_char) -> c_int;

fn glutCreateSubWindow(++win: c_int, ++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int) -> c_int;

fn glutDestroyWindow(++win: c_int);

fn glutPostRedisplay();

fn glutPostWindowRedisplay(++win: c_int);

fn glutSwapBuffers();

fn glutGetWindow() -> c_int;

fn glutSetWindow(++win: c_int);

fn glutSetWindowTitle(++title: *c_char);

fn glutSetIconTitle(++title: *c_char);

fn glutPositionWindow(++x: c_int, ++y: c_int);

fn glutReshapeWindow(++width: c_int, ++height: c_int);

fn glutPopWindow();

fn glutPushWindow();

fn glutIconifyWindow();

fn glutShowWindow();

fn glutHideWindow();

fn glutFullScreen();

fn glutSetCursor(++cursor: c_int);

fn glutWarpPointer(++x: c_int, ++y: c_int);

fn glutEstablishOverlay();

fn glutRemoveOverlay();

fn glutUseLayer(++layer: GLenum);

fn glutPostOverlayRedisplay();

fn glutPostWindowOverlayRedisplay(++win: c_int);

fn glutShowOverlay();

fn glutHideOverlay();

fn glutCreateMenu(++arg1: *u8) -> c_int;

fn glutDestroyMenu(++menu: c_int);

fn glutGetMenu() -> c_int;

fn glutSetMenu(++menu: c_int);

fn glutAddMenuEntry(++label: *c_char, ++value: c_int);

fn glutAddSubMenu(++label: *c_char, ++submenu: c_int);

fn glutChangeToMenuEntry(++item: c_int, ++label: *c_char, ++value: c_int);

fn glutChangeToSubMenu(++item: c_int, ++label: *c_char, ++submenu: c_int);

fn glutRemoveMenuItem(++item: c_int);

fn glutAttachMenu(++button: c_int);

fn glutDetachMenu(++button: c_int);

fn glutDisplayFunc(++func: *u8);

fn glutReshapeFunc(++func: *u8);

fn glutKeyboardFunc(++func: *u8);

fn glutMouseFunc(++func: *u8);

fn glutMotionFunc(++func: *u8);

fn glutPassiveMotionFunc(++func: *u8);

fn glutEntryFunc(++func: *u8);

fn glutVisibilityFunc(++func: *u8);

fn glutIdleFunc(++func: *u8);

fn glutTimerFunc(++millis: c_uint, ++func: *u8, ++value: c_int);

fn glutMenuStateFunc(++func: *u8);

fn glutSpecialFunc(++func: *u8);

fn glutSpaceballMotionFunc(++func: *u8);

fn glutSpaceballRotateFunc(++func: *u8);

fn glutSpaceballButtonFunc(++func: *u8);

fn glutButtonBoxFunc(++func: *u8);

fn glutDialsFunc(++func: *u8);

fn glutTabletMotionFunc(++func: *u8);

fn glutTabletButtonFunc(++func: *u8);

fn glutMenuStatusFunc(++func: *u8);

fn glutOverlayDisplayFunc(++func: *u8);

fn glutWindowStatusFunc(++func: *u8);

fn glutKeyboardUpFunc(++func: *u8);

fn glutSpecialUpFunc(++func: *u8);

fn glutJoystickFunc(++func: *u8, ++pollInterval: c_int);

fn glutSetColor(++arg1: c_int, ++red: GLfloat, ++green: GLfloat, ++blue: GLfloat);

fn glutGetColor(++ndx: c_int, ++component: c_int) -> GLfloat;

fn glutCopyColormap(++win: c_int);

fn glutGet(++_type: GLenum) -> c_int;

fn glutDeviceGet(++_type: GLenum) -> c_int;

fn glutExtensionSupported(++name: *c_char) -> c_int;

fn glutGetModifiers() -> c_int;

fn glutLayerGet(++_type: GLenum) -> c_int;

fn glutGetProcAddress(++procName: *c_char) -> *c_void;

fn glutBitmapCharacter(++font: *c_void, ++character: c_int);

fn glutBitmapWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutStrokeCharacter(++font: *c_void, ++character: c_int);

fn glutStrokeWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutBitmapLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutStrokeLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutWireSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCube(++size: GLdouble);

fn glutSolidCube(++size: GLdouble);

fn glutWireTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutSolidTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutWireDodecahedron();

fn glutSolidDodecahedron();

fn glutWireTeapot(++size: GLdouble);

fn glutSolidTeapot(++size: GLdouble);

fn glutWireOctahedron();

fn glutSolidOctahedron();

fn glutWireTetrahedron();

fn glutSolidTetrahedron();

fn glutWireIcosahedron();

fn glutSolidIcosahedron();

fn glutVideoResizeGet(++param: GLenum) -> c_int;

fn glutSetupVideoResizing();

fn glutStopVideoResizing();

fn glutVideoResize(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutVideoPan(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutReportErrors();

fn glutIgnoreKeyRepeat(++ignore: c_int);

fn glutSetKeyRepeat(++repeatMode: c_int);

fn glutForceJoystickFunc();

fn glutGameModeString(++string: *c_char);

fn glutEnterGameMode() -> c_int;

fn glutLeaveGameMode();

fn glutGameModeGet(++mode: GLenum) -> c_int;

}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate uuid;
extern crate time;

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

use uuid::Uuid;

use iron::prelude::*;
use iron::status;

use mount::Mount;
use staticfile::Static;

pub struct Connection {
    uuid: Uuid
}

fn main() {
    let connections = Arc::new(Mutex::new(HashMap::new()));

    let mut router = router::Router::new();

    {
        let connections = connections.clone();
        let game_connect = move |_: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let new_uuid = Uuid::new_v4();
            let new_conn = Connection { uuid: new_uuid };
            conn_map.insert(new_conn.uuid, new_conn);
            println!("connect: new user with uuid {}", new_uuid);
            println!("{} connected users", conn_map.len());

            Ok(Response::with((status::Ok, format!("{}", new_uuid))))
        };
        router.get("/connect", game_connect, "connect");
    }

    {
        let connections = connections.clone();
        let game_disconnect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            // NOTE(jordan): Must "let _ = ..." Otherwise this gives compiler warning "unused
            // result which must be used"
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.remove(&req_uuid) {
                Some(dropped_conn) => {
                    println!("disconnect: user with uuid {}", dropped_conn.uuid);
                    println!("{} connected users", conn_map.len());
                    Ok(Response::with((status::Ok, "dropped")))
                },
                None => {
                    println!("error: disconnect: tried to drop unconnected user {}", req_uuid);
                    Ok(
                        Response::with((
                            status::Conflict,
                            "error: cannot drop a user who is not connected"
                        ))
                    )
                },
            }
        };
        router.post("/disconnect", game_disconnect, "disconnect");
    }

    {
        let connections = connections.clone();
        let game_ping = move |req: &mut Request| -> IronResult<Response> {
            let conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.get(&req_uuid) {
                Some(conn) => {
                    println!("ping[{}]: user with uuid {} sent ping",
                             time::precise_time_ns(),
                             conn.uuid);
                    Ok(Response::with((status::Ok, "pong")))
                },
                None => {
                    println!("error: ping: nonexistent user {} tried to ping", req_uuid);
                    Ok(Response::with((status::NotFound, "")))
                },
            }
        };
        let game_ping_ref = Arc::new(game_ping);
        let game_ping_1 = game_ping_ref.clone();
        router.post("/ping", move |req: &mut Request| game_ping_1(req), "ping:ping");
        let game_ping_2 = game_ping_ref.clone();
        router.post("/keep-alive", move |req: &mut Request| game_ping_2(req), "ping:keep-alive");
    }

    let mut assets_mount = Mount::new();
    assets_mount
        .mount("/", router)
        .mount("/client", Static::new(Path::new("../client")));

    Iron::new(assets_mount).http("localhost:3000").unwrap();
}

#[cfg(test)]
mod tests {
    // NOTE: bring into scope everything defined above
    use super::*;

    #[test]
    fn it_works() {
        // TODO: write a test
    }
}
<commit_msg>Simplify server response boilerplate<commit_after>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate uuid;
extern crate time;

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

use uuid::Uuid;

use iron::prelude::*;
use iron::status;

use mount::Mount;
use staticfile::Static;

pub struct Connection {
    uuid: Uuid
}

fn respond(status: status::Status, msg: &str) -> Response {
    Response::with((status, msg))
}

fn respond_ok(msg: &str) -> Response {
    respond(status::Ok, msg)
}

fn main() {
    let connections = Arc::new(Mutex::new(HashMap::new()));

    let mut router = router::Router::new();

    {
        let connections = connections.clone();
        let game_connect = move |_: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let new_uuid = Uuid::new_v4();
            let new_conn = Connection { uuid: new_uuid };
            conn_map.insert(new_conn.uuid, new_conn);
            println!("connect: new user with uuid {}", new_uuid);
            println!("{} connected users", conn_map.len());

            Ok(respond_ok(&format!("{}", new_uuid)))
        };
        router.get("/connect", game_connect, "connect");
    }

    {
        let connections = connections.clone();
        let game_disconnect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            // NOTE(jordan): Must "let _ = ..." Otherwise this gives compiler warning "unused
            // result which must be used"
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.remove(&req_uuid) {
                Some(dropped_conn) => {
                    println!("disconnect: user with uuid {}", dropped_conn.uuid);
                    println!("{} connected users", conn_map.len());
                    Ok(respond_ok("dropped"))
                },
                None => {
                    println!("error: disconnect: tried to drop unconnected user {}", req_uuid);
                    Ok(
                        respond(status::Conflict, "error: cannot drop a user who is not connected")
                    )
                },
            }
        };
        router.post("/disconnect", game_disconnect, "disconnect");
    }

    {
        let connections = connections.clone();
        let game_ping = move |req: &mut Request| -> IronResult<Response> {
            let conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.get(&req_uuid) {
                Some(conn) => {
                    println!("ping[{}]: user with uuid {} sent ping",
                             time::precise_time_ns(),
                             conn.uuid);
                    Ok(respond_ok("pong"))
                },
                None => {
                    println!("error: ping: nonexistent user {} tried to ping", req_uuid);
                    Ok(respond(status::NotFound, ""))
                },
            }
        };
        let game_ping_ref = Arc::new(game_ping);
        let game_ping_1 = game_ping_ref.clone();
        router.post("/ping", move |req: &mut Request| game_ping_1(req), "ping:ping");
        let game_ping_2 = game_ping_ref.clone();
        router.post("/keep-alive", move |req: &mut Request| game_ping_2(req), "ping:keep-alive");
    }

    let mut assets_mount = Mount::new();
    assets_mount
        .mount("/", router)
        .mount("/client", Static::new(Path::new("../client")));

    Iron::new(assets_mount).http("localhost:3000").unwrap();
}

#[cfg(test)]
mod tests {
    // NOTE: bring into scope everything defined above
    use super::*;

    #[test]
    fn it_works() {
        // TODO: write a test
    }
}
<|endoftext|>


<commit_before>use parking_lot::Mutex;

use crate::gc::{Address, Region, K, M};
use crate::mem;
use crate::os::{self, MemoryPermission};
use crate::vm::{ManagedCodeHeader, CODE_ALIGNMENT};

const TOTAL_SIZE: usize = 1 * M;
const CHUNK_SIZE: usize = 8 * K;

/// Non-contiguous space of memory. Used for permanent space
/// and code space.
pub struct CodeSpace {
    total: Region,
    mutex: Mutex<AllocData>,
    chunk_size: usize,
}

struct AllocData {
    top: Address,
    limit: Address,
}

impl CodeSpace {
    pub fn new() -> CodeSpace {
        let reservation = os::reserve_align(TOTAL_SIZE, 0, true);
        let space_start = reservation.start;
        let space_end = space_start.offset(TOTAL_SIZE);

        let alloc_data = AllocData {
            top: space_start,
            limit: space_start,
        };

        CodeSpace {
            total: Region::new(space_start, space_end),
            mutex: Mutex::new(alloc_data),
            chunk_size: mem::page_align(CHUNK_SIZE),
        }
    }

    pub fn alloc(&self, size: usize) -> Address {
        debug_assert!(size > 0);

        let mut data = self.mutex.lock();
        let aligned_size = mem::align_usize(size, CODE_ALIGNMENT);

        if data.top.offset(aligned_size) > data.limit {
            let size = mem::align_usize(
                aligned_size - data.limit.offset_from(data.top),
                self.chunk_size,
            );
            let new_limit = data.limit.offset(size);

            if new_limit > self.total.end {
                panic!("OOM in code space");
            }

            os::protect(data.limit, size, MemoryPermission::ReadWriteExecute);
            data.limit = new_limit;
        }

        debug_assert!(data.top.offset(aligned_size) <= data.limit);
        let object_address = data.top;
        data.top = data.top.offset(aligned_size);
        object_address
    }

    pub fn allocated_region(&self) -> Region {
        let start = self.total.start;
        let end = self.mutex.lock().top;
        Region::new(start, end)
    }

    pub fn drop_all_native_code_objects(&self) {
        os::jit_writable();

        let allocated_region = self.allocated_region();
        let mut current = allocated_region.start;

        while current < allocated_region.end {
            let code_header = current.to_mut_ptr::<ManagedCodeHeader>();
            let code_header = unsafe { &mut *code_header };
            code_header.drop_native_code_object();

            let object = current.to_mut_obj();
            current = current.offset(object.size())
        }

        assert_eq!(current, allocated_region.end);
        os::jit_executable();
    }
}

impl Drop for CodeSpace {
    fn drop(&mut self) {
        os::free(self.total.start, self.total.size());
    }
}
<commit_msg>increase default code space size<commit_after>use parking_lot::Mutex;

use crate::gc::{Address, Region, K, M};
use crate::mem;
use crate::os::{self, MemoryPermission};
use crate::vm::{ManagedCodeHeader, CODE_ALIGNMENT};

const TOTAL_SIZE: usize = 2 * M;
const CHUNK_SIZE: usize = 8 * K;

/// Non-contiguous space of memory. Used for permanent space
/// and code space.
pub struct CodeSpace {
    total: Region,
    mutex: Mutex<AllocData>,
    chunk_size: usize,
}

struct AllocData {
    top: Address,
    limit: Address,
}

impl CodeSpace {
    pub fn new() -> CodeSpace {
        let reservation = os::reserve_align(TOTAL_SIZE, 0, true);
        let space_start = reservation.start;
        let space_end = space_start.offset(TOTAL_SIZE);

        let alloc_data = AllocData {
            top: space_start,
            limit: space_start,
        };

        CodeSpace {
            total: Region::new(space_start, space_end),
            mutex: Mutex::new(alloc_data),
            chunk_size: mem::page_align(CHUNK_SIZE),
        }
    }

    pub fn alloc(&self, size: usize) -> Address {
        debug_assert!(size > 0);

        let mut data = self.mutex.lock();
        let aligned_size = mem::align_usize(size, CODE_ALIGNMENT);

        if data.top.offset(aligned_size) > data.limit {
            let size = mem::align_usize(
                aligned_size - data.limit.offset_from(data.top),
                self.chunk_size,
            );
            let new_limit = data.limit.offset(size);

            if new_limit > self.total.end {
                panic!("OOM in code space");
            }

            os::protect(data.limit, size, MemoryPermission::ReadWriteExecute);
            data.limit = new_limit;
        }

        debug_assert!(data.top.offset(aligned_size) <= data.limit);
        let object_address = data.top;
        data.top = data.top.offset(aligned_size);
        object_address
    }

    pub fn allocated_region(&self) -> Region {
        let start = self.total.start;
        let end = self.mutex.lock().top;
        Region::new(start, end)
    }

    pub fn drop_all_native_code_objects(&self) {
        os::jit_writable();

        let allocated_region = self.allocated_region();
        let mut current = allocated_region.start;

        while current < allocated_region.end {
            let code_header = current.to_mut_ptr::<ManagedCodeHeader>();
            let code_header = unsafe { &mut *code_header };
            code_header.drop_native_code_object();

            let object = current.to_mut_obj();
            current = current.offset(object.size())
        }

        assert_eq!(current, allocated_region.end);
        os::jit_executable();
    }
}

impl Drop for CodeSpace {
    fn drop(&mut self) {
        os::free(self.total.start, self.total.size());
    }
}
<|endoftext|>


<commit_before>/*
 * Implemenation of a bitfield as a vec. Only
 * supports bytes (Vec<u8>) as the underlying
 * storage.
 *
 * A future implementation should be more efficient,
 * this is just to get the job done for now.
 */
use std::cmp::max;

#[derive(Eq,Clone)]
pub struct BooleanBitfield{
    len: usize,
    vec: Vec<u8>
}

impl BooleanBitfield {
    /// Create a new bitfield with a length of zero.
    pub fn new() -> Self {
        Self {
            len: 0,
            vec: vec![]
        }
    }

    /// Create a new bitfield of a certain capacity
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            len: 0,
            vec: Vec::with_capacity(capacity / 8 + 1)
        }
    }

    /// Read the value of a bit.
    ///
    /// Will return `true` if the bit has been set to `true`
    /// without then being set to `False`.
    pub fn get_bit(&self, i: &usize) -> bool {
        let bit = |i: &usize| *i % 8;
        let byte = |i: &usize| *i / 8;

        if byte(i) >= self.vec.len() {
            false
        } else {
             self.vec[byte(i)] & (1 << (bit(i) as u8)) != 0
        }
    }

    /// Set the value of a bit.
    ///
    /// If this bit is larger than the length of the underlying byte
    /// array it will be extended.
    pub fn set_bit(&mut self, i: &usize, to: &bool) {
        let bit = |i: &usize| *i % 8;
        let byte = |i: &usize| *i / 8;

        self.len = max(self.len, i + 1);

        if byte(i) >= self.vec.len() {
            self.vec.resize(byte(i) + 1, 0);
        }
        match to {
            true =>  {
                self.vec[byte(i)] =
                    self.vec[byte(i)] |  (1 << (bit(i) as u8))
            }
            false => {
                self.vec[byte(i)] =
                    self.vec[byte(i)] & !(1 << (bit(i) as u8))
            }
        }
    }

    /// Return the "length" of this bitfield. Length is defined as
    /// the highest bit that has been set.
    ///
    /// Note: this is distinct from the length of the underlying
    /// vector.
    pub fn len(&self) -> usize { self.len }

    /// Iterate through the underlying vector and count the number of
    /// true bits.
    pub fn num_true_bits(&self) -> u64 {
        let mut count: u64 = 0;
        for byte in &self.vec {
            for bit in 0..8 {
                if byte & (1 << (bit as u8)) != 0 {
                    count += 1;
                }
            }
        }
        count
    }

    /// Clone and return the underlying byte array (`Vec<u8>`).
    pub fn to_be_vec(&self) -> Vec<u8> {
        let mut o = self.vec.clone();
        o.reverse();
        o
    }
}

impl PartialEq for BooleanBitfield {
    fn eq(&self, other: &BooleanBitfield) -> bool {
        (self.vec == other.vec) &
            (self.len == other.len)
    }
}

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

    #[test]
    fn test_bitfield_set() {
        let mut b = BooleanBitfield::new();
        b.set_bit(&0, &false);
        assert_eq!(b.to_be_vec(), [0]);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        assert_eq!(b.to_be_vec(), [128]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [0]);
        assert_eq!(b.len(), 8);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        b.set_bit(&0, &true);
        assert_eq!(b.to_be_vec(), [129]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [1]);
        assert_eq!(b.len(), 8);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        assert_eq!(b.to_be_vec(), [1, 0]);
        assert_eq!(b.len(), 9);
        b.set_bit(&8, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);
        assert_eq!(b.len(), 9);

        b = BooleanBitfield::new();
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [128, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);
        assert_eq!(b.len(), 16);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [129, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [1, 0]);
        assert_eq!(b.len(), 16);
    }

    #[test]
    fn test_bitfield_get() {
        let test_nums = vec![0, 8, 15, 42, 1337];
        for i in test_nums {
            let mut b = BooleanBitfield::new();
            assert_eq!(b.get_bit(&i), false);
            b.set_bit(&i, &true);
            assert_eq!(b.get_bit(&i), true);
            b.set_bit(&i, &true);
        }
    }

    #[test]
    fn test_bitfield_num_true_bits() {
        let mut b = BooleanBitfield::new();
        assert_eq!(b.num_true_bits(), 0);
        b.set_bit(&15, &true);
        assert_eq!(b.num_true_bits(), 1);
        b.set_bit(&15, &false);
        assert_eq!(b.num_true_bits(), 0);
        b.set_bit(&0, &true);
        b.set_bit(&7, &true);
        b.set_bit(&8, &true);
        b.set_bit(&1337, &true);
        assert_eq!(b.num_true_bits(), 4);
    }
}
<commit_msg>Ensure an empty bitfield serializes to 1 byte<commit_after>/*
 * Implemenation of a bitfield as a vec. Only
 * supports bytes (Vec<u8>) as the underlying
 * storage.
 *
 * A future implementation should be more efficient,
 * this is just to get the job done for now.
 */
use std::cmp::max;

#[derive(Eq,Clone)]
pub struct BooleanBitfield{
    len: usize,
    vec: Vec<u8>
}

impl BooleanBitfield {
    /// Create a new bitfield with a length of zero.
    pub fn new() -> Self {
        Self {
            len: 0,
            vec: vec![0]
        }
    }

    /// Create a new bitfield of a certain capacity
    pub fn with_capacity(capacity: usize) -> Self {
        let mut vec = Vec::with_capacity(capacity / 8 + 1);
        vec.push(0);
        Self {
            len: 0,
            vec
        }
    }

    /// Read the value of a bit.
    ///
    /// Will return `true` if the bit has been set to `true`
    /// without then being set to `False`.
    pub fn get_bit(&self, i: &usize) -> bool {
        let bit = |i: &usize| *i % 8;
        let byte = |i: &usize| *i / 8;

        if byte(i) >= self.vec.len() {
            false
        } else {
             self.vec[byte(i)] & (1 << (bit(i) as u8)) != 0
        }
    }

    /// Set the value of a bit.
    ///
    /// If this bit is larger than the length of the underlying byte
    /// array it will be extended.
    pub fn set_bit(&mut self, i: &usize, to: &bool) {
        let bit = |i: &usize| *i % 8;
        let byte = |i: &usize| *i / 8;

        self.len = max(self.len, i + 1);

        if byte(i) >= self.vec.len() {
            self.vec.resize(byte(i) + 1, 0);
        }
        match to {
            true =>  {
                self.vec[byte(i)] =
                    self.vec[byte(i)] |  (1 << (bit(i) as u8))
            }
            false => {
                self.vec[byte(i)] =
                    self.vec[byte(i)] & !(1 << (bit(i) as u8))
            }
        }
    }

    /// Return the "length" of this bitfield. Length is defined as
    /// the highest bit that has been set.
    ///
    /// Note: this is distinct from the length of the underlying
    /// vector.
    pub fn len(&self) -> usize { self.len }

    /// Iterate through the underlying vector and count the number of
    /// true bits.
    pub fn num_true_bits(&self) -> u64 {
        let mut count: u64 = 0;
        for byte in &self.vec {
            for bit in 0..8 {
                if byte & (1 << (bit as u8)) != 0 {
                    count += 1;
                }
            }
        }
        count
    }

    /// Clone and return the underlying byte array (`Vec<u8>`).
    pub fn to_be_vec(&self) -> Vec<u8> {
        let mut o = self.vec.clone();
        o.reverse();
        o
    }
}

impl PartialEq for BooleanBitfield {
    fn eq(&self, other: &BooleanBitfield) -> bool {
        (self.vec == other.vec) &
            (self.len == other.len)
    }
}

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

    #[test]
    fn test_new_bitfield_len() {
        let b = BooleanBitfield::new();
        assert_eq!(b.len(), 0);
        assert_eq!(b.to_be_vec(), vec![0]);

        let b = BooleanBitfield::with_capacity(100);
        assert_eq!(b.len(), 0);
        assert_eq!(b.to_be_vec(), vec![0]);
    }

    #[test]
    fn test_bitfield_set() {
        let mut b = BooleanBitfield::new();
        b.set_bit(&0, &false);
        assert_eq!(b.to_be_vec(), [0]);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        assert_eq!(b.to_be_vec(), [128]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [0]);
        assert_eq!(b.len(), 8);

        b = BooleanBitfield::new();
        b.set_bit(&7, &true);
        b.set_bit(&0, &true);
        assert_eq!(b.to_be_vec(), [129]);
        b.set_bit(&7, &false);
        assert_eq!(b.to_be_vec(), [1]);
        assert_eq!(b.len(), 8);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        assert_eq!(b.to_be_vec(), [1, 0]);
        assert_eq!(b.len(), 9);
        b.set_bit(&8, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);
        assert_eq!(b.len(), 9);

        b = BooleanBitfield::new();
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [128, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [0, 0]);
        assert_eq!(b.len(), 16);

        b = BooleanBitfield::new();
        b.set_bit(&8, &true);
        b.set_bit(&15, &true);
        assert_eq!(b.to_be_vec(), [129, 0]);
        b.set_bit(&15, &false);
        assert_eq!(b.to_be_vec(), [1, 0]);
        assert_eq!(b.len(), 16);
    }

    #[test]
    fn test_bitfield_get() {
        let test_nums = vec![0, 8, 15, 42, 1337];
        for i in test_nums {
            let mut b = BooleanBitfield::new();
            assert_eq!(b.get_bit(&i), false);
            b.set_bit(&i, &true);
            assert_eq!(b.get_bit(&i), true);
            b.set_bit(&i, &true);
        }
    }

    #[test]
    fn test_bitfield_num_true_bits() {
        let mut b = BooleanBitfield::new();
        assert_eq!(b.num_true_bits(), 0);
        b.set_bit(&15, &true);
        assert_eq!(b.num_true_bits(), 1);
        b.set_bit(&15, &false);
        assert_eq!(b.num_true_bits(), 0);
        b.set_bit(&0, &true);
        b.set_bit(&7, &true);
        b.set_bit(&8, &true);
        b.set_bit(&1337, &true);
        assert_eq!(b.num_true_bits(), 4);
    }
}
<|endoftext|>


<commit_before>//! Defines the fields used in the query result structs

// don't show deprecation warnings about NewField when we build this file
#![allow(deprecated)]

use crate::prelude::*;
use serde::Deserialize;
use std::path::PathBuf;

/// This trait is used to furnish the caller with the watchman
/// field name for an entry in the file results
#[doc(hidden)]
pub trait QueryFieldName {
    fn field_name() -> &'static str;
}

/// This trait is used to produce the complete list of file
/// result field names for a query
#[doc(hidden)]
pub trait QueryFieldList {
    fn field_list() -> Vec<&'static str>;
}

/// This macro defines a field struct that can be composed using
/// the `query_result_type!` macro into a struct that can be used
/// with the `Client::query` method.
macro_rules! define_field {(
    $(#[$meta:meta])*
    $tyname:ident, $ty:ty, $field_name:literal) => {
        #[derive(Deserialize, Clone, Debug)]
        $(#[$meta])*
        pub struct $tyname {
            #[serde(rename = $field_name)]
            val: $ty,
        }

        impl QueryFieldName for $tyname {
            fn field_name() -> &'static str {
                $field_name
            }
        }

        impl $tyname {
            /// Consumes the field and returns the underlying
            /// value storage
            pub fn into_inner(self) -> $ty {
                self.val
            }
        }

        impl std::ops::Deref for $tyname {
            type Target = $ty;
            fn deref(&self) -> &Self::Target {
                &self.val
            }
        }

        impl std::ops::DerefMut for $tyname {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.val
            }
        }
    };
}

define_field!(
    /// The field corresponding to the `name` of the file.
    NameField,
    PathBuf,
    "name"
);

define_field!(
    /// The field corresponding to the `exists` status of the file
    ExistsField,
    bool,
    "exists"
);

define_field!(
    /// The field corresponding to the `cclock` field.
    /// the cclock is the created clock; the clock value when we first observed the file,
    /// or the clock value when it last switched from !exists to exists.
    CreatedClockField,
    ClockSpec,
    "cclock"
);

define_field!(
    /// The field corresponding to the `oclock` field.
    /// the oclock is the observed clock; the clock value where we last observed some
    /// change in this file or its metadata.
    ObservedClockField,
    ClockSpec,
    "cclock"
);

define_field!(
    /// The field corresponding to the `content.sha1hex` field.
    /// For regular files this evaluates to the sha1 hash of the
    /// file contents.
    ContentSha1HexField,
    ContentSha1Hex,
    "content.sha1hex"
);

define_field!(
    /// The field corresponding to the `ctime` field.
    /// ctime is the last inode change time measured in integer seconds since the
    /// unix epoch.
    CTimeField,
    i64,
    "ctime"
);

define_field!(
    /// The field corresponding to the `ctime_f` field.
    /// ctime is the last inode change time measured in floating point seconds
    /// (including the fractional portion) since the unix epoch.
    CTimeAsFloatField,
    f32,
    "ctime_f"
);

define_field!(
    /// The field corresponding to the `mtime` field.
    /// mtime is the last modified time measured in integer seconds
    /// since the unix epoch.
    MTimeField,
    i64,
    "mtime"
);

define_field!(
    /// The field corresponding to the `mtime_f` field.
    /// mtime is the last modified time measured in floating point seconds
    /// (including the fractional portion) since the unix epoch.
    MTimeAsFloatField,
    f32,
    "mtime_f"
);

define_field!(
    /// The field corresponding to the `size` field.
    /// This represents the size of the file in bytes.
    SizeField,
    usize,
    "size"
);

define_field!(
    /// The field corresponding to the `mode` field.
    /// This encodes the full file type and permission bits.
    /// Note that most programs and users are more comfortable with
    /// this value when printed in octal.
    /// It is recommended to use `FileTypeField` if all you need is the
    /// file type and not the permission bits, as it is cheaper to
    /// determine just the type in a virtualized filesystem.
    ModeAndPermissionsField,
    u64,
    "mode"
);

define_field!(
    /// The field corresponding to the `uid` field.
    /// The uid field is the owning uid expressed as an integer.
    /// This field is not meaningful on Windows.
    OwnerUidField,
    u32,
    "uid"
);

define_field!(
    /// The field corresponding to the `gid` field.
    /// The gid field is the owning gid expressed as an integer.
    /// This field is not meaningful on Windows.
    OwnerGidField,
    u32,
    "gid"
);

define_field!(
    /// The field corresponding to the `ino` field.
    /// The ino field is the inode number expressed as an integer.
    /// This field is not meaningful on Windows.
    InodeNumberField,
    u64,
    "ino"
);

define_field!(
    /// The field corresponding to the `dev` field.
    /// The dev field is the device number expressed as an integer.
    /// This field is not meaningful on Windows.
    DeviceNumberField,
    u64,
    "dev"
);

define_field!(
    /// The field corresponding to the `nlink` field.
    /// The nlink field is the number of hard links to the file
    /// expressed as an integer.
    NumberOfLinksField,
    u64,
    "nlink"
);

define_field!(
    /// The field corresponding to the `type` field.
    /// The type field encodes the type of the file.
    FileTypeField,
    FileType,
    "type"
);

define_field!(
    /// The field corresponding to the `symlink_target` field.
    /// For files of type symlink this evaluates to the result
    /// of readlink(2) on the file.
    SymlinkTargetField,
    Option<String>,
    "symlink_target"
);

define_field!(
    /// The field corresponding to the `new` field.
    /// The new field evaluates to true if a file is newer than
    /// the since generator criteria.
    ///
    /// Use of this field is discouraged as there are a number of
    /// situations in which the newness has a counter-intuitive
    /// value.  In addition, computing newness in a virtualized
    /// filesystem is relatively expensive.
    ///
    /// If your application needs to reason about the transition
    /// from `!exists -> exists` then you should track the
    /// `ExistsField` in your application.
    #[deprecated(note = "NewField can have counter-intuitive \
                         values in a number of situations so it \
                         is recommended that you track \
                         ExistsField instead")]
    NewField,
    bool,
    "new"
);

/// A macro to help define a type to hold file information from
/// a query.
/// This macro enables a type-safe way to define the set of fields
/// to be returned and de-serialize only those fields.
///
/// This defines a struct that will receive the name and content
/// hash fields from the results.  When used together with
/// `Client::query`, the query will automatically use the appropriate
/// list of field names:
///
/// ```
/// use watchman_client::prelude::*;
/// use serde::Deserialize;
///
/// query_result_type! {
///     struct NameAndHash {
///         name: NameField,
///         hash: ContentSha1HexField,
///     }
/// }
/// ```
///
/// The struct must consist of 2 or more fields; the macro subsystem
/// won't allow for generating an appropriate type definition for a single
/// field result.
///
/// If you need only a single field, look at [NameOnly](struct.NameOnly.html).
///
/// The field types must implement an undocumented trait that enables
/// the automatic field naming and correct deserialization regardless
/// of the field name in the struct.  As such, you should consider
/// the set of fields to be limited to those provided by this crate.
#[macro_export]
macro_rules! query_result_type {(
    $struct_vis:vis struct $tyname:ident {
        $($field_vis:vis $field_name:ident : $field_ty:ty),+ $(,)?
    }
    ) => (

#[derive(Deserialize, Debug, Clone)]
$struct_vis struct $tyname {
    $(
        #[serde(flatten)]
        $field_vis $field_name: $field_ty,
    )*
}

impl QueryFieldList for $tyname {
    fn field_list() -> Vec <&'static str> {
         vec![
        $(
            <$field_ty>::field_name(),
        )*
        ]
    }
}
    )
}

/// Use the `NameOnly` struct when your desired field list in your
/// query results consist only of the name field.
/// It is not possible to use the `query_result_type!` macro to define
/// an appropriate type due to limitations in the Rust macro system.
#[derive(Deserialize, Debug, Clone)]
#[serde(from = "PathBuf")]
pub struct NameOnly {
    pub name: NameField,
}

impl QueryFieldList for NameOnly {
    fn field_list() -> Vec<&'static str> {
        vec!["name"]
    }
}

impl From<PathBuf> for NameOnly {
    fn from(path: PathBuf) -> Self {
        Self {
            name: NameField { val: path },
        }
    }
}
<commit_msg>rust: fix type of size field<commit_after>//! Defines the fields used in the query result structs

// don't show deprecation warnings about NewField when we build this file
#![allow(deprecated)]

use crate::prelude::*;
use serde::Deserialize;
use std::path::PathBuf;

/// This trait is used to furnish the caller with the watchman
/// field name for an entry in the file results
#[doc(hidden)]
pub trait QueryFieldName {
    fn field_name() -> &'static str;
}

/// This trait is used to produce the complete list of file
/// result field names for a query
#[doc(hidden)]
pub trait QueryFieldList {
    fn field_list() -> Vec<&'static str>;
}

/// This macro defines a field struct that can be composed using
/// the `query_result_type!` macro into a struct that can be used
/// with the `Client::query` method.
macro_rules! define_field {(
    $(#[$meta:meta])*
    $tyname:ident, $ty:ty, $field_name:literal) => {
        #[derive(Deserialize, Clone, Debug)]
        $(#[$meta])*
        pub struct $tyname {
            #[serde(rename = $field_name)]
            val: $ty,
        }

        impl QueryFieldName for $tyname {
            fn field_name() -> &'static str {
                $field_name
            }
        }

        impl $tyname {
            /// Consumes the field and returns the underlying
            /// value storage
            pub fn into_inner(self) -> $ty {
                self.val
            }
        }

        impl std::ops::Deref for $tyname {
            type Target = $ty;
            fn deref(&self) -> &Self::Target {
                &self.val
            }
        }

        impl std::ops::DerefMut for $tyname {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.val
            }
        }
    };
}

define_field!(
    /// The field corresponding to the `name` of the file.
    NameField,
    PathBuf,
    "name"
);

define_field!(
    /// The field corresponding to the `exists` status of the file
    ExistsField,
    bool,
    "exists"
);

define_field!(
    /// The field corresponding to the `cclock` field.
    /// the cclock is the created clock; the clock value when we first observed the file,
    /// or the clock value when it last switched from !exists to exists.
    CreatedClockField,
    ClockSpec,
    "cclock"
);

define_field!(
    /// The field corresponding to the `oclock` field.
    /// the oclock is the observed clock; the clock value where we last observed some
    /// change in this file or its metadata.
    ObservedClockField,
    ClockSpec,
    "cclock"
);

define_field!(
    /// The field corresponding to the `content.sha1hex` field.
    /// For regular files this evaluates to the sha1 hash of the
    /// file contents.
    ContentSha1HexField,
    ContentSha1Hex,
    "content.sha1hex"
);

define_field!(
    /// The field corresponding to the `ctime` field.
    /// ctime is the last inode change time measured in integer seconds since the
    /// unix epoch.
    CTimeField,
    i64,
    "ctime"
);

define_field!(
    /// The field corresponding to the `ctime_f` field.
    /// ctime is the last inode change time measured in floating point seconds
    /// (including the fractional portion) since the unix epoch.
    CTimeAsFloatField,
    f32,
    "ctime_f"
);

define_field!(
    /// The field corresponding to the `mtime` field.
    /// mtime is the last modified time measured in integer seconds
    /// since the unix epoch.
    MTimeField,
    i64,
    "mtime"
);

define_field!(
    /// The field corresponding to the `mtime_f` field.
    /// mtime is the last modified time measured in floating point seconds
    /// (including the fractional portion) since the unix epoch.
    MTimeAsFloatField,
    f32,
    "mtime_f"
);

define_field!(
    /// The field corresponding to the `size` field.
    /// This represents the size of the file in bytes.
    SizeField,
    u64,
    "size"
);

define_field!(
    /// The field corresponding to the `mode` field.
    /// This encodes the full file type and permission bits.
    /// Note that most programs and users are more comfortable with
    /// this value when printed in octal.
    /// It is recommended to use `FileTypeField` if all you need is the
    /// file type and not the permission bits, as it is cheaper to
    /// determine just the type in a virtualized filesystem.
    ModeAndPermissionsField,
    u64,
    "mode"
);

define_field!(
    /// The field corresponding to the `uid` field.
    /// The uid field is the owning uid expressed as an integer.
    /// This field is not meaningful on Windows.
    OwnerUidField,
    u32,
    "uid"
);

define_field!(
    /// The field corresponding to the `gid` field.
    /// The gid field is the owning gid expressed as an integer.
    /// This field is not meaningful on Windows.
    OwnerGidField,
    u32,
    "gid"
);

define_field!(
    /// The field corresponding to the `ino` field.
    /// The ino field is the inode number expressed as an integer.
    /// This field is not meaningful on Windows.
    InodeNumberField,
    u64,
    "ino"
);

define_field!(
    /// The field corresponding to the `dev` field.
    /// The dev field is the device number expressed as an integer.
    /// This field is not meaningful on Windows.
    DeviceNumberField,
    u64,
    "dev"
);

define_field!(
    /// The field corresponding to the `nlink` field.
    /// The nlink field is the number of hard links to the file
    /// expressed as an integer.
    NumberOfLinksField,
    u64,
    "nlink"
);

define_field!(
    /// The field corresponding to the `type` field.
    /// The type field encodes the type of the file.
    FileTypeField,
    FileType,
    "type"
);

define_field!(
    /// The field corresponding to the `symlink_target` field.
    /// For files of type symlink this evaluates to the result
    /// of readlink(2) on the file.
    SymlinkTargetField,
    Option<String>,
    "symlink_target"
);

define_field!(
    /// The field corresponding to the `new` field.
    /// The new field evaluates to true if a file is newer than
    /// the since generator criteria.
    ///
    /// Use of this field is discouraged as there are a number of
    /// situations in which the newness has a counter-intuitive
    /// value.  In addition, computing newness in a virtualized
    /// filesystem is relatively expensive.
    ///
    /// If your application needs to reason about the transition
    /// from `!exists -> exists` then you should track the
    /// `ExistsField` in your application.
    #[deprecated(note = "NewField can have counter-intuitive \
                         values in a number of situations so it \
                         is recommended that you track \
                         ExistsField instead")]
    NewField,
    bool,
    "new"
);

/// A macro to help define a type to hold file information from
/// a query.
/// This macro enables a type-safe way to define the set of fields
/// to be returned and de-serialize only those fields.
///
/// This defines a struct that will receive the name and content
/// hash fields from the results.  When used together with
/// `Client::query`, the query will automatically use the appropriate
/// list of field names:
///
/// ```
/// use watchman_client::prelude::*;
/// use serde::Deserialize;
///
/// query_result_type! {
///     struct NameAndHash {
///         name: NameField,
///         hash: ContentSha1HexField,
///     }
/// }
/// ```
///
/// The struct must consist of 2 or more fields; the macro subsystem
/// won't allow for generating an appropriate type definition for a single
/// field result.
///
/// If you need only a single field, look at [NameOnly](struct.NameOnly.html).
///
/// The field types must implement an undocumented trait that enables
/// the automatic field naming and correct deserialization regardless
/// of the field name in the struct.  As such, you should consider
/// the set of fields to be limited to those provided by this crate.
#[macro_export]
macro_rules! query_result_type {(
    $struct_vis:vis struct $tyname:ident {
        $($field_vis:vis $field_name:ident : $field_ty:ty),+ $(,)?
    }
    ) => (

#[derive(Deserialize, Debug, Clone)]
$struct_vis struct $tyname {
    $(
        #[serde(flatten)]
        $field_vis $field_name: $field_ty,
    )*
}

impl QueryFieldList for $tyname {
    fn field_list() -> Vec <&'static str> {
         vec![
        $(
            <$field_ty>::field_name(),
        )*
        ]
    }
}
    )
}

/// Use the `NameOnly` struct when your desired field list in your
/// query results consist only of the name field.
/// It is not possible to use the `query_result_type!` macro to define
/// an appropriate type due to limitations in the Rust macro system.
#[derive(Deserialize, Debug, Clone)]
#[serde(from = "PathBuf")]
pub struct NameOnly {
    pub name: NameField,
}

impl QueryFieldList for NameOnly {
    fn field_list() -> Vec<&'static str> {
        vec!["name"]
    }
}

impl From<PathBuf> for NameOnly {
    fn from(path: PathBuf) -> Self {
        Self {
            name: NameField { val: path },
        }
    }
}
<|endoftext|>


<commit_before>use linalg::matrix::Matrix;
use rand::{Rng, thread_rng};

pub struct NeuralNet<'a> {
	layer_sizes: &'a [usize]
}

impl<'a> NeuralNet<'a> {
	pub fn new(layer_sizes: &[usize]) -> NeuralNet {
		NeuralNet{layer_sizes: layer_sizes}
	}

	fn create_layers(&self) {
		let total_layers = self.layer_sizes.len();

		let mut layers = Vec::with_capacity(total_layers-1);

		for l in 0..total_layers-1 {
			layers.push(
				initialize_weights(self.layer_sizes[l],self.layer_sizes[l+1]));
		}
	}
}

fn initialize_weights(rows: usize, cols: usize) -> Matrix<f64> {
	let mut weights = Vec::with_capacity(rows * cols);
	let eps_init = (6f64).sqrt() / ((rows + cols) as f64).sqrt();

	let mut rng = thread_rng();

	for _i in 0..rows*cols {
		let w = (rng.gen_range(0f64,1f64) * 2f64 * eps_init) - eps_init;
		weights.push(w);
	}

	Matrix::new(rows, cols, weights)
}<commit_msg>Implementing nnet weight initialization.<commit_after>use linalg::matrix::Matrix;
use linalg::vector::Vector;
use learning::SupModel;
use rand::{Rng, thread_rng};

/// Neural Network struct
///
/// Requires the number of neurons in each layer to be specified.
pub struct NeuralNet<'a> {
    layer_sizes: &'a [usize],
    weights: Vec<f64>,
}

impl<'a> NeuralNet<'a> {

	/// Create a new neural network with the specified layer sizes.
	///
	/// The layer sizes slice should include the input, hidden layers, and output layer sizes.
	///
	/// # Examples
	///
	/// ```
	/// use rusty_machine::learning::nnet::NeuralNet;
	///
	/// // Create a neural net with 4 layers, 3 neurons in each.
	/// let layers = &[3; 4];
	/// let mut a = NeuralNet::new(layers);
	/// ```
    pub fn new(layer_sizes: &[usize]) -> NeuralNet {
        NeuralNet {
            layer_sizes: layer_sizes,
            weights: NeuralNet::create_weights(layer_sizes),
        }
    }

    /// Creates initial weights for all neurons in the network.
    fn create_weights(layer_sizes: &[usize]) -> Vec<f64> {
        let total_layers = layer_sizes.len();

        let mut capacity = 0usize;

        for l in 0..total_layers - 1 {
            capacity += (layer_sizes[l]+1) * layer_sizes[l + 1]
        }

        let mut layers = Vec::with_capacity(capacity);

        for l in 0..total_layers - 1 {
            layers.append(&mut NeuralNet::initialize_weights(layer_sizes[l]+1, layer_sizes[l + 1]));
        }

        layers
    }

    /// Initializes the weights for a single layer in the network.
    fn initialize_weights(rows: usize, cols: usize) -> Vec<f64> {
        let mut weights = Vec::with_capacity(rows * cols);
        let eps_init = (6f64).sqrt() / ((rows + cols) as f64).sqrt();

        let mut rng = thread_rng();

        for _i in 0..rows * cols {
            let w = (rng.gen_range(0f64, 1f64) * 2f64 * eps_init) - eps_init;
            weights.push(w);
        }

        weights
    }
}

impl<'a> SupModel<Matrix<f64>, Vector<usize>> for NeuralNet<'a> {
    fn predict(&self, data: Matrix<f64>) -> Vector<usize> {
        unimplemented!()
    }

    fn train(&mut self, data: Matrix<f64>, values: Vector<usize>) {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit Interrupt Descriptor Table implementation.
//!
//! Refer to section 6.10 of the _Intel® 64 and IA-32 Architectures
//! Software Developer’s Manual_ for more information.
use core::mem;
use core::ptr;

use spin::Mutex;

use super::{Registers, DTable, DTablePtr, segment};
use io::keyboard;

#[path = "../../x86_all/interrupts.rs"] mod interrupts_all;
#[path = "../../x86_all/pics.rs"] pub mod pics;
pub use self::interrupts_all::*;

//==------------------------------------------------------------------------==
// Interface into ASM interrupt handling
extern {
    /// Offset of the 64-bit GDT main code segment.
    /// Exported by `boot.asm`
    static gdt64_offset: u16;

    /// Array of interrupt handlers from ASM
    static interrupt_handlers: [*const u8; IDT_ENTRIES];
}

/// State stored when handling an interrupt.
#[allow(dead_code)]
#[repr(C, packed)]
pub struct InterruptCtx64 { /// callee-saved registers
                            pub registers: Registers
                          , /// interrupt ID number
                            pub int_id:  u32
                          , __pad_1: u32
                          , /// error number
                            pub err_no:  u32
                          , __pad_2: u32
                          }

impl InterruptContext for InterruptCtx64 {
    type Registers = Registers;
    // All these inline functions are basically just faking
    // object orientation in a way the Rust compiler understands
    #[inline] fn registers(&self) -> Self::Registers { self.registers }
    #[inline] fn err_no(&self) -> u32 { self.err_no }
    #[inline] fn int_id(&self) -> u32 { self.int_id }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT gate trait

/// An IDT entry is called a gate.
///
/// Based on code from the OS Dev Wiki
/// http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy,Clone)]
pub struct Gate64 { /// bits 0 - 15 of the offset
                    pub offset_lower: u16
                  , /// code segment selector (GDT or LDT)
                    pub selector: segment::Selector
                  , /// always zero
                    zero: u8
                  , /// indicates the gate's type and attributes.
                    /// the second half indicates the type:
                    ///   + `0b1100`: Call gate
                    ///   + `0b1110`: Interrupt gate
                    ///   + `0b1111`: Trap Gate
                    pub type_attr: GateType
                  , /// bits 16 - 31 of the offset
                    pub offset_mid: u16
                  , /// bits 32 - 63 of the offset
                    pub offset_upper: u32
                  , /// always zero (according to the spec, this is "reserved")
                    reserved: u32
                  }

impl Gate64 {
    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// This would be in the `Gate` trait, but this has to be a `const fn` so
    /// that it can be usedm in static initializers, and trait functions cannot
    /// be `const`.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    const fn absent() -> Self {
        Gate64 { offset_lower: 0
               , selector: segment::Selector::from_raw(0)
               , zero: 0
               , type_attr: GateType::Absent
               , offset_mid: 0
               , offset_upper: 0
               , reserved: 0
               }
    }
}

impl Gate for Gate64 {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from_handler(handler: Handler) -> Self {
        unsafe { // trust me on this.
                 // `mem::transmute()` is glorious black magic
            let (low, mid, high): (u16, u16, u32)
                = mem::transmute(handler);

            Gate64 { offset_lower: low
                   , selector: segment::Selector::from_raw(gdt64_offset)
                   , zero: 0
                   // Bit 7 is the present bit
                   // Bits 4-0 indicate this is an interrupt gate
                   , type_attr: GateType::Interrupt
                   , offset_mid: mid
                   , offset_upper: high
                   , reserved: 0
                   }
        }
    }

    unsafe fn from_raw(handler: *const u8) -> Self {
        let (low, mid, high): (u16, u16, u32)
            = mem::transmute(handler as u64);

        Gate64 { offset_lower: low
               , selector: segment::Selector::from_raw(gdt64_offset)
               , zero: 0
               , type_attr: GateType::Interrupt
               , offset_mid: mid
               , offset_upper: high
               , reserved: 0
               }
    }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT trait
struct Idt64([Gate64; IDT_ENTRIES]);

impl Idt for Idt64 {
    type Ctx = InterruptCtx64;
    type GateSize = Gate64;
    type PtrSize = u64;

    fn get_ptr(&self) -> DTablePtr<u64> {
        DTablePtr { limit: (mem::size_of::<Self::GateSize>() * IDT_ENTRIES)
                            as u16
                  , base: &self.0[0] as *const Gate64 as u64
                  }
    }

    /// Add an entry for the given handler at the given index
    fn add_gate(&mut self, index: usize, handler: Handler) {
        self.0[index] = Gate64::from_handler(handler)
    }

}

impl DTable for Idt64 {
    #[inline] unsafe fn load(&self) {
        asm!(  "lidt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        println!("{:<38}{:>40}", " . . Loading IDT", "[ OKAY ]");
    }
}

impl Idt64 {
    fn add_handlers(&mut self) -> &mut Self {
        for (i, &h_ptr) in interrupt_handlers.iter()
            .enumerate()
            .filter(|&(_, &h_ptr)| h_ptr != ptr::null() ) {
                unsafe { self.0[i] = Gate64::from_raw(h_ptr) }
        }

        println!("{:<38}{:>40}", " . . Adding interrupt handlers to IDT"
             , "[ OKAY ]");
        self
    }
}

/// Global Interrupt Descriptor Table instance
/// Our global IDT.
static IDT: Mutex<Idt64>
    = Mutex::new(Idt64([Gate64::absent(); IDT_ENTRIES]));

/// Assembly interrupt handlers call into this
#[no_mangle]
pub unsafe extern "C" fn handle_interrupt(state: &InterruptCtx64) {
    let id = state.int_id();
    match id {
        // interrupts 0 - 16 are CPU exceptions
        0x00...0x0f => Idt64::handle_cpu_exception(state)
        // System timer
      , 0x20 => { /* TODO: make this work */ }
        // Keyboard
      , 0x21 => {
          // TODO: dispatch keypress event to subscribers (NYI)
            if let Some(input) = keyboard::read_char() {
                if input == '\r' {
                    println!("");
                } else {
                    print!("{}", input);
                }
            }
        }
        // Loonix syscall vector
      , 0x80 => { // TODO: currently, we do nothing here, do we want
                  // our syscalls on this vector as well?
        }
      , _ => panic!("Unknown interrupt: #{} Sorry!", id)
    }
    // send the PICs the end interrupt signal
    pics::end_pic_interrupt(id as u8);
}

pub unsafe fn initialize() {
    // println!(" . Enabling interrupts:" );
    // println!( " . . Initialising PICs {:>40}"
    //         , pics::initialize().unwrap_or("[ FAIL ]") );
    pics::initialize();
    IDT.lock()
       .add_handlers()
       .load();                 // Load the IDT pointer
    // print!("Testing interrupt handling...");
    // asm!("int $0" :: "N" (0x80));
    // println!("   [DONE]");
    Idt64::enable_interrupts(); // enable interrupts

}
<commit_msg>[x86_all] added some documentation to interrupts<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit Interrupt Descriptor Table implementation.
//!
//! Refer to section 6.10 of the _Intel® 64 and IA-32 Architectures
//! Software Developer’s Manual_ for more information.
use core::mem;
use core::ptr;

use spin::Mutex;

use super::{Registers, DTable, DTablePtr, segment};
use io::keyboard;

#[path = "../../x86_all/interrupts.rs"] mod interrupts_all;
#[path = "../../x86_all/pics.rs"] pub mod pics;
pub use self::interrupts_all::*;

//==------------------------------------------------------------------------==
// Interface into ASM interrupt handling
extern {
    /// Offset of the 64-bit GDT main code segment.
    /// Exported by `boot.asm`
    static gdt64_offset: u16;

    /// Array of interrupt handlers from ASM
    static interrupt_handlers: [*const u8; IDT_ENTRIES];
}

/// State stored when handling an interrupt.
#[allow(dead_code)]
#[repr(C, packed)]
pub struct InterruptCtx64 { /// callee-saved registers
                            pub registers: Registers
                          , /// interrupt ID number
                            pub int_id:  u32
                          , __pad_1: u32
                          , /// error number
                            pub err_no:  u32
                          , __pad_2: u32
                          }

impl InterruptContext for InterruptCtx64 {
    type Registers = Registers;
    // All these inline functions are basically just faking
    // object orientation in a way the Rust compiler understands
    #[inline] fn registers(&self) -> Self::Registers { self.registers }
    #[inline] fn err_no(&self) -> u32 { self.err_no }
    #[inline] fn int_id(&self) -> u32 { self.int_id }
}

//==------------------------------------------------------------------------==
// 64-bit implementation of the IDT gate trait

/// An IDT entry is called a gate.
///
/// Based on code from the OS Dev Wiki
/// http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy,Clone)]
pub struct Gate64 { /// bits 0 - 15 of the offset
                    pub offset_lower: u16
                  , /// code segment selector (GDT or LDT)
                    pub selector: segment::Selector
                  , /// always zero
                    zero: u8
                  , /// indicates the gate's type and attributes.
                    /// the second half indicates the type:
                    ///   + `0b1100`: Call gate
                    ///   + `0b1110`: Interrupt gate
                    ///   + `0b1111`: Trap Gate
                    pub type_attr: GateType
                  , /// bits 16 - 31 of the offset
                    pub offset_mid: u16
                  , /// bits 32 - 63 of the offset
                    pub offset_upper: u32
                  , /// always zero (according to the spec, this is "reserved")
                    reserved: u32
                  }

impl Gate64 {
    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// This would be in the `Gate` trait, but this has to be a `const fn` so
    /// that it can be usedm in static initializers, and trait functions cannot
    /// be `const`.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    const fn absent() -> Self {
        Gate64 { offset_lower: 0
               , selector: segment::Selector::from_raw(0)
               , zero: 0
               , type_attr: GateType::Absent
               , offset_mid: 0
               , offset_upper: 0
               , reserved: 0
               }
    }
}

impl Gate for Gate64 {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from_handler(handler: Handler) -> Self {
        unsafe { // trust me on this.
                 // `mem::transmute()` is glorious black magic
            let (low, mid, high): (u16, u16, u32)
                = mem::transmute(handler);

            Gate64 { offset_lower: low
                   , selector: segment::Selector::from_raw(gdt64_offset)
                   , zero: 0
                   // Bit 7 is the present bit
                   // Bits 4-0 indicate this is an interrupt gate
                   , type_attr: GateType::Interrupt
                   , offset_mid: mid
                   , offset_upper: high
                   , reserved: 0
                   }
        }
    }

    ///  Creates a new IDT gate from a raw reference to a handler.
    ///
    ///  This should probably not be used ever.
    unsafe fn from_raw(handler: *const u8) -> Self {
        let (low, mid, high): (u16, u16, u32)
            = mem::transmute(handler as u64);

        Gate64 { offset_lower: low
               , selector: segment::Selector::from_raw(gdt64_offset)
               , zero: 0
               , type_attr: GateType::Interrupt
               , offset_mid: mid
               , offset_upper: high
               , reserved: 0
               }
    }
}

//==-------------------------------------------------------------------------==
// 64-bit implementation of the IDT trait
struct Idt64([Gate64; IDT_ENTRIES]);

impl Idt for Idt64 {
    type Ctx = InterruptCtx64;
    type GateSize = Gate64;
    type PtrSize = u64;

    fn get_ptr(&self) -> DTablePtr<u64> {
        DTablePtr { limit: (mem::size_of::<Self::GateSize>() * IDT_ENTRIES)
                            as u16
                  , base: &self.0[0] as *const Gate64 as u64
                  }
    }

    /// Add an entry for the given handler at the given index
    fn add_gate(&mut self, index: usize, handler: Handler) {
        self.0[index] = Gate64::from_handler(handler)
    }

}

impl DTable for Idt64 {
    #[inline] unsafe fn load(&self) {
        asm!(  "lidt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        println!("{:<38}{:>40}", " . . Loading IDT", "[ OKAY ]");
    }
}

impl Idt64 {
    fn add_handlers(&mut self) -> &mut Self {
        for (i, &h_ptr) in interrupt_handlers.iter()
            .enumerate()
            .filter(|&(_, &h_ptr)| h_ptr != ptr::null() ) {
                unsafe { self.0[i] = Gate64::from_raw(h_ptr) }
        }

        println!("{:<38}{:>40}", " . . Adding interrupt handlers to IDT"
             , "[ OKAY ]");
        self
    }
}

//==--------------------------------------------------------------------------==
// Top-level interrupt handling
/// Global Interrupt Descriptor Table instance
/// Our global IDT.
static IDT: Mutex<Idt64>
    = Mutex::new(Idt64([Gate64::absent(); IDT_ENTRIES]));

/// Kernel interrupt-handling function.
///
/// Assembly interrupt handlers call into this, and it dispatches interrupts to
/// the appropriate consumers.
#[no_mangle]
pub unsafe extern "C" fn handle_interrupt(state: &InterruptCtx64) {
    let id = state.int_id();
    match id {
        // interrupts 0 - 16 are CPU exceptions
        0x00...0x0f => Idt64::handle_cpu_exception(state)
        // System timer
      , 0x20 => { /* TODO: make this work */ }
        // Keyboard
      , 0x21 => {
          // TODO: dispatch keypress event to subscribers (NYI)
            if let Some(input) = keyboard::read_char() {
                if input == '\r' {
                    println!("");
                } else {
                    print!("{}", input);
                }
            }
        }
        // Loonix syscall vector
      , 0x80 => { // TODO: currently, we do nothing here, do we want
                  // our syscalls on this vector as well?
        }
      , _ => panic!("Unknown interrupt: #{} Sorry!", id)
    }
    // send the PICs the end interrupt signal
    pics::end_pic_interrupt(id as u8);
}

/// Initialize interrupt handling.
///
/// This function initializes the PICs, populates the IDT with interrupt
/// handlers, loads the IDT pointer, and enables interrupts.
///
/// This is called from the kernel during the init process.
pub unsafe fn initialize() {
    // println!(" . Enabling interrupts:" );
    // println!( " . . Initialising PICs {:>40}"
    //         , pics::initialize().unwrap_or("[ FAIL ]") );
    pics::initialize();
    IDT.lock()
       .add_handlers()
       .load();                 // Load the IDT pointer
    // print!("Testing interrupt handling...");
    // asm!("int $0" :: "N" (0x80));
    // println!("   [DONE]");
    Idt64::enable_interrupts(); // enable interrupts

}
<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(asm)]
#![feature(heap_api)]
#![feature(question_mark)]

extern crate alloc;
extern crate ransid;
extern crate syscall;

use std::cell::RefCell;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{Read, Write};
use std::{slice, thread};
use ransid::{Console, Event};
use syscall::{physmap, physunmap, Packet, Result, Scheme, MAP_WRITE, MAP_WRITE_COMBINE};

use display::Display;
use mode_info::VBEModeInfo;
use primitive::fast_set64;

pub mod display;
pub mod mode_info;
pub mod primitive;

struct DisplayScheme {
    console: RefCell<Console>,
    display: RefCell<Display>,
    input: RefCell<VecDeque<u8>>
}

impl Scheme for DisplayScheme {
    fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
        if path == b"input" {
            Ok(1)
        } else {
            Ok(0)
        }
    }

    fn dup(&self, id: usize) -> Result<usize> {
        Ok(id)
    }

    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn read(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let mut input = self.input.borrow_mut();
        while i < buf.len() && ! input.is_empty() {
            buf[i] = input.pop_front().unwrap();
            i += 1;
        }
        Ok(i)
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        if id == 1 {
            let mut input = self.input.borrow_mut();
            for &b in buf.iter() {
                input.push_back(b);
            }
            Ok(buf.len())
        } else {
            let mut display = self.display.borrow_mut();
            self.console.borrow_mut().write(buf, |event| {
                match event {
                    Event::Char { x, y, c, color, bold, .. } => display.char(x * 8, y * 16, c, color.data, bold, false),
                    Event::Rect { x, y, w, h, color } => display.rect(x * 8, y * 16, w * 8, h * 16, color.data),
                    Event::Scroll { rows, color } => display.scroll(rows * 16, color.data)
                }
            });
            Ok(buf.len())
        }
    }

    fn close(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }
}

fn main() {
    let width;
    let height;
    let physbaseptr;

    {
        let mode_info = unsafe { &*(physmap(0x5200, 4096, 0).expect("vesad: failed to map VBE info") as *const VBEModeInfo) };

        width = mode_info.xresolution as usize;
        height = mode_info.yresolution as usize;
        physbaseptr = mode_info.physbaseptr as usize;

        unsafe { let _ = physunmap(mode_info as *const _ as usize); }
    }

    if physbaseptr > 0 {
        thread::spawn(move || {
            let mut socket = File::create(":display").expect("vesad: failed to create display scheme");

            let size = width * height;

            let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
            unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };

            let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) };
            unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };

            let scheme = DisplayScheme {
                console: RefCell::new(Console::new(width/8, height/16)),
                display: RefCell::new(Display::new(width, height,
                    unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
                    unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
                )),
                input: RefCell::new(VecDeque::new())
            };

            let mut blocked = VecDeque::new();
            loop {
                let mut packet = Packet::default();
                socket.read(&mut packet).expect("vesad: failed to read display scheme");
                //println!("vesad: {:?}", packet);
                if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.input.borrow().is_empty() {
                    blocked.push_back(packet);
                } else {
                    scheme.handle(&mut packet);
                    socket.write(&packet).expect("vesad: failed to write display scheme");
                }
                while ! scheme.input.borrow().is_empty() {
                    if let Some(mut packet) = blocked.pop_front() {
                        scheme.handle(&mut packet);
                        socket.write(&packet).expect("vesad: failed to write display scheme");
                    }
                }
            }
        });
    }
}
<commit_msg>Add cursor<commit_after>#![feature(alloc)]
#![feature(asm)]
#![feature(heap_api)]
#![feature(question_mark)]

extern crate alloc;
extern crate ransid;
extern crate syscall;

use std::cell::RefCell;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{Read, Write};
use std::{slice, thread};
use ransid::{Console, Event};
use syscall::{physmap, physunmap, Packet, Result, Scheme, MAP_WRITE, MAP_WRITE_COMBINE};

use display::Display;
use mode_info::VBEModeInfo;
use primitive::fast_set64;

pub mod display;
pub mod mode_info;
pub mod primitive;

struct DisplayScheme {
    console: RefCell<Console>,
    display: RefCell<Display>,
    input: RefCell<VecDeque<u8>>
}

impl Scheme for DisplayScheme {
    fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
        if path == b"input" {
            Ok(1)
        } else {
            Ok(0)
        }
    }

    fn dup(&self, id: usize) -> Result<usize> {
        Ok(id)
    }

    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn read(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        let mut input = self.input.borrow_mut();
        while i < buf.len() && ! input.is_empty() {
            buf[i] = input.pop_front().unwrap();
            i += 1;
        }
        Ok(i)
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        if id == 1 {
            let mut input = self.input.borrow_mut();
            for &b in buf.iter() {
                input.push_back(b);
            }
            Ok(buf.len())
        } else {
            let mut display = self.display.borrow_mut();
            let mut console = self.console.borrow_mut();
            if console.x < console.w && console.y < console.h {
                display.rect(console.x * 8, console.y * 16, 8, 16, 0);
            }
            console.write(buf, |event| {
                match event {
                    Event::Char { x, y, c, color, bold, .. } => display.char(x * 8, y * 16, c, color.data, bold, false),
                    Event::Rect { x, y, w, h, color } => display.rect(x * 8, y * 16, w * 8, h * 16, color.data),
                    Event::Scroll { rows, color } => display.scroll(rows * 16, color.data)
                }
            });
            if console.x < console.w && console.y < console.h {
                display.rect(console.x * 8, console.y * 16, 8, 16, 0xFFFFFF);
            }
            Ok(buf.len())
        }
    }

    fn close(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }
}

fn main() {
    let width;
    let height;
    let physbaseptr;

    {
        let mode_info = unsafe { &*(physmap(0x5200, 4096, 0).expect("vesad: failed to map VBE info") as *const VBEModeInfo) };

        width = mode_info.xresolution as usize;
        height = mode_info.yresolution as usize;
        physbaseptr = mode_info.physbaseptr as usize;

        unsafe { let _ = physunmap(mode_info as *const _ as usize); }
    }

    if physbaseptr > 0 {
        thread::spawn(move || {
            let mut socket = File::create(":display").expect("vesad: failed to create display scheme");

            let size = width * height;

            let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
            unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };

            let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) };
            unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };

            let scheme = DisplayScheme {
                console: RefCell::new(Console::new(width/8, height/16)),
                display: RefCell::new(Display::new(width, height,
                    unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
                    unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
                )),
                input: RefCell::new(VecDeque::new())
            };

            let mut blocked = VecDeque::new();
            loop {
                let mut packet = Packet::default();
                socket.read(&mut packet).expect("vesad: failed to read display scheme");
                //println!("vesad: {:?}", packet);
                if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.input.borrow().is_empty() {
                    blocked.push_back(packet);
                } else {
                    scheme.handle(&mut packet);
                    socket.write(&packet).expect("vesad: failed to write display scheme");
                }
                while ! scheme.input.borrow().is_empty() {
                    if let Some(mut packet) = blocked.pop_front() {
                        scheme.handle(&mut packet);
                        socket.write(&packet).expect("vesad: failed to write display scheme");
                    }
                }
            }
        });
    }
}
<|endoftext|>