<commit_before>#![deny(missing_docs)]
#![warn(dead_code)]

//! A user friendly game engine written in Rust.

#[cfg(feature = "include_gfx")]
extern crate libc;
#[cfg(feature = "include_gfx")]
extern crate gfx;
#[cfg(feature = "include_gfx")]
extern crate gfx_device_gl;
#[cfg(feature = "include_gfx")]
extern crate gfx_graphics;
#[cfg(feature = "include_opengl")]
extern crate opengl_graphics;
#[cfg(feature = "include_glium")]
extern crate glium_graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;
extern crate graphics;
extern crate fps_counter;
extern crate current;
extern crate shader_version;

extern crate piston;

#[cfg(feature = "include_sdl2")]
pub use sdl2_window::Sdl2Window as WindowBackEnd;
#[cfg(feature = "include_glfw")]
pub use glfw_window::GlfwWindow as WindowBackEnd;
#[cfg(feature = "include_glutin")]
pub use glutin_window::GlutinWindow as WindowBackEnd;

#[cfg(feature = "include_gfx")]
use gfx_graphics::Gfx2d;
#[cfg(feature = "include_gfx")]
use gfx_device_gl::{ Device, Resources, CommandBuffer, Output };

#[cfg(feature = "include_opengl")]
use opengl_graphics::GlGraphics;
#[cfg(feature = "include_glium")]
use glium_graphics::{ Glium2d, GliumWindow };
use fps_counter::FPSCounter;

use std::rc::Rc;
use std::cell::RefCell;

use piston::window::WindowSettings;
use current::{ Current, CurrentGuard };

fn start_window<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    let mut window = Rc::new(RefCell::new(WindowBackEnd::new(
        opengl,
        window_settings,
    )));
    let mut fps_counter = Rc::new(RefCell::new(FPSCounter::new()));

    #[cfg(feature = "include_sdl2")]
    fn disable_vsync() { sdl2::video::gl_set_swap_interval(0); }

    #[cfg(not(feature = "include_sdl2"))]
    fn disable_vsync() {}

    disable_vsync();

    let window_guard = CurrentGuard::new(&mut window);
    let fps_counter_guard = CurrentGuard::new(&mut fps_counter);

    f();

    drop(window_guard);
    drop(fps_counter_guard);
}

#[cfg(feature = "include_opengl")]
fn start_opengl<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let mut gl = Rc::new(RefCell::new(GlGraphics::new(opengl)));

    let gl_guard = CurrentGuard::new(&mut gl);

    f();

    drop(gl_guard);
}

#[cfg(not(feature = "include_opengl"))]
fn start_opengl<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_glium")]
fn start_glium<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let window = current_window();
    let mut glium_window = Rc::new(RefCell::new(GliumWindow::new(&window).unwrap()));
    let mut glium2d = Rc::new(RefCell::new(Glium2d::new(opengl, &*glium_window.borrow())));

    let glium_window_guard = CurrentGuard::new(&mut glium_window);
    let glium2d_guard = CurrentGuard::new(&mut glium2d);

    f();

    drop(glium2d_guard);
    drop(glium_window_guard);
}

#[cfg(not(feature = "include_glium"))]
fn start_glium<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_gfx")]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    use piston::window::Window;
    use gfx::render::RenderFactory;

    let window = current_window();

    let (device, mut factory) = gfx_device_gl::create(|s| {
        #[cfg(feature = "include_sdl2")]
        fn get_proc_address(_: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            unsafe { std::mem::transmute(sdl2::video::gl_get_proc_address(s)) }
        }

        #[cfg(feature = "include_glfw")]
        fn get_proc_address(window: &mut WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        #[cfg(feature = "include_glutin")]
        fn get_proc_address(window: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        get_proc_address(&mut *window.borrow_mut(), s)
    });
    let mut renderer: Rc<RefCell<
        gfx::Renderer<gfx_device_gl::Resources,
        <gfx_device_gl::Device as gfx::Device>::CommandBuffer
    >>> =
        Rc::new(RefCell::new(factory.create_renderer()));
    let mut device = Rc::new(RefCell::new(device));
    let factory = Rc::new(RefCell::new(factory));
    let mut g2d = Rc::new(RefCell::new(Gfx2d::new(&mut *device.borrow_mut(), &mut *factory.borrow_mut())));
    let size = window.borrow().size();
    let mut output = Rc::new(RefCell::new(factory.borrow_mut().make_fake_output(
        size.width as u16, size.height as u16)));

    let device_guard = CurrentGuard::new(&mut device);
    let g2d_guard = CurrentGuard::new(&mut g2d);
    let renderer_guard = CurrentGuard::new(&mut renderer);
    let output_guard = CurrentGuard::new(&mut output);

    f();

    drop(g2d_guard);
    drop(renderer_guard);
    drop(output_guard);
    drop(device_guard);
}

#[cfg(not(feature = "include_gfx"))]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    f();
}

/// Initializes window and sets up current objects.
pub fn start<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    start_window(opengl, window_settings, || {
        start_opengl(opengl, || {
            start_gfx(|| {
                start_glium(opengl, || f());
            })
        })
    });
}

/// The current window
pub fn current_window() -> Rc<RefCell<WindowBackEnd>> {
    unsafe {
        Current::<Rc<RefCell<WindowBackEnd>>>::new().clone()
    }
}
/// The current Gfx device
#[cfg(feature = "include_gfx")]
pub fn current_gfx_device() -> Rc<RefCell<Device>> {
    unsafe {
        Current::<Rc<RefCell<Device>>>::new().clone()
    }
}
/// The current opengl_graphics back-end
#[cfg(feature = "include_opengl")]
pub fn current_gl_graphics() -> Rc<RefCell<GlGraphics>> {
    unsafe {
        Current::<Rc<RefCell<GlGraphics>>>::new().clone()
    }
}
/// The current gfx_graphics back-end
#[cfg(feature = "include_gfx")]
pub fn current_gfx_graphics() -> Rc<RefCell<Gfx2d<Resources>>> {
    unsafe {
        Current::<Rc<RefCell<Gfx2d<Resources>>>>::new().clone()
    }
}
/// The current glium window.
#[cfg(feature = "include_glium")]
pub fn current_glium_window() -> Rc<RefCell<GliumWindow>> {
    unsafe {
        Current::<Rc<RefCell<GliumWindow>>>::new().clone()
    }
}
/// The current glium 2d.
#[cfg(feature = "include_glium")]
pub fn current_glium_2d() -> Rc<RefCell<Glium2d>> {
    unsafe {
        Current::<Rc<RefCell<Glium2d>>>::new().clone()
    }
}
/// The current Gfx renderer
#[cfg(feature = "include_gfx")]
pub fn current_renderer() -> Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>>>::new().clone()
    }
}
/// The current Gfx frame
#[cfg(feature = "include_gfx")]
pub fn current_output() -> Rc<RefCell<Output>> {
    unsafe {
        Current::<Rc<RefCell<Output>>>::new().clone()
    }
}
/// The current FPS counter
pub fn current_fps_counter() -> Rc<RefCell<FPSCounter>> {
    unsafe {
        Current::<Rc<RefCell<FPSCounter>>>::new().clone()
    }
}

/// Returns an event iterator for the event loop
pub fn events() -> piston::event::WindowEvents<WindowBackEnd, piston::event::Event> {
    use piston::event::Events;

    current_window().events()
}

/// Updates the FPS counter and gets the frames per second.
pub fn fps_tick() -> usize {
    let fps_counter = current_fps_counter();
    let mut fps_counter = fps_counter.borrow_mut();
    fps_counter.tick()
}

/// Sets title of the current window.
pub fn set_title(text: String) {
    use piston::window::AdvancedWindow;

    let window = current_window();
    let mut window = window.borrow_mut();
    window.set_title(text);
}

/// Returns true if the current window should be closed.
pub fn should_close() -> bool {
    use piston::window::Window;

    let window = current_window();
    let window = window.borrow();
    window.should_close()
}

/// Renders 2D graphics using Gfx.
#[cfg(feature = "include_gfx")]
pub fn render_2d_gfx<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context,
            &mut gfx_graphics::GfxGraphics<Resources, CommandBuffer, Output>)
{
    use gfx::Device;
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let renderer = current_renderer();
    let mut renderer = renderer.borrow_mut();
    let renderer = &mut *renderer;
    let gfx = current_gfx_graphics();
    let mut gfx = gfx.borrow_mut();
    let output = current_output();
    let output = output.borrow();
    gfx.draw(
        renderer,
        &*output,
        Viewport {
            rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
            draw_size: [draw_size.width, draw_size.height],
            window_size: [size.width, size.height],
        },
        |c, g| {
            if let Some(bg_color) = bg_color {
                graphics::clear(bg_color, g);
            }
            f(c, g);
        });
    let gfx_device = current_gfx_device();
    let mut gfx_device = gfx_device.borrow_mut();
    gfx_device.submit(renderer.as_buffer());
    renderer.reset();
}

/// Renders 2D graphics using OpenGL.
///
/// Panics if called nested within the closure
/// to prevent mutable aliases to the graphics back-end.
#[cfg(feature = "include_opengl")]
pub fn render_2d_opengl<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context, &mut opengl_graphics::GlGraphics)
{
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let gl = current_gl_graphics();
    let mut gl = gl.borrow_mut();
    gl.draw(Viewport {
        rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
        draw_size: [draw_size.width, draw_size.height],
        window_size: [size.width, size.height]
    }, |c, g| {
        use graphics::*;
        if let Some(bg_color) = bg_color {
            graphics::clear(bg_color, g);
        }
        f(c, g);
    });
}

<commit_msg>sync is handled through `WindowSettings`<commit_after>#![deny(missing_docs)]
#![warn(dead_code)]

//! A user friendly game engine written in Rust.

#[cfg(feature = "include_gfx")]
extern crate libc;
#[cfg(feature = "include_gfx")]
extern crate gfx;
#[cfg(feature = "include_gfx")]
extern crate gfx_device_gl;
#[cfg(feature = "include_gfx")]
extern crate gfx_graphics;
#[cfg(feature = "include_opengl")]
extern crate opengl_graphics;
#[cfg(feature = "include_glium")]
extern crate glium_graphics;
#[cfg(feature = "include_sdl2")]
extern crate sdl2;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;
extern crate graphics;
extern crate fps_counter;
extern crate current;
extern crate shader_version;

extern crate piston;

#[cfg(feature = "include_sdl2")]
pub use sdl2_window::Sdl2Window as WindowBackEnd;
#[cfg(feature = "include_glfw")]
pub use glfw_window::GlfwWindow as WindowBackEnd;
#[cfg(feature = "include_glutin")]
pub use glutin_window::GlutinWindow as WindowBackEnd;

#[cfg(feature = "include_gfx")]
use gfx_graphics::Gfx2d;
#[cfg(feature = "include_gfx")]
use gfx_device_gl::{ Device, Resources, CommandBuffer, Output };

#[cfg(feature = "include_opengl")]
use opengl_graphics::GlGraphics;
#[cfg(feature = "include_glium")]
use glium_graphics::{ Glium2d, GliumWindow };
use fps_counter::FPSCounter;

use std::rc::Rc;
use std::cell::RefCell;

use piston::window::WindowSettings;
use current::{ Current, CurrentGuard };

fn start_window<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    let mut window = Rc::new(RefCell::new(WindowBackEnd::new(
        opengl,
        window_settings,
    )));
    let mut fps_counter = Rc::new(RefCell::new(FPSCounter::new()));

    let window_guard = CurrentGuard::new(&mut window);
    let fps_counter_guard = CurrentGuard::new(&mut fps_counter);

    f();

    drop(window_guard);
    drop(fps_counter_guard);
}

#[cfg(feature = "include_opengl")]
fn start_opengl<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let mut gl = Rc::new(RefCell::new(GlGraphics::new(opengl)));

    let gl_guard = CurrentGuard::new(&mut gl);

    f();

    drop(gl_guard);
}

#[cfg(not(feature = "include_opengl"))]
fn start_opengl<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_glium")]
fn start_glium<F>(opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    let window = current_window();
    let mut glium_window = Rc::new(RefCell::new(GliumWindow::new(&window).unwrap()));
    let mut glium2d = Rc::new(RefCell::new(Glium2d::new(opengl, &*glium_window.borrow())));

    let glium_window_guard = CurrentGuard::new(&mut glium_window);
    let glium2d_guard = CurrentGuard::new(&mut glium2d);

    f();

    drop(glium2d_guard);
    drop(glium_window_guard);
}

#[cfg(not(feature = "include_glium"))]
fn start_glium<F>(_opengl: shader_version::OpenGL, mut f: F)
    where
        F: FnMut()
{
    f();
}

#[cfg(feature = "include_gfx")]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    use piston::window::Window;
    use gfx::render::RenderFactory;

    let window = current_window();

    let (device, mut factory) = gfx_device_gl::create(|s| {
        #[cfg(feature = "include_sdl2")]
        fn get_proc_address(_: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            unsafe { std::mem::transmute(sdl2::video::gl_get_proc_address(s)) }
        }

        #[cfg(feature = "include_glfw")]
        fn get_proc_address(window: &mut WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        #[cfg(feature = "include_glutin")]
        fn get_proc_address(window: &WindowBackEnd, s: &str) ->
            *const libc::types::common::c95::c_void {
            window.window.get_proc_address(s)
        }

        get_proc_address(&mut *window.borrow_mut(), s)
    });
    let mut renderer: Rc<RefCell<
        gfx::Renderer<gfx_device_gl::Resources,
        <gfx_device_gl::Device as gfx::Device>::CommandBuffer
    >>> =
        Rc::new(RefCell::new(factory.create_renderer()));
    let mut device = Rc::new(RefCell::new(device));
    let factory = Rc::new(RefCell::new(factory));
    let mut g2d = Rc::new(RefCell::new(Gfx2d::new(&mut *device.borrow_mut(), &mut *factory.borrow_mut())));
    let size = window.borrow().size();
    let mut output = Rc::new(RefCell::new(factory.borrow_mut().make_fake_output(
        size.width as u16, size.height as u16)));

    let device_guard = CurrentGuard::new(&mut device);
    let g2d_guard = CurrentGuard::new(&mut g2d);
    let renderer_guard = CurrentGuard::new(&mut renderer);
    let output_guard = CurrentGuard::new(&mut output);

    f();

    drop(g2d_guard);
    drop(renderer_guard);
    drop(output_guard);
    drop(device_guard);
}

#[cfg(not(feature = "include_gfx"))]
fn start_gfx<F>(mut f: F)
    where
        F: FnMut()
{
    f();
}

/// Initializes window and sets up current objects.
pub fn start<F>(
    opengl: shader_version::OpenGL,
    window_settings: WindowSettings,
    mut f: F
)
    where
        F: FnMut()
{
    start_window(opengl, window_settings, || {
        start_opengl(opengl, || {
            start_gfx(|| {
                start_glium(opengl, || f());
            })
        })
    });
}

/// The current window
pub fn current_window() -> Rc<RefCell<WindowBackEnd>> {
    unsafe {
        Current::<Rc<RefCell<WindowBackEnd>>>::new().clone()
    }
}
/// The current Gfx device
#[cfg(feature = "include_gfx")]
pub fn current_gfx_device() -> Rc<RefCell<Device>> {
    unsafe {
        Current::<Rc<RefCell<Device>>>::new().clone()
    }
}
/// The current opengl_graphics back-end
#[cfg(feature = "include_opengl")]
pub fn current_gl_graphics() -> Rc<RefCell<GlGraphics>> {
    unsafe {
        Current::<Rc<RefCell<GlGraphics>>>::new().clone()
    }
}
/// The current gfx_graphics back-end
#[cfg(feature = "include_gfx")]
pub fn current_gfx_graphics() -> Rc<RefCell<Gfx2d<Resources>>> {
    unsafe {
        Current::<Rc<RefCell<Gfx2d<Resources>>>>::new().clone()
    }
}
/// The current glium window.
#[cfg(feature = "include_glium")]
pub fn current_glium_window() -> Rc<RefCell<GliumWindow>> {
    unsafe {
        Current::<Rc<RefCell<GliumWindow>>>::new().clone()
    }
}
/// The current glium 2d.
#[cfg(feature = "include_glium")]
pub fn current_glium_2d() -> Rc<RefCell<Glium2d>> {
    unsafe {
        Current::<Rc<RefCell<Glium2d>>>::new().clone()
    }
}
/// The current Gfx renderer
#[cfg(feature = "include_gfx")]
pub fn current_renderer() -> Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>> {
    unsafe {
        Current::<Rc<RefCell<gfx::Renderer<Resources, CommandBuffer>>>>::new().clone()
    }
}
/// The current Gfx frame
#[cfg(feature = "include_gfx")]
pub fn current_output() -> Rc<RefCell<Output>> {
    unsafe {
        Current::<Rc<RefCell<Output>>>::new().clone()
    }
}
/// The current FPS counter
pub fn current_fps_counter() -> Rc<RefCell<FPSCounter>> {
    unsafe {
        Current::<Rc<RefCell<FPSCounter>>>::new().clone()
    }
}

/// Returns an event iterator for the event loop
pub fn events() -> piston::event::WindowEvents<WindowBackEnd, piston::event::Event> {
    use piston::event::Events;

    current_window().events()
}

/// Updates the FPS counter and gets the frames per second.
pub fn fps_tick() -> usize {
    let fps_counter = current_fps_counter();
    let mut fps_counter = fps_counter.borrow_mut();
    fps_counter.tick()
}

/// Sets title of the current window.
pub fn set_title(text: String) {
    use piston::window::AdvancedWindow;

    let window = current_window();
    let mut window = window.borrow_mut();
    window.set_title(text);
}

/// Returns true if the current window should be closed.
pub fn should_close() -> bool {
    use piston::window::Window;

    let window = current_window();
    let window = window.borrow();
    window.should_close()
}

/// Renders 2D graphics using Gfx.
#[cfg(feature = "include_gfx")]
pub fn render_2d_gfx<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context,
            &mut gfx_graphics::GfxGraphics<Resources, CommandBuffer, Output>)
{
    use gfx::Device;
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let renderer = current_renderer();
    let mut renderer = renderer.borrow_mut();
    let renderer = &mut *renderer;
    let gfx = current_gfx_graphics();
    let mut gfx = gfx.borrow_mut();
    let output = current_output();
    let output = output.borrow();
    gfx.draw(
        renderer,
        &*output,
        Viewport {
            rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
            draw_size: [draw_size.width, draw_size.height],
            window_size: [size.width, size.height],
        },
        |c, g| {
            if let Some(bg_color) = bg_color {
                graphics::clear(bg_color, g);
            }
            f(c, g);
        });
    let gfx_device = current_gfx_device();
    let mut gfx_device = gfx_device.borrow_mut();
    gfx_device.submit(renderer.as_buffer());
    renderer.reset();
}

/// Renders 2D graphics using OpenGL.
///
/// Panics if called nested within the closure
/// to prevent mutable aliases to the graphics back-end.
#[cfg(feature = "include_opengl")]
pub fn render_2d_opengl<F>(
    bg_color: Option<[f32; 4]>,
    mut f: F
)
    where
        F: FnMut(graphics::Context, &mut opengl_graphics::GlGraphics)
{
    use piston::window::Window;
    use graphics::Viewport;

    let window = current_window();
    let window = window.borrow();
    let size = window.size();
    let draw_size = window.draw_size();
    let gl = current_gl_graphics();
    let mut gl = gl.borrow_mut();
    gl.draw(Viewport {
        rect: [0, 0, draw_size.width as i32, draw_size.height as i32],
        draw_size: [draw_size.width, draw_size.height],
        window_size: [size.width, size.height]
    }, |c, g| {
        use graphics::*;
        if let Some(bg_color) = bg_color {
            graphics::clear(bg_color, g);
        }
        f(c, g);
    });
}

<|endoftext|>


<commit_before>//! A basic ZipReader/Writer crate

#![feature(phase)]
#![feature(unsafe_destructor)]
#![warn(missing_docs)]

#[phase(plugin, link)] extern crate log;
extern crate time;
extern crate flate2;
extern crate bzip2;

pub use reader::ZipReader;
pub use writer::ZipWriter;
pub use compression::CompressionMethod;
pub use types::ZipFile;

mod util;
mod spec;
mod reader_spec;
mod writer_spec;
mod crc32;
mod reader;
mod types;
pub mod compression;
mod writer;
mod cp437;
pub mod result;
<commit_msg>Use #[macro_use] instead of phase<commit_after>//! A basic ZipReader/Writer crate

#![feature(unsafe_destructor)]
#![warn(missing_docs)]

#[macro_use] extern crate log;
extern crate time;
extern crate flate2;
extern crate bzip2;

pub use reader::ZipReader;
pub use writer::ZipWriter;
pub use compression::CompressionMethod;
pub use types::ZipFile;

mod util;
mod spec;
mod reader_spec;
mod writer_spec;
mod crc32;
mod reader;
mod types;
pub mod compression;
mod writer;
mod cp437;
pub mod result;
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate redis;

use std::str;
use std::cell::Cell;
use std::thread;
use std::ops::{Deref, Drop};
use std::convert::From;
use std::iter::Iterator;
use std::marker::PhantomData;
use rustc_serialize::{json, Decodable};
use redis::{Value, RedisResult, ErrorKind, Commands};

#[derive(RustcDecodable, RustcEncodable)]
struct Job {
    id: u64
}

pub trait TaskDecodable where Self: Sized {
    fn decode_task(value: &Value) -> RedisResult<Self>;
}

impl<T: Decodable> TaskDecodable for T {
    fn decode_task(value: &Value) -> RedisResult<T> {
        match value {
            &Value::Data(ref v) => {
                let s = try!(str::from_utf8(&v));
                Ok(try!(json::decode(&s).map_err(|_| (ErrorKind::TypeError, "JSON decode failed"))))

            },
            v @ _ => {
                println!("what do we have here: {:?}", v);
                try!(Err((ErrorKind::TypeError, "Can only decode from a string")))
            }
        }
    }
}

struct TaskGuard<'a, T: 'a> {
    task: T,
    worker: &'a Worker<T>
}

impl<'a, T: TaskDecodable> TaskGuard<'a, T> {
    fn stop(&self) {
        self.worker.stop();
    }
}

impl<'a, T> Deref for TaskGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Drop for TaskGuard<'a, T> {
    fn drop(&mut self) {
        // Pop job from backup queue
        let backup = &self.worker.backup_queue[..];
        let _ : () = self.worker.client.lpop(backup).expect("LPOP from backup queue failed");
    }
}

struct Worker<T> {
    queue_name: String,
    backup_queue: String,
    stopped: Cell<bool>,
    pub client: redis::Connection,
    _job_type: PhantomData<T>,
}

impl<T: TaskDecodable> Worker<T> {
    pub fn new(name: String, client: redis::Connection) -> Worker<T> {
        let backup_queue = [thread::current().name().unwrap_or("default".into()), "1"].join(":");
        Worker {
            queue_name: name,
            backup_queue: backup_queue,
            client: client,
            stopped: Cell::new(false),
            _job_type: PhantomData,
        }
    }

    pub fn stop(&self) {
        self.stopped.set(true);
    }

    pub fn next(&mut self) -> Option<RedisResult<TaskGuard<T>>> {
        if self.stopped.get() {
            return None;
        }

        let v;
        {
            let qname = &self.queue_name[..];
            let backup = &self.backup_queue[..];

            v = match self.client.brpoplpush(qname, backup, 0) {
                Ok(v) => v,
                Err(e) => {
                    return Some(Err(From::from((ErrorKind::TypeError, "next failed"))));
                }
            };
        }

        let v = match v {
            v @ Value::Data(_) => v,
            _ => {
                return Some(Err(From::from((ErrorKind::TypeError, "Not a 2-item Bulk reply"))));
            }
        };

        let task = T::decode_task(&v).unwrap();

        Some(Ok(TaskGuard{task: task, worker: self}))
    }
}

#[test]
fn decodes_job() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();

    let _ : () = con.rpush("default", "{\"id\":42}").unwrap();

    let mut worker = Worker::<Job>::new("default".into(), con);
    let j = worker.next().unwrap().unwrap();
    assert_eq!(42, j.id);
}

#[test]
fn releases_job() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let mut worker = Worker::<Job>::new("default".into(), con);

    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();

    let _ : () = con.lpush("default", "{\"id\":42}").unwrap();

    {
        let j = worker.next().unwrap().unwrap();
        assert_eq!(42, j.id);
        let in_backup : Vec<String> = con.lrange("releases_job:1", 0, -1).unwrap();
        assert_eq!(1, in_backup.len());
        assert_eq!("{\"id\":42}", in_backup[0]);
    }

    let in_backup : Vec<String> = con.lrange("releases_job:1", 0, -1).unwrap();
    assert_eq!(0, in_backup.len());
}

#[test]
fn can_be_stopped() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":1}").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":2}").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":3}").unwrap();

    let len : u32 = con.llen("stopper").unwrap();
    assert_eq!(3, len);

    let mut worker = Worker::<Job>::new("stopper".into(), con);
    while let Some(mut task) = worker.next() {
        let task = task.unwrap();
        task.stop();
    }

    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let len : u32 = con.llen("stopper").unwrap();
    assert_eq!(2, len);
}
<commit_msg>Make stuff public<commit_after>extern crate rustc_serialize;
extern crate redis;

use std::str;
use std::cell::Cell;
use std::thread;
use std::ops::{Deref, Drop};
use std::convert::From;
use std::marker::PhantomData;
use rustc_serialize::{json, Decodable};
use redis::{Value, RedisResult, ErrorKind, Commands};

#[derive(RustcDecodable, RustcEncodable)]
struct Job {
    id: u64
}

pub trait TaskDecodable where Self: Sized {
    fn decode_task(value: &Value) -> RedisResult<Self>;
}

impl<T: Decodable> TaskDecodable for T {
    fn decode_task(value: &Value) -> RedisResult<T> {
        match value {
            &Value::Data(ref v) => {
                let s = try!(str::from_utf8(&v));
                Ok(try!(json::decode(&s).map_err(|_| (ErrorKind::TypeError, "JSON decode failed"))))

            },
            v @ _ => {
                println!("what do we have here: {:?}", v);
                try!(Err((ErrorKind::TypeError, "Can only decode from a string")))
            }
        }
    }
}

pub struct TaskGuard<'a, T: 'a> {
    task: T,
    worker: &'a Worker<T>
}

impl<'a, T: TaskDecodable> TaskGuard<'a, T> {
    pub fn stop(&self) {
        self.worker.stop();
    }

    pub fn inner(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Deref for TaskGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.task
    }
}

impl<'a, T> Drop for TaskGuard<'a, T> {
    fn drop(&mut self) {
        // Pop job from backup queue
        let backup = &self.worker.backup_queue[..];
        let _ : () = self.worker.client.lpop(backup).expect("LPOP from backup queue failed");
    }
}

pub struct Worker<T> {
    queue_name: String,
    backup_queue: String,
    stopped: Cell<bool>,
    pub client: redis::Connection,
    _job_type: PhantomData<T>,
}

impl<T: TaskDecodable> Worker<T> {
    pub fn new(name: String, client: redis::Connection) -> Worker<T> {
        let backup_queue = [thread::current().name().unwrap_or("default".into()), "1"].join(":");
        Worker {
            queue_name: name,
            backup_queue: backup_queue,
            client: client,
            stopped: Cell::new(false),
            _job_type: PhantomData,
        }
    }

    pub fn stop(&self) {
        self.stopped.set(true);
    }

    pub fn is_stopped(&self) -> bool {
        self.stopped.get()
    }

    pub fn next(&self) -> Option<RedisResult<TaskGuard<T>>> {
        if self.stopped.get() {
            return None;
        }

        let v;
        {
            let qname = &self.queue_name[..];
            let backup = &self.backup_queue[..];

            v = match self.client.brpoplpush(qname, backup, 0) {
                Ok(v) => v,
                Err(_) => {
                    return Some(Err(From::from((ErrorKind::TypeError, "next failed"))));
                }
            };
        }

        let v = match v {
            v @ Value::Data(_) => v,
            _ => {
                return Some(Err(From::from((ErrorKind::TypeError, "Not a 2-item Bulk reply"))));
            }
        };

        let task = T::decode_task(&v).unwrap();

        Some(Ok(TaskGuard{task: task, worker: self}))
    }
}

#[test]
fn decodes_job() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();

    let _ : () = con.rpush("default", "{\"id\":42}").unwrap();

    let mut worker = Worker::<Job>::new("default".into(), con);
    let j = worker.next().unwrap().unwrap();
    assert_eq!(42, j.id);
}

#[test]
fn releases_job() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let mut worker = Worker::<Job>::new("default".into(), con);

    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();

    let _ : () = con.lpush("default", "{\"id\":42}").unwrap();

    {
        let j = worker.next().unwrap().unwrap();
        assert_eq!(42, j.id);
        let in_backup : Vec<String> = con.lrange("releases_job:1", 0, -1).unwrap();
        assert_eq!(1, in_backup.len());
        assert_eq!("{\"id\":42}", in_backup[0]);
    }

    let in_backup : Vec<String> = con.lrange("releases_job:1", 0, -1).unwrap();
    assert_eq!(0, in_backup.len());
}

#[test]
fn can_be_stopped() {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let _ : () = con.del("stopper").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":1}").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":2}").unwrap();
    let _ : () = con.lpush("stopper", "{\"id\":3}").unwrap();

    let len : u32 = con.llen("stopper").unwrap();
    assert_eq!(3, len);

    let mut worker = Worker::<Job>::new("stopper".into(), con);
    while let Some(mut task) = worker.next() {
        let task = task.unwrap();
        task.stop();
    }

    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let con = client.get_connection().unwrap();
    let len : u32 = con.llen("stopper").unwrap();
    assert_eq!(2, len);
}
<|endoftext|>


<commit_before>#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {Forward, Reverse}
use self::Direction::*;

impl Direction {
	fn reverse(self) -> Direction {
		match self {
			Forward => Reverse,
			Reverse => Forward
		}
	}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum GlyphOrient {Perpendicular, Parallel}
use self::GlyphOrient::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct DirBehavior(Direction, GlyphOrient);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum DirPreference {Horiz(DirBehavior), Vert(DirBehavior), BiOrient(DirBehavior, DirBehavior)}	// enable scripts without preference?
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Rot180 {Normal, Rotated}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct StreakTypesetting(DirBehavior, Rot180);

impl StreakTypesetting {
	fn effective_direction(&self) -> Direction {
		match self.1 {
			Rot180::Normal => self.0 . 0,
			Rot180::Rotated => self.0 . 0 .reverse()
		}
	}
}

/// ISO 15924 alphabetical code
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ScriptCode([u8; 4]);

pub static LATIN: ScriptCode = ScriptCode(['L' as u8, 'a' as u8, 't' as u8, 'n' as u8]);	// "Latn"

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MainAxis {Ltr, Rtl, Ttb, Btt}

pub struct NonNativeConf;

pub struct Run<'a>(pub &'a str, pub ScriptCode);

pub fn make_default_streak<'a>(run: &'a Run, main_axis: MainAxis) -> Streak<'a> {
	use self::MainAxis::*;
	Streak(run.0, run.1, StreakTypesetting(DirBehavior(Forward, Perpendicular), if run.1 == LATIN {
		match main_axis {
			Ltr | Ttb => Rot180::Normal,
			Rtl | Btt => Rot180::Rotated
		}
	} else {
		unimplemented!();
	}))
}

pub fn make_runs(s: &str) -> Vec<Run> {vec![Run(s, LATIN)]}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Streak<'a>(&'a str, ScriptCode, StreakTypesetting);

impl<'a> Streak<'a> {
	/// what order do the parts have if you split the streak
	pub fn direction(&self) -> Direction {self.2.effective_direction()}
}

pub fn bidi_algorithm(streaks: &mut [Streak]) {}

pub struct FontPreference<'a>(Font<'a>);

/*impl FontPreference {
	fn lookup(&self) -> Vec<Burst> {
		Vec::new()
	}
}*/

/// contains glyphs and typesetting information
pub struct FontCollection<'a>(&'a[u8]);
/// what features of the font collection do we want to use?
pub struct FontConfiguration;

/// contains character mapping
pub struct Font<'a>(pub Encoding<'a>, &'a FontCollection<'a>);

struct GlyphPoint(i16, i16);
enum ContourSegment {
	Line(GlyphPoint, GlyphPoint),
	Curve(GlyphPoint, GlyphPoint, GlyphPoint)
}

pub fn read_u32(data: &[u8]) -> Option<u32> {
	if data.len() > 3 {
		Some((data[0] as u32) << 24 | (data[1] as u32) << 16 | (data[2] as u32) << 8 | data[3] as u32)
	} else {
		None
	}
}

pub fn read_u16(data: &[u8]) -> Option<u16> {
	if data.len() > 1 {
		Some((data[0] as u16) << 8 | data[1] as u16)
	} else {
		None
	}
}

fn fourcc(tag: u32) -> String {
	let mut s = String::with_capacity(4);
	s.push((tag >> 24) as u8 as char);
	s.push((tag >> 16) as u8 as char);
	s.push((tag >> 8) as u8 as char);
	s.push(tag as u8 as char);
	s
}

macro_rules! try_opt {
	($e:expr) => (match $e {Some(x)=>x, None=>return None})
}

fn scan_table_records(data: &[u8], start: usize, label: u32, num_tables: usize) -> Option<(usize, &[u8])> {
	for pos in start..num_tables {
		if try_opt!(read_u32(&data[12+16*pos..])) == label {
			let start = read_u32(&data[12+16*pos+8..]).unwrap() as usize;
			return Some((pos, &data[start..read_u32(&data[12+16*pos+12..]).unwrap() as usize+start]));
		}
	}
	None
}

fn find_best_cmap(cmap: &[u8]) -> Option<&[u8]> {
	let mut bmp = None;
	for encoding in 0..read_u16(&cmap[2..]).unwrap() as usize {
		let enc_header = &(&cmap[4+8*encoding..])[..8];
		let (plat, enc) = (read_u16(enc_header).unwrap(), read_u16(&enc_header[2..]).unwrap());
		println!("{}:{}", plat, enc);
		match (plat, enc) {
			(0, 3) | (3, 1) => {bmp=Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]);},
			(0, 4) | (3, 10) => return Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]),
			_ => {}	// unknown encoding
		}
	}
	bmp
}

enum Encoding<'a> {
	Fmt4(CmapFmt4<'a>)
}

trait Cmap {
	fn lookup<'a>(&self, &'a str) -> (Vec<GlyphIndex>, &'a str);
}

impl<'a> Encoding<'a> {
	pub fn lookup(&self, c: char) -> Option<GlyphIndex> {
		match *self {
			Encoding::Fmt4 (CmapFmt4 {end, start, delta, crazy_indexing_part: range_offset}) => {
				if c as u32 > 0xffff {return Some(GlyphIndex(0))}
				let mut range = 0..end.len()/2;
				while range.start != range.end {
					let pivot = ((range.end - range.start) & !1) + range.start*2;
					range = if read_u16(&end[pivot..]).unwrap() > c as u16 {
						pivot/2+1..range.end
					} else {
						range.start..pivot/2+1
					};
				}
				let seg_offset = range.start*2;
				let block_start = read_u16(&start[seg_offset..]).unwrap();
				if block_start < c as u16 {return Some(GlyphIndex(0))}
				let block_index = c as u16 - block_start;
				return Some(GlyphIndex((read_u16(&delta[seg_offset..]).unwrap()).wrapping_add({
					let offset = read_u16(&range_offset[seg_offset..]).unwrap();
					if offset == 0 {
						block_index
					} else {	// this path is untested because the spec is really weird and I've never seen it used
						let res = read_u16(&range_offset[seg_offset+(offset as usize &!1)+block_index as usize..]).unwrap();
						if res == 0 {
							return Some(GlyphIndex(0))
						} else {
							res
						}
					}
				})))
			}
		}
	}
}

struct CmapFmt4<'a> {
	end: &'a[u8],
	start: &'a[u8],
	delta: &'a[u8],
	crazy_indexing_part: &'a[u8]
}

fn load_enc_table(mut enc: &[u8]) -> Option<Encoding> {
	let format = try_opt!(read_u16(enc));
	println!("Format{}", format);
	match format {
		4 => {
			let len = try_opt!(read_u16(&enc[2..])) as usize;
			if len > enc.len() {return None}
			enc = &enc[..len];
			let segsX2 = try_opt!(read_u16(&enc[6..])) as usize;
			if segsX2 < 2 || segsX2 % 2 != 0 || 4*segsX2 + 16 < len {return None}
			let end = &enc[14..14+segsX2];
			if read_u16(&end[segsX2-2..]).unwrap() != 0xffff {return None}
			Some(Encoding::Fmt4(CmapFmt4{
				end: end,
				start: &enc[16+segsX2..16+2*segsX2],
				delta: &enc[16+2*segsX2..16+3*segsX2],
				crazy_indexing_part: &enc[16+3*segsX2..]
			}))
		},
		_ => None	// not implemented
	}
}

pub fn load_font_collection(data: &[u8]) -> Option<FontCollection> {
	Some(FontCollection(data))
}

pub fn load_font<'a>(collection: &'a FontCollection<'a>, font: &str) -> Option<Font<'a>> {
	let data = collection.0;
	let num_tables = try_opt!(read_u16(&data[4..])) as usize;
	let (_pos, cmap) = try_opt!(scan_table_records(data, 0, 0x636d6170, num_tables));
	let best_enc = try_opt!(find_best_cmap(cmap));
	let enc = try_opt!(load_enc_table(best_enc));
	Some(Font(enc, collection))
}

#[derive(Debug)]
pub struct GlyphIndex(u16);

struct Burst<'a, 'b: 'a>(Vec<GlyphIndex>, &'a Font<'b>, StreakTypesetting);

pub struct TypeSetting<'a, 'b: 'a>(Vec<Burst<'a, 'b>>);

fn typeset<'a, 'b>(streak: Streak, fonts: &FontPreference<'a>) -> TypeSetting<'b, 'a> {
	TypeSetting(Vec::new())
}<commit_msg>repair compilation<commit_after>#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {Forward, Reverse}
use self::Direction::*;

impl Direction {
	fn reverse(self) -> Direction {
		match self {
			Forward => Reverse,
			Reverse => Forward
		}
	}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum GlyphOrient {Perpendicular, Parallel}
use self::GlyphOrient::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct DirBehavior(Direction, GlyphOrient);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum DirPreference {Horiz(DirBehavior), Vert(DirBehavior), BiOrient(DirBehavior, DirBehavior)}	// enable scripts without preference?
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Rot180 {Normal, Rotated}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct StreakTypesetting(DirBehavior, Rot180);

impl StreakTypesetting {
	fn effective_direction(&self) -> Direction {
		match self.1 {
			Rot180::Normal => self.0 . 0,
			Rot180::Rotated => self.0 . 0 .reverse()
		}
	}
}

/// ISO 15924 alphabetical code
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ScriptCode([u8; 4]);

pub static LATIN: ScriptCode = ScriptCode(['L' as u8, 'a' as u8, 't' as u8, 'n' as u8]);	// "Latn"

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MainAxis {Ltr, Rtl, Ttb, Btt}

pub struct NonNativeConf;

pub struct Run<'a>(pub &'a str, pub ScriptCode);

pub fn make_default_streak<'a>(run: &'a Run, main_axis: MainAxis) -> Streak<'a> {
	use self::MainAxis::*;
	Streak(run.0, run.1, StreakTypesetting(DirBehavior(Forward, Perpendicular), if run.1 == LATIN {
		match main_axis {
			Ltr | Ttb => Rot180::Normal,
			Rtl | Btt => Rot180::Rotated
		}
	} else {
		unimplemented!();
	}))
}

pub fn make_runs(s: &str) -> Vec<Run> {vec![Run(s, LATIN)]}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Streak<'a>(&'a str, ScriptCode, StreakTypesetting);

impl<'a> Streak<'a> {
	/// what order do the parts have if you split the streak
	pub fn direction(&self) -> Direction {self.2.effective_direction()}
}

pub fn bidi_algorithm(streaks: &mut [Streak]) {}

pub struct FontPreference<'a>(Font<'a>);

/*impl FontPreference {
	fn lookup(&self) -> Vec<Burst> {
		Vec::new()
	}
}*/

/// contains glyphs and typesetting information
pub struct FontCollection<'a>(&'a[u8]);
/// what features of the font collection do we want to use?
pub struct FontConfiguration;

/// contains character mapping
pub struct Font<'a>(Encoding<'a>, &'a FontCollection<'a>);

struct GlyphPoint(i16, i16);
enum ContourSegment {
	Line(GlyphPoint, GlyphPoint),
	Curve(GlyphPoint, GlyphPoint, GlyphPoint)
}

pub fn read_u32(data: &[u8]) -> Option<u32> {
	if data.len() > 3 {
		Some((data[0] as u32) << 24 | (data[1] as u32) << 16 | (data[2] as u32) << 8 | data[3] as u32)
	} else {
		None
	}
}

pub fn read_u16(data: &[u8]) -> Option<u16> {
	if data.len() > 1 {
		Some((data[0] as u16) << 8 | data[1] as u16)
	} else {
		None
	}
}

fn fourcc(tag: u32) -> String {
	let mut s = String::with_capacity(4);
	s.push((tag >> 24) as u8 as char);
	s.push((tag >> 16) as u8 as char);
	s.push((tag >> 8) as u8 as char);
	s.push(tag as u8 as char);
	s
}

macro_rules! try_opt {
	($e:expr) => (match $e {Some(x)=>x, None=>return None})
}

fn scan_table_records(data: &[u8], start: usize, label: u32, num_tables: usize) -> Option<(usize, &[u8])> {
	for pos in start..num_tables {
		if try_opt!(read_u32(&data[12+16*pos..])) == label {
			let start = read_u32(&data[12+16*pos+8..]).unwrap() as usize;
			return Some((pos, &data[start..read_u32(&data[12+16*pos+12..]).unwrap() as usize+start]));
		}
	}
	None
}

fn find_best_cmap(cmap: &[u8]) -> Option<&[u8]> {
	let mut bmp = None;
	for encoding in 0..read_u16(&cmap[2..]).unwrap() as usize {
		let enc_header = &(&cmap[4+8*encoding..])[..8];
		let (plat, enc) = (read_u16(enc_header).unwrap(), read_u16(&enc_header[2..]).unwrap());
		println!("{}:{}", plat, enc);
		match (plat, enc) {
			(0, 3) | (3, 1) => {bmp=Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]);},
			(0, 4) | (3, 10) => return Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]),
			_ => {}	// unknown encoding
		}
	}
	bmp
}

enum Encoding<'a> {
	Fmt4(CmapFmt4<'a>)
}

trait Cmap {
	fn lookup<'a>(&self, &'a str) -> (Vec<GlyphIndex>, &'a str);
}

impl<'a> Encoding<'a> {
	pub fn lookup(&self, c: char) -> Option<GlyphIndex> {
		match *self {
			Encoding::Fmt4 (CmapFmt4 {end, start, delta, crazy_indexing_part: range_offset}) => {
				if c as u32 > 0xffff {return Some(GlyphIndex(0))}
				let mut range = 0..end.len()/2;
				while range.start != range.end {
					let pivot = ((range.end - range.start) & !1) + range.start*2;
					range = if read_u16(&end[pivot..]).unwrap() > c as u16 {
						pivot/2+1..range.end
					} else {
						range.start..pivot/2+1
					};
				}
				let seg_offset = range.start*2;
				let block_start = read_u16(&start[seg_offset..]).unwrap();
				if block_start < c as u16 {return Some(GlyphIndex(0))}
				let block_index = c as u16 - block_start;
				return Some(GlyphIndex((read_u16(&delta[seg_offset..]).unwrap()).wrapping_add({
					let offset = read_u16(&range_offset[seg_offset..]).unwrap();
					if offset == 0 {
						block_index
					} else {	// this path is untested because the spec is really weird and I've never seen it used
						let res = read_u16(&range_offset[seg_offset+(offset as usize &!1)+block_index as usize..]).unwrap();
						if res == 0 {
							return Some(GlyphIndex(0))
						} else {
							res
						}
					}
				})))
			}
		}
	}
}

struct CmapFmt4<'a> {
	end: &'a[u8],
	start: &'a[u8],
	delta: &'a[u8],
	crazy_indexing_part: &'a[u8]
}

fn load_enc_table(mut enc: &[u8]) -> Option<Encoding> {
	let format = try_opt!(read_u16(enc));
	println!("Format{}", format);
	match format {
		4 => {
			let len = try_opt!(read_u16(&enc[2..])) as usize;
			if len > enc.len() {return None}
			enc = &enc[..len];
			let segsX2 = try_opt!(read_u16(&enc[6..])) as usize;
			if segsX2 < 2 || segsX2 % 2 != 0 || 4*segsX2 + 16 < len {return None}
			let end = &enc[14..14+segsX2];
			if read_u16(&end[segsX2-2..]).unwrap() != 0xffff {return None}
			Some(Encoding::Fmt4(CmapFmt4{
				end: end,
				start: &enc[16+segsX2..16+2*segsX2],
				delta: &enc[16+2*segsX2..16+3*segsX2],
				crazy_indexing_part: &enc[16+3*segsX2..]
			}))
		},
		_ => None	// not implemented
	}
}

pub fn load_font_collection(data: &[u8]) -> Option<FontCollection> {
	Some(FontCollection(data))
}

pub fn load_font<'a>(collection: &'a FontCollection<'a>, font: &str) -> Option<Font<'a>> {
	let data = collection.0;
	let num_tables = try_opt!(read_u16(&data[4..])) as usize;
	let (_pos, cmap) = try_opt!(scan_table_records(data, 0, 0x636d6170, num_tables));
	let best_enc = try_opt!(find_best_cmap(cmap));
	let enc = try_opt!(load_enc_table(best_enc));
	Some(Font(enc, collection))
}

#[derive(Debug)]
pub struct GlyphIndex(u16);

struct Burst<'a, 'b: 'a>(Vec<GlyphIndex>, &'a Font<'b>, StreakTypesetting);

pub struct TypeSetting<'a, 'b: 'a>(Vec<Burst<'a, 'b>>);

fn typeset<'a, 'b>(streak: Streak, fonts: &FontPreference<'a>) -> TypeSetting<'b, 'a> {
	TypeSetting(Vec::new())
}<|endoftext|>


<commit_before>//! The main entry point for the SpaceAPi server.
//!
//! Running this code starts a HTTP server instance. The default port is 3000, but you can set your
//! own favorite port by exporting the `PORT` environment variable.

extern crate rustc_serialize;
extern crate iron;
extern crate spaceapi;

mod utils;

use std::io::Write;
use std::net::Ipv4Addr;

use rustc_serialize::json::ToJson;
use iron::{Chain, Request, Response, IronResult, IronError, Iron, Set};
use iron::{status, headers};
use iron::modifiers::Header;

use spaceapi::datastore::DataStore;
use spaceapi::redis_store::RedisStore;
use spaceapi::Optional::{Value, Absent};

fn build_response_json(people_present: Option<u32>, raspi_temperature: Option<f32>) -> String {
    let people_present_sensor = match people_present {
        Some(count) => Value(vec![
            spaceapi::PeopleNowPresentSensor {
                value: count,
                location: Value("Hackerspace".to_string()),
                name: Absent,
                description: Absent,
                names: Absent,
            }
        ]),
        None => Absent,
    };

    let temperature_sensor = match raspi_temperature {
        Some(degrees) => Value(vec![
            spaceapi::TemperatureSensor {
                value: degrees,
                unit: "°C".to_string(),
                location: "Hackerspace".to_string(),
                name: Value("Raspberry CPU".to_string()),
                description: Absent,
            }
        ]),
        None => Absent,
    };

    let status = spaceapi::Status {

        // Hackerspace properties
        api: "0.13".to_string(),
        space: "coredump".to_string(),
        logo: "https://www.coredump.ch/logo.png".to_string(),
        url: "https://www.coredump.ch/".to_string(),
        location: spaceapi::Location {
            address: Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
            lat: 47.22936,
            lon: 8.82949,
        },
        contact: spaceapi::Contact {
            irc: Value("irc://freenode.net/#coredump".to_string()),
            twitter: Value("@coredump_ch".to_string()),
            foursquare: Value("525c20e5498e875d8231b1e5".to_string()),
            email: Value("danilo@coredump.ch".to_string()),
        },

        // Hackerspace features / projects
        spacefed: Value(spaceapi::Spacefed {
            spacenet: false,
            spacesaml: false,
            spacephone: false,
        }),
        projects: Value(vec![
            "https://www.coredump.ch/projekte/".to_string(),
            "https://discourse.coredump.ch/c/projects".to_string(),
            "https://github.com/coredump-ch/".to_string(),
        ]),
        cam: Absent,
        feeds: Value(spaceapi::Feeds {
            blog: Value(spaceapi::Feed {
                _type: Value("rss".to_string()),
                url: "https://www.coredump.ch/feed/".to_string(),
            }),
            wiki: Absent,
            calendar: Absent,
            flickr: Absent,
        }),
        events: Absent,
        radio_show: Absent,

        // SpaceAPI internal usage
        cache: Value(spaceapi::Cache {
            schedule: "m.02".to_string(),
        }),
        issue_report_channels: vec![
            "email".to_string(),
            "twitter".to_string(),
        ],

        // Mutable data
        state: spaceapi::State {
            open: Some(false),
            message: Value("Open every Monday from 20:00".to_string()),
            lastchange: Absent,
            trigger_person: Absent,
            icon: Absent,
        },
        sensors: Value(spaceapi::Sensors {
            people_now_present: people_present_sensor,
            temperature: temperature_sensor,
        }),

    };
    status.to_json().to_string()
}

fn status_endpoint(_: &mut Request) -> IronResult<Response> {
    // Fetch data from datastore
    let datastore = RedisStore::new().unwrap();
    let people_present: Option<u32> = match datastore.retrieve("people_present") {
        Ok(v) => match v.parse::<u32>() {
            Ok(i) => Some(i),
            Err(_) => None,
        },
        Err(_) => None,
    };
    let raspi_temperature: Option<f32> = match datastore.retrieve("raspi_temperature") {
        Ok(v) => match v.parse::<f32>() {
            Ok(i) => Some(i),
            Err(_) => None,
        },
        Err(_) => None,
    };

    // Get response body
    let body = build_response_json(people_present, raspi_temperature);

    // Create response
    let mut response = Response::with((status::Ok, body));

    // Set headers
    response.set_mut(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())));
    response.set_mut(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])));
    response.set_mut(Header(headers::AccessControlAllowOrigin::Any));

    Ok(response)
}

pub struct SpaceapiServer {
    host: Ipv4Addr,
    port: u16,
    status: spaceapi::Status,
}

impl SpaceapiServer {

    pub fn new(host: Ipv4Addr, status: spaceapi::Status) -> SpaceapiServer {
        SpaceapiServer {
            host: host,
            port: utils::get_port(),
            status: status,
        }
    }

    pub fn serve(&self) {
        println!("Starting HTTP server on {}:{}...", self.host, self.port);
        Iron::new(status_endpoint).http((self.host, self.port)).unwrap();
    }

}

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

    #[test]
    /// Verify that the response JSON looks OK.
    fn verify_response_json() {
        let people_present = Some(23);
        let temperature = Some(42.5);
        let json = build_response_json(people_present, temperature);
        assert_eq!(json, "{\
            \"api\":\"0.13\",\
            \"cache\":{\"schedule\":\"m.02\"},\
            \"contact\":{\
                \"email\":\"danilo@coredump.ch\",\
                \"foursquare\":\"525c20e5498e875d8231b1e5\",\
                \"irc\":\"irc://freenode.net/#coredump\",\
                \"twitter\":\"@coredump_ch\"\
            },\
            \"feeds\":{\
                \"blog\":{\"type\":\"rss\",\"url\":\"https://www.coredump.ch/feed/\"}\
            },\
            \"issue_report_channels\":[\"email\",\"twitter\"],\
            \"location\":{\
                \"address\":\"Spinnereistrasse 2, 8640 Rapperswil, Switzerland\",\
                \"lat\":47.22936,\"lon\":8.82949\
            },\
            \"logo\":\"https://www.coredump.ch/logo.png\",\
            \"projects\":[\
                \"https://www.coredump.ch/projekte/\",\
                \"https://discourse.coredump.ch/c/projects\",\
                \"https://github.com/coredump-ch/\"\
            ],\
            \"sensors\":{\
                \"people_now_present\":[{\
                    \"location\":\"Hackerspace\",\"value\":23\
                }],\
                \"temperature\":[{\
                    \"location\":\"Hackerspace\",\"name\":\"Raspberry CPU\",\
                    \"unit\":\"°C\",\"value\":42.5\
                }]\
            },\
            \"space\":\"coredump\",\
            \"spacefed\":{\"spacenet\":false,\"spacephone\":false,\"spacesaml\":false},\
            \"state\":{\"message\":\"Open every Monday from 20:00\",\"open\":false},\
            \"url\":\"https://www.coredump.ch/\"\
        }");
    }
}
<commit_msg>Remove duplicated files<commit_after>//! The main entry point for the SpaceAPi server.
//!
//! Running this code starts a HTTP server instance. The default port is 3000, but you can set your
//! own favorite port by exporting the `PORT` environment variable.

extern crate rustc_serialize;
extern crate iron;
extern crate spaceapi;

mod utils;
mod datastore;
mod redis_store;

use std::io::Write;
use std::net::Ipv4Addr;

use rustc_serialize::json::ToJson;
use iron::{Chain, Request, Response, IronResult, IronError, Iron, Set};
use iron::{status, headers};
use iron::modifiers::Header;

use self::datastore::DataStore;
use self::redis_store::RedisStore;
use spaceapi::Optional::{Value, Absent};

fn build_response_json(people_present: Option<u32>, raspi_temperature: Option<f32>) -> String {
    let people_present_sensor = match people_present {
        Some(count) => Value(vec![
            spaceapi::PeopleNowPresentSensor {
                value: count,
                location: Value("Hackerspace".to_string()),
                name: Absent,
                description: Absent,
                names: Absent,
            }
        ]),
        None => Absent,
    };

    let temperature_sensor = match raspi_temperature {
        Some(degrees) => Value(vec![
            spaceapi::TemperatureSensor {
                value: degrees,
                unit: "°C".to_string(),
                location: "Hackerspace".to_string(),
                name: Value("Raspberry CPU".to_string()),
                description: Absent,
            }
        ]),
        None => Absent,
    };

    let status = spaceapi::Status {

        // Hackerspace properties
        api: "0.13".to_string(),
        space: "coredump".to_string(),
        logo: "https://www.coredump.ch/logo.png".to_string(),
        url: "https://www.coredump.ch/".to_string(),
        location: spaceapi::Location {
            address: Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
            lat: 47.22936,
            lon: 8.82949,
        },
        contact: spaceapi::Contact {
            irc: Value("irc://freenode.net/#coredump".to_string()),
            twitter: Value("@coredump_ch".to_string()),
            foursquare: Value("525c20e5498e875d8231b1e5".to_string()),
            email: Value("danilo@coredump.ch".to_string()),
        },

        // Hackerspace features / projects
        spacefed: Value(spaceapi::Spacefed {
            spacenet: false,
            spacesaml: false,
            spacephone: false,
        }),
        projects: Value(vec![
            "https://www.coredump.ch/projekte/".to_string(),
            "https://discourse.coredump.ch/c/projects".to_string(),
            "https://github.com/coredump-ch/".to_string(),
        ]),
        cam: Absent,
        feeds: Value(spaceapi::Feeds {
            blog: Value(spaceapi::Feed {
                _type: Value("rss".to_string()),
                url: "https://www.coredump.ch/feed/".to_string(),
            }),
            wiki: Absent,
            calendar: Absent,
            flickr: Absent,
        }),
        events: Absent,
        radio_show: Absent,

        // SpaceAPI internal usage
        cache: Value(spaceapi::Cache {
            schedule: "m.02".to_string(),
        }),
        issue_report_channels: vec![
            "email".to_string(),
            "twitter".to_string(),
        ],

        // Mutable data
        state: spaceapi::State {
            open: Some(false),
            message: Value("Open every Monday from 20:00".to_string()),
            lastchange: Absent,
            trigger_person: Absent,
            icon: Absent,
        },
        sensors: Value(spaceapi::Sensors {
            people_now_present: people_present_sensor,
            temperature: temperature_sensor,
        }),

    };
    status.to_json().to_string()
}

fn status_endpoint(_: &mut Request) -> IronResult<Response> {
    // Fetch data from datastore
    let datastore = RedisStore::new().unwrap();
    let people_present: Option<u32> = match datastore.retrieve("people_present") {
        Ok(v) => match v.parse::<u32>() {
            Ok(i) => Some(i),
            Err(_) => None,
        },
        Err(_) => None,
    };
    let raspi_temperature: Option<f32> = match datastore.retrieve("raspi_temperature") {
        Ok(v) => match v.parse::<f32>() {
            Ok(i) => Some(i),
            Err(_) => None,
        },
        Err(_) => None,
    };

    // Get response body
    let body = build_response_json(people_present, raspi_temperature);

    // Create response
    let mut response = Response::with((status::Ok, body));

    // Set headers
    response.set_mut(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())));
    response.set_mut(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])));
    response.set_mut(Header(headers::AccessControlAllowOrigin::Any));

    Ok(response)
}

pub struct SpaceapiServer {
    host: Ipv4Addr,
    port: u16,
    status: spaceapi::Status,
}

impl SpaceapiServer {

    pub fn new(host: Ipv4Addr, status: spaceapi::Status) -> SpaceapiServer {
        SpaceapiServer {
            host: host,
            port: utils::get_port(),
            status: status,
        }
    }

    pub fn serve(&self) {
        println!("Starting HTTP server on {}:{}...", self.host, self.port);
        Iron::new(status_endpoint).http((self.host, self.port)).unwrap();
    }

}

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

    #[test]
    /// Verify that the response JSON looks OK.
    fn verify_response_json() {
        let people_present = Some(23);
        let temperature = Some(42.5);
        let json = build_response_json(people_present, temperature);
        assert_eq!(json, "{\
            \"api\":\"0.13\",\
            \"cache\":{\"schedule\":\"m.02\"},\
            \"contact\":{\
                \"email\":\"danilo@coredump.ch\",\
                \"foursquare\":\"525c20e5498e875d8231b1e5\",\
                \"irc\":\"irc://freenode.net/#coredump\",\
                \"twitter\":\"@coredump_ch\"\
            },\
            \"feeds\":{\
                \"blog\":{\"type\":\"rss\",\"url\":\"https://www.coredump.ch/feed/\"}\
            },\
            \"issue_report_channels\":[\"email\",\"twitter\"],\
            \"location\":{\
                \"address\":\"Spinnereistrasse 2, 8640 Rapperswil, Switzerland\",\
                \"lat\":47.22936,\"lon\":8.82949\
            },\
            \"logo\":\"https://www.coredump.ch/logo.png\",\
            \"projects\":[\
                \"https://www.coredump.ch/projekte/\",\
                \"https://discourse.coredump.ch/c/projects\",\
                \"https://github.com/coredump-ch/\"\
            ],\
            \"sensors\":{\
                \"people_now_present\":[{\
                    \"location\":\"Hackerspace\",\"value\":23\
                }],\
                \"temperature\":[{\
                    \"location\":\"Hackerspace\",\"name\":\"Raspberry CPU\",\
                    \"unit\":\"°C\",\"value\":42.5\
                }]\
            },\
            \"space\":\"coredump\",\
            \"spacefed\":{\"spacenet\":false,\"spacephone\":false,\"spacesaml\":false},\
            \"state\":{\"message\":\"Open every Monday from 20:00\",\"open\":false},\
            \"url\":\"https://www.coredump.ch/\"\
        }");
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

//! Fast and lightweight Slab Allocator.

extern crate libc;

use std::{mem, ptr};
use std::ops::{Drop, Index};
use std::iter::{Iterator, IntoIterator};

pub struct Slab<T> {
    capacity: usize,
    len: usize,
    mem: *mut T
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    current_offset: usize
}

pub struct SlabMutIter<'a, T: 'a> {
    iter: SlabIter<'a, T>
}

impl<T> Slab<T> {
    /// Creates a new Slab
    pub fn new() -> Slab<T> { Slab::with_capacity(1) }

    /// Creates a new, empty Slab with room for `capacity` elems
    ///
    /// # Panics
    ///
    /// Panics if the host system is out of memory
    pub fn with_capacity(capacity: usize) -> Slab<T> {
        let maybe_ptr = unsafe {
            libc::malloc((mem::size_of::<T>() * capacity)) as *mut T
        };

        // malloc will return NULL if called with zero
        if maybe_ptr.is_null() && capacity != 0 {
            panic!("Unable to allocate requested capacity")
        }

        return Slab {
            capacity: capacity,
            len: 0,
            mem: maybe_ptr
        }
    }

    /// Inserts a new element into the slab, re-allocating if neccessary.
    ///
    /// # Panics
    /// * If the host system is out of memory.
    #[inline]
    pub fn insert(&mut self, elem: T) {
        if self.len == self.capacity {
            self.reallocate();
        }

        // let offset = self.len as isize;
        // let ptr = unsafe { self.mem.offset(offset) };
        // unsafe { ptr::write(ptr, elem) };
        let next_elem_offset = self.len as isize;
        unsafe {
            ptr::write(self.mem.offset(next_elem_offset), elem);
        }
        self.len += 1;
    }

    /// Removes the element at `offset`.
    ///
    /// # Panics
    ///
    /// * If `offset` is out of bounds.
    #[inline]
    pub fn remove(&mut self, offset: usize) -> T {
        if offset >= self.len {
            panic!("Offset {} out of bounds for slab.len: {}", offset, self.len)
        }

        let last_elem_offset = (self.len - 1) as isize;
        let elem = unsafe {
            let elem_ptr = self.mem.offset(offset as isize);
            let last_elem_ptr = self.mem.offset(last_elem_offset);
            mem::replace(&mut (*elem_ptr), ptr::read(last_elem_ptr))
        };

        self.len -= 1;

        return elem;
    }

    /// Returns the number of elements in the slab
    #[inline]
    pub fn len(&self) -> usize { self.len }

    /// Returns an iterator over the slab
    #[inline]
    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            current_offset: 0
        }
    }

    /// Returns a mutable iterator over the slab
    #[inline]
    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter { iter: self.iter() }
    }

    /// Reserves capacity * 2 extra space in this slab
    ///
    /// # Panics
    ///
    /// Panics if the host system is out of memory
    #[inline]
    fn reallocate(&mut self) {
        let new_capacity = if self.capacity != 0 { self.capacity * 2 } else { 1 };
        let maybe_ptr = unsafe {
            libc::realloc(self.mem as *mut libc::c_void,
                          (mem::size_of::<T>() * new_capacity)) as *mut T
        };

        if maybe_ptr.is_null() {
            panic!("Unable to allocate new capacity")
        }

        self.capacity = new_capacity;
        self.mem = maybe_ptr;
    }
}

impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        for x in 0..self.len() {
            unsafe {
                let elem_ptr = self.mem.offset(x as isize);
                ptr::drop_in_place(elem_ptr);
            }
        }

        unsafe { libc::free(self.mem as *mut _ as *mut libc::c_void) };
    }
}

impl<T> Index<usize> for Slab<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        unsafe {
            &(*(self.mem.offset(index as isize)))
        }
    }
}

impl<'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        while self.current_offset < self.slab.len() {
            let offset = self.current_offset;
            self.current_offset += 1;
            unsafe {
                return Some(&(*self.slab.mem.offset(offset as isize)));
            }
        }

        None
    }
}

impl<'a, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        unsafe { mem::transmute(self.iter.next()) }
    }
}

impl<'a, T> IntoIterator for &'a Slab<T> {
    type Item = &'a T;
    type IntoIter = SlabIter<'a, T>;
    fn into_iter(self) -> SlabIter<'a, T> {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut Slab<T> {
    type Item = &'a mut T;
    type IntoIter = SlabMutIter<'a, T>;
    fn into_iter(self) -> SlabMutIter<'a, T> {
        self.iter_mut()
    }
}
<commit_msg>insert refactor<commit_after>// Copyright 2016 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

//! Fast and lightweight Slab Allocator.

extern crate libc;

use std::{mem, ptr};
use std::ops::{Drop, Index};
use std::iter::{Iterator, IntoIterator};

pub struct Slab<T> {
    capacity: usize,
    len: usize,
    mem: *mut T
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    current_offset: usize
}

pub struct SlabMutIter<'a, T: 'a> {
    iter: SlabIter<'a, T>
}

impl<T> Slab<T> {
    /// Creates a new Slab
    pub fn new() -> Slab<T> { Slab::with_capacity(1) }

    /// Creates a new, empty Slab with room for `capacity` elems
    ///
    /// # Panics
    ///
    /// Panics if the host system is out of memory
    pub fn with_capacity(capacity: usize) -> Slab<T> {
        let maybe_ptr = unsafe {
            libc::malloc((mem::size_of::<T>() * capacity)) as *mut T
        };

        // malloc will return NULL if called with zero
        if maybe_ptr.is_null() && capacity != 0 {
            panic!("Unable to allocate requested capacity")
        }

        return Slab {
            capacity: capacity,
            len: 0,
            mem: maybe_ptr
        }
    }

    /// Inserts a new element into the slab, re-allocating if neccessary.
    ///
    /// # Panics
    /// * If the host system is out of memory.
    #[inline]
    pub fn insert(&mut self, elem: T) {
        if self.len == self.capacity { self.reallocate(); }

        unsafe {
            let ptr = self.mem.offset(self.len as isize);
            ptr::write(ptr, elem);
        }

        self.len += 1;
    }

    /// Removes the element at `offset`.
    ///
    /// # Panics
    ///
    /// * If `offset` is out of bounds.
    #[inline]
    pub fn remove(&mut self, offset: usize) -> T {
        if offset >= self.len {
            panic!("Offset {} out of bounds for slab.len: {}", offset, self.len)
        }

        let last_elem_offset = (self.len - 1) as isize;
        let elem = unsafe {
            let elem_ptr = self.mem.offset(offset as isize);
            let last_elem_ptr = self.mem.offset(last_elem_offset);
            mem::replace(&mut (*elem_ptr), ptr::read(last_elem_ptr))
        };

        self.len -= 1;

        return elem;
    }

    /// Returns the number of elements in the slab
    #[inline]
    pub fn len(&self) -> usize { self.len }

    /// Returns an iterator over the slab
    #[inline]
    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            current_offset: 0
        }
    }

    /// Returns a mutable iterator over the slab
    #[inline]
    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter { iter: self.iter() }
    }

    /// Reserves capacity * 2 extra space in this slab
    ///
    /// # Panics
    ///
    /// Panics if the host system is out of memory
    #[inline]
    fn reallocate(&mut self) {
        let new_capacity = if self.capacity != 0 { self.capacity * 2 } else { 1 };
        let maybe_ptr = unsafe {
            libc::realloc(self.mem as *mut libc::c_void,
                          (mem::size_of::<T>() * new_capacity)) as *mut T
        };

        if maybe_ptr.is_null() {
            panic!("Unable to allocate new capacity")
        }

        self.capacity = new_capacity;
        self.mem = maybe_ptr;
    }
}

impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        for x in 0..self.len() {
            unsafe {
                let elem_ptr = self.mem.offset(x as isize);
                ptr::drop_in_place(elem_ptr);
            }
        }

        unsafe { libc::free(self.mem as *mut _ as *mut libc::c_void) };
    }
}

impl<T> Index<usize> for Slab<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        unsafe {
            &(*(self.mem.offset(index as isize)))
        }
    }
}

impl<'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        while self.current_offset < self.slab.len() {
            let offset = self.current_offset;
            self.current_offset += 1;
            unsafe {
                return Some(&(*self.slab.mem.offset(offset as isize)));
            }
        }

        None
    }
}

impl<'a, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        unsafe { mem::transmute(self.iter.next()) }
    }
}

impl<'a, T> IntoIterator for &'a Slab<T> {
    type Item = &'a T;
    type IntoIter = SlabIter<'a, T>;
    fn into_iter(self) -> SlabIter<'a, T> {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut Slab<T> {
    type Item = &'a mut T;
    type IntoIter = SlabMutIter<'a, T>;
    fn into_iter(self) -> SlabMutIter<'a, T> {
        self.iter_mut()
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate rand;

pub fn petname(words: u16, separator: &str) -> String {
    let petnames = Petnames::default();
    let mut rng = rand::thread_rng();
    generate(&petnames, &mut rng, words, separator)
}

pub fn generate<RNG>(
    petnames: &Petnames, rng: &mut RNG,
    words: u16, separator: &str) -> String
    where RNG: rand::Rng
{
    // Adverbs all the way, finishing with adjective then name.
    let mut parts = Vec::with_capacity(words as usize);
    for num in (0..words).rev() {
        parts.push(*match num {
            0 => rng.choose(&petnames.names).unwrap(),
            1 => rng.choose(&petnames.adjectives).unwrap(),
            _ => rng.choose(&petnames.adverbs).unwrap(),
        });
    };
    // Join the string parts.
    parts.join(separator)
}

pub struct Petnames<'a> {
    pub adjectives: Vec<&'a str>,
    pub adverbs: Vec<&'a str>,
    pub names: Vec<&'a str>,
}

impl<'a> Petnames<'a> {

    pub fn default() -> Petnames<'a> {
        let adjectives = concat!(
            include_str!("../words/large/adjectives.txt"), "\n",
            include_str!("../words/medium/adjectives.txt"), "\n",
            include_str!("../words/small/adjectives.txt"), "\n",
        );
        let adverbs = concat!(
            include_str!("../words/large/adverbs.txt"), "\n",
            include_str!("../words/medium/adverbs.txt"), "\n",
            include_str!("../words/small/adverbs.txt"), "\n",
        );
        let names = concat!(
            include_str!("../words/large/names.txt"), "\n",
            include_str!("../words/medium/names.txt"), "\n",
            include_str!("../words/small/names.txt"), "\n",
        );
        Self{
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

}

#[cfg(test)]
mod tests {

    #[test]
    fn test() {
    }

}
<commit_msg>Simple tests.<commit_after>#![allow(dead_code)]

extern crate rand;

pub fn petname(words: u16, separator: &str) -> String {
    let petnames = Petnames::default();
    let mut rng = rand::thread_rng();
    generate(&petnames, &mut rng, words, separator)
}

pub fn generate<RNG>(
    petnames: &Petnames, rng: &mut RNG,
    words: u16, separator: &str) -> String
    where RNG: rand::Rng
{
    // Adverbs all the way, finishing with adjective then name.
    let mut parts = Vec::with_capacity(words as usize);
    for num in (0..words).rev() {
        parts.push(*match num {
            0 => rng.choose(&petnames.names).unwrap(),
            1 => rng.choose(&petnames.adjectives).unwrap(),
            _ => rng.choose(&petnames.adverbs).unwrap(),
        });
    };
    parts.join(separator)
}

pub struct Petnames<'a> {
    pub adjectives: Vec<&'a str>,
    pub adverbs: Vec<&'a str>,
    pub names: Vec<&'a str>,
}

impl<'a> Petnames<'a> {

    pub fn default() -> Petnames<'a> {
        let adjectives = concat!(
            include_str!("../words/large/adjectives.txt"), "\n",
            include_str!("../words/medium/adjectives.txt"), "\n",
            include_str!("../words/small/adjectives.txt"), "\n",
        );
        let adverbs = concat!(
            include_str!("../words/large/adverbs.txt"), "\n",
            include_str!("../words/medium/adverbs.txt"), "\n",
            include_str!("../words/small/adverbs.txt"), "\n",
        );
        let names = concat!(
            include_str!("../words/large/names.txt"), "\n",
            include_str!("../words/medium/names.txt"), "\n",
            include_str!("../words/small/names.txt"), "\n",
        );
        Self{
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

}

#[cfg(test)]
mod tests {

    use super::{generate, Petnames, rand};

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames{
            adjectives: vec!("adjective"),
            adverbs: vec!("adverb"),
            names: vec!("name"),
        };
        assert_eq!(
            generate(&petnames, &mut rand::thread_rng(), 3, "-"),
            "adverb-adjective-name");
    }

}
<|endoftext|>


<commit_before>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
// warnings even though the macro expands into something with allow(dead_code)
#![allow(dead_code)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]

// Re-exported external crates
pub use libc;

// Private internal modules
#[macro_use] mod macros;

// Public crates
#[cfg(not(target_os = "redox"))]
pub mod dir;
pub mod env;
pub mod errno;
#[deny(missing_docs)]
pub mod features;
pub mod fcntl;
#[deny(missing_docs)]
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "illumos",
          target_os = "openbsd"))]
pub mod ifaddrs;
#[cfg(any(target_os = "android",
          target_os = "linux"))]
pub mod kmod;
#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "linux"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "fushsia",
          target_os = "linux",
          target_os = "netbsd"))]
pub mod mqueue;
#[deny(missing_docs)]
#[cfg(not(target_os = "redox"))]
pub mod net;
#[deny(missing_docs)]
pub mod poll;
#[deny(missing_docs)]
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
pub mod pty;
pub mod sched;
pub mod sys;
pub mod time;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
          any(target_arch = "x86", target_arch = "x86_64")))]
pub mod ucontext;
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::{c_char, PATH_MAX};

use std::{ptr, result};
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Errno>;

/// Nix's main error type.
///
/// It's a wrapper around Errno.  As such, it's very interoperable with
/// [`std::io::Error`], but it has the advantages of:
/// * `Clone`
/// * `Copy`
/// * `Eq`
/// * Small size
/// * Represents all of the system's errnos, instead of just the most common
/// ones.
pub type Error = Errno;

pub trait NixPath {
    fn is_empty(&self) -> bool;

    fn len(&self) -> usize;

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(OsStr::new(self))
    }

    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn is_empty(&self) -> bool {
        self.as_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn is_empty(&self) -> bool {
        self.to_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Error::from(Errno::ENAMETOOLONG))
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn is_empty(&self) -> bool {
        self.is_empty()
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Error::from(Errno::ENAMETOOLONG))
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Error::from(Errno::EINVAL)),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}
<commit_msg>Forbid dead code again<commit_after>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]

// Re-exported external crates
pub use libc;

// Private internal modules
#[macro_use] mod macros;

// Public crates
#[cfg(not(target_os = "redox"))]
pub mod dir;
pub mod env;
pub mod errno;
#[deny(missing_docs)]
pub mod features;
pub mod fcntl;
#[deny(missing_docs)]
#[cfg(any(target_os = "android",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "illumos",
          target_os = "openbsd"))]
pub mod ifaddrs;
#[cfg(any(target_os = "android",
          target_os = "linux"))]
pub mod kmod;
#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "linux"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "fushsia",
          target_os = "linux",
          target_os = "netbsd"))]
pub mod mqueue;
#[deny(missing_docs)]
#[cfg(not(target_os = "redox"))]
pub mod net;
#[deny(missing_docs)]
pub mod poll;
#[deny(missing_docs)]
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
pub mod pty;
pub mod sched;
pub mod sys;
pub mod time;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
          any(target_arch = "x86", target_arch = "x86_64")))]
pub mod ucontext;
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::{c_char, PATH_MAX};

use std::{ptr, result};
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Errno>;

/// Nix's main error type.
///
/// It's a wrapper around Errno.  As such, it's very interoperable with
/// [`std::io::Error`], but it has the advantages of:
/// * `Clone`
/// * `Copy`
/// * `Eq`
/// * Small size
/// * Represents all of the system's errnos, instead of just the most common
/// ones.
pub type Error = Errno;

pub trait NixPath {
    fn is_empty(&self) -> bool;

    fn len(&self) -> usize;

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(OsStr::new(self))
    }

    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn is_empty(&self) -> bool {
        self.as_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn is_empty(&self) -> bool {
        self.to_bytes().is_empty()
    }

    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Error::from(Errno::ENAMETOOLONG))
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn is_empty(&self) -> bool {
        self.is_empty()
    }

    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Error::from(Errno::ENAMETOOLONG))
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Error::from(Errno::EINVAL)),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn is_empty(&self) -> bool {
        NixPath::is_empty(self.as_os_str())
    }

    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}
<|endoftext|>